<commit_before>use std::map::HashMap;

use ast::{crate, expr_, expr_mac, mac_invoc, mac_invoc_tt,
          tt_delim, tt_tok, item_mac, stmt_, stmt_mac};
use fold::*;
use ext::base::*;
use ext::qquote::{qq_helper};
use parse::{parser, parse_expr_from_source_str, new_parser_from_tts};

use codemap::{span, ExpandedFrom};

fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
               e: expr_, s: span, fld: ast_fold,
               orig: fn@(expr_, span, ast_fold) -> (expr_, span))
    -> (expr_, span)
{
    return match e {
      // expr_mac should really be expr_ext or something; it's the
      // entry-point for all syntax extensions.
          expr_mac(mac) => {

            match mac.node {
              // Old-style macros. For compatibility, will erase this whole
              // block once we've transitioned.
              mac_invoc(pth, args, body) => {
                assert (vec::len(pth.idents) > 0u);
                /* using idents and token::special_idents would make the
                the macro names be hygienic */
                let extname = cx.parse_sess().interner.get(pth.idents[0]);
                match exts.find(*extname) {
                  None => {
                    cx.span_fatal(pth.span,
                                  fmt!("macro undefined: '%s'", *extname))
                  }
                  Some(item_decorator(_)) => {
                    cx.span_fatal(
                        pth.span,
                        fmt!("%s can only be used as a decorator", *extname));
                  }
                  Some(normal({expander: exp, span: exp_sp})) => {
                    let expanded = exp(cx, mac.span, args, body);

                    cx.bt_push(ExpandedFrom({call_site: s,
                                callie: {name: *extname, span: exp_sp}}));
                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    (fully_expanded, s)
                  }
                  Some(macro_defining(ext)) => {
                    let named_extension = ext(cx, mac.span, args, body);
                    exts.insert(named_extension.name, named_extension.ext);
                    (ast::expr_rec(~[], None), s)
                  }
                  Some(normal_tt(_)) => {
                    cx.span_fatal(pth.span,
                                  fmt!("this tt-style macro should be \
                                        invoked '%s!(...)'", *extname))
                  }
                  Some(item_tt(*)) => {
                    cx.span_fatal(pth.span,
                                  ~"cannot use item macros in this context");
                  }
                }
              }

              // Token-tree macros, these will be the only case when we're
              // finished transitioning.
              mac_invoc_tt(pth, tts) => {
                assert (vec::len(pth.idents) == 1u);
                /* using idents and token::special_idents would make the
                the macro names be hygienic */
                let extname = cx.parse_sess().interner.get(pth.idents[0]);
                match exts.find(*extname) {
                  None => {
                    cx.span_fatal(pth.span,
                                  fmt!("macro undefined: '%s'", *extname))
                  }
                  Some(normal_tt({expander: exp, span: exp_sp})) => {
                    let expanded = match exp(cx, mac.span, tts) {
                      mr_expr(e) => e,
                      mr_any(expr_maker,_,_) => expr_maker(),
                      _ => cx.span_fatal(
                          pth.span, fmt!("non-expr macro in expr pos: %s",
                                         *extname))
                    };

                    cx.bt_push(ExpandedFrom({call_site: s,
                                callie: {name: *extname, span: exp_sp}}));
                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    (fully_expanded, s)
                  }
                  Some(normal({expander: exp, span: exp_sp})) => {
                    //convert the new-style invoc for the old-style macro
                    let arg = base::tt_args_to_original_flavor(cx, pth.span,
                                                               tts);
                    let expanded = exp(cx, mac.span, arg, None);

                    cx.bt_push(ExpandedFrom({call_site: s,
                                callie: {name: *extname, span: exp_sp}}));
                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    (fully_expanded, s)
                  }
                  _ => {
                    cx.span_fatal(pth.span,
                                  fmt!("'%s' is not a tt-style macro",
                                       *extname))
                  }

                }
              }
              _ => cx.span_bug(mac.span, ~"naked syntactic bit")
            }
          }
          _ => orig(e, s, fld)
        };
}

// This is a secondary mechanism for invoking syntax extensions on items:
// "decorator" attributes, such as #[auto_serialize]. These are invoked by an
// attribute prefixing an item, and are interpreted by feeding the item
// through the named attribute _as a syntax extension_ and splicing in the
// resulting item vec into place in favour of the decorator. Note that
// these do _not_ work for macro extensions, just item_decorator ones.
//
// NB: there is some redundancy between this and expand_item, below, and
// they might benefit from some amount of semantic and language-UI merger.
fn expand_mod_items(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
                    module_: ast::_mod, fld: ast_fold,
                    orig: fn@(ast::_mod, ast_fold) -> ast::_mod)
    -> ast::_mod
{
    // Fold the contents first:
    let module_ = orig(module_, fld);

    // For each item, look through the attributes.  If any of them are
    // decorated with "item decorators", then use that function to transform
    // the item into a new set of items.
    let new_items = do vec::flat_map(module_.items) |item| {
        do vec::foldr(item.attrs, ~[*item]) |attr, items| {
            let mname = match attr.node.value.node {
              ast::meta_word(n) => n,
              ast::meta_name_value(n, _) => n,
              ast::meta_list(n, _) => n
            };
            match exts.find(mname) {
              None | Some(normal(_)) | Some(macro_defining(_))
              | Some(normal_tt(_)) | Some(item_tt(*)) => items,
              Some(item_decorator(dec_fn)) => {
                dec_fn(cx, attr.span, attr.node.value, items)
              }
            }
        }
    };

    return {items: new_items, ..module_};
}

// When we enter a module, record it, for the sake of `module!`
fn expand_item(exts: HashMap<~str, syntax_extension>,
               cx: ext_ctxt, &&it: @ast::item, fld: ast_fold,
               orig: fn@(&&v: @ast::item, ast_fold) -> Option<@ast::item>)
    -> Option<@ast::item>
{
    let is_mod = match it.node {
      ast::item_mod(_) | ast::item_foreign_mod(_) => true,
      _ => false
    };
    let maybe_it = match it.node {
      ast::item_mac(*) => expand_item_mac(exts, cx, it, fld),
      _ => Some(it)
    };

    match maybe_it {
      Some(it) => {
        if is_mod { cx.mod_push(it.ident); }
        let ret_val = orig(it, fld);
        if is_mod { cx.mod_pop(); }
        return ret_val;
      }
      None => return None
    }
}

// Support for item-position macro invocations, exactly the same
// logic as for expression-position macro invocations.
fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
                   cx: ext_ctxt, &&it: @ast::item,
                   fld: ast_fold) -> Option<@ast::item> {
    match it.node {
      item_mac({node: mac_invoc_tt(pth, tts), _}) => {
        let extname = cx.parse_sess().interner.get(pth.idents[0]);
        let (expanded, ex_span) = match exts.find(*extname) {
          None => {
            cx.span_fatal(pth.span,
                          fmt!("macro undefined: '%s!'", *extname))
          }
          Some(normal_tt(expand)) => {
            if it.ident != parse::token::special_idents::invalid {
                cx.span_fatal(pth.span,
                              fmt!("macro %s! expects no ident argument, \
                                    given '%s'", *extname,
                                   *cx.parse_sess().interner.get(it.ident)));
            }
            (expand.expander(cx, it.span, tts), expand.span)
          }
          Some(item_tt(expand)) => {
            if it.ident == parse::token::special_idents::invalid {
                cx.span_fatal(pth.span,
                              fmt!("macro %s! expects an ident argument",
                                   *extname));
            }
            (expand.expander(cx, it.span, it.ident, tts), expand.span)
          }
          _ => cx.span_fatal(
              it.span, fmt!("%s! is not legal in item position", *extname))
        };

        cx.bt_push(ExpandedFrom({call_site: it.span,
                                  callie: {name: *extname,
                                           span: ex_span}}));
        let maybe_it = match expanded {
            mr_item(it) => fld.fold_item(it),
            mr_expr(_) => cx.span_fatal(pth.span,
                                        ~"expr macro in item position: " +
                                        *extname),
            mr_any(_, item_maker, _) =>
                option::chain(item_maker(), |i| {fld.fold_item(i)}),
            mr_def(mdef) => {
                exts.insert(mdef.name, mdef.ext);
                None
            }
        };
        cx.bt_pop();
        return maybe_it;
      }
      _ => cx.span_bug(it.span, ~"invalid item macro invocation")
    }
}

fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
               && s: stmt_, sp: span, fld: ast_fold,
               orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
    -> (stmt_, span)
{
    return match s {
        stmt_mac(mac) => {
            match mac.node {
                mac_invoc_tt(pth, tts) => {
                    assert(vec::len(pth.idents) == 1u);
                    let extname = cx.parse_sess().interner.get(pth.idents[0]);
                    match exts.find(*extname) {
                        None => {
                            cx.span_fatal(
                                pth.span,
                                fmt!("macro undefined: '%s'", *extname))
                        }
                        Some(normal_tt({expander: exp, span: exp_sp})) => {
                            let expanded = match exp(cx, mac.span, tts) {
                                mr_expr(e) =>
                                @{node: ast::stmt_expr(e, cx.next_id()),
                                  span: e.span},
                                mr_any(_,_,stmt_mkr) => stmt_mkr(),
                                _ => cx.span_fatal(
                                    pth.span,
                                    fmt!("non-stmt macro in stmt pos: %s",
                                         *extname))
                            };

                            cx.bt_push(ExpandedFrom(
                                {call_site: sp,
                                 callie: {name: *extname, span: exp_sp}}));
                            //keep going, outside-in
                            let fully_expanded = fld.fold_stmt(expanded).node;
                            cx.bt_pop();

                            (fully_expanded, sp)
                        }
                        _ => {
                            cx.span_fatal(pth.span,
                                          fmt!("'%s' is not a tt-style macro",
                                               *extname))
                        }
                    }
                }
                _ => cx.span_bug(mac.span, ~"naked syntactic bit")
            }
        }
        _ => orig(s, sp, fld)
    };
}

fn new_span(cx: ext_ctxt, sp: span) -> span {
    /* this discards information in the case of macro-defining macros */
    return span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
}

// FIXME (#2247): this is a terrible kludge to inject some macros into
// the default compilation environment. When the macro-definition system
// is substantially more mature, these should move from here, into a
// compiled part of libcore at very least.

fn core_macros() -> ~str {
    return
~"{
    macro_rules! ignore (($($x:tt)*) => (()))
    #macro[[#error[f, ...], log(core::error, #fmt[f, ...])]];
    #macro[[#warn[f, ...], log(core::warn, #fmt[f, ...])]];
    #macro[[#info[f, ...], log(core::info, #fmt[f, ...])]];
    #macro[[#debug[f, ...], log(core::debug, #fmt[f, ...])]];

    macro_rules! die(
        ($msg: expr) => (
            {
                do core::str::as_buf($msg) |msg_buf, _msg_len| {
                    do core::str::as_buf(file!()) |file_buf, _file_len| {
                        unsafe {
                            let msg_buf = core::cast::transmute(msg_buf);
                            let file_buf = core::cast::transmute(file_buf);
                            let line = line!() as core::libc::size_t;
                            core::rt::rt_fail_(msg_buf, file_buf, line)
                        }
                    }
                }
            }
        );
        () => (
            die!(\"explicit failure\")
        )
    )
}";
}

fn expand_crate(parse_sess: parse::parse_sess,
                cfg: ast::crate_cfg, c: @crate) -> @crate {
    let exts = syntax_expander_table();
    let afp = default_ast_fold();
    let cx: ext_ctxt = mk_ctxt(parse_sess, cfg);
    let f_pre =
        @{fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr),
          fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod),
          fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item),
          fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt),
          new_span: |a| new_span(cx, a),
          .. *afp};
    let f = make_fold(f_pre);
    let cm = parse_expr_from_source_str(~"<core-macros>",
                                        @core_macros(),
                                        cfg,
                                        parse_sess);

    // This is run for its side-effects on the expander env,
    // as it registers all the core macros as expanders.
    f.fold_expr(cm);

    let res = @f.fold_crate(*c);
    return res;
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Use `biased_match!` to avoid over-deep indentation in expand.rs.<commit_after>use std::map::HashMap;

use ast::{crate, expr_, expr_mac, mac_invoc, mac_invoc_tt,
          tt_delim, tt_tok, item_mac, stmt_, stmt_mac};
use fold::*;
use ext::base::*;
use ext::qquote::{qq_helper};
use parse::{parser, parse_expr_from_source_str, new_parser_from_tts};

use codemap::{span, ExpandedFrom};

fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
               e: expr_, s: span, fld: ast_fold,
               orig: fn@(expr_, span, ast_fold) -> (expr_, span))
    -> (expr_, span)
{
    return match e {
      // expr_mac should really be expr_ext or something; it's the
      // entry-point for all syntax extensions.
          expr_mac(mac) => {

            match mac.node {
              // Old-style macros. For compatibility, will erase this whole
              // block once we've transitioned.
              mac_invoc(pth, args, body) => {
                assert (vec::len(pth.idents) > 0u);
                /* using idents and token::special_idents would make the
                the macro names be hygienic */
                let extname = cx.parse_sess().interner.get(pth.idents[0]);
                match exts.find(*extname) {
                  None => {
                    cx.span_fatal(pth.span,
                                  fmt!("macro undefined: '%s'", *extname))
                  }
                  Some(item_decorator(_)) => {
                    cx.span_fatal(
                        pth.span,
                        fmt!("%s can only be used as a decorator", *extname));
                  }
                  Some(normal({expander: exp, span: exp_sp})) => {
                    let expanded = exp(cx, mac.span, args, body);

                    cx.bt_push(ExpandedFrom({call_site: s,
                                callie: {name: *extname, span: exp_sp}}));
                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    (fully_expanded, s)
                  }
                  Some(macro_defining(ext)) => {
                    let named_extension = ext(cx, mac.span, args, body);
                    exts.insert(named_extension.name, named_extension.ext);
                    (ast::expr_rec(~[], None), s)
                  }
                  Some(normal_tt(_)) => {
                    cx.span_fatal(pth.span,
                                  fmt!("this tt-style macro should be \
                                        invoked '%s!(...)'", *extname))
                  }
                  Some(item_tt(*)) => {
                    cx.span_fatal(pth.span,
                                  ~"cannot use item macros in this context");
                  }
                }
              }

              // Token-tree macros, these will be the only case when we're
              // finished transitioning.
              mac_invoc_tt(pth, tts) => {
                assert (vec::len(pth.idents) == 1u);
                /* using idents and token::special_idents would make the
                the macro names be hygienic */
                let extname = cx.parse_sess().interner.get(pth.idents[0]);
                match exts.find(*extname) {
                  None => {
                    cx.span_fatal(pth.span,
                                  fmt!("macro undefined: '%s'", *extname))
                  }
                  Some(normal_tt({expander: exp, span: exp_sp})) => {
                    let expanded = match exp(cx, mac.span, tts) {
                      mr_expr(e) => e,
                      mr_any(expr_maker,_,_) => expr_maker(),
                      _ => cx.span_fatal(
                          pth.span, fmt!("non-expr macro in expr pos: %s",
                                         *extname))
                    };

                    cx.bt_push(ExpandedFrom({call_site: s,
                                callie: {name: *extname, span: exp_sp}}));
                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    (fully_expanded, s)
                  }
                  Some(normal({expander: exp, span: exp_sp})) => {
                    //convert the new-style invoc for the old-style macro
                    let arg = base::tt_args_to_original_flavor(cx, pth.span,
                                                               tts);
                    let expanded = exp(cx, mac.span, arg, None);

                    cx.bt_push(ExpandedFrom({call_site: s,
                                callie: {name: *extname, span: exp_sp}}));
                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    (fully_expanded, s)
                  }
                  _ => {
                    cx.span_fatal(pth.span,
                                  fmt!("'%s' is not a tt-style macro",
                                       *extname))
                  }

                }
              }
              _ => cx.span_bug(mac.span, ~"naked syntactic bit")
            }
          }
          _ => orig(e, s, fld)
        };
}

// This is a secondary mechanism for invoking syntax extensions on items:
// "decorator" attributes, such as #[auto_serialize]. These are invoked by an
// attribute prefixing an item, and are interpreted by feeding the item
// through the named attribute _as a syntax extension_ and splicing in the
// resulting item vec into place in favour of the decorator. Note that
// these do _not_ work for macro extensions, just item_decorator ones.
//
// NB: there is some redundancy between this and expand_item, below, and
// they might benefit from some amount of semantic and language-UI merger.
fn expand_mod_items(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
                    module_: ast::_mod, fld: ast_fold,
                    orig: fn@(ast::_mod, ast_fold) -> ast::_mod)
    -> ast::_mod
{
    // Fold the contents first:
    let module_ = orig(module_, fld);

    // For each item, look through the attributes.  If any of them are
    // decorated with "item decorators", then use that function to transform
    // the item into a new set of items.
    let new_items = do vec::flat_map(module_.items) |item| {
        do vec::foldr(item.attrs, ~[*item]) |attr, items| {
            let mname = match attr.node.value.node {
              ast::meta_word(n) => n,
              ast::meta_name_value(n, _) => n,
              ast::meta_list(n, _) => n
            };
            match exts.find(mname) {
              None | Some(normal(_)) | Some(macro_defining(_))
              | Some(normal_tt(_)) | Some(item_tt(*)) => items,
              Some(item_decorator(dec_fn)) => {
                dec_fn(cx, attr.span, attr.node.value, items)
              }
            }
        }
    };

    return {items: new_items, ..module_};
}

// When we enter a module, record it, for the sake of `module!`
fn expand_item(exts: HashMap<~str, syntax_extension>,
               cx: ext_ctxt, &&it: @ast::item, fld: ast_fold,
               orig: fn@(&&v: @ast::item, ast_fold) -> Option<@ast::item>)
    -> Option<@ast::item>
{
    let is_mod = match it.node {
      ast::item_mod(_) | ast::item_foreign_mod(_) => true,
      _ => false
    };
    let maybe_it = match it.node {
      ast::item_mac(*) => expand_item_mac(exts, cx, it, fld),
      _ => Some(it)
    };

    match maybe_it {
      Some(it) => {
        if is_mod { cx.mod_push(it.ident); }
        let ret_val = orig(it, fld);
        if is_mod { cx.mod_pop(); }
        return ret_val;
      }
      None => return None
    }
}

