summary refs log tree commit diff
path: root/src/comp/syntax
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2011-07-06 15:22:23 -0700
committerPaul Stansifer <paul.stansifer@gmail.com>2011-07-11 18:52:50 -0700
commit425732311af6d7a4f972dff04e1abb7db6a22f3b (patch)
tree5b3d5493c7fc3a32a28b166f5ea393d640537c23 /src/comp/syntax
parent80cf4ecd3bfe602004145e57cf7fdfb067b76ce1 (diff)
downloadrust-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.rs2
-rw-r--r--src/comp/syntax/ext/base.rs23
-rw-r--r--src/comp/syntax/ext/expand.rs65
-rw-r--r--src/comp/syntax/ext/simplext.rs272
-rw-r--r--src/comp/syntax/fold.rs4
-rw-r--r--src/comp/syntax/parse/parser.rs59
-rw-r--r--src/comp/syntax/print/pprust.rs2
-rw-r--r--src/comp/syntax/visit.rs6
-rw-r--r--src/comp/syntax/walk.rs8
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) { }