diff options
| author | Paul Stansifer <paul.stansifer@gmail.com> | 2011-07-06 15:22:23 -0700 |
|---|---|---|
| committer | Paul Stansifer <paul.stansifer@gmail.com> | 2011-07-11 18:52:50 -0700 |
| commit | 425732311af6d7a4f972dff04e1abb7db6a22f3b (patch) | |
| tree | 5b3d5493c7fc3a32a28b166f5ea393d640537c23 /src/comp/syntax | |
| parent | 80cf4ecd3bfe602004145e57cf7fdfb067b76ce1 (diff) | |
| download | rust-425732311af6d7a4f972dff04e1abb7db6a22f3b.tar.gz rust-425732311af6d7a4f972dff04e1abb7db6a22f3b.zip | |
Move macro expansion to a separate phase, change macro syntax, and add parse_sess to session.
Diffstat (limited to 'src/comp/syntax')
| -rw-r--r-- | src/comp/syntax/ast.rs | 2 | ||||
| -rw-r--r-- | src/comp/syntax/ext/base.rs | 23 | ||||
| -rw-r--r-- | src/comp/syntax/ext/expand.rs | 65 | ||||
| -rw-r--r-- | src/comp/syntax/ext/simplext.rs | 272 | ||||
| -rw-r--r-- | src/comp/syntax/fold.rs | 4 | ||||
| -rw-r--r-- | src/comp/syntax/parse/parser.rs | 59 | ||||
| -rw-r--r-- | src/comp/syntax/print/pprust.rs | 2 | ||||
| -rw-r--r-- | src/comp/syntax/visit.rs | 6 | ||||
| -rw-r--r-- | src/comp/syntax/walk.rs | 8 |
9 files changed, 298 insertions, 143 deletions
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 26cefb3c0d6..a75aa4d8c23 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -305,7 +305,7 @@ tag expr_ { expr_field(@expr, ident); expr_index(@expr, @expr); expr_path(path); - expr_ext(path, (@expr)[], option::t[str], @expr); + expr_ext(path, (@expr)[], option::t[str]); expr_fail(option::t[@expr]); expr_break; expr_cont; diff --git a/src/comp/syntax/ext/base.rs b/src/comp/syntax/ext/base.rs index 0990b3bdacb..84319cf5f38 100644 --- a/src/comp/syntax/ext/base.rs +++ b/src/comp/syntax/ext/base.rs @@ -2,7 +2,7 @@ import std::ivec; import std::vec; import std::option; import std::map::hashmap; -import parse::parser::parse_sess; +import driver::session::session; import codemap::span; import std::map::new_str_hash; import codemap; @@ -41,14 +41,14 @@ type ext_ctxt = span_msg_fn span_unimpl, next_id_fn next_id); -fn mk_ctxt(&parse_sess sess) -> ext_ctxt { - fn ext_span_fatal_(&codemap::codemap cm, span sp, str msg) -> ! { - codemap::emit_error(option::some(sp), msg, cm); +fn mk_ctxt(&session sess) -> ext_ctxt { + fn ext_span_fatal_(&session sess, span sp, str msg) -> ! { + sess.span_err(sp, msg); fail; } - auto ext_span_fatal = bind ext_span_fatal_(sess.cm, _, _); - fn ext_span_unimpl_(&codemap::codemap cm, span sp, str msg) -> ! { - codemap::emit_error(option::some(sp), "unimplemented " + msg, cm); + auto ext_span_fatal = bind ext_span_fatal_(sess, _, _); + fn ext_span_unimpl_(&session sess, span sp, str msg) -> ! { + sess.span_err(sp, "unimplemented " + msg); fail; } @@ -59,9 +59,12 @@ fn mk_ctxt(&parse_sess sess) -> ext_ctxt { // the extensions the file name of the crate being compiled so they can // use it to guess whether paths should be prepended with "std::". This is // super-ugly and needs a better solution. - auto crate_file_name_hack = sess.cm.files.(0).name; - auto ext_span_unimpl = bind ext_span_unimpl_(sess.cm, _, _); - auto ext_next_id = bind parse::parser::next_node_id(sess); + auto crate_file_name_hack = sess.get_codemap().files.(0).name; + auto ext_span_unimpl = bind ext_span_unimpl_(sess, _, _); + fn ext_next_id_(&session sess) -> ast::node_id { + ret sess.next_node_id(); // temporary, until bind works better + } + auto ext_next_id = bind ext_next_id_(sess); ret rec(crate_file_name_hack=crate_file_name_hack, span_fatal=ext_span_fatal, span_unimpl=ext_span_unimpl, diff --git a/src/comp/syntax/ext/expand.rs b/src/comp/syntax/ext/expand.rs new file mode 100644 index 00000000000..3af9fdc5070 --- /dev/null +++ b/src/comp/syntax/ext/expand.rs @@ -0,0 +1,65 @@ + +import codemap::emit_error; +import driver::session; +import syntax::ast::crate; +import syntax::ast::expr_; +import syntax::ast::expr_ext; +import syntax::fold::*; + +import std::option::none; +import std::option::some; + +import std::map::hashmap; +import std::ivec; + +fn expand_expr(&hashmap[str, base::syntax_extension] exts, + &session::session sess, &expr_ e, ast_fold fld, + &fn(&ast::expr_, ast_fold) -> expr_ orig) -> expr_ { + ret alt(e) { + case (expr_ext(?pth, ?args, ?body)) { + assert(ivec::len(pth.node.idents) > 0u); + auto extname = pth.node.idents.(0); + auto ext_cx = base::mk_ctxt(sess); + alt (exts.find(extname)) { + case (none) { + emit_error(some(pth.span), "unknown syntax expander: '" + + extname + "'", sess.get_codemap()); + fail + } + case (some(base::normal(?ext))) { + //keep going, outside-in + fld.fold_expr(ext(ext_cx, pth.span, args, body)).node + } + case (some(base::macro_defining(?ext))) { + auto named_extension = ext(ext_cx, pth.span, args, body); + exts.insert(named_extension._0, named_extension._1); + ast::expr_tup([]) + } + } + + } + case (_) { orig(e, fld) } + }; +} + +fn expand_crate(&session::session sess, &@crate c) -> @crate { + auto exts = ext::base::syntax_expander_table(); + auto afp = default_ast_fold(); + auto f_pre = + rec(fold_expr = bind expand_expr(exts, sess, _, _, afp.fold_expr) + with *afp); + auto f = make_fold(f_pre); + auto res = @f.fold_crate(*c); + dummy_out(f); //temporary: kill circular reference + ret res; + +} + +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/comp/syntax/ext/simplext.rs b/src/comp/syntax/ext/simplext.rs index 46b1fd636ce..59505a5a89a 100644 --- a/src/comp/syntax/ext/simplext.rs +++ b/src/comp/syntax/ext/simplext.rs @@ -16,121 +16,245 @@ import base::expr_to_str; import base::expr_to_ident; import fold::*; +import ast::respan; import ast::ident; +import ast::path; import ast::path_; import ast::expr_path; +import ast::expr_vec; +import ast::expr_ext; export add_new_extension; - -//temporary, until 'position' shows up in the snapshot -fn position[T](&T x, &vec[T] v) -> option::t[uint] { - let uint i = 0u; - while (i < len(v)) { - if (x == v.(i)) { ret some[uint](i); } - i += 1u; +fn lookup(&vec[invk_binding] ibs, ident i) -> option::t[invk_binding] { + for (invk_binding ib in ibs) { + alt (ib) { + case (ident_binding(?p_id, _)) { if (i == p_id) { ret some(ib); }} + case (path_binding(?p_id, _)) { if (i == p_id) { ret some(ib); }} + case (expr_binding(?p_id, _)) { if (i == p_id) { ret some(ib); }} + } } - ret none[uint]; + ret none; } // substitute, in a position that's required to be an ident -fn subst_ident(&ext_ctxt cx, &(@ast::expr)[] args, - @vec[ident] param_names, &ident i, ast_fold fld) -> ident { - alt (position(i, *param_names)) { - case (some[uint](?idx)) { - ret expr_to_ident(cx, args.(idx), - "This argument is expanded as an " - + "identifier; it must be one."); +fn subst_ident(&ext_ctxt cx, &(invk_binding)[] ibs, &ident i, ast_fold fld) + -> ident { + ret alt (lookup(ibs, i)) { + case (some(ident_binding(_, ?a_id))) { a_id.node } + case (some(path_binding(_, ?pth))) { + cx.span_fatal(pth.span, "This argument is expanded as an " + + "identifier; it must be one.") } - case (none[uint]) { - ret i; + case (some(expr_binding(_, ?expr))) { + cx.span_fatal(expr.span, "This argument is expanded as an " + + "identifier; it must be one.") } + case (none) { i } } } -fn subst_path(&ext_ctxt cx, &(@ast::expr)[] args, - @vec[ident] param_names, &path_ p, ast_fold fld) -> path_ { + +fn subst_path(&ext_ctxt cx, &(invk_binding)[] ibs, &path_ p, ast_fold fld) + -> path_ { // Don't substitute into qualified names. if (ivec::len(p.types) > 0u || ivec::len(p.idents) != 1u) { ret p; } - alt (position(p.idents.(0), *param_names)) { - case (some[uint](?idx)) { - alt (args.(idx).node) { - case (expr_path(?new_path)) { - ret new_path.node; - } - case (_) { - cx.span_fatal(args.(idx).span, - "This argument is expanded as a path; " - + "it must be one."); - } - } + ret alt (lookup(ibs, p.idents.(0))) { + case (some(ident_binding(_, ?id))) { + rec(global=false, idents=~[id.node], types=~[]) } - case (none[uint]) { ret p; } + case (some(path_binding(_, ?a_pth))) { a_pth.node } + case (some(expr_binding(_, ?expr))) { + cx.span_fatal(expr.span, "This argument is expanded as an " + + "path; it must be one.") + } + case (none) { p } } } -fn subst_expr(&ext_ctxt cx, &(@ast::expr)[] args, @vec[ident] param_names, - &ast::expr_ e, ast_fold fld, - fn(&ast::expr_, ast_fold) -> ast::expr_ orig) -> ast::expr_ { +fn subst_expr(&ext_ctxt cx, &(invk_binding)[] ibs, &ast::expr_ e, + ast_fold fld, fn(&ast::expr_, ast_fold) -> ast::expr_ orig) + -> ast::expr_ { ret alt(e) { case (expr_path(?p)){ // Don't substitute into qualified names. - if (ivec::len(p.node.types) > 0u || - ivec::len(p.node.idents) != 1u) { e } - alt (position(p.node.idents.(0), *param_names)) { - case (some[uint](?idx)) { - args.(idx).node + if (ivec::len(p.node.types) > 0u || + ivec::len(p.node.idents) != 1u) { e } + alt (lookup(ibs, p.node.idents.(0))) { + case (some(ident_binding(_, ?id))) { + expr_path(respan(id.span, + rec(global=false, + idents=~[id.node],types=~[]))) } - case (none[uint]) { e } + case (some(path_binding(_, ?a_pth))) { expr_path(*a_pth) } + case (some(expr_binding(_, ?a_exp))) { a_exp.node } + case (none) { orig(e,fld) } } } case (_) { orig(e,fld) } } } +type pat_ext = rec(vec[@ast::expr] invk, @ast::expr body); + +// maybe box? +tag invk_binding { + expr_binding(ident, @ast::expr); + path_binding(ident, @ast::path); + ident_binding(ident, ast::spanned[ident]); +} + +fn path_to_ident(&path pth) -> option::t[ident] { + if (ivec::len(pth.node.idents) == 1u + && ivec::len(pth.node.types) == 0u) { + ret some(pth.node.idents.(0u)); + } + ret none; +} fn add_new_extension(&ext_ctxt cx, span sp, &(@ast::expr)[] args, option::t[str] body) -> tup(str, syntax_extension) { - if (ivec::len(args) < 2u) { - cx.span_fatal(sp, "malformed extension description"); + let option::t[str] macro_name = none; + let vec[pat_ext] pat_exts = []; + for (@ast::expr arg in args) { + alt(arg.node) { + case(expr_vec(?elts, ?mut, ?seq_kind)) { + + if (len(elts) != 2u) { + cx.span_fatal((*arg).span, + "extension clause must consist of [" + + "macro invocation, expansion body]"); + } + alt(elts.(0u).node) { + case(expr_ext(?pth, ?invk_args, ?body)) { + let str clause_name = alt(path_to_ident(pth)) { + case (some(?id)) { id } + case (none) { + cx.span_fatal + (elts.(0u).span, + "macro name must not be a path") + } + }; + if (macro_name == none) { + macro_name = some(clause_name); + } else if (macro_name != some(clause_name)) { + cx.span_fatal(elts.(0u).span, "macros must have" + + " only one name"); + } + pat_exts += [rec(invk=invk_args, body=elts.(1u))]; + } + case(_) { + cx.span_fatal(elts.(0u).span, "extension clause must" + + " start with a macro invocation."); + } + } + } + case(_) { + cx.span_fatal((*arg).span, "extension must be [clause, " + + " ...]"); + } + } } - fn generic_extension(&ext_ctxt cx, span sp, &(@ast::expr)[] args, - option::t[str] body, @vec[ident] param_names, - @ast::expr dest_form) -> @ast::expr { - if (ivec::len(args) != len(*param_names)) { - cx.span_fatal(sp, #fmt("extension expects %u arguments, got %u", - len(*param_names), ivec::len(args))); + auto ext = bind generic_extension(_,_,_,_,@pat_exts); + + ret tup(alt (macro_name) { + case (some(?id)) { id } + case (none) { + cx.span_fatal(sp, "macro definition must have " + + "at least one clause") + } + }, + normal(ext)); + + + fn generic_extension(&ext_ctxt cx, span sp, &vec[@ast::expr] args, + option::t[str] body, @vec[pat_ext] clauses) + -> @ast::expr { + + /* returns a list of bindings, or none if the match fails. */ + fn match_invk(@ast::expr pattern, @ast::expr argument) + -> option::t[vec[invk_binding]] { + auto pat = pattern.node; + auto arg = argument.node; + ret alt (pat) { + case (expr_vec(?p_elts, _, _)) { + alt (arg) { + case (expr_vec(?a_elts, _, _)) { + if (vec::len(p_elts) != vec::len(a_elts)) { + none[vec[invk_binding]] + } + let uint i = 0u; + let vec[invk_binding] res = []; + while (i < vec::len(p_elts)) { + alt (match_invk(p_elts.(i), a_elts.(i))) { + case (some(?v)) { res += v; } + case (none) { ret none; } + } + i += 1u; + } + some(res) + } + case (_) { none } + } + } + case (expr_path(?p_pth)) { + alt (path_to_ident(p_pth)) { + case (some(?p_id)) { + /* let's bind! */ + alt (arg) { + case (expr_path(?a_pth)) { + alt (path_to_ident(a_pth)) { + case (some(?a_id)) { + some([ident_binding + (p_id, respan(argument.span, + a_id))]) + } + case (none) { + some([path_binding(p_id, @a_pth)]) + } + } + } + case (_) { + some([expr_binding(p_id, argument)]) + } + } + } + // FIXME this still compares on internal spans + case (_) { if(pat == arg) { some([]) } else { none } } + } + } + // FIXME this still compares on internal spans + case (_) { if (pat == arg) { some([]) } else { none } } + } } - // FIXME: This binds to alias arguments. - auto afp = default_ast_fold(); - auto f_pre = - rec(fold_ident = bind subst_ident(cx, args, param_names, _, _), - fold_path = bind subst_path(cx, args, param_names, _, _), - fold_expr = bind subst_expr(cx, args, param_names, _, _, - afp.fold_expr) + for (pat_ext pe in *clauses) { + if (vec::len(args) != vec::len(pe.invk)) { cont; } + let uint i = 0u; + let vec[invk_binding] bindings = []; + while (i < vec::len(args)) { + alt (match_invk(pe.invk.(i), args.(i))) { + case (some(?v)) { bindings += v; } + case (none) { cont } + } + i += 1u; + } + auto afp = default_ast_fold(); + auto f_pre = + rec(fold_ident = bind subst_ident(cx, bindings, _, _), + fold_path = bind subst_path(cx, bindings, _, _), + fold_expr = bind subst_expr(cx, bindings, _, _, + afp.fold_expr) with *afp); - auto f = make_fold(f_pre); - auto result = f.fold_expr(dest_form); - dummy_out(f); //temporary: kill circular reference - ret result; - - } - - let vec[ident] param_names = vec::empty[ident](); - let uint idx = 1u; - while(1u+idx < ivec::len(args)) { - param_names += - [expr_to_ident(cx, args.(idx), - "this parameter name must be an identifier.")]; - idx += 1u; + auto f = make_fold(f_pre); + auto result = f.fold_expr(pe.body); + dummy_out(f); //temporary: kill circular reference + ret result; + } + cx.span_fatal(sp, "no clauses match macro invocation"); } - - ret tup(expr_to_str(cx, args.(0), "first arg must be a literal string."), - normal(bind generic_extension(_,_,_,_,@param_names, - args.(ivec::len(args)-1u)))); } diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 659a527dbe2..1487ff3e2e0 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -414,11 +414,11 @@ fn noop_fold_expr(&expr_ e, ast_fold fld) -> expr_ { case (expr_path(?pth)) { expr_path(fld.fold_path(pth)) } - case (expr_ext(?pth, ?args, ?body, ?expanded)) { + case (expr_ext(?pth, ?args, ?body)) { expr_ext(fld.fold_path(pth), ivec::map(fld.fold_expr, args), body, fld.fold_expr(expanded)) } - case (expr_fail(_)) { e } + case (expr_fail(?e)) { expr_fail(option::map(fld.fold_expr, e)) } case (expr_break()) { e } case (expr_cont()) { e } case (expr_ret(?e)) { diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 7d6fc8561cc..7a711b1dbfa 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -50,7 +50,6 @@ type parser = fn get_reader() -> lexer::reader ; fn get_filemap() -> codemap::filemap ; fn get_bad_expr_words() -> hashmap[str, ()] ; - fn get_syntax_expanders() -> hashmap[str, ex::syntax_extension] ; fn get_chpos() -> uint ; fn get_id() -> ast::node_id ; fn get_sess() -> parse_sess; @@ -82,8 +81,7 @@ fn new_parser(parse_sess sess, ast::crate_cfg cfg, lexer::reader rdr, mutable restriction restr, lexer::reader rdr, vec[op_spec] precs, - hashmap[str, ()] bad_words, - hashmap[str, ex::syntax_extension] syntax_expanders) { + hashmap[str, ()] bad_words) { fn peek() -> token::token { ret tok; } fn bump() { // log rdr.get_filename() @@ -116,9 +114,6 @@ fn new_parser(parse_sess sess, ast::crate_cfg cfg, lexer::reader rdr, fn get_reader() -> lexer::reader { ret rdr; } fn get_filemap() -> codemap::filemap { ret rdr.get_filemap(); } fn get_bad_expr_words() -> hashmap[str, ()] { ret bad_words; } - fn get_syntax_expanders() -> hashmap[str, ex::syntax_extension] { - ret syntax_expanders; - } fn get_chpos() -> uint { ret rdr.get_chpos(); } fn get_id() -> ast::node_id { ret next_node_id(sess); } fn get_sess() -> parse_sess { ret sess; } @@ -129,8 +124,7 @@ fn new_parser(parse_sess sess, ast::crate_cfg cfg, lexer::reader rdr, auto npos = rdr.get_chpos(); ret stdio_parser(sess, cfg, ftype, lexer::next_token(rdr), npos, npos, npos, UNRESTRICTED, rdr, - prec_table(), bad_expr_word_table(), - ex::syntax_expander_table()); + prec_table(), bad_expr_word_table()); } // These are the words that shouldn't be allowed as value identifiers, @@ -1028,38 +1022,7 @@ fn parse_syntax_ext_naked(&parser p, uint lo) -> @ast::expr { auto es = parse_seq_ivec(token::LPAREN, token::RPAREN, some(token::COMMA), parse_expr, p); auto hi = es.span.hi; - auto ext_span = rec(lo=lo, hi=hi); - auto ex = expand_syntax_ext(p, ext_span, pth, es.node, none); - ret mk_expr(p, lo, hi, ex); -} - -/* - * FIXME: This is a crude approximation of the syntax-extension system, - * for purposes of prototyping and/or hard-wiring any extensions we - * wish to use while bootstrapping. The eventual aim is to permit - * loading rust crates to process extensions. - */ -fn expand_syntax_ext(&parser p, span sp, &ast::path path, - &(@ast::expr)[] args, option::t[str] body) -> - ast::expr_ { - assert (ivec::len(path.node.idents) > 0u); - auto extname = path.node.idents.(0); - alt (p.get_syntax_expanders().find(extname)) { - case (none) { p.fatal("unknown syntax expander: '" + extname + "'"); } - case (some(ex::normal(?ext))) { - auto ext_cx = ex::mk_ctxt(p.get_sess()); - ret ast::expr_ext(path, args, body, ext(ext_cx, sp, args, body)); - } - // because we have expansion inside parsing, new macros are only - // visible further down the file - case (some(ex::macro_defining(?ext))) { - auto ext_cx = ex::mk_ctxt(p.get_sess()); - auto name_and_extension = ext(ext_cx, sp, args, body); - p.get_syntax_expanders().insert(name_and_extension._0, - name_and_extension._1); - ret ast::expr_tup(~[]); - } - } + ret mk_expr(p, lo, hi, ast::expr_ext(pth, es.node, none)); } fn parse_self_method(&parser p) -> @ast::expr { @@ -1698,7 +1661,7 @@ fn stmt_ends_with_semi(&ast::stmt stmt) -> bool { case (ast::expr_field(_, _)) { true } case (ast::expr_index(_, _)) { true } case (ast::expr_path(_)) { true } - case (ast::expr_ext(_, _, _, _)) { true } + case (ast::expr_ext(_, _, _)) { true } case (ast::expr_fail(_)) { true } case (ast::expr_break) { true } case (ast::expr_cont) { true } @@ -2443,10 +2406,9 @@ fn parse_native_view(&parser p) -> (@ast::view_item)[] { } fn parse_crate_from_source_file(&str input, &ast::crate_cfg cfg, - &codemap::codemap cm) -> @ast::crate { - auto sess = @rec(cm=cm, mutable next_id=0); + &parse_sess sess) -> @ast::crate { auto p = new_parser_from_file(sess, cfg, input, 0u); - ret parse_crate_mod(p, cfg); + ret parse_crate_mod(p, cfg, sess); } fn parse_crate_from_source_str(&str name, &str source, &ast::crate_cfg cfg, @@ -2458,12 +2420,12 @@ fn parse_crate_from_source_str(&str name, &str source, &ast::crate_cfg cfg, auto itr = @interner::mk(str::hash, str::eq); auto rdr = lexer::new_reader(sess.cm, source, filemap, itr); auto p = new_parser(sess, cfg, rdr, ftype); - ret parse_crate_mod(p, cfg); + ret parse_crate_mod(p, cfg, sess); } // Parses a source module as a crate -fn parse_crate_mod(&parser p, &ast::crate_cfg cfg) -> @ast::crate { - +fn parse_crate_mod(&parser p, &ast::crate_cfg cfg, parse_sess sess) + -> @ast::crate { auto lo = p.get_lo_pos(); auto crate_attrs = parse_inner_attrs_and_next(p); auto first_item_outer_attrs = crate_attrs._1; @@ -2570,8 +2532,7 @@ fn parse_crate_directives(&parser p, token::token term, } fn parse_crate_from_crate_file(&str input, &ast::crate_cfg cfg, - &codemap::codemap cm) -> @ast::crate { - auto sess = @rec(cm=cm, mutable next_id=0); + &parse_sess sess) -> @ast::crate { auto p = new_parser_from_file(sess, cfg, input, 0u); auto lo = p.get_lo_pos(); auto prefix = std::fs::dirname(p.get_filemap().name); diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 8fb5770e641..9566fef32e6 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -961,7 +961,7 @@ fn print_expr(&ps s, &@ast::expr expr) { print_expr(s, expr); pclose(s); } - case (ast::expr_ext(?path, ?args, ?body, _)) { + case (ast::expr_ext(?path, ?args, ?body)) { word(s.s, "#"); print_path(s, path); if (ivec::len(args) > 0u) { diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index 71d44e29f80..b1d928939ef 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -362,8 +362,10 @@ fn visit_expr[E](&@expr ex, &E e, &vt[E] v) { case (expr_path(?p)) { for (@ty tp in p.node.types) { v.visit_ty(tp, e, v); } } - case (expr_ext(_, _, _, ?expansion)) { - v.visit_expr(expansion, e, v); + case (expr_ext(_, ?args, _)) { + for(@ast::expr arg in args) { + vt(v).visit_expr(arg, e, v); + } } case (expr_fail(?eo)) { visit_expr_opt(eo, e, v); diff --git a/src/comp/syntax/walk.rs b/src/comp/syntax/walk.rs index bc188b8c604..1902c5e69a9 100644 --- a/src/comp/syntax/walk.rs +++ b/src/comp/syntax/walk.rs @@ -367,10 +367,10 @@ fn walk_expr(&ast_visitor v, @ast::expr e) { case (ast::expr_path(?p)) { for (@ast::ty tp in p.node.types) { walk_ty(v, tp); } } - case (ast::expr_ext(_, ?args, ?body, ?expansion)) { - // Only walk expansion, not args/body. - - walk_expr(v, expansion); + case (ast::expr_ext(_, ?args, _)) { + for (@ast::expr e in args) { + walk_expr(v, e); + } } case (ast::expr_fail(?eo)) { walk_expr_opt(v, eo); } case (ast::expr_break) { } |