// avoid excess indentation when a series of nested `match`es
// has only one "good" outcome
macro_rules! biased_match (
    (   ($e    :expr) ~ ($p    :pat) else $err    :stmt ;
     $( ($e_cdr:expr) ~ ($p_cdr:pat) else $err_cdr:stmt ; )*
     => $body:expr
    ) => (
        match $e {
            $p => {
                biased_match!($( ($e_cdr) ~ ($p_cdr) else $err_cdr ; )*
                              => $body)
            }
            _ => { $err }
        }
    );
    ( => $body:expr ) => ( $body )
)

// Support for item-position macro invocations, exactly the same
// logic as for expression-position macro invocations.
fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
                   cx: ext_ctxt, &&it: @ast::item,
                   fld: ast_fold) -> Option<@ast::item> {
    let (pth, tts) = biased_match!(
        (it.node) ~ (item_mac({node: mac_invoc_tt(pth, tts), _})) else {
            cx.span_bug(it.span, ~"invalid item macro invocation")
        };
        => (pth, tts)
    );

    let extname = cx.parse_sess().interner.get(pth.idents[0]);
    let (expanded, ex_span) = match exts.find(*extname) {
        None => cx.span_fatal(pth.span,
                              fmt!("macro undefined: '%s!'", *extname)),

        Some(normal_tt(expand)) => {
            if it.ident != parse::token::special_idents::invalid {
                cx.span_fatal(pth.span,
                              fmt!("macro %s! expects no ident argument, \
                                    given '%s'", *extname,
                                   *cx.parse_sess().interner.get(it.ident)));
            }
            (expand.expander(cx, it.span, tts), expand.span)
        }
        Some(item_tt(expand)) => {
            if it.ident == parse::token::special_idents::invalid {
                cx.span_fatal(pth.span,
                              fmt!("macro %s! expects an ident argument",
                                   *extname));
            }
            (expand.expander(cx, it.span, it.ident, tts), expand.span)
        }
        _ => cx.span_fatal(
            it.span, fmt!("%s! is not legal in item position", *extname))
    };

    cx.bt_push(ExpandedFrom({call_site: it.span,
                              callie: {name: *extname, span: ex_span}}));
    let maybe_it = match expanded {
        mr_item(it) => fld.fold_item(it),
        mr_expr(_) => cx.span_fatal(pth.span,
                                    ~"expr macro in item position: "
                                    + *extname),
        mr_any(_, item_maker, _) =>
            option::chain(item_maker(), |i| {fld.fold_item(i)}),
        mr_def(mdef) => {
            exts.insert(mdef.name, mdef.ext);
            None
        }
    };
    cx.bt_pop();
    return maybe_it;
}

fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
               && s: stmt_, sp: span, fld: ast_fold,
               orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
    -> (stmt_, span)
{
    let (mac, pth, tts) = biased_match! (
        (s)        ~ (stmt_mac(mac))          else return orig(s, sp, fld);
        (mac.node) ~ (mac_invoc_tt(pth, tts)) else {
            cx.span_bug(mac.span, ~"naked syntactic bit")
        };
        => (mac, pth, tts));

    assert(vec::len(pth.idents) == 1u);
    let extname = cx.parse_sess().interner.get(pth.idents[0]);
    match exts.find(*extname) {
        None =>
            cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),

        Some(normal_tt({expander: exp, span: exp_sp})) => {
            let expanded = match exp(cx, mac.span, tts) {
                mr_expr(e) =>
                    @{node: ast::stmt_expr(e, cx.next_id()), span: e.span},
                mr_any(_,_,stmt_mkr) => stmt_mkr(),
                _ => cx.span_fatal(
                    pth.span,
                    fmt!("non-stmt macro in stmt pos: %s", *extname))
            };

            cx.bt_push(ExpandedFrom(
                {call_site: sp, callie: {name: *extname, span: exp_sp}}));
            //keep going, outside-in
            let fully_expanded = fld.fold_stmt(expanded).node;
            cx.bt_pop();

            return (fully_expanded, sp)
        }
        _ => {
            cx.span_fatal(pth.span,
                          fmt!("'%s' is not a tt-style macro",
                               *extname))
        }
    }

}

fn new_span(cx: ext_ctxt, sp: span) -> span {
    /* this discards information in the case of macro-defining macros */
    return span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
}

// FIXME (#2247): this is a terrible kludge to inject some macros into
// the default compilation environment. When the macro-definition system
// is substantially more mature, these should move from here, into a
// compiled part of libcore at very least.

fn core_macros() -> ~str {
    return
~"{
    macro_rules! ignore (($($x:tt)*) => (()))
    #macro[[#error[f, ...], log(core::error, #fmt[f, ...])]];
    #macro[[#warn[f, ...], log(core::warn, #fmt[f, ...])]];
    #macro[[#info[f, ...], log(core::info, #fmt[f, ...])]];
    #macro[[#debug[f, ...], log(core::debug, #fmt[f, ...])]];

    macro_rules! die(
        ($msg: expr) => (
            {
                do core::str::as_buf($msg) |msg_buf, _msg_len| {
                    do core::str::as_buf(file!()) |file_buf, _file_len| {
                        unsafe {
                            let msg_buf = core::cast::transmute(msg_buf);
                            let file_buf = core::cast::transmute(file_buf);
                            let line = line!() as core::libc::size_t;
                            core::rt::rt_fail_(msg_buf, file_buf, line)
                        }
                    }
                }
            }
        );
        () => (
            die!(\"explicit failure\")
        )
    )
}";
}

fn expand_crate(parse_sess: parse::parse_sess,
                cfg: ast::crate_cfg, c: @crate) -> @crate {
    let exts = syntax_expander_table();
    let afp = default_ast_fold();
    let cx: ext_ctxt = mk_ctxt(parse_sess, cfg);
    let f_pre =
        @{fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr),
          fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod),
          fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item),
          fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt),
          new_span: |a| new_span(cx, a),
          .. *afp};
    let f = make_fold(f_pre);
    let cm = parse_expr_from_source_str(~"<core-macros>",
                                        @core_macros(),
                                        cfg,
                                        parse_sess);

    // This is run for its side-effects on the expander env,
    // as it registers all the core macros as expanders.
    f.fold_expr(cm);

    let res = @f.fold_crate(*c);
    return res;
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! For each definition, we track the following data.  A definition
//! here is defined somewhat circularly as "something with a def-id",
//! but it generally corresponds to things like structs, enums, etc.
//! There are also some rather random cases (like const initializer
//! expressions) that are mostly just leftovers.

use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use serialize::{Encodable, Decodable, Encoder, Decoder};
use std::fmt::Write;
use std::hash::{Hash, Hasher};
use syntax::ast;
use syntax::symbol::{Symbol, InternedString};
use ty::TyCtxt;
use util::nodemap::NodeMap;

#[derive(Clone)]
pub struct DefPathTable {
    index_to_key: Vec<DefKey>,
    key_to_index: FxHashMap<DefKey, DefIndex>,
}

impl DefPathTable {
    fn insert(&mut self, key: DefKey) -> DefIndex {
        let index = DefIndex::new(self.index_to_key.len());
        debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
        self.index_to_key.push(key.clone());
        self.key_to_index.insert(key, index);
        index
    }

    #[inline(always)]
    pub fn def_key(&self, index: DefIndex) -> DefKey {
        self.index_to_key[index.as_usize()].clone()
    }

    #[inline(always)]
    pub fn def_index_for_def_key(&self, key: &DefKey) -> Option<DefIndex> {
        self.key_to_index.get(key).cloned()
    }

    #[inline(always)]
    pub fn contains_key(&self, key: &DefKey) -> bool {
        self.key_to_index.contains_key(key)
    }

    pub fn retrace_path(&self,
                        path_data: &[DisambiguatedDefPathData])
                        -> Option<DefIndex> {
        let root_key = DefKey {
            parent: None,
            disambiguated_data: DisambiguatedDefPathData {
                data: DefPathData::CrateRoot,
                disambiguator: 0,
            },
        };

        let root_index = self.key_to_index
                             .get(&root_key)
                             .expect("no root key?")
                             .clone();

        debug!("retrace_path: root_index={:?}", root_index);

        let mut index = root_index;
        for data in path_data {
            let key = DefKey { parent: Some(index), disambiguated_data: data.clone() };
            debug!("retrace_path: key={:?}", key);
            match self.key_to_index.get(&key) {
                Some(&i) => index = i,
                None => return None,
            }
        }

        Some(index)
    }
}

impl Encodable for DefPathTable {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.index_to_key.encode(s)
    }
}

impl Decodable for DefPathTable {
    fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
        let index_to_key: Vec<DefKey> = Decodable::decode(d)?;
        let key_to_index = index_to_key.iter()
                                       .enumerate()
                                       .map(|(index, key)| (key.clone(), DefIndex::new(index)))
                                       .collect();
        Ok(DefPathTable {
            index_to_key: index_to_key,
            key_to_index: key_to_index,
        })
    }
}

/// The definition table containing node definitions
#[derive(Clone)]
pub struct Definitions {
    table: DefPathTable,
    node_to_def_index: NodeMap<DefIndex>,
    def_index_to_node: Vec<ast::NodeId>,
}

/// A unique identifier that we can use to lookup a definition
/// precisely. It combines the index of the definition's parent (if
/// any) with a `DisambiguatedDefPathData`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct DefKey {
    /// Parent path.
    pub parent: Option<DefIndex>,

    /// Identifier of this node.
    pub disambiguated_data: DisambiguatedDefPathData,
}

/// Pair of `DefPathData` and an integer disambiguator. The integer is
/// normally 0, but in the event that there are multiple defs with the
/// same `parent` and `data`, we use this field to disambiguate
/// between them. This introduces some artificial ordering dependency
/// but means that if you have (e.g.) two impls for the same type in
/// the same module, they do get distinct def-ids.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct DisambiguatedDefPathData {
    pub data: DefPathData,
    pub disambiguator: u32
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct DefPath {
    /// the path leading from the crate root to the item
    pub data: Vec<DisambiguatedDefPathData>,

    /// what krate root is this path relative to?
    pub krate: CrateNum,
}

impl DefPath {
    pub fn is_local(&self) -> bool {
        self.krate == LOCAL_CRATE
    }

    pub fn make<FN>(krate: CrateNum,
                    start_index: DefIndex,
                    mut get_key: FN) -> DefPath
        where FN: FnMut(DefIndex) -> DefKey
    {
        let mut data = vec![];
        let mut index = Some(start_index);
        loop {
            debug!("DefPath::make: krate={:?} index={:?}", krate, index);
            let p = index.unwrap();
            let key = get_key(p);
            debug!("DefPath::make: key={:?}", key);
            match key.disambiguated_data.data {
                DefPathData::CrateRoot => {
                    assert!(key.parent.is_none());
                    break;
                }
                _ => {
                    data.push(key.disambiguated_data);
                    index = key.parent;
                }
            }
        }
        data.reverse();
        DefPath { data: data, krate: krate }
    }

    pub fn to_string(&self, tcx: TyCtxt) -> String {
        let mut s = String::with_capacity(self.data.len() * 16);

        s.push_str(&tcx.original_crate_name(self.krate).as_str());
        s.push_str("/");
        s.push_str(&tcx.crate_disambiguator(self.krate).as_str());

        for component in &self.data {
            write!(s,
                   "::{}[{}]",
                   component.data.as_interned_str(),
                   component.disambiguator)
                .unwrap();
        }

        s
    }

    pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
        debug!("deterministic_hash({:?})", self);
        let mut state = StableHasher::new();
        self.deterministic_hash_to(tcx, &mut state);
        state.finish()
    }

    pub fn deterministic_hash_to<H: Hasher>(&self, tcx: TyCtxt, state: &mut H) {
        tcx.original_crate_name(self.krate).as_str().hash(state);
        tcx.crate_disambiguator(self.krate).as_str().hash(state);
        self.data.hash(state);
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum DefPathData {
    // Root: these should only be used for the root nodes, because
    // they are treated specially by the `def_path` function.
    /// The crate root (marker)
    CrateRoot,

    // Catch-all for random DefId things like DUMMY_NODE_ID
    Misc,

    // Different kinds of items and item-like things:
    /// An impl
    Impl,
    /// Something in the type NS
    TypeNs(InternedString),
    /// Something in the value NS
    ValueNs(InternedString),
    /// A module declaration
    Module(InternedString),
    /// A macro rule
    MacroDef(InternedString),
    /// A closure expression
    ClosureExpr,

    // Subportions of items
    /// A type parameter (generic parameter)
    TypeParam(InternedString),
    /// A lifetime definition
    LifetimeDef(InternedString),
    /// A variant of a enum
    EnumVariant(InternedString),
    /// A struct field
    Field(InternedString),
    /// Implicit ctor for a tuple-like struct
    StructCtor,
    /// Initializer for a const
    Initializer,
    /// Pattern binding
    Binding(InternedString),
    /// An `impl Trait` type node.
    ImplTrait
}

impl Definitions {
    /// Create new empty definition map.
    pub fn new() -> Definitions {
        Definitions {
            table: DefPathTable {
                index_to_key: vec![],
                key_to_index: FxHashMap(),
            },
            node_to_def_index: NodeMap(),
            def_index_to_node: vec![],
        }
    }

    pub fn def_path_table(&self) -> &DefPathTable {
        &self.table
    }

    /// Get the number of definitions.
    pub fn len(&self) -> usize {
        self.def_index_to_node.len()
    }

    pub fn def_key(&self, index: DefIndex) -> DefKey {
        self.table.def_key(index)
    }

    pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
        self.table.def_index_for_def_key(&key)
    }

    /// Returns the path from the crate root to `index`. The root
    /// nodes are not included in the path (i.e., this will be an
    /// empty vector for the crate root). For an inlined item, this
    /// will be the path of the item in the external crate (but the
    /// path will begin with the path to the external crate).
    pub fn def_path(&self, index: DefIndex) -> DefPath {
        DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p))
    }

    pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
        self.node_to_def_index.get(&node).cloned()
    }

    pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
        self.opt_def_index(node).map(DefId::local)
    }

    pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
        self.opt_local_def_id(node).unwrap()
    }

    pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
        if def_id.krate == LOCAL_CRATE {
            assert!(def_id.index.as_usize() < self.def_index_to_node.len());
            Some(self.def_index_to_node[def_id.index.as_usize()])
        } else {
            None
        }
    }

    /// Add a definition with a parent definition.
    pub fn create_def_with_parent(&mut self,
                                  parent: Option<DefIndex>,
                                  node_id: ast::NodeId,
                                  data: DefPathData)
                                  -> DefIndex {
        debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
               parent, node_id, data);

        assert!(!self.node_to_def_index.contains_key(&node_id),
                "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
                node_id,
                data,
                self.table.def_key(self.node_to_def_index[&node_id]));

        assert!(parent.is_some() ^ (data == DefPathData::CrateRoot));

        // Find a unique DefKey. This basically means incrementing the disambiguator
        // until we get no match.
        let mut key = DefKey {
            parent: parent,
            disambiguated_data: DisambiguatedDefPathData {
                data: data,
                disambiguator: 0
            }
        };

        while self.table.contains_key(&key) {
            key.disambiguated_data.disambiguator += 1;
        }

        debug!("create_def_with_parent: after disambiguation, key = {:?}", key);

        // Create the definition.
        let index = self.table.insert(key);
        debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
        self.node_to_def_index.insert(node_id, index);
        assert_eq!(index.as_usize(), self.def_index_to_node.len());
        self.def_index_to_node.push(node_id);

        index
    }
}

impl DefPathData {
    pub fn get_opt_name(&self) -> Option<ast::Name> {
        use self::DefPathData::*;
        match *self {
            TypeNs(ref name) |
            ValueNs(ref name) |
            Module(ref name) |
            MacroDef(ref name) |
            TypeParam(ref name) |
            LifetimeDef(ref name) |
            EnumVariant(ref name) |
            Binding(ref name) |
            Field(ref name) => Some(Symbol::intern(name)),

            Impl |
            CrateRoot |
            Misc |
            ClosureExpr |
            StructCtor |
            Initializer |
            ImplTrait => None
        }
    }

    pub fn as_interned_str(&self) -> InternedString {
        use self::DefPathData::*;
        let s = match *self {
            TypeNs(ref name) |
            ValueNs(ref name) |
            Module(ref name) |
            MacroDef(ref name) |
            TypeParam(ref name) |
            LifetimeDef(ref name) |
            EnumVariant(ref name) |
            Binding(ref name) |
            Field(ref name) => {
                return name.clone();
            }

            // note that this does not show up in user printouts
            CrateRoot => "{{root}}",

            Impl => "{{impl}}",
            Misc => "{{?}}",
            ClosureExpr => "{{closure}}",
            StructCtor => "{{constructor}}",
            Initializer => "{{initializer}}",
            ImplTrait => "{{impl-Trait}}",
        };

        Symbol::intern(s).as_str()
    }

    pub fn to_string(&self) -> String {
        self.as_interned_str().to_string()
    }
}
<commit_msg>definitions: Add some documentation.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! For each definition, we track the following data.  A definition
//! here is defined somewhat circularly as "something with a def-id",
//! but it generally corresponds to things like structs, enums, etc.
//! There are also some rather random cases (like const initializer
//! expressions) that are mostly just leftovers.

use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use serialize::{Encodable, Decodable, Encoder, Decoder};
use std::fmt::Write;
use std::hash::{Hash, Hasher};
use syntax::ast;
use syntax::symbol::{Symbol, InternedString};
use ty::TyCtxt;
use util::nodemap::NodeMap;

/// The DefPathTable maps DefIndexes to DefKeys and vice versa.
/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
/// stores the DefIndex of its parent.
/// There is one DefPathTable for each crate.
#[derive(Clone)]
pub struct DefPathTable {
    index_to_key: Vec<DefKey>,
    key_to_index: FxHashMap<DefKey, DefIndex>,
}

impl DefPathTable {
    fn insert(&mut self, key: DefKey) -> DefIndex {
        let index = DefIndex::new(self.index_to_key.len());
        debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
        self.index_to_key.push(key.clone());
        self.key_to_index.insert(key, index);
        index
    }

    #[inline(always)]
    pub fn def_key(&self, index: DefIndex) -> DefKey {
        self.index_to_key[index.as_usize()].clone()
    }

    #[inline(always)]
    pub fn def_index_for_def_key(&self, key: &DefKey) -> Option<DefIndex> {
        self.key_to_index.get(key).cloned()
    }

    #[inline(always)]
    pub fn contains_key(&self, key: &DefKey) -> bool {
        self.key_to_index.contains_key(key)
    }

    pub fn retrace_path(&self,
                        path_data: &[DisambiguatedDefPathData])
                        -> Option<DefIndex> {
        let root_key = DefKey {
            parent: None,
            disambiguated_data: DisambiguatedDefPathData {
                data: DefPathData::CrateRoot,
                disambiguator: 0,
            },
        };

        let root_index = self.key_to_index
                             .get(&root_key)
                             .expect("no root key?")
                             .clone();

        debug!("retrace_path: root_index={:?}", root_index);

        let mut index = root_index;
        for data in path_data {
            let key = DefKey { parent: Some(index), disambiguated_data: data.clone() };
            debug!("retrace_path: key={:?}", key);
            match self.key_to_index.get(&key) {
                Some(&i) => index = i,
                None => return None,
            }
        }

        Some(index)
    }
}

impl Encodable for DefPathTable {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.index_to_key.encode(s)
    }
}

impl Decodable for DefPathTable {
    fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
        let index_to_key: Vec<DefKey> = Decodable::decode(d)?;
        let key_to_index = index_to_key.iter()
                                       .enumerate()
                                       .map(|(index, key)| (key.clone(), DefIndex::new(index)))
                                       .collect();
        Ok(DefPathTable {
            index_to_key: index_to_key,
            key_to_index: key_to_index,
        })
    }
}

/// The definition table containing node definitions.
/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a
/// mapping from NodeIds to local DefIds.
#[derive(Clone)]
pub struct Definitions {
    table: DefPathTable,
    node_to_def_index: NodeMap<DefIndex>,
    def_index_to_node: Vec<ast::NodeId>,
}

/// A unique identifier that we can use to lookup a definition
/// precisely. It combines the index of the definition's parent (if
/// any) with a `DisambiguatedDefPathData`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct DefKey {
    /// Parent path.
    pub parent: Option<DefIndex>,

    /// Identifier of this node.
    pub disambiguated_data: DisambiguatedDefPathData,
}

/// Pair of `DefPathData` and an integer disambiguator. The integer is
/// normally 0, but in the event that there are multiple defs with the
/// same `parent` and `data`, we use this field to disambiguate
/// between them. This introduces some artificial ordering dependency
/// but means that if you have (e.g.) two impls for the same type in
/// the same module, they do get distinct def-ids.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct DisambiguatedDefPathData {
    pub data: DefPathData,
    pub disambiguator: u32
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct DefPath {
    /// the path leading from the crate root to the item
    pub data: Vec<DisambiguatedDefPathData>,

    /// what krate root is this path relative to?
    pub krate: CrateNum,
}

impl DefPath {
    pub fn is_local(&self) -> bool {
        self.krate == LOCAL_CRATE
    }

    pub fn make<FN>(krate: CrateNum,
                    start_index: DefIndex,
                    mut get_key: FN) -> DefPath
        where FN: FnMut(DefIndex) -> DefKey
    {
        let mut data = vec![];
        let mut index = Some(start_index);
        loop {
            debug!("DefPath::make: krate={:?} index={:?}", krate, index);
            let p = index.unwrap();
            let key = get_key(p);
            debug!("DefPath::make: key={:?}", key);
            match key.disambiguated_data.data {
                DefPathData::CrateRoot => {
                    assert!(key.parent.is_none());
                    break;
                }
                _ => {
                    data.push(key.disambiguated_data);
                    index = key.parent;
                }
            }
        }
        data.reverse();
        DefPath { data: data, krate: krate }
    }

    pub fn to_string(&self, tcx: TyCtxt) -> String {
        let mut s = String::with_capacity(self.data.len() * 16);

        s.push_str(&tcx.original_crate_name(self.krate).as_str());
        s.push_str("/");
        s.push_str(&tcx.crate_disambiguator(self.krate).as_str());

        for component in &self.data {
            write!(s,
                   "::{}[{}]",
                   component.data.as_interned_str(),
                   component.disambiguator)
                .unwrap();
        }

        s
    }

    pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
        debug!("deterministic_hash({:?})", self);
        let mut state = StableHasher::new();
        self.deterministic_hash_to(tcx, &mut state);
        state.finish()
    }

    pub fn deterministic_hash_to<H: Hasher>(&self, tcx: TyCtxt, state: &mut H) {
        tcx.original_crate_name(self.krate).as_str().hash(state);
        tcx.crate_disambiguator(self.krate).as_str().hash(state);
        self.data.hash(state);
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum DefPathData {
    // Root: these should only be used for the root nodes, because
    // they are treated specially by the `def_path` function.
    /// The crate root (marker)
    CrateRoot,

    // Catch-all for random DefId things like DUMMY_NODE_ID
    Misc,

    // Different kinds of items and item-like things:
    /// An impl
    Impl,
    /// Something in the type NS
    TypeNs(InternedString),
    /// Something in the value NS
    ValueNs(InternedString),
    /// A module declaration
    Module(InternedString),
    /// A macro rule
    MacroDef(InternedString),
    /// A closure expression
    ClosureExpr,

    // Subportions of items
    /// A type parameter (generic parameter)
    TypeParam(InternedString),
    /// A lifetime definition
    LifetimeDef(InternedString),
    /// A variant of a enum
    EnumVariant(InternedString),
    /// A struct field
    Field(InternedString),
    /// Implicit ctor for a tuple-like struct
    StructCtor,
    /// Initializer for a const
    Initializer,
    /// Pattern binding
    Binding(InternedString),
    /// An `impl Trait` type node.
    ImplTrait
}

impl Definitions {
    /// Create new empty definition map.
    pub fn new() -> Definitions {
        Definitions {
            table: DefPathTable {
                index_to_key: vec![],
                key_to_index: FxHashMap(),
            },
            node_to_def_index: NodeMap(),
            def_index_to_node: vec![],
        }
    }

    pub fn def_path_table(&self) -> &DefPathTable {
        &self.table
    }

    /// Get the number of definitions.
    pub fn len(&self) -> usize {
        self.def_index_to_node.len()
    }

    pub fn def_key(&self, index: DefIndex) -> DefKey {
        self.table.def_key(index)
    }

    pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
        self.table.def_index_for_def_key(&key)
    }

    /// Returns the path from the crate root to `index`. The root
    /// nodes are not included in the path (i.e., this will be an
    /// empty vector for the crate root). For an inlined item, this
    /// will be the path of the item in the external crate (but the
    /// path will begin with the path to the external crate).
    pub fn def_path(&self, index: DefIndex) -> DefPath {
        DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p))
    }

    pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
        self.node_to_def_index.get(&node).cloned()
    }

    pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
        self.opt_def_index(node).map(DefId::local)
    }

    pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
        self.opt_local_def_id(node).unwrap()
    }

    pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
        if def_id.krate == LOCAL_CRATE {
            assert!(def_id.index.as_usize() < self.def_index_to_node.len());
            Some(self.def_index_to_node[def_id.index.as_usize()])
        } else {
            None
        }
    }

    /// Add a definition with a parent definition.
    pub fn create_def_with_parent(&mut self,
                                  parent: Option<DefIndex>,
                                  node_id: ast::NodeId,
                                  data: DefPathData)
                                  -> DefIndex {
        debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
               parent, node_id, data);

        assert!(!self.node_to_def_index.contains_key(&node_id),
                "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
                node_id,
                data,
                self.table.def_key(self.node_to_def_index[&node_id]));

        assert!(parent.is_some() ^ (data == DefPathData::CrateRoot));

        // Find a unique DefKey. This basically means incrementing the disambiguator
        // until we get no match.
        let mut key = DefKey {
            parent: parent,
            disambiguated_data: DisambiguatedDefPathData {
                data: data,
                disambiguator: 0
            }
        };

        while self.table.contains_key(&key) {
            key.disambiguated_data.disambiguator += 1;
        }

        debug!("create_def_with_parent: after disambiguation, key = {:?}", key);

        // Create the definition.
        let index = self.table.insert(key);
        debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
        self.node_to_def_index.insert(node_id, index);
        assert_eq!(index.as_usize(), self.def_index_to_node.len());
        self.def_index_to_node.push(node_id);

        index
    }
}

impl DefPathData {
    pub fn get_opt_name(&self) -> Option<ast::Name> {
        use self::DefPathData::*;
        match *self {
            TypeNs(ref name) |
            ValueNs(ref name) |
            Module(ref name) |
            MacroDef(ref name) |
            TypeParam(ref name) |
            LifetimeDef(ref name) |
            EnumVariant(ref name) |
            Binding(ref name) |
            Field(ref name) => Some(Symbol::intern(name)),

            Impl |
            CrateRoot |
            Misc |
            ClosureExpr |
            StructCtor |
            Initializer |
            ImplTrait => None
        }
    }

    pub fn as_interned_str(&self) -> InternedString {
        use self::DefPathData::*;
        let s = match *self {
            TypeNs(ref name) |
            ValueNs(ref name) |
            Module(ref name) |
            MacroDef(ref name) |
            TypeParam(ref name) |
            LifetimeDef(ref name) |
            EnumVariant(ref name) |
            Binding(ref name) |
            Field(ref name) => {
                return name.clone();
            }

            // note that this does not show up in user printouts
            CrateRoot => "{{root}}",

            Impl => "{{impl}}",
            Misc => "{{?}}",
            ClosureExpr => "{{closure}}",
            StructCtor => "{{constructor}}",
            Initializer => "{{initializer}}",
            ImplTrait => "{{impl-Trait}}",
        };

        Symbol::intern(s).as_str()
    }

    pub fn to_string(&self) -> String {
        self.as_interned_str().to_string()
    }
}
<|endoftext|>


<commit_before>use inflector::Inflector;

use botocore::{Service, Shape, Operation};

use self::ec2::Ec2Generator;
use self::json::JsonGenerator;
use self::query::QueryGenerator;
use self::rest_json::RestJsonGenerator;

mod ec2;
mod json;
mod query;
mod rest_json;

pub trait GenerateProtocol {
    fn generate_methods(&self, service: &Service) -> String;

    fn generate_prelude(&self, service: &Service) -> String;

    fn generate_struct_attributes(&self) -> String;

    fn generate_support_types(&self, _name: &str, _shape: &Shape, _service: &Service)
        -> Option<String> {
        None
    }

    fn generate_error_types(&self, _service: &Service) -> Option<String> {
        None
    }

    fn timestamp_type(&self) -> &'static str;
}

pub fn generate_source(service: &Service) -> String {
    match &service.metadata.protocol[..] {
        "json" => generate(service, JsonGenerator),
        "ec2" => generate(service, Ec2Generator),
        "query" => generate(service, QueryGenerator),
        "rest-json" => generate(service, RestJsonGenerator),
        protocol => panic!("Unknown protocol {}", protocol),
    }
}

fn generate<P>(service: &Service, protocol_generator: P) -> String where P: GenerateProtocol {
    format!(
        "{prelude}

        {types}
        {error_types}

        {client}",
        client = generate_client(service, &protocol_generator),
        prelude = &protocol_generator.generate_prelude(service),
        types = generate_types(service, &protocol_generator),
        error_types = protocol_generator.generate_error_types(service).unwrap_or("".to_string()),
    )
}

fn generate_client<P>(service: &Service, protocol_generator: &P) -> String
where P: GenerateProtocol {
    format!(
        "/// A client for the {service_name} API.
        pub struct {type_name}<P> where P: ProvideAwsCredentials {{
            credentials_provider: P,
            region: region::Region,
        }}

        impl<P> {type_name}<P> where P: ProvideAwsCredentials {{
            pub fn new(credentials_provider: P, region: region::Region) -> Self {{
                {type_name} {{
                    credentials_provider: credentials_provider,
                    region: region,
                }}
            }}

            {methods}
        }}
        ",
        methods = protocol_generator.generate_methods(service),
        service_name = match &service.metadata.service_abbreviation {
            &Some(ref service_abbreviation) => service_abbreviation.as_str(),
            &None => service.metadata.service_full_name.as_ref()
        },
        type_name = service.client_type_name(),
    )
}

fn generate_list(name: &str, shape: &Shape) -> String {
    format!("pub type {} = Vec<{}>;", name, shape.member())
}

fn generate_map(name: &str, shape: &Shape) -> String {
    format!(
        "pub type {} = ::std::collections::HashMap<{}, {}>;",
        name,
        shape.key(),
        shape.value(),
    )
}

fn generate_primitive_type(name: &str, shape_type: &str, for_timestamps: &str) -> String {
    let primitive_type = match shape_type {
        "blob" => "Vec<u8>",
        "boolean" => "bool",
        "double" => "f64",
        "float" => "f32",
        "integer" => "i32",
        "long" => "i64",
        "string" => "String",
        "timestamp" => for_timestamps,
        primitive_type => panic!("Unknown primitive type: {}", primitive_type),
    };

    format!("pub type {} = {};", name, primitive_type)
}

fn generate_types<P>(service: &Service, protocol_generator: &P) -> String
where P: GenerateProtocol {
    service.shapes.iter().filter_map(|(name, shape)| {
        if name == "String" {
            return protocol_generator.generate_support_types(name, shape, &service);
        }

        if shape.exception() && service.typed_errors() {
            return None;
        }

        let mut parts = Vec::with_capacity(3);

        if let Some(ref docs) = shape.documentation {
            parts.push(format!("#[doc=\"{}\"]", docs.replace("\"", "\\\"")));
        }

        match &shape.shape_type[..] {
            "structure" => parts.push(generate_struct(service, name, shape, protocol_generator)),
            "map" => parts.push(generate_map(name, shape)),
            "list" => parts.push(generate_list(name, shape)),
            shape_type => parts.push(generate_primitive_type(name, shape_type, protocol_generator.timestamp_type())),
        }

        if let Some(support_types) = protocol_generator.generate_support_types(name, shape, &service) {
            parts.push(support_types);
        }

        Some(parts.join("\n"))
    }).collect::<Vec<String>>().join("\n")
}

fn generate_struct<P>(
    service: &Service,
    name: &str,
    shape: &Shape,
    protocol_generator: &P,
) -> String where P: GenerateProtocol {
    if shape.members.is_none() || shape.members.as_ref().unwrap().is_empty() {
        format!(
            "{attributes}
            pub struct {name};
            ",
            attributes = protocol_generator.generate_struct_attributes(),
            name = name,
        )
    } else {
        format!(
            "{attributes}
            pub struct {name} {{
                {struct_fields}
            }}
            ",
            attributes = protocol_generator.generate_struct_attributes(),
            name = name,
            struct_fields = generate_struct_fields(service, shape),
        )
    }

}

pub fn generate_field_name(member_name: &str) -> String {
    let name = member_name.to_snake_case();
    if name == "return" || name == "type" {
        name + "_"
    } else {
        name
    }
}

fn generate_struct_fields(service: &Service, shape: &Shape) -> String {
    shape.members.as_ref().unwrap().iter().map(|(member_name, member)| {
        let mut lines = Vec::with_capacity(4);
        let name = generate_field_name(member_name);

        if let Some(ref docs) = member.documentation {
            lines.push(format!("#[doc=\"{}\"]", docs.replace("\"", "\\\"")));
        }

        lines.push("#[allow(unused_attributes)]".to_owned());
        lines.push(format!("#[serde(rename=\"{}\")]", member_name));

        if let Some(shape_type) = service.shape_type_for_member(member) {
            if shape_type == "blob" {
                lines.push(
                    "#[serde(
                        deserialize_with=\"::serialization::SerdeBlob::deserialize_blob\",
                        serialize_with=\"::serialization::SerdeBlob::serialize_blob\",
                        default,
                    )]".to_owned()
                );
            }
        }

        if shape.required(member_name) {
            lines.push(format!("pub {}: {},",  name, member.shape));
        } else if name == "type" {
            lines.push(format!("pub aws_{}: Option<{}>,",  name, member.shape));
        } else {
            lines.push(format!("pub {}: Option<{}>,",  name, member.shape));
        }

        lines.join("\n")
    }).collect::<Vec<String>>().join("\n")
}

impl Operation {
    pub fn error_type_name(&self) -> String {
        format!("{}Error", self.name)
    }
}
<commit_msg>capitalize the first letter of all type names (some botocore services name types like 'fooBarBaz')<commit_after>use inflector::Inflector;

use botocore::{Service, Shape, Operation};
use std::ascii::AsciiExt;
use self::ec2::Ec2Generator;
use self::json::JsonGenerator;
use self::query::QueryGenerator;
use self::rest_json::RestJsonGenerator;

mod ec2;
mod json;
mod query;
mod rest_json;

pub trait GenerateProtocol {
    fn generate_methods(&self, service: &Service) -> String;

    fn generate_prelude(&self, service: &Service) -> String;

    fn generate_struct_attributes(&self) -> String;

    fn generate_support_types(&self, _name: &str, _shape: &Shape, _service: &Service)
        -> Option<String> {
        None
    }

    fn generate_error_types(&self, _service: &Service) -> Option<String> {
        None
    }

    fn timestamp_type(&self) -> &'static str;
}

pub fn generate_source(service: &Service) -> String {
    match &service.metadata.protocol[..] {
        "json" => generate(service, JsonGenerator),
        "ec2" => generate(service, Ec2Generator),
        "query" => generate(service, QueryGenerator),
        "rest-json" => generate(service, RestJsonGenerator),
        protocol => panic!("Unknown protocol {}", protocol),
    }
}

fn generate<P>(service: &Service, protocol_generator: P) -> String where P: GenerateProtocol {
    format!(
        "{prelude}

        {types}
        {error_types}

        {client}",
        client = generate_client(service, &protocol_generator),
        prelude = &protocol_generator.generate_prelude(service),
        types = generate_types(service, &protocol_generator),
        error_types = protocol_generator.generate_error_types(service).unwrap_or("".to_string()),
    )
}

fn generate_client<P>(service: &Service, protocol_generator: &P) -> String
where P: GenerateProtocol {
    format!(
        "/// A client for the {service_name} API.
        pub struct {type_name}<P> where P: ProvideAwsCredentials {{
            credentials_provider: P,
            region: region::Region,
        }}

        impl<P> {type_name}<P> where P: ProvideAwsCredentials {{
            pub fn new(credentials_provider: P, region: region::Region) -> Self {{
                {type_name} {{
                    credentials_provider: credentials_provider,
                    region: region,
                }}
            }}

            {methods}
        }}
        ",
        methods = protocol_generator.generate_methods(service),
        service_name = match &service.metadata.service_abbreviation {
            &Some(ref service_abbreviation) => service_abbreviation.as_str(),
            &None => service.metadata.service_full_name.as_ref()
        },
        type_name = service.client_type_name(),
    )
}

fn generate_list(name: &str, shape: &Shape) -> String {
    format!("pub type {} = Vec<{}>;", name, capitalize_first(shape.member().to_string()))
}

fn generate_map(name: &str, shape: &Shape) -> String {
    format!(
        "pub type {} = ::std::collections::HashMap<{}, {}>;",
        name,
        capitalize_first(shape.key().to_string()),
        capitalize_first(shape.value().to_string()),
    )
}

fn generate_primitive_type(name: &str, shape_type: &str, for_timestamps: &str) -> String {
    let primitive_type = match shape_type {
        "blob" => "Vec<u8>",
        "boolean" => "bool",
        "double" => "f64",
        "float" => "f32",
        "integer" => "i32",
        "long" => "i64",
        "string" => "String",
        "timestamp" => for_timestamps,
        primitive_type => panic!("Unknown primitive type: {}", primitive_type),
    };

    format!("pub type {} = {};", name, primitive_type)
}

fn generate_types<P>(service: &Service, protocol_generator: &P) -> String
where P: GenerateProtocol {
    service.shapes.iter().filter_map(|(name, shape)| {
        let type_name = &capitalize_first(name.to_string());

        if type_name == "String" {
            return protocol_generator.generate_support_types(type_name, shape, &service);
        }

        if shape.exception() && service.typed_errors() {
            return None;
        }

        let mut parts = Vec::with_capacity(3);

        if let Some(ref docs) = shape.documentation {
            parts.push(format!("#[doc=\"{}\"]", docs.replace("\"", "\\\"")));
        }

        match &shape.shape_type[..] {
            "structure" => parts.push(generate_struct(service, type_name, shape, protocol_generator)),
            "map" => parts.push(generate_map(type_name, shape)),
            "list" => parts.push(generate_list(type_name, shape)),
            shape_type => parts.push(generate_primitive_type(type_name, shape_type, protocol_generator.timestamp_type())),
        }

        if let Some(support_types) = protocol_generator.generate_support_types(type_name, shape, &service) {
            parts.push(support_types);
        }

        Some(parts.join("\n"))
    }).collect::<Vec<String>>().join("\n")
}

fn generate_struct<P>(
    service: &Service,
    name: &str,
    shape: &Shape,
    protocol_generator: &P,
) -> String where P: GenerateProtocol {
    if shape.members.is_none() || shape.members.as_ref().unwrap().is_empty() {
        format!(
            "{attributes}
            pub struct {name};
            ",
            attributes = protocol_generator.generate_struct_attributes(),
            name = name,
        )
    } else {
        format!(
            "{attributes}
            pub struct {name} {{
                {struct_fields}
            }}
            ",
            attributes = protocol_generator.generate_struct_attributes(),
            name = name,
            struct_fields = generate_struct_fields(service, shape),
        )
    }

}

pub fn generate_field_name(member_name: &str) -> String {
    let name = member_name.to_snake_case();
    if name == "return" || name == "type" {
        name + "_"
    } else {
        name
    }
}

fn generate_struct_fields(service: &Service, shape: &Shape) -> String {
    shape.members.as_ref().unwrap().iter().map(|(member_name, member)| {
        let mut lines = Vec::with_capacity(4);
        let name = generate_field_name(member_name);

        if let Some(ref docs) = member.documentation {
            lines.push(format!("#[doc=\"{}\"]", docs.replace("\"", "\\\"")));
        }

        lines.push("#[allow(unused_attributes)]".to_owned());
        lines.push(format!("#[serde(rename=\"{}\")]", member_name));

        if let Some(shape_type) = service.shape_type_for_member(member) {
            if shape_type == "blob" {
                lines.push(
                    "#[serde(
                        deserialize_with=\"::serialization::SerdeBlob::deserialize_blob\",
                        serialize_with=\"::serialization::SerdeBlob::serialize_blob\",
                        default,
                    )]".to_owned()
                );
            }
        }

        let type_name = capitalize_first(member.shape.to_string());

        if shape.required(member_name) {
            lines.push(format!("pub {}: {},",  name, type_name));
        } else if name == "type" {
            lines.push(format!("pub aws_{}: Option<{}>,",  name, type_name));
        } else {
            lines.push(format!("pub {}: Option<{}>,",  name, type_name));
        }

        lines.join("\n")
    }).collect::<Vec<String>>().join("\n")
}

impl Operation {
    pub fn error_type_name(&self) -> String {
        format!("{}Error", self.name)
    }
}

fn capitalize_first(word: String) -> String {
    assert!(word.is_ascii());

    let mut result = word.into_bytes();
    result[0] = result[0].to_ascii_uppercase();

    String::from_utf8(result).unwrap()
}<|endoftext|>


<commit_before><commit_msg>add a mir-opt test that we don't add the spurious drop<commit_after>// ignore-wasm32-bare compiled with panic=abort by default

// Test that after the call to `std::mem::drop` we do not generate a
// MIR drop of the argument. (We used to have a `DROP(_2)` in the code
// below, as part of bb3.)

fn main() {
    std::mem::drop("".to_string());
}

// END RUST SOURCE
// START rustc.main.ElaborateDrops.before.mir
//    bb2: {
//        StorageDead(_3);
//        _1 = const std::mem::drop::<std::string::String>(move _2) -> [return: bb3, unwind: bb4];
//    }
//    bb3: {
//        StorageDead(_2);
//        StorageDead(_4);
//        StorageDead(_1);
//        _0 = ();
//        return;
//    }
// END rustc.main.ElaborateDrops.before.mir
<|endoftext|>


<commit_before><commit_msg>Extract commands from mentions<commit_after><|endoftext|>


<commit_before><commit_msg>Cleaning up some things code<commit_after><|endoftext|>


<commit_before>//! # The Redox Library
//!
//! The Redox Library contains a collection of commonly used low-level software
//! constructs to be used on top of the base operating system, including graphics
//! support and windowing, a basic filesystem, audio support, a simple console
//! with shell style functions, an event system, and environment argument support.

#![crate_type="rlib"]
#![feature(alloc)]
#![feature(allocator)]
#![feature(allow_internal_unstable)]
#![feature(asm)]
#![feature(associated_consts)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(collections_bound)]
#![feature(core)]
#![feature(core_intrinsics)]
#![feature(core_panic)]
#![feature(core_simd)]
#![feature(int_error_internals)]
#![feature(lang_items)]
#![feature(macro_reexport)]
#![feature(rand)]
#![feature(raw)]
#![feature(reflect_marker)]
#![feature(slice_concat_ext)]
#![feature(unicode)]
#![feature(unsafe_no_drop_flag)]
#![feature(box_patterns)]
#![feature(vec_push_all)]
#![feature(wrapping)]
#![feature(zero_one)]
#![feature(no_std)]
#![feature(prelude_import)]
#![no_std]

//#![warn(missing_docs)]

/* STD COPY { */
    // We want to reexport a few macros from core but libcore has already been
    // imported by the compiler (via our #[no_std] attribute) In this case we just
    // add a new crate name so we can attach the reexports to it.
    #[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
                    unreachable, unimplemented, write, writeln)]
    extern crate core as __core;

    #[macro_use]
    #[macro_reexport(vec, format)]
    extern crate collections as core_collections;

    #[allow(deprecated)] extern crate rand as core_rand;
    extern crate alloc;
    extern crate rustc_unicode;
    //TODO extern crate libc;

    // NB: These reexports are in the order they should be listed in rustdoc

    pub use core::any;
    pub use core::cell;
    pub use core::clone;
    pub use core::cmp;
    pub use core::convert;
    pub use core::default;
    pub use core::hash;
    pub use core::intrinsics;
    pub use core::iter;
    pub use core::marker;
    pub use core::mem;
    pub use core::ops;
    pub use core::ptr;
    pub use core::raw;
    #[allow(deprecated)]
    pub use core::simd;
    pub use core::result;
    pub use core::option;
    pub mod error;

    pub use alloc::arc;
    pub use alloc::boxed;
    pub use alloc::rc;

    pub use core_collections::borrow;
    pub use core_collections::fmt;
    pub use core_collections::slice;
    pub use core_collections::str;
    pub use core_collections::string;
    pub use core_collections::vec;

    pub use rustc_unicode::char;

    /* Exported macros */

    #[macro_use]
    pub mod macros;

    // TODO mod rtdeps;

    /* The Prelude. */
    #[prelude_import]
    pub mod prelude;

    /* Primitive types */

    // NB: slice and str are primitive types too, but their module docs + primitive
    // doc pages are inlined from the public re-exports of core_collections::{slice,
    // str} above.

    pub use core::isize;
    pub use core::i8;
    pub use core::i16;
    pub use core::i32;
    pub use core::i64;

    pub use core::usize;
    pub use core::u8;
    pub use core::u16;
    pub use core::u32;
    pub use core::u64;

    pub use core::num;
    //#[path = "num/f32.rs"]   pub mod f32;
    //#[path = "num/f64.rs"]   pub mod f64;

    pub mod ascii;

    /* Common traits */

    //pub mod num;

    /* Runtime and platform support */

    #[macro_use]
    pub mod thread;

    pub mod collections;
    // TODO pub mod dynamic_lib;
    pub mod env;
    // TODO pub mod ffi;
    pub mod fs;
    pub mod io;
    pub mod net;
    // TODO pub mod os;
    pub mod path;
    pub mod process;
    pub mod sync;
    pub mod time;

    //TODO #[macro_use]
    //TODO #[path = "sys/common/mod.rs"] mod sys_common;

    //TODO #[cfg(unix)]
    //TODO #[path = "sys/unix/mod.rs"] mod sys;
    //TODO #[cfg(windows)]
    //TODO #[path = "sys/windows/mod.rs"] mod sys;

    pub mod rt;
    //TODO mod panicking;
    pub use __core::panicking;

    pub mod rand_old;
    pub mod hashmap;

    // Some external utilities of the standard library rely on randomness (aka
    // rustc_back::TempDir and tests) and need a way to get at the OS rng we've got
    // here. This module is not at all intended for stabilization as-is, however,
    // but it may be stabilized long-term. As a result we're exposing a hidden,
    // unstable module so we can get our build working.
    #[doc(hidden)]
    //TODO #[unstable(feature = "rand", issue = "0")]
    pub mod rand {
        pub use core_rand::{/*thread_rng, ThreadRng,*/ Rng};
    }
/* } STD COPY */

/* Additional Stuff { */
    pub use boxed::Box;
    pub use env::*;
    pub use fs::*;
    pub use io::*;
    pub use rand_old::*;
    pub use string::*;
    pub use vec::Vec;

    pub use url::*;
    pub use get_slice::*;
    pub use to_num::*;

    pub mod alloc_system;

    /// A module for necessary C and assembly constructs
    #[path="../../kernel/externs.rs"]
    pub mod externs;

    /// A module for system calls
    pub mod syscall;

    /// A module for audio
    pub mod audio;

    pub mod panic;

    pub mod url;

    pub mod get_slice;
    pub mod to_num;
/* } Additional Stuff */
<commit_msg>Remove simd, it was removed from core<commit_after>//! # The Redox Library
//!
//! The Redox Library contains a collection of commonly used low-level software
//! constructs to be used on top of the base operating system, including graphics
//! support and windowing, a basic filesystem, audio support, a simple console
//! with shell style functions, an event system, and environment argument support.

#![crate_type="rlib"]
#![feature(alloc)]
#![feature(allocator)]
#![feature(allow_internal_unstable)]
#![feature(asm)]
#![feature(associated_consts)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(collections_bound)]
#![feature(core)]
#![feature(core_intrinsics)]
#![feature(core_panic)]
#![feature(int_error_internals)]
#![feature(lang_items)]
#![feature(macro_reexport)]
#![feature(rand)]
#![feature(raw)]
#![feature(reflect_marker)]
#![feature(slice_concat_ext)]
#![feature(unicode)]
#![feature(unsafe_no_drop_flag)]
#![feature(box_patterns)]
#![feature(vec_push_all)]
#![feature(wrapping)]
#![feature(zero_one)]
#![feature(no_std)]
#![feature(prelude_import)]
#![no_std]

//#![warn(missing_docs)]

/* STD COPY { */
    // We want to reexport a few macros from core but libcore has already been
    // imported by the compiler (via our #[no_std] attribute) In this case we just
    // add a new crate name so we can attach the reexports to it.
    #[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
                    unreachable, unimplemented, write, writeln)]
    extern crate core as __core;

    #[macro_use]
    #[macro_reexport(vec, format)]
    extern crate collections as core_collections;

    #[allow(deprecated)] extern crate rand as core_rand;
    extern crate alloc;
    extern crate rustc_unicode;
    //TODO extern crate libc;

    // NB: These reexports are in the order they should be listed in rustdoc

    pub use core::any;
    pub use core::cell;
    pub use core::clone;
    pub use core::cmp;
    pub use core::convert;
    pub use core::default;
    pub use core::hash;
    pub use core::intrinsics;
    pub use core::iter;
    pub use core::marker;
    pub use core::mem;
    pub use core::ops;
    pub use core::ptr;
    pub use core::raw;
    pub use core::result;
    pub use core::option;
    pub mod error;

    pub use alloc::arc;
    pub use alloc::boxed;
    pub use alloc::rc;

    pub use core_collections::borrow;
    pub use core_collections::fmt;
    pub use core_collections::slice;
    pub use core_collections::str;
    pub use core_collections::string;
    pub use core_collections::vec;

    pub use rustc_unicode::char;

    /* Exported macros */

    #[macro_use]
    pub mod macros;

    // TODO mod rtdeps;

    /* The Prelude. */
    #[prelude_import]
    pub mod prelude;

    /* Primitive types */

    // NB: slice and str are primitive types too, but their module docs + primitive
    // doc pages are inlined from the public re-exports of core_collections::{slice,
    // str} above.

    pub use core::isize;
    pub use core::i8;
    pub use core::i16;
    pub use core::i32;
    pub use core::i64;

    pub use core::usize;
    pub use core::u8;
    pub use core::u16;
    pub use core::u32;
    pub use core::u64;

    pub use core::num;
    //#[path = "num/f32.rs"]   pub mod f32;
    //#[path = "num/f64.rs"]   pub mod f64;

    pub mod ascii;

    /* Common traits */

    //pub mod num;

    /* Runtime and platform support */

    #[macro_use]
    pub mod thread;

    pub mod collections;
    // TODO pub mod dynamic_lib;
    pub mod env;
    // TODO pub mod ffi;
    pub mod fs;
    pub mod io;
    pub mod net;
    // TODO pub mod os;
    pub mod path;
    pub mod process;
    pub mod sync;
    pub mod time;

    //TODO #[macro_use]
    //TODO #[path = "sys/common/mod.rs"] mod sys_common;

    //TODO #[cfg(unix)]
    //TODO #[path = "sys/unix/mod.rs"] mod sys;
    //TODO #[cfg(windows)]
    //TODO #[path = "sys/windows/mod.rs"] mod sys;

    pub mod rt;
    //TODO mod panicking;
    pub use __core::panicking;

    pub mod rand_old;
    pub mod hashmap;

    // Some external utilities of the standard library rely on randomness (aka
    // rustc_back::TempDir and tests) and need a way to get at the OS rng we've got
    // here. This module is not at all intended for stabilization as-is, however,
    // but it may be stabilized long-term. As a result we're exposing a hidden,
    // unstable module so we can get our build working.
    #[doc(hidden)]
    //TODO #[unstable(feature = "rand", issue = "0")]
    pub mod rand {
        pub use core_rand::{/*thread_rng, ThreadRng,*/ Rng};
    }
/* } STD COPY */

/* Additional Stuff { */
    pub use boxed::Box;
    pub use env::*;
    pub use fs::*;
    pub use io::*;
    pub use rand_old::*;
    pub use string::*;
    pub use vec::Vec;

    pub use url::*;
    pub use get_slice::*;
    pub use to_num::*;

    pub mod alloc_system;

    /// A module for necessary C and assembly constructs
    #[path="../../kernel/externs.rs"]
    pub mod externs;

    /// A module for system calls
    pub mod syscall;

    /// A module for audio
    pub mod audio;

    pub mod panic;

    pub mod url;

    pub mod get_slice;
    pub mod to_num;
/* } Additional Stuff */
<|endoftext|>


<commit_before><commit_msg> removed filter for testing<commit_after><|endoftext|>


<commit_before><commit_msg>Add query sending to connection<commit_after><|endoftext|>


<commit_before><commit_msg>Adds Rust solution for problem #1<commit_after><|endoftext|>