]> git.lizzy.rs Git - rust.git/commitdiff
Move everything syntax-related to syntax/, break deps on rest of compiler
authorMarijn Haverbeke <marijnh@gmail.com>
Tue, 5 Jul 2011 09:48:19 +0000 (11:48 +0200)
committerMarijn Haverbeke <marijnh@gmail.com>
Tue, 5 Jul 2011 13:57:21 +0000 (15:57 +0200)
src/comp/syntax is currently just a sub-module of rustc, but it will,
in the near future, be its own crate. This includes:

 - The AST data structure
 - The parser
 - The pretty-printer
 - Visit, walk, and fold
 - The syntax extension system
 - Some utility stuff that should be in the stdlib*

*) Stdlib extensions currently require a snapshot before they can be
   used, and the win build is very broken right now. This is temporary
   and will be cleaned up when one of those problems goes away.

A lot of code was moved by this patch, mostly towards a more organized
layout. Some package paths did get longer, and I guess the new layout
will take some getting used to. Sorry about that!

Please try not to re-introduce any dependencies in syntax/ on any of
the other src/comp/ subdirs.

68 files changed:
src/comp/back/link.rs
src/comp/back/x86.rs
src/comp/driver/rustc.rs
src/comp/driver/session.rs
src/comp/front/ast.rs [deleted file]
src/comp/front/attr.rs
src/comp/front/codemap.rs [deleted file]
src/comp/front/config.rs
src/comp/front/eval.rs [deleted file]
src/comp/front/ext.rs [deleted file]
src/comp/front/extenv.rs [deleted file]
src/comp/front/extfmt.rs [deleted file]
src/comp/front/extsimplext.rs [deleted file]
src/comp/front/fold.rs [deleted file]
src/comp/front/lexer.rs [deleted file]
src/comp/front/parser.rs [deleted file]
src/comp/front/token.rs [deleted file]
src/comp/lib/llvm.rs
src/comp/metadata/creader.rs
src/comp/metadata/cwriter.rs
src/comp/metadata/decoder.rs
src/comp/metadata/encoder.rs
src/comp/metadata/tydecode.rs
src/comp/metadata/tyencode.rs
src/comp/middle/alias.rs
src/comp/middle/ast_map.rs
src/comp/middle/resolve.rs
src/comp/middle/trans.rs
src/comp/middle/tstate/ann.rs
src/comp/middle/tstate/annotate.rs
src/comp/middle/tstate/auxiliary.rs
src/comp/middle/tstate/bitvectors.rs
src/comp/middle/tstate/ck.rs
src/comp/middle/tstate/collect_locals.rs
src/comp/middle/tstate/pre_post_conditions.rs
src/comp/middle/tstate/states.rs
src/comp/middle/ty.rs
src/comp/middle/typeck.rs
src/comp/middle/visit.rs [deleted file]
src/comp/middle/walk.rs [deleted file]
src/comp/pretty/pp.rs [deleted file]
src/comp/pretty/ppaux.rs [deleted file]
src/comp/pretty/pprust.rs [deleted file]
src/comp/rustc.rc
src/comp/syntax/_std.rs [new file with mode: 0644]
src/comp/syntax/ast.rs [new file with mode: 0644]
src/comp/syntax/codemap.rs [new file with mode: 0644]
src/comp/syntax/ext/base.rs [new file with mode: 0644]
src/comp/syntax/ext/env.rs [new file with mode: 0644]
src/comp/syntax/ext/fmt.rs [new file with mode: 0644]
src/comp/syntax/ext/simplext.rs [new file with mode: 0644]
src/comp/syntax/fold.rs [new file with mode: 0644]
src/comp/syntax/parse/eval.rs [new file with mode: 0644]
src/comp/syntax/parse/lexer.rs [new file with mode: 0644]
src/comp/syntax/parse/parser.rs [new file with mode: 0644]
src/comp/syntax/parse/token.rs [new file with mode: 0644]
src/comp/syntax/print/pp.rs [new file with mode: 0644]
src/comp/syntax/print/pprust.rs [new file with mode: 0644]
src/comp/syntax/util/interner.rs [new file with mode: 0644]
src/comp/syntax/visit.rs [new file with mode: 0644]
src/comp/syntax/walk.rs [new file with mode: 0644]
src/comp/util/common.rs
src/comp/util/data.rs [deleted file]
src/comp/util/ppaux.rs [new file with mode: 0644]
src/lib/int.rs
src/lib/map.rs
src/lib/uint.rs
src/lib/vec.rs

index 562b029dfe8eb01a817104ff26946b85a06cb71b..47168a3dd8c536b09cbeaf8c56f46152663bd50f 100644 (file)
@@ -13,7 +13,7 @@
 import std::sha1::sha1;
 import std::sort;
 import trans::crate_ctxt;
-import front::ast;
+import syntax::ast;
 import lib::llvm::llvm::ModuleRef;
 import lib::llvm::llvm::ValueRef;
 import lib::llvm::mk_pass_manager;
@@ -436,7 +436,7 @@ fn mangle_exported_name(&@crate_ctxt ccx, &vec[str] path, &ty::t t) -> str {
 
 fn mangle_internal_name_by_type_only(&@crate_ctxt ccx, &ty::t t, &str name) ->
    str {
-    auto s = pretty::ppaux::ty_to_short_str(ccx.tcx, t);
+    auto s = util::ppaux::ty_to_short_str(ccx.tcx, t);
     auto hash = get_symbol_hash(ccx, t);
     ret mangle([name, s, hash]);
 }
index 6a0872734ff067a4a8057c278989df362f0aabe9..018c99e153a7029e3435d74f5811591ba9e579f9 100644 (file)
@@ -4,7 +4,7 @@
 import std::str;
 import std::vec;
 import std::os::target_os;
-import util::common::istr;
+import syntax::_std::istr;
 
 fn get_module_asm() -> str { ret ""; }
 
index 10f374d2392f250597712a9c72f1b8364c598332..9ad42103a9013498c279f7fe9e748410b9b9b1e4 100644 (file)
@@ -2,19 +2,19 @@
 
 // -*- rust -*-
 import metadata::creader;
-import front::parser;
-import front::token;
-import front::eval;
-import front::ast;
+import syntax::parse::parser;
+import syntax::parse::token;
+import syntax::ast;
+import syntax::codemap;
 import front::attr;
 import middle::trans;
 import middle::resolve;
 import middle::ty;
 import middle::typeck;
 import middle::tstate::ck;
-import pretty::pp;
-import pretty::pprust;
-import pretty::ppaux;
+import syntax::print::pp;
+import syntax::print::pprust;
+import util::ppaux;
 import back::link;
 import lib::llvm;
 import util::common;
@@ -76,12 +76,14 @@ fn to_meta_word(&str cfgspec) -> @ast::meta_item {
     ret vec::map(to_meta_word, cfgspecs);
 }
 
-fn parse_input(session::session sess, parser::parser p, str input) ->
-   @ast::crate {
+fn parse_input(session::session sess, &ast::crate_cfg cfg, str input)
+    -> @ast::crate {
     ret if (str::ends_with(input, ".rc")) {
-            parser::parse_crate_from_crate_file(p)
+            parser::parse_crate_from_crate_file
+                (input, cfg, sess.get_codemap())
         } else if (str::ends_with(input, ".rs")) {
-            parser::parse_crate_from_source_file(p)
+            parser::parse_crate_from_source_file
+                (input, cfg, sess.get_codemap())
         } else { sess.fatal("unknown input file type: " + input); fail };
 }
 
@@ -99,9 +101,8 @@ fn time[T](bool do_it, str what, fn() -> T  thunk) -> T {
 fn compile_input(session::session sess, ast::crate_cfg cfg, str input,
                  str output) {
     auto time_passes = sess.get_opts().time_passes;
-    auto p = parser::new_parser(sess, cfg, input, 0u, 0);
     auto crate =
-        time(time_passes, "parsing", bind parse_input(sess, p, input));
+        time(time_passes, "parsing", bind parse_input(sess, cfg, input));
     if (sess.get_opts().output_type == link::output_type_none) { ret; }
     crate = time(time_passes, "configuration",
                  bind front::config::strip_unconfigured_items(crate));
@@ -129,17 +130,17 @@ fn compile_input(session::session sess, ast::crate_cfg cfg, str input,
 
 fn pretty_print_input(session::session sess, ast::crate_cfg cfg,
                       str input, pp_mode ppm) {
-    fn ann_paren_for_expr(&ppaux::ann_node node) {
+    fn ann_paren_for_expr(&pprust::ann_node node) {
         alt (node) {
-            case (ppaux::node_expr(?s, ?expr)) {
+            case (pprust::node_expr(?s, ?expr)) {
                 pprust::popen(s);
             }
             case (_) {}
         }
     }
-    fn ann_typed_post(&ty::ctxt tcx, &ppaux::ann_node node) {
+    fn ann_typed_post(&ty::ctxt tcx, &pprust::ann_node node) {
         alt (node) {
-            case (ppaux::node_expr(?s, ?expr)) {
+            case (pprust::node_expr(?s, ?expr)) {
                 pp::space(s.s);
                 pp::word(s.s, "as");
                 pp::space(s.s);
@@ -149,18 +150,18 @@ fn ann_typed_post(&ty::ctxt tcx, &ppaux::ann_node node) {
             case (_) {}
         }
     }
-    fn ann_identified_post(&ppaux::ann_node node) {
+    fn ann_identified_post(&pprust::ann_node node) {
         alt (node) {
-            case (ppaux::node_item(?s, ?item)) {
+            case (pprust::node_item(?s, ?item)) {
                 pp::space(s.s);
                 pprust::synth_comment(s, int::to_str(item.id, 10u));
             }
-            case (ppaux::node_block(?s, ?blk)) {
+            case (pprust::node_block(?s, ?blk)) {
                 pp::space(s.s);
                 pprust::synth_comment(s, "block " +
                                       int::to_str(blk.node.id, 10u));
             }
-            case (ppaux::node_expr(?s, ?expr)) {
+            case (pprust::node_expr(?s, ?expr)) {
                 pp::space(s.s);
                 pprust::synth_comment(s, int::to_str(expr.id, 10u));
                 pprust::pclose(s);
@@ -169,8 +170,7 @@ fn ann_identified_post(&ppaux::ann_node node) {
         }
     }
 
-    auto p = front::parser::new_parser(sess, cfg, input, 0u, 0);
-    auto crate = parse_input(sess, p, input);
+    auto crate = parse_input(sess, cfg, input);
     auto ann;
     alt (ppm) {
         case (ppm_typed) {
@@ -186,10 +186,11 @@ fn ann_identified_post(&ppaux::ann_node node) {
                       post=ann_identified_post);
         }
         case (ppm_normal) {
-            ann = ppaux::no_ann();
+            ann = pprust::no_ann();
         }
     }
-    pprust::print_crate(sess, crate, input, std::io::stdout(), ann);
+    pprust::print_crate(sess.get_codemap(), crate, input,
+                        std::io::stdout(), ann);
 }
 
 fn version(str argv0) {
@@ -268,9 +269,9 @@ fn build_target_config() -> @session::config {
     let @session::config target_cfg =
         @rec(os=get_os(triple),
              arch=get_arch(triple),
-             int_type=common::ty_i32,
-             uint_type=common::ty_u32,
-             float_type=common::ty_f64);
+             int_type=ast::ty_i32,
+             uint_type=ast::ty_u32,
+             float_type=ast::ty_f64);
     ret target_cfg;
 }
 
@@ -342,11 +343,11 @@ fn build_session_options(str binary, getopts::match match, str binary_dir) ->
 
 fn build_session(@session::options sopts) -> session::session {
     auto target_cfg = build_target_config();
-    auto crate_cache = common::new_int_hash[session::crate_metadata]();
+    auto crate_cache = syntax::_std::new_int_hash[session::crate_metadata]();
     auto target_crate_num = 0;
     auto sess =
         session::session(target_crate_num, target_cfg, sopts, crate_cache, [],
-                         [], [], front::codemap::new_codemap(), 0u);
+                         [], [], codemap::new_codemap(), 0u);
     ret sess;
 }
 
index 8d296f355ae57b3e40e31d0515375ae9c2dba86e..8ef558f2fdebb5217036c2e05e3d5fae19b530ad 100644 (file)
@@ -1,10 +1,9 @@
 
-import front::ast;
-import front::codemap;
-import util::common::span;
-import util::common::ty_mach;
+import syntax::ast;
+import syntax::codemap;
+import codemap::span;
+import syntax::ast::ty_mach;
 import std::uint;
-import std::term;
 import std::io;
 import std::map;
 import std::option;
 
 type crate_metadata = rec(str name, vec[u8] data);
 
-fn span_to_str(span sp, codemap::codemap cm) -> str {
-    auto lo = codemap::lookup_pos(cm, sp.lo);
-    auto hi = codemap::lookup_pos(cm, sp.hi);
-    ret #fmt("%s:%u:%u:%u:%u", lo.filename, lo.line, lo.col, hi.line, hi.col);
-}
-
-fn emit_diagnostic(option::t[span] sp, str msg, str kind, u8 color,
-                   codemap::codemap cm) {
-    auto ss = "<input>:0:0:0:0";
-    alt (sp) {
-        case (some(?ssp)) { ss = span_to_str(ssp, cm); }
-        case (none) { }
-    }
-    io::stdout().write_str(ss + ": ");
-    if (term::color_supported()) {
-        term::fg(io::stdout().get_buf_writer(), color);
-    }
-    io::stdout().write_str(#fmt("%s:", kind));
-    if (term::color_supported()) {
-        term::reset(io::stdout().get_buf_writer());
-    }
-    io::stdout().write_str(#fmt(" %s\n", msg));
-}
-
 obj session(ast::crate_num cnum,
             @config targ_cfg,
             @options opts,
@@ -80,20 +55,19 @@ fn emit_diagnostic(option::t[span] sp, str msg, str kind, u8 color,
     fn get_targ_crate_num() -> ast::crate_num { ret cnum; }
     fn span_fatal(span sp, str msg) -> ! {
         // FIXME: Use constants, but rustboot doesn't know how to export them.
-
-        emit_diagnostic(some(sp), msg, "error", 9u8, cm);
+        codemap::emit_error(some(sp), msg, cm);
         fail;
     }
     fn fatal(str msg) -> ! {
-        emit_diagnostic(none[span], msg, "error", 9u8, cm);
+        codemap::emit_error(none, msg, cm);
         fail;
     }
     fn span_err(span sp, str msg) {
-        emit_diagnostic(some(sp), msg, "error", 9u8, cm);
+        codemap::emit_error(some(sp), msg, cm);
         err_count += 1u;
     }
     fn err(str msg) {
-        emit_diagnostic(none, msg, "error", 9u8, cm);
+        codemap::emit_error(none, msg, cm);
         err_count += 1u;
     }
     fn abort_if_errors() {
@@ -103,19 +77,17 @@ fn abort_if_errors() {
     }
     fn span_warn(span sp, str msg) {
         // FIXME: Use constants, but rustboot doesn't know how to export them.
-
-        emit_diagnostic(some(sp), msg, "warning", 11u8, cm);
+        codemap::emit_warning(some(sp), msg, cm);
     }
     fn warn(str msg) {
-        emit_diagnostic(none[span], msg, "warning", 11u8, cm);
+        codemap::emit_warning(none, msg, cm);
     }
     fn span_note(span sp, str msg) {
         // FIXME: Use constants, but rustboot doesn't know how to export them.
-
-        emit_diagnostic(some(sp), msg, "note", 10u8, cm);
+        codemap::emit_note(some(sp), msg, cm);
     }
     fn note(str msg) {
-        emit_diagnostic(none, msg, "note", 10u8, cm);
+        codemap::emit_note(none, msg, cm);
     }
     fn span_bug(span sp, str msg) -> ! {
         self.span_fatal(sp, #fmt("internal compiler error %s", msg));
@@ -172,7 +144,9 @@ fn get_used_crate_files() -> vec[str] {
     fn lookup_pos(uint pos) -> codemap::loc {
         ret codemap::lookup_pos(cm, pos);
     }
-    fn span_str(span sp) -> str { ret span_to_str(sp, self.get_codemap()); }
+    fn span_str(span sp) -> str {
+        ret codemap::span_to_str(sp, self.get_codemap());
+    }
 }
 // Local Variables:
 // fill-column: 78;
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
deleted file mode 100644 (file)
index 600a76c..0000000
+++ /dev/null
@@ -1,625 +0,0 @@
-
-import std::option;
-import std::str;
-import std::vec;
-import util::common::span;
-import util::common::spanned;
-import util::common::ty_mach;
-import util::common::filename;
-
-type ident = str;
-// Functions may or may not have names.
-type fn_ident = option::t[ident];
-
-// FIXME: with typestate constraint, could say
-// idents and types are the same length, and are
-// non-empty
-type path_ = rec(vec[ident] idents, vec[@ty] types);
-
-type path = spanned[path_];
-
-fn path_name(&path p) -> str { ret str::connect(p.node.idents, "::"); }
-
-type crate_num = int;
-type node_id = int;
-type def_id = tup(crate_num, node_id);
-
-const crate_num local_crate = 0;
-fn local_def(node_id id) -> def_id {
-    ret tup(local_crate, id);
-}
-
-type ty_param = ident;
-
-tag def {
-    def_fn(def_id, purity);
-    def_obj_field(def_id);
-    def_mod(def_id);
-    def_native_mod(def_id);
-    def_const(def_id);
-    def_arg(def_id);
-    def_local(def_id);
-    def_variant(def_id, /* tag */def_id);
-
-    /* variant */
-    def_ty(def_id);
-    def_ty_arg(uint);
-    def_binding(def_id);
-    def_use(def_id);
-    def_native_ty(def_id);
-    def_native_fn(def_id);
-}
-
-fn variant_def_ids(&def d) -> tup(def_id, def_id) {
-    alt (d) {
-        case (def_variant(?tag_id, ?var_id)) { ret tup(tag_id, var_id); }
-    }
-}
-
-fn def_id_of_def(def d) -> def_id {
-    alt (d) {
-        case (def_fn(?id,_)) { ret id; }
-        case (def_obj_field(?id)) { ret id; }
-        case (def_mod(?id)) { ret id; }
-        case (def_native_mod(?id)) { ret id; }
-        case (def_const(?id)) { ret id; }
-        case (def_arg(?id)) { ret id; }
-        case (def_local(?id)) { ret id; }
-        case (def_variant(_, ?id)) { ret id; }
-        case (def_ty(?id)) { ret id; }
-        case (def_ty_arg(_)) { fail; }
-        case (def_binding(?id)) { ret id; }
-        case (def_use(?id)) { ret id; }
-        case (def_native_ty(?id)) { ret id; }
-        case (def_native_fn(?id)) { ret id; }
-    }
-    fail;
-}
-
-// The set of meta_items that define the compilation environment of the crate,
-// used to drive conditional compilation
-type crate_cfg = vec[@meta_item];
-
-type crate = spanned[crate_];
-
-type crate_ = rec(vec[@crate_directive] directives,
-                  _mod module,
-                  vec[attribute] attrs,
-                  crate_cfg config);
-
-tag crate_directive_ {
-    cdir_src_mod(ident, option::t[filename], vec[attribute]);
-    cdir_dir_mod(ident, option::t[filename],
-                 vec[@crate_directive], vec[attribute]);
-    cdir_view_item(@view_item);
-    cdir_syntax(path);
-    cdir_auth(path, _auth);
-}
-
-type crate_directive = spanned[crate_directive_];
-
-type meta_item = spanned[meta_item_];
-
-tag meta_item_ {
-    meta_word(ident);
-    meta_list(ident, vec[@meta_item]);
-    meta_name_value(ident, str);
-}
-
-type block = spanned[block_];
-
-type block_ = rec(vec[@stmt] stmts, option::t[@expr] expr, node_id id);
-
-type pat = rec(node_id id,
-               pat_ node,
-               span span);
-
-tag pat_ {
-    pat_wild;
-    pat_bind(ident);
-    pat_lit(@lit);
-    pat_tag(path, vec[@pat]);
-}
-
-tag mutability { mut; imm; maybe_mut; }
-
-tag layer { layer_value; layer_state; layer_gc; }
-
-tag _auth { auth_unsafe; }
-
-tag proto { proto_iter; proto_fn; }
-
-tag binop {
-    add;
-    sub;
-    mul;
-    div;
-    rem;
-    and;
-    or;
-    bitxor;
-    bitand;
-    bitor;
-    lsl;
-    lsr;
-    asr;
-    eq;
-    lt;
-    le;
-    ne;
-    ge;
-    gt;
-}
-
-fn binop_to_str(binop op) -> str {
-    alt (op) {
-        case (add) { ret "+"; }
-        case (sub) { ret "-"; }
-        case (mul) { ret "*"; }
-        case (div) { ret "/"; }
-        case (rem) { ret "%"; }
-        case (and) { ret "&&"; }
-        case (or) { ret "||"; }
-        case (bitxor) { ret "^"; }
-        case (bitand) { ret "&"; }
-        case (bitor) { ret "|"; }
-        case (lsl) { ret "<<"; }
-        case (lsr) { ret ">>"; }
-        case (asr) { ret ">>>"; }
-        case (eq) { ret "=="; }
-        case (lt) { ret "<"; }
-        case (le) { ret "<="; }
-        case (ne) { ret "!="; }
-        case (ge) { ret ">="; }
-        case (gt) { ret ">"; }
-    }
-}
-
-pred lazy_binop(binop b) -> bool {
-    alt (b) {
-        case (and) { true }
-        case (or)  { true }
-        case (_)   { false }
-    }
-}
-
-tag unop { box(mutability); deref; not; neg; }
-
-fn unop_to_str(unop op) -> str {
-    alt (op) {
-        case (box(?mt)) { if (mt == mut) { ret "@mutable "; } ret "@"; }
-        case (deref) { ret "*"; }
-        case (not) { ret "!"; }
-        case (neg) { ret "-"; }
-    }
-}
-
-tag mode { val; alias(bool); }
-
-type stmt = spanned[stmt_];
-
-tag stmt_ {
-    stmt_decl(@decl, node_id);
-    stmt_expr(@expr, node_id);
-
-    // These only exist in crate-level blocks.
-    stmt_crate_directive(@crate_directive);
-}
-
-tag init_op { init_assign; init_recv; init_move; }
-
-type initializer = rec(init_op op, @expr expr);
-
-type local_ =
-    rec(option::t[@ty] ty,
-        bool infer,
-        ident ident,
-        option::t[initializer] init,
-        node_id id);
-
-type local = spanned[local_];
-
-type decl = spanned[decl_];
-
-tag decl_ { decl_local(@local); decl_item(@item); }
-
-type arm = rec(@pat pat, block block);
-
-type elt = rec(mutability mut, @expr expr);
-
-type field_ = rec(mutability mut, ident ident, @expr expr);
-
-type field = spanned[field_];
-
-tag spawn_dom { dom_implicit; dom_thread; }
-
-tag check_mode { checked; unchecked; }
-
-// FIXME: temporary
-tag seq_kind { sk_unique; sk_rc; }
-
-type expr = rec(node_id id,
-                expr_ node,
-                span span);
-
-tag expr_ {
-    expr_vec(vec[@expr], mutability, seq_kind);
-    expr_tup(vec[elt]);
-    expr_rec(vec[field], option::t[@expr]);
-    expr_call(@expr, vec[@expr]);
-    expr_self_method(ident);
-    expr_bind(@expr, vec[option::t[@expr]]);
-    expr_spawn(spawn_dom, option::t[str], @expr, vec[@expr]);
-    expr_binary(binop, @expr, @expr);
-    expr_unary(unop, @expr);
-    expr_lit(@lit);
-    expr_cast(@expr, @ty);
-    expr_if(@expr, block, option::t[@expr]);
-    expr_ternary(@expr, @expr, @expr);
-    expr_while(@expr, block);
-    expr_for(@local, @expr, block);
-    expr_for_each(@local, @expr, block);
-    expr_do_while(block, @expr);
-    expr_alt(@expr, vec[arm]);
-    expr_fn(_fn);
-    expr_block(block);
-    /*
-     * FIXME: many of these @exprs should be constrained with
-     * is_lval once we have constrained types working.
-     */
-    expr_move(@expr, @expr);
-    expr_assign(@expr,@expr);
-    expr_swap(@expr, @expr);
-    expr_assign_op(binop, @expr, @expr);
-    expr_send(@expr, @expr);
-    expr_recv(@expr, @expr);
-    expr_field(@expr, ident);
-    expr_index(@expr, @expr);
-    expr_path(path);
-    expr_ext(path, vec[@expr], option::t[str], @expr);
-    expr_fail(option::t[@expr]);
-    expr_break;
-    expr_cont;
-    expr_ret(option::t[@expr]);
-    expr_put(option::t[@expr]);
-    expr_be(@expr);
-    expr_log(int, @expr);
-
-    /* just an assert, no significance to typestate */
-    expr_assert(@expr);
-
-    /* preds that typestate is aware of */
-    expr_check(check_mode, @expr);
-   /* FIXME Would be nice if expr_check desugared
-      to expr_if_check. */
-    expr_if_check(@expr, block, option::t[@expr]);
-    expr_port(option::t[@ty]);
-    expr_chan(@expr);
-    expr_anon_obj(anon_obj, vec[ty_param], obj_def_ids);
-}
-
-type lit = spanned[lit_];
-
-tag lit_ {
-    lit_str(str, seq_kind);
-    lit_char(char);
-    lit_int(int);
-    lit_uint(uint);
-    lit_mach_int(ty_mach, int);
-    lit_float(str);
-    lit_mach_float(ty_mach, str);
-    lit_nil;
-    lit_bool(bool);
-}
-
-fn is_path(&@expr e) -> bool {
-    ret alt (e.node) {
-        case (expr_path(_)) { true }
-        case (_) { false }
-    };
-}
-
-
-// NB: If you change this, you'll probably want to change the corresponding
-// type structure in middle/ty.rs as well.
-type mt = rec(@ty ty, mutability mut);
-
-type ty_field_ = rec(ident ident, mt mt);
-
-type ty_arg_ = rec(mode mode, @ty ty);
-
-type ty_method_ =
-    rec(proto proto,
-        ident ident,
-        vec[ty_arg] inputs,
-        @ty output,
-        controlflow cf,
-        vec[@constr] constrs);
-
-type ty_field = spanned[ty_field_];
-
-type ty_arg = spanned[ty_arg_];
-
-type ty_method = spanned[ty_method_];
-
-type ty = spanned[ty_];
-
-tag ty_ {
-    ty_nil;
-    ty_bot; /* return type of ! functions and type of
-             ret/fail/break/cont. there is no syntax
-             for this type. */
-
-     /* bot represents the value of functions that don't return a value
-        locally to their context. in contrast, things like log that do
-        return, but don't return a meaningful value, have result type nil. */
-    ty_bool;
-    ty_int;
-    ty_uint;
-    ty_float;
-    ty_machine(util::common::ty_mach);
-    ty_char;
-    ty_str;
-    ty_istr; // interior string
-
-    ty_box(mt);
-    ty_vec(mt);
-    ty_ivec(mt); // interior vector
-
-    ty_ptr(mt);
-    ty_task;
-    ty_port(@ty);
-    ty_chan(@ty);
-    ty_tup(vec[mt]);
-    ty_rec(vec[ty_field]);
-    ty_fn(proto, vec[ty_arg], @ty, controlflow, vec[@constr]);
-    ty_obj(vec[ty_method]);
-    ty_path(path, node_id);
-    ty_type;
-    ty_constr(@ty, vec[@constr]);
-}
-
-
-/*
-A constraint arg that's a function argument is referred to by its position
-rather than name.  This is so we could have higher-order functions that have
-constraints (potentially -- right now there's no way to write that), and also
-so that the typestate pass doesn't have to map a function name onto its decl.
-So, the constr_arg type is parameterized: it's instantiated with uint for
-declarations, and ident for uses.
-*/
-tag constr_arg_general_[T] { carg_base; carg_ident(T); carg_lit(@lit); }
-
-type constr_arg = constr_arg_general[uint];
-
-type constr_arg_general[T] = spanned[constr_arg_general_[T]];
-
-type constr_ = rec(path path,
-                   vec[@constr_arg_general[uint]] args,
-                   node_id id);
-
-type constr = spanned[constr_];
-
-
-/* The parser generates ast::constrs; resolve generates
- a mapping from each function to a list of ty::constr_defs,
- corresponding to these. */
-type arg = rec(mode mode, @ty ty, ident ident, node_id id);
-
-type fn_decl =
-    rec(vec[arg] inputs,
-        @ty output,
-        purity purity,
-        controlflow cf,
-        vec[@constr] constraints);
-
-tag purity {
-    pure_fn; // declared with "pred"
-
-    impure_fn; // declared with "fn"
-
-}
-
-tag controlflow {
-    noreturn; // functions with return type _|_ that always
-              // raise an error or exit (i.e. never return to the caller)
-
-    return; // everything else
-
-}
-
-type _fn = rec(fn_decl decl, proto proto, block body);
-
-type method_ = rec(ident ident, _fn meth, node_id id);
-
-type method = spanned[method_];
-
-type obj_field = rec(mutability mut, @ty ty, ident ident, node_id id);
-type anon_obj_field = rec(mutability mut, @ty ty, @expr expr, ident ident,
-                          node_id id);
-
-type _obj =
-    rec(vec[obj_field] fields, vec[@method] methods, option::t[@method] dtor);
-
-type anon_obj =
-    rec(
-        // New fields and methods, if they exist.
-        option::t[vec[anon_obj_field]] fields,
-        vec[@method] methods,
-
-        // with_obj: the original object being extended, if it exists.
-        option::t[@expr] with_obj);
-
-type _mod = rec(vec[@view_item] view_items, vec[@item] items);
-
-tag native_abi {
-    native_abi_rust;
-    native_abi_cdecl;
-    native_abi_llvm;
-    native_abi_rust_intrinsic;
-}
-
-type native_mod =
-    rec(str native_name,
-        native_abi abi,
-        vec[@view_item] view_items,
-        vec[@native_item] items);
-
-type variant_arg = rec(@ty ty, node_id id);
-
-type variant_ = rec(str name, vec[variant_arg] args, node_id id);
-
-type variant = spanned[variant_];
-
-type view_item = spanned[view_item_];
-
-tag view_item_ {
-    view_item_use(ident, vec[@meta_item], node_id);
-    view_item_import(ident, vec[ident], node_id);
-    view_item_import_glob(vec[ident], node_id);
-    view_item_export(ident, node_id);
-}
-
-type obj_def_ids = rec(node_id ty, node_id ctor);
-
-
-// Meta-data associated with an item
-type attribute = spanned[attribute_];
-
-
-// Distinguishes between attributes that decorate items and attributes that
-// are contained as statements within items. These two cases need to be
-// distinguished for pretty-printing.
-tag attr_style { attr_outer; attr_inner; }
-
-type attribute_ = rec(attr_style style, meta_item value);
-
-type item = rec(ident ident,
-                vec[attribute] attrs,
-                node_id id, // For objs and resources, this is the type def_id
-                item_ node,
-                span span);
-
-tag item_ {
-    item_const(@ty, @expr);
-    item_fn(_fn, vec[ty_param]);
-    item_mod(_mod);
-    item_native_mod(native_mod);
-    item_ty(@ty, vec[ty_param]);
-    item_tag(vec[variant], vec[ty_param]);
-    item_obj(_obj, vec[ty_param], node_id /* constructor id */);
-    item_res(_fn /* dtor */, node_id /* dtor id */,
-             vec[ty_param], node_id /* ctor id */);
-}
-
-type native_item = rec(ident ident,
-                       native_item_ node,
-                       node_id id,
-                       span span);
-
-tag native_item_ {
-    native_item_ty;
-    native_item_fn(option::t[str], fn_decl, vec[ty_param]);
-}
-
-fn is_exported(ident i, _mod m) -> bool {
-    auto nonlocal = true;
-    for (@ast::item it in m.items) {
-        if (it.ident == i) { nonlocal = false; }
-        alt (it.node) {
-            case (item_tag(?variants, _)) {
-                for (variant v in variants) {
-                    if (v.node.name == i) { nonlocal = false; }
-                }
-            }
-            case (_) { }
-        }
-        if (!nonlocal) { break; }
-    }
-    auto count = 0u;
-    for (@ast::view_item vi in m.view_items) {
-        alt (vi.node) {
-            case (ast::view_item_export(?id, _)) {
-                if (str::eq(i, id)) {
-                    // even if it's nonlocal (since it's explicit)
-
-                    ret true;
-                }
-                count += 1u;
-            }
-            case (_) {/* fall through */ }
-        }
-    }
-    // If there are no declared exports then 
-    // everything not imported is exported
-
-    ret count == 0u && !nonlocal;
-}
-
-fn is_call_expr(@expr e) -> bool {
-    alt (e.node) {
-        case (expr_call(_, _)) { ret true; }
-        case (_) { ret false; }
-    }
-}
-
-fn is_constraint_arg(@expr e) -> bool {
-    alt (e.node) {
-        case (expr_lit(_)) { ret true; }
-        case (expr_path(_)) { ret true; }
-        case (_) { ret false; }
-    }
-}
-
-fn eq_ty(&@ty a, &@ty b) -> bool { ret std::box::ptr_eq(a, b); }
-
-fn hash_ty(&@ty t) -> uint { ret t.span.lo << 16u + t.span.hi; }
-
-fn block_from_expr(@expr e) -> block {
-    let block_ blk_ =
-        rec(stmts=[],
-            expr=option::some[@expr](e),
-            id=e.id);
-    ret rec(node=blk_, span=e.span);
-}
-
-// This is a convenience function to transfor ternary expressions to if
-// expressions so that they can be treated the same
-fn ternary_to_if(&@expr e) -> @ast::expr {
-    alt (e.node) {
-        case (expr_ternary(?cond, ?then, ?els)) {
-            auto then_blk = block_from_expr(then);
-            auto els_blk = block_from_expr(els);
-            auto els_expr = @rec(id=els.id, node=expr_block(els_blk),
-                                 span=els.span);
-            ret @rec(id=e.id,
-                     node=expr_if(cond, then_blk, option::some(els_expr)),
-                     span=e.span);
-        }
-        case (_) { fail; }
-    }
-}
-
-// Path stringification
-fn path_to_str(&ast::path pth) -> str {
-    auto result = str::connect(pth.node.idents, "::");
-    if (vec::len[@ast::ty](pth.node.types) > 0u) {
-        fn f(&@ast::ty t) -> str { ret pretty::pprust::ty_to_str(*t); }
-        result += "[";
-        result += str::connect(vec::map(f, pth.node.types), ",");
-        result += "]";
-    }
-    ret result;
-}
-
-
-//
-// 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:
-//
index 1312851c5f01931b0ebc541123411105f22562dd..00e64e33f6bbdc39cbdd976af8d471f19afb042e 100644 (file)
@@ -2,7 +2,7 @@
 
 import std::vec;
 import std::option;
-import front::ast;
+import syntax::ast;
 import util::common;
 
 export attr_metas;
@@ -105,9 +105,11 @@ fn eq(@ast::meta_item a, @ast::meta_item b) -> bool {
 }
 
 fn contains(&vec[@ast::meta_item] haystack, @ast::meta_item needle) -> bool {
-    log #fmt("looking for %s", pretty::pprust::meta_item_to_str(*needle));
+    log #fmt("looking for %s",
+             syntax::print::pprust::meta_item_to_str(*needle));
     for (@ast::meta_item item in haystack) {
-        log #fmt("looking in %s", pretty::pprust::meta_item_to_str(*item));
+        log #fmt("looking in %s",
+                 syntax::print::pprust::meta_item_to_str(*item));
         if (eq(item, needle)) {
             log "found it!";
             ret true;
@@ -166,7 +168,7 @@ fn remove_meta_items_by_name(&vec[@ast::meta_item] items,
     ret vec::filter_map(filter, items);
 }
 
-fn span[T](&T item) -> common::spanned[T] {
+fn span[T](&T item) -> ast::spanned[T] {
     ret rec(node=item, span=rec(lo=0u, hi=0u));
 }
 
diff --git a/src/comp/front/codemap.rs b/src/comp/front/codemap.rs
deleted file mode 100644 (file)
index 3e1aa3c..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-
-import std::vec;
-
-
-/* A codemap is a thing that maps uints to file/line/column positions
- * in a crate. This to make it possible to represent the positions
- * with single-word things, rather than passing records all over the
- * compiler.
- */
-type filemap = @rec(str name, uint start_pos, mutable vec[uint] lines);
-
-type codemap = @rec(mutable vec[filemap] files);
-
-type loc = rec(str filename, uint line, uint col);
-
-fn new_codemap() -> codemap {
-    let vec[filemap] files = [];
-    ret @rec(mutable files=files);
-}
-
-fn new_filemap(str filename, uint start_pos) -> filemap {
-    ret @rec(name=filename, start_pos=start_pos, mutable lines=[0u]);
-}
-
-fn next_line(filemap file, uint pos) { vec::push[uint](file.lines, pos); }
-
-fn lookup_pos(codemap map, uint pos) -> loc {
-    auto a = 0u;
-    auto b = vec::len[filemap](map.files);
-    while (b - a > 1u) {
-        auto m = (a + b) / 2u;
-        if (map.files.(m).start_pos > pos) { b = m; } else { a = m; }
-    }
-    auto f = map.files.(a);
-    a = 0u;
-    b = vec::len[uint](f.lines);
-    while (b - a > 1u) {
-        auto m = (a + b) / 2u;
-        if (f.lines.(m) > pos) { b = m; } else { a = m; }
-    }
-    ret rec(filename=f.name, line=a + 1u, col=pos - f.lines.(a));
-}
-//
-// 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:
-//
index bbfc90015723f5ae35e63fefaafccff84136f539..63646ffca69d86430b2fa5845d5e0fd0795f049e 100644 (file)
@@ -1,7 +1,7 @@
 import std::option;
 import std::vec;
-import ast;
-import fold;
+import syntax::ast;
+import syntax::fold;
 import attr;
 
 export strip_unconfigured_items;
diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs
deleted file mode 100644 (file)
index 95b9a85..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-
-import std::vec;
-import std::str;
-import std::option;
-import std::option::some;
-import std::option::none;
-import driver::session;
-import front::parser::parser;
-import front::parser::new_parser;
-import front::parser::parse_inner_attrs_and_next;
-import front::parser::parse_mod_items;
-
-export eval_crate_directives_to_mod;
-export mode_parse;
-
-tag eval_mode { mode_depend; mode_parse; }
-
-type ctx =
-    @rec(parser p,
-         eval_mode mode,
-         mutable vec[str] deps,
-         session::session sess,
-         mutable uint chpos,
-         mutable int next_id,
-         ast::crate_cfg cfg);
-
-fn eval_crate_directives(ctx cx, vec[@ast::crate_directive] cdirs,
-                         str prefix, &mutable vec[@ast::view_item] view_items,
-                         &mutable vec[@ast::item] items) {
-    for (@ast::crate_directive sub_cdir in cdirs) {
-        eval_crate_directive(cx, sub_cdir, prefix, view_items, items);
-    }
-}
-
-fn eval_crate_directives_to_mod(ctx cx,
-                                vec[@ast::crate_directive] cdirs, str prefix)
-   -> ast::_mod {
-    let vec[@ast::view_item] view_items = [];
-    let vec[@ast::item] items = [];
-    eval_crate_directives(cx, cdirs, prefix, view_items, items);
-    ret rec(view_items=view_items, items=items);
-}
-
-fn eval_crate_directive_block(ctx cx, &ast::block blk, str prefix,
-                              &mutable vec[@ast::view_item] view_items,
-                              &mutable vec[@ast::item] items) {
-    for (@ast::stmt s in blk.node.stmts) {
-        alt (s.node) {
-            case (ast::stmt_crate_directive(?cdir)) {
-                eval_crate_directive(cx, cdir, prefix, view_items, items);
-            }
-            case (_) {
-                cx.sess.span_fatal(s.span,
-                                 "unsupported stmt in crate-directive block");
-            }
-        }
-    }
-}
-
-fn eval_crate_directive(ctx cx, @ast::crate_directive cdir, str prefix,
-                        &mutable vec[@ast::view_item] view_items,
-                        &mutable vec[@ast::item] items) {
-    alt (cdir.node) {
-        case (ast::cdir_src_mod(?id, ?file_opt, ?attrs)) {
-            auto file_path = id + ".rs";
-            alt (file_opt) {
-                case (some(?f)) { file_path = f; }
-                case (none) { }
-            }
-            auto full_path = if (std::fs::path_is_absolute(file_path)) {
-                file_path
-            } else {
-                prefix + std::fs::path_sep() + file_path
-            };
-            if (cx.mode == mode_depend) { cx.deps += [full_path]; ret; }
-            auto p0 =
-                new_parser(cx.sess, cx.cfg, full_path, cx.chpos,
-                           cx.next_id);
-            auto inner_attrs = parse_inner_attrs_and_next(p0);
-            auto mod_attrs = attrs + inner_attrs._0;
-            auto first_item_outer_attrs = inner_attrs._1;
-            auto m0 = parse_mod_items(p0, token::EOF, first_item_outer_attrs);
-
-            auto i = front::parser::mk_item(p0, cdir.span.lo, cdir.span.hi,
-                                            id, ast::item_mod(m0),
-                                            mod_attrs);
-            // Thread defids and chpos through the parsers
-            cx.chpos = p0.get_chpos();
-            cx.next_id = p0.next_id();
-            vec::push[@ast::item](items, i);
-        }
-        case (ast::cdir_dir_mod(?id, ?dir_opt, ?cdirs, ?attrs)) {
-            auto path = id;
-            alt (dir_opt) { case (some(?d)) { path = d; } case (none) { } }
-            auto full_path = if (std::fs::path_is_absolute(path)) {
-                path
-            } else {
-                prefix + std::fs::path_sep() + path
-            };
-            auto m0 = eval_crate_directives_to_mod(cx, cdirs, full_path);
-            auto i = @rec(ident=id,
-                          attrs=attrs,
-                          id=cx.next_id,
-                          node=ast::item_mod(m0),
-                          span=cdir.span);
-            cx.next_id += 1;
-            vec::push[@ast::item](items, i);
-        }
-        case (ast::cdir_view_item(?vi)) {
-            vec::push[@ast::view_item](view_items, vi);
-        }
-        case (ast::cdir_syntax(?pth)) { }
-        case (ast::cdir_auth(?pth, ?eff)) { }
-    }
-}
-//
-// 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/front/ext.rs b/src/comp/front/ext.rs
deleted file mode 100644 (file)
index e4562f2..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-import std::vec;
-import std::option;
-import std::map::hashmap;
-import driver::session::session;
-import front::parser::parser;
-import util::common::span;
-import util::common::new_str_hash;
-
-type syntax_expander = 
-    fn(&ext_ctxt, span, &vec[@ast::expr], option::t[str]) -> @ast::expr;
-type macro_definer = fn(&ext_ctxt, span, &vec[@ast::expr],
-                        option::t[str]) -> tup(str, syntax_extension);
-
-tag syntax_extension {
-    normal(syntax_expander);
-    macro_defining(macro_definer);
-}
-
-// A temporary hard-coded map of methods for expanding syntax extension
-// AST nodes into full ASTs
-fn syntax_expander_table() -> hashmap[str, syntax_extension] {
-    auto syntax_expanders = new_str_hash[syntax_extension]();
-    syntax_expanders.insert("fmt", normal(extfmt::expand_syntax_ext));
-    syntax_expanders.insert("env", normal(extenv::expand_syntax_ext));
-    syntax_expanders.insert("macro",    
-                            macro_defining(extsimplext::add_new_extension));
-    ret syntax_expanders;
-}
-
-type span_msg_fn = fn(span, str) -> !  ;
-
-type next_id_fn = fn() -> ast::node_id ;
-
-
-// Provides a limited set of services necessary for syntax extensions
-// to do their thing
-type ext_ctxt =
-    rec(span_msg_fn span_fatal,
-        span_msg_fn span_unimpl,
-        next_id_fn next_id);
-
-fn mk_ctxt(parser parser) -> ext_ctxt {
-    auto sess = parser.get_session();
-    fn ext_span_fatal_(session sess, span sp, str msg) -> ! {
-        sess.span_fatal(sp, msg);
-    }
-    auto ext_span_fatal = bind ext_span_fatal_(sess, _, _);
-    fn ext_span_unimpl_(session sess, span sp, str msg) -> ! {
-        sess.span_unimpl(sp, msg);
-    }
-    auto ext_span_unimpl = bind ext_span_unimpl_(sess, _, _);
-    fn ext_next_id_(parser parser) -> ast::node_id { parser.get_id() }
-    auto ext_next_id = bind ext_next_id_(parser);
-    ret rec(span_fatal=ext_span_fatal,
-            span_unimpl=ext_span_unimpl,
-            next_id=ext_next_id);
-}
-
-fn expr_to_str(&ext_ctxt cx, @ast::expr expr, str error) -> str {
-    alt (expr.node) {
-        case (ast::expr_lit(?l)) {
-            alt (l.node) {
-                case (ast::lit_str(?s, _)) { ret s; }
-                case (_) { cx.span_fatal(l.span, error); }
-            }
-        }
-        case (_) { cx.span_fatal(expr.span, error); }
-    }
-}
-
-fn expr_to_ident(&ext_ctxt cx, @ast::expr expr, str error) -> ast::ident {
-    alt(expr.node) {
-        case (ast::expr_path(?p)) {
-            if (vec::len(p.node.types) > 0u 
-                || vec::len(p.node.idents) != 1u) {
-                cx.span_fatal(expr.span, error);
-            } else {
-                ret p.node.idents.(0);
-            }
-        }
-        case (_) {
-            cx.span_fatal(expr.span, error);
-        }
-    }
-}
-
-
-
-//
-// 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/front/extenv.rs b/src/comp/front/extenv.rs
deleted file mode 100644 (file)
index acfb93e..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-/*
- * The compiler code necessary to support the #env extension.  Eventually this
- * should all get sucked into either the compiler syntax extension plugin
- * interface.
- */
-import util::common;
-import std::str;
-import std::vec;
-import std::option;
-import std::generic_os;
-import ext::*;
-export expand_syntax_ext;
-
-fn expand_syntax_ext(&ext_ctxt cx, common::span sp, &vec[@ast::expr] args,
-                     option::t[str] body) -> @ast::expr {
-    if (vec::len[@ast::expr](args) != 1u) {
-        cx.span_fatal(sp, "malformed #env call");
-    }
-    // FIXME: if this was more thorough it would manufacture an
-    // option::t[str] rather than just an maybe-empty string.
-
-    auto var = expr_to_str(cx, args.(0), "#env requires a string");
-    alt (generic_os::getenv(var)) {
-        case (option::none) { ret make_new_str(cx, sp, ""); }
-        case (option::some(?s)) { ret make_new_str(cx, sp, s); }
-    }
-}
-
-fn make_new_lit(&ext_ctxt cx, common::span sp, ast::lit_ lit) -> @ast::expr {
-    auto sp_lit = @rec(node=lit, span=sp);
-    ret @rec(id=cx.next_id(), node=ast::expr_lit(sp_lit), span=sp);
-}
-
-fn make_new_str(&ext_ctxt cx, common::span sp, str s) -> @ast::expr {
-    ret make_new_lit(cx, sp, ast::lit_str(s, ast::sk_rc));
-}
-//
-// 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/front/extfmt.rs b/src/comp/front/extfmt.rs
deleted file mode 100644 (file)
index 0696e0d..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-
-
-/*
- * The compiler code necessary to support the #fmt extension.  Eventually this
- * should all get sucked into either the standard library extfmt module or the
- * compiler syntax extension plugin interface.
- */
-import util::common;
-import std::str;
-import std::vec;
-import std::option;
-import std::option::none;
-import std::option::some;
-import std::extfmt::ct::*;
-import ext::*;
-export expand_syntax_ext;
-
-fn expand_syntax_ext(&ext_ctxt cx, common::span sp, &vec[@ast::expr] args,
-                     option::t[str] body) -> @ast::expr {
-    if (vec::len[@ast::expr](args) == 0u) {
-        cx.span_fatal(sp, "#fmt requires a format string");
-    }
-    auto fmt = expr_to_str(cx, args.(0), "first argument to #fmt must be a "
-                           + "string literal.");
-    auto fmtspan = args.(0).span;
-    log "Format string:";
-    log fmt;
-    fn parse_fmt_err_(&ext_ctxt cx, common::span sp, str msg) -> ! {
-        cx.span_fatal(sp, msg);
-    }
-    auto parse_fmt_err = bind parse_fmt_err_(cx, fmtspan, _);
-    auto pieces = parse_fmt_string(fmt, parse_fmt_err);
-    ret pieces_to_expr(cx, sp, pieces, args);
-}
-
-// FIXME: A lot of these functions for producing expressions can probably
-// be factored out in common with other code that builds expressions.
-// FIXME: Cleanup the naming of these functions
-fn pieces_to_expr(&ext_ctxt cx, common::span sp, vec[piece] pieces,
-                  vec[@ast::expr] args) -> @ast::expr {
-    fn make_new_lit(&ext_ctxt cx, common::span sp, ast::lit_ lit) ->
-       @ast::expr {
-        auto sp_lit = @rec(node=lit, span=sp);
-        ret @rec(id=cx.next_id(), node=ast::expr_lit(sp_lit), span=sp);
-    }
-    fn make_new_str(&ext_ctxt cx, common::span sp, str s) -> @ast::expr {
-        auto lit = ast::lit_str(s, ast::sk_rc);
-        ret make_new_lit(cx, sp, lit);
-    }
-    fn make_new_int(&ext_ctxt cx, common::span sp, int i) -> @ast::expr {
-        auto lit = ast::lit_int(i);
-        ret make_new_lit(cx, sp, lit);
-    }
-    fn make_new_uint(&ext_ctxt cx, common::span sp, uint u) -> @ast::expr {
-        auto lit = ast::lit_uint(u);
-        ret make_new_lit(cx, sp, lit);
-    }
-    fn make_add_expr(&ext_ctxt cx, common::span sp, @ast::expr lhs,
-                     @ast::expr rhs) -> @ast::expr {
-        auto binexpr = ast::expr_binary(ast::add, lhs, rhs);
-        ret @rec(id=cx.next_id(), node=binexpr, span=sp);
-    }
-    fn make_path_expr(&ext_ctxt cx, common::span sp, vec[ast::ident] idents)
-       -> @ast::expr {
-        let vec[@ast::ty] types = [];
-        auto path = rec(idents=idents, types=types);
-        auto sp_path = rec(node=path, span=sp);
-        auto pathexpr = ast::expr_path(sp_path);
-        ret @rec(id=cx.next_id(), node=pathexpr, span=sp);
-    }
-    fn make_vec_expr(&ext_ctxt cx, common::span sp, vec[@ast::expr] exprs) ->
-       @ast::expr {
-        auto vecexpr = ast::expr_vec(exprs, ast::imm, ast::sk_rc);
-        ret @rec(id=cx.next_id(), node=vecexpr, span=sp);
-    }
-    fn make_call(&ext_ctxt cx, common::span sp, vec[ast::ident] fn_path,
-                 vec[@ast::expr] args) -> @ast::expr {
-        auto pathexpr = make_path_expr(cx, sp, fn_path);
-        auto callexpr = ast::expr_call(pathexpr, args);
-        ret @rec(id=cx.next_id(), node=callexpr, span=sp);
-    }
-    fn make_rec_expr(&ext_ctxt cx, common::span sp,
-                     vec[tup(ast::ident, @ast::expr)] fields) -> @ast::expr {
-        let vec[ast::field] astfields = [];
-        for (tup(ast::ident, @ast::expr) field in fields) {
-            auto ident = field._0;
-            auto val = field._1;
-            auto astfield =
-                rec(node=rec(mut=ast::imm, ident=ident, expr=val), span=sp);
-            astfields += [astfield];
-        }
-        auto recexpr = ast::expr_rec(astfields, option::none[@ast::expr]);
-        ret @rec(id=cx.next_id(), node=recexpr, span=sp);
-    }
-    fn make_path_vec(str ident) -> vec[str] {
-        // FIXME: #fmt can't currently be used from within std
-        // because we're explicitly referencing the 'std' crate here
-
-        ret ["std", "extfmt", "rt", ident];
-    }
-    fn make_rt_path_expr(&ext_ctxt cx, common::span sp, str ident) ->
-       @ast::expr {
-        auto path = make_path_vec(ident);
-        ret make_path_expr(cx, sp, path);
-    }
-    // Produces an AST expression that represents a RT::conv record,
-    // which tells the RT::conv* functions how to perform the conversion
-
-    fn make_rt_conv_expr(&ext_ctxt cx, common::span sp, &conv cnv) ->
-       @ast::expr {
-        fn make_flags(&ext_ctxt cx, common::span sp, vec[flag] flags) ->
-           @ast::expr {
-            let vec[@ast::expr] flagexprs = [];
-            for (flag f in flags) {
-                auto fstr;
-                alt (f) {
-                    case (flag_left_justify) { fstr = "flag_left_justify"; }
-                    case (flag_left_zero_pad) { fstr = "flag_left_zero_pad"; }
-                    case (flag_space_for_sign) {
-                        fstr = "flag_space_for_sign";
-                    }
-                    case (flag_sign_always) { fstr = "flag_sign_always"; }
-                    case (flag_alternate) { fstr = "flag_alternate"; }
-                }
-                flagexprs += [make_rt_path_expr(cx, sp, fstr)];
-            }
-            // FIXME: 0-length vectors can't have their type inferred
-            // through the rec that these flags are a member of, so
-            // this is a hack placeholder flag
-
-            if (vec::len[@ast::expr](flagexprs) == 0u) {
-                flagexprs += [make_rt_path_expr(cx, sp, "flag_none")];
-            }
-            ret make_vec_expr(cx, sp, flagexprs);
-        }
-        fn make_count(&ext_ctxt cx, common::span sp, &count cnt) ->
-           @ast::expr {
-            alt (cnt) {
-                case (count_implied) {
-                    ret make_rt_path_expr(cx, sp, "count_implied");
-                }
-                case (count_is(?c)) {
-                    auto count_lit = make_new_int(cx, sp, c);
-                    auto count_is_path = make_path_vec("count_is");
-                    auto count_is_args = [count_lit];
-                    ret make_call(cx, sp, count_is_path, count_is_args);
-                }
-                case (_) {
-                    cx.span_unimpl(sp, "unimplemented #fmt conversion");
-                }
-            }
-        }
-        fn make_ty(&ext_ctxt cx, common::span sp, &ty t) -> @ast::expr {
-            auto rt_type;
-            alt (t) {
-                case (ty_hex(?c)) {
-                    alt (c) {
-                        case (case_upper) { rt_type = "ty_hex_upper"; }
-                        case (case_lower) { rt_type = "ty_hex_lower"; }
-                    }
-                }
-                case (ty_bits) { rt_type = "ty_bits"; }
-                case (ty_octal) { rt_type = "ty_octal"; }
-                case (_) { rt_type = "ty_default"; }
-            }
-            ret make_rt_path_expr(cx, sp, rt_type);
-        }
-        fn make_conv_rec(&ext_ctxt cx, common::span sp, @ast::expr flags_expr,
-                         @ast::expr width_expr, @ast::expr precision_expr,
-                         @ast::expr ty_expr) -> @ast::expr {
-            ret make_rec_expr(cx, sp,
-                              [tup("flags", flags_expr),
-                               tup("width", width_expr),
-                               tup("precision", precision_expr),
-                               tup("ty", ty_expr)]);
-        }
-        auto rt_conv_flags = make_flags(cx, sp, cnv.flags);
-        auto rt_conv_width = make_count(cx, sp, cnv.width);
-        auto rt_conv_precision = make_count(cx, sp, cnv.precision);
-        auto rt_conv_ty = make_ty(cx, sp, cnv.ty);
-        ret make_conv_rec(cx, sp, rt_conv_flags, rt_conv_width,
-                          rt_conv_precision, rt_conv_ty);
-    }
-    fn make_conv_call(&ext_ctxt cx, common::span sp, str conv_type, &conv cnv,
-                      @ast::expr arg) -> @ast::expr {
-        auto fname = "conv_" + conv_type;
-        auto path = make_path_vec(fname);
-        auto cnv_expr = make_rt_conv_expr(cx, sp, cnv);
-        auto args = [cnv_expr, arg];
-        ret make_call(cx, arg.span, path, args);
-    }
-    fn make_new_conv(&ext_ctxt cx, common::span sp, conv cnv, @ast::expr arg)
-       -> @ast::expr {
-        // FIXME: Extract all this validation into extfmt::ct
-
-        fn is_signed_type(conv cnv) -> bool {
-            alt (cnv.ty) {
-                case (ty_int(?s)) {
-                    alt (s) {
-                        case (signed) { ret true; }
-                        case (unsigned) { ret false; }
-                    }
-                }
-                case (_) { ret false; }
-            }
-        }
-        auto unsupported = "conversion not supported in #fmt string";
-        alt (cnv.param) {
-            case (option::none) { }
-            case (_) { cx.span_unimpl(sp, unsupported); }
-        }
-        for (flag f in cnv.flags) {
-            alt (f) {
-                case (flag_left_justify) { }
-                case (flag_sign_always) {
-                    if (!is_signed_type(cnv)) {
-                        cx.span_fatal(sp,
-                                    "+ flag only valid in " +
-                                        "signed #fmt conversion");
-                    }
-                }
-                case (flag_space_for_sign) {
-                    if (!is_signed_type(cnv)) {
-                        cx.span_fatal(sp,
-                                    "space flag only valid in " +
-                                        "signed #fmt conversions");
-                    }
-                }
-                case (flag_left_zero_pad) { }
-                case (_) { cx.span_unimpl(sp, unsupported); }
-            }
-        }
-        alt (cnv.width) {
-            case (count_implied) { }
-            case (count_is(_)) { }
-            case (_) { cx.span_unimpl(sp, unsupported); }
-        }
-        alt (cnv.precision) {
-            case (count_implied) { }
-            case (count_is(_)) { }
-            case (_) { cx.span_unimpl(sp, unsupported); }
-        }
-        alt (cnv.ty) {
-            case (ty_str) {
-                ret make_conv_call(cx, arg.span, "str", cnv, arg);
-            }
-            case (ty_int(?sign)) {
-                alt (sign) {
-                    case (signed) {
-                        ret make_conv_call(cx, arg.span, "int", cnv, arg);
-                    }
-                    case (unsigned) {
-                        ret make_conv_call(cx, arg.span, "uint", cnv, arg);
-                    }
-                }
-            }
-            case (ty_bool) {
-                ret make_conv_call(cx, arg.span, "bool", cnv, arg);
-            }
-            case (ty_char) {
-                ret make_conv_call(cx, arg.span, "char", cnv, arg);
-            }
-            case (ty_hex(_)) {
-                ret make_conv_call(cx, arg.span, "uint", cnv, arg);
-            }
-            case (ty_bits) {
-                ret make_conv_call(cx, arg.span, "uint", cnv, arg);
-            }
-            case (ty_octal) {
-                ret make_conv_call(cx, arg.span, "uint", cnv, arg);
-            }
-            case (_) { cx.span_unimpl(sp, unsupported); }
-        }
-    }
-    fn log_conv(conv c) {
-        alt (c.param) {
-            case (some(?p)) { log "param: " + std::int::to_str(p, 10u); }
-            case (_) { log "param: none"; }
-        }
-        for (flag f in c.flags) {
-            alt (f) {
-                case (flag_left_justify) { log "flag: left justify"; }
-                case (flag_left_zero_pad) { log "flag: left zero pad"; }
-                case (flag_space_for_sign) { log "flag: left space pad"; }
-                case (flag_sign_always) { log "flag: sign always"; }
-                case (flag_alternate) { log "flag: alternate"; }
-            }
-        }
-        alt (c.width) {
-            case (count_is(?i)) {
-                log "width: count is " + std::int::to_str(i, 10u);
-            }
-            case (count_is_param(?i)) {
-                log "width: count is param " + std::int::to_str(i, 10u);
-            }
-            case (count_is_next_param) { log "width: count is next param"; }
-            case (count_implied) { log "width: count is implied"; }
-        }
-        alt (c.precision) {
-            case (count_is(?i)) {
-                log "prec: count is " + std::int::to_str(i, 10u);
-            }
-            case (count_is_param(?i)) {
-                log "prec: count is param " + std::int::to_str(i, 10u);
-            }
-            case (count_is_next_param) { log "prec: count is next param"; }
-            case (count_implied) { log "prec: count is implied"; }
-        }
-        alt (c.ty) {
-            case (ty_bool) { log "type: bool"; }
-            case (ty_str) { log "type: str"; }
-            case (ty_char) { log "type: char"; }
-            case (ty_int(?s)) {
-                alt (s) {
-                    case (signed) { log "type: signed"; }
-                    case (unsigned) { log "type: unsigned"; }
-                }
-            }
-            case (ty_bits) { log "type: bits"; }
-            case (ty_hex(?cs)) {
-                alt (cs) {
-                    case (case_upper) { log "type: uhex"; }
-                    case (case_lower) { log "type: lhex"; }
-                }
-            }
-            case (ty_octal) { log "type: octal"; }
-        }
-    }
-    auto fmt_sp = args.(0).span;
-    auto n = 0u;
-    auto tmp_expr = make_new_str(cx, sp, "");
-    auto nargs = vec::len[@ast::expr](args);
-    for (piece pc in pieces) {
-        alt (pc) {
-            case (piece_string(?s)) {
-                auto s_expr = make_new_str(cx, fmt_sp, s);
-                tmp_expr = make_add_expr(cx, fmt_sp, tmp_expr, s_expr);
-            }
-            case (piece_conv(?conv)) {
-                n += 1u;
-                if (n >= nargs) {
-                    cx.span_fatal(sp,
-                                "not enough arguments to #fmt " +
-                                    "for the given format string");
-                }
-                log "Building conversion:";
-                log_conv(conv);
-                auto arg_expr = args.(n);
-                auto c_expr = make_new_conv(cx, fmt_sp, conv, arg_expr);
-                tmp_expr = make_add_expr(cx, fmt_sp, tmp_expr, c_expr);
-            }
-        }
-    }
-    auto expected_nargs = n + 1u; // n conversions + the fmt string
-
-    if (expected_nargs < nargs) {
-        cx.span_fatal(sp,
-                    #fmt("too many arguments to #fmt. found %u, expected %u",
-                         nargs, expected_nargs));
-    }
-    ret tmp_expr;
-}
-//
-// 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/front/extsimplext.rs b/src/comp/front/extsimplext.rs
deleted file mode 100644 (file)
index 3de737f..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-use std;
-
-import util::common::span;
-import std::vec;
-import std::option;
-import vec::map;
-import vec::len;
-import option::some;
-import option::none;
-
-import ext::syntax_extension;
-import ext::ext_ctxt;
-import ext::normal;
-import ext::expr_to_str;
-import ext::expr_to_ident;
-
-import fold::*;
-import ast::ident;
-import ast::path_;
-import ast::expr_path;
-
-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;
-    }
-    ret none[uint];
-}
-
-// substitute, in a position that's required to be an ident
-fn subst_ident(&ext_ctxt cx, &vec[@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.");
-        }
-        case (none[uint]) {
-            ret i;
-        }
-    }
-}
-
-fn subst_path(&ext_ctxt cx, &vec[@ast::expr] args, 
-              @vec[ident] param_names, &path_ p, ast_fold fld) -> path_ {
-    // Don't substitute into qualified names.
-    if (len(p.types) > 0u || 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.");
-                }
-            }
-        }
-        case (none[uint]) { ret p; }
-    }
-}
-
-
-fn subst_expr(&ext_ctxt cx, &vec[@ast::expr] args, @vec[ident] param_names, 
-              &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 (len(p.node.types) > 0u || len(p.node.idents) != 1u) { e }
-            alt (position(p.node.idents.(0), *param_names)) {
-                case (some[uint](?idx)) {
-                    args.(idx).node
-                }
-                case (none[uint]) { e }
-            }
-        }
-        case (_) { orig(e,fld) }
-    }
-}
-
-
-fn add_new_extension(&ext_ctxt cx, span sp, &vec[@ast::expr] args,
-                     option::t[str] body) -> tup(str, syntax_extension) {
-    if (len(args) < 2u) {
-        cx.span_fatal(sp, "malformed extension description");
-    }
-
-    fn generic_extension(&ext_ctxt cx, span sp, &vec[@ast::expr] args,
-                         option::t[str] body, @vec[ident] param_names,
-                         @ast::expr dest_form) -> @ast::expr {
-        if (len(args) != len(*param_names)) {
-            cx.span_fatal(sp, #fmt("extension expects %u arguments, got %u",
-                                 len(*param_names), len(args)));
-        }
-
-        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)
-                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 < len(args)) {
-        param_names +=
-            [expr_to_ident(cx, args.(idx),
-                           "this parameter name must be an identifier.")];
-        idx += 1u;
-    }
-
-    ret tup(expr_to_str(cx, args.(0), "first arg must be a literal string."),
-            normal(bind generic_extension(_,_,_,_,@param_names,
-                                          args.(len(args)-1u))));
-}
-
-
-
-//
-// 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/front/fold.rs b/src/comp/front/fold.rs
deleted file mode 100644 (file)
index 0fc884d..0000000
+++ /dev/null
@@ -1,708 +0,0 @@
-import util::common::span;
-import ast::*;
-
-import std::vec;
-import std::option;
-import vec::map;
-
-export ast_fold_precursor;
-export ast_fold;
-export default_ast_fold;
-export make_fold;
-export dummy_out;
-
-type ast_fold = @mutable a_f;
-
-// We may eventually want to be able to fold over type parameters, too
-
-type ast_fold_precursor = 
-    rec(fn (&crate_ c, ast_fold) -> crate_                fold_crate,
-        fn (&crate_directive_ cd, ast_fold) -> crate_directive_ 
-                                                 fold_crate_directive,
-        fn (&view_item_ i, ast_fold) -> view_item_        fold_view_item,
-        fn (&@native_item i, ast_fold) -> @native_item    fold_native_item,
-        fn (&@item i, ast_fold) -> @item                  fold_item,
-        //unlike the others, item_ is non-trivial
-        fn (&item_ i, ast_fold) -> item_        fold_item_underscore,
-        fn (&method_ m, ast_fold) -> method_              fold_method,
-        fn (&block_ b, ast_fold) -> block_                fold_block,
-        fn (&stmt_ s, ast_fold) -> stmt_                  fold_stmt,
-        fn (&arm a, ast_fold) -> arm                      fold_arm,
-        fn (&pat_ p, ast_fold) -> pat_                    fold_pat,
-        fn (&decl_ d, ast_fold) -> decl_                  fold_decl,
-        fn (&expr_ e, ast_fold) -> expr_                  fold_expr,
-        fn (&ty_ t, ast_fold) -> ty_                      fold_ty,
-        fn (&constr_ c, ast_fold) -> constr_              fold_constr,
-        fn (&_fn f, ast_fold) -> _fn                      fold_fn,
-        fn (&_mod m, ast_fold) -> _mod                    fold_mod,
-        fn (&native_mod, ast_fold) -> native_mod          fold_native_mod,
-        fn (&variant_, ast_fold) -> variant_              fold_variant,
-        fn (&ident, ast_fold) -> ident                    fold_ident,
-        fn (&path_, ast_fold) -> path_                    fold_path,
-        fn (&local_, ast_fold) -> local_                  fold_local
-        );
-
-type a_f =
-    rec(fn (&crate c) -> crate                        fold_crate,
-        fn (&@crate_directive cd) -> @crate_directive fold_crate_directive,
-        fn (&@view_item i) -> @view_item              fold_view_item,
-        fn (&@native_item i) -> @native_item          fold_native_item,
-        fn (&@item i) -> @item                        fold_item,
-        fn (&item_ i) -> item_                        fold_item_underscore,
-        fn (&@method m) -> @method                    fold_method,
-        fn (&block b) -> block                        fold_block,
-        fn (&@stmt s) -> @stmt                        fold_stmt,
-        fn (&arm a) -> arm                            fold_arm,
-        fn (&@pat p) -> @pat                          fold_pat,
-        fn (&@decl d) -> @decl                        fold_decl,
-        fn (&@expr e) -> @expr                        fold_expr,
-        fn (&@ty t) -> @ty                            fold_ty,
-        fn (&@constr c) -> @constr                    fold_constr,
-        fn (&_fn f) -> _fn                            fold_fn,
-        fn (&_mod m) -> _mod                          fold_mod,
-        fn (&native_mod) -> native_mod                fold_native_mod,
-        fn (&variant) -> variant                      fold_variant,
-        fn (&ident) -> ident                          fold_ident,
-        fn (&path) -> path                            fold_path,
-        fn (&@local) -> @local                        fold_local
-        );
-
-//fn nf_dummy[T](&T node) -> T { fail; }
-fn nf_crate_dummy(&crate c) -> crate { fail; }
-fn nf_crate_directive_dummy(&@crate_directive c) 
-    -> @crate_directive { fail; }
-fn nf_view_item_dummy(&@view_item v) -> @view_item { fail; } 
-fn nf_native_item_dummy(&@native_item n) -> @native_item { fail; } 
-fn nf_item_dummy(&@item i) -> @item { fail; } 
-fn nf_item_underscore_dummy(&item_ i) -> item_ { fail; } 
-fn nf_method_dummy(&@method m) -> @method { fail; } 
-fn nf_block_dummy(&block b) -> block { fail; } 
-fn nf_stmt_dummy(&@stmt s) -> @stmt { fail; } 
-fn nf_arm_dummy(&arm a) -> arm { fail; } 
-fn nf_pat_dummy(&@pat p) -> @pat { fail; } 
-fn nf_decl_dummy(&@decl d) -> @decl { fail; } 
-fn nf_expr_dummy(&@expr e) -> @expr { fail; } 
-fn nf_ty_dummy(&@ty t) -> @ty { fail; } 
-fn nf_constr_dummy(&@constr c) -> @constr { fail; } 
-fn nf_fn_dummy(&_fn f) -> _fn { fail; } 
-fn nf_mod_dummy(&_mod m) -> _mod { fail; } 
-fn nf_native_mod_dummy(&native_mod n) -> native_mod { fail; } 
-fn nf_variant_dummy(&variant v) -> variant { fail; } 
-fn nf_ident_dummy(&ident i) -> ident { fail; } 
-fn nf_path_dummy(&path p) -> path { fail; } 
-fn nf_obj_field_dummy(&obj_field o) -> obj_field { fail; }
-fn nf_local_dummy(&@local o) -> @local { fail; }
-
-/* some little folds that probably aren't useful to have in ast_fold itself*/
-
-//used in noop_fold_item and noop_fold_crate and noop_fold_crate_directive
-fn fold_meta_item_(&@meta_item mi, ast_fold fld) -> @meta_item {
-    ret @rec(node=
-             alt (mi.node) {
-                 case (meta_word(?id)) { meta_word(fld.fold_ident(id)) }
-                 case (meta_list(?id, ?mis)) {
-                     auto fold_meta_item = bind fold_meta_item_(_,fld);
-                     meta_list(id, map(fold_meta_item, mis))
-                 }
-                 case (meta_name_value(?id,?s)) {
-                     meta_name_value(fld.fold_ident(id),s)
-                 }
-             },
-             span=mi.span);
-}
-//used in noop_fold_item and noop_fold_crate
-fn fold_attribute_(&attribute at, fn(&@meta_item) -> @meta_item fmi) 
-    -> attribute {
-    ret rec(node=rec(style=at.node.style,
-                     value=*fmi(@at.node.value)),
-            span=at.span);
-}
-//used in noop_fold_native_item and noop_fold_fn
-fn fold_arg_(&arg a, ast_fold fld) -> arg {
-    ret rec(mode=a.mode, ty=fld.fold_ty(a.ty), 
-            ident=fld.fold_ident(a.ident), id=a.id);
-}
-
-
-
-
-fn noop_fold_crate(&crate_ c, ast_fold fld) -> crate_ {
-    auto fold_meta_item = bind fold_meta_item_(_,fld);
-    auto fold_attribute = bind fold_attribute_(_,fold_meta_item);
-
-    ret rec(directives=map(fld.fold_crate_directive, c.directives),
-            module=fld.fold_mod(c.module),
-            attrs=map(fold_attribute, c.attrs),
-            config=map(fold_meta_item, c.config));
-}
-
-fn noop_fold_crate_directive(&crate_directive_ cd, ast_fold fld) 
-    -> crate_directive_ {
-    ret alt(cd) {
-        case(cdir_src_mod(?id,?fname,?attrs)) { 
-            cdir_src_mod(fld.fold_ident(id), fname, attrs)
-                }
-        case(cdir_dir_mod(?id,?fname,?cds,?attrs)) {
-            cdir_dir_mod(fld.fold_ident(id),fname,
-                         map(fld.fold_crate_directive, cds), attrs)
-                }
-        case(cdir_view_item(?vi)) { 
-            cdir_view_item(fld.fold_view_item(vi))
-                }
-        case(cdir_syntax(_)) { cd }
-        case(cdir_auth(_,_)) { cd }
-    }
-}
-
-fn noop_fold_view_item(&view_item_ vi, ast_fold fld) -> view_item_ {
-    ret vi;
-}
-
-
-fn noop_fold_native_item(&@native_item ni, ast_fold fld) -> @native_item {
-    auto fold_arg = bind fold_arg_(_, fld);
-
-    ret @rec(ident=fld.fold_ident(ni.ident),
-             node=alt (ni.node) {
-                 case (native_item_ty) { native_item_ty }
-                 case (native_item_fn(?st, ?fdec, ?typms)) {
-                     native_item_fn(st, 
-                                    rec(inputs=map(fold_arg, fdec.inputs),
-                                        output=fld.fold_ty(fdec.output),
-                                        purity=fdec.purity, cf=fdec.cf,
-                                        constraints=map(fld.fold_constr,
-                                                        fdec.constraints)),
-                                    typms)
-                 }
-             },
-             id=ni.id,
-             span=ni.span);
-}
-
-fn noop_fold_item(&@item i, ast_fold fld) -> @item {
-    auto fold_meta_item = bind fold_meta_item_(_,fld);
-    auto fold_attribute = bind fold_attribute_(_,fold_meta_item);
-
-    ret @rec(ident=fld.fold_ident(i.ident),
-             attrs=map(fold_attribute,i.attrs),
-             id=i.id, node=fld.fold_item_underscore(i.node),
-             span=i.span);
-}
-
-fn noop_fold_item_underscore(&item_ i, ast_fold fld) -> item_ {
-    fn fold_obj_field_(&obj_field of, ast_fold fld) -> obj_field {
-        ret rec(mut=of.mut, ty=fld.fold_ty(of.ty), 
-                ident=fld.fold_ident(of.ident), id=of.id);
-    }
-    auto fold_obj_field = bind fold_obj_field_(_,fld);
-
-    ret alt(i) {
-        case (item_const(?t, ?e)) {
-            item_const(fld.fold_ty(t), fld.fold_expr(e))
-        }
-        case (item_fn(?f, ?typms)) {
-            item_fn(fld.fold_fn(f), typms)
-        }
-        case (item_mod(?m)) { item_mod(fld.fold_mod(m)) }
-        case (item_native_mod(?nm)) {
-            item_native_mod(fld.fold_native_mod(nm))
-                }
-        case (item_ty(?t, ?typms)) {
-            item_ty(fld.fold_ty(t), typms)
-                }
-        case (item_tag(?variants, ?typms)) {
-            item_tag(map(fld.fold_variant, variants), typms)
-                }
-        case (item_obj(?o, ?typms, ?d)) {
-            item_obj(rec(fields=map(fold_obj_field,o.fields),
-                         methods=map(fld.fold_method,o.methods),
-                         dtor=option::map(fld.fold_method,o.dtor)),
-                     typms, d)
-                }
-        case (item_res(?dtor, ?did, ?typms, ?cid)) {
-            item_res(fld.fold_fn(dtor), did, typms, cid)
-        }
-    };
-}
-
-fn noop_fold_method(&method_ m, ast_fold fld) -> method_ {
-    ret rec(ident=fld.fold_ident(m.ident),
-            meth=fld.fold_fn(m.meth), id=m.id); 
-}
-
-
-fn noop_fold_block(&block_ b, ast_fold fld) -> block_ {
-    ret rec(stmts=map(fld.fold_stmt, b.stmts),
-            expr=option::map(fld.fold_expr, b.expr), id=b.id);
-}
-
-fn noop_fold_stmt(&stmt_ s, ast_fold fld) -> stmt_ {
-    ret alt(s) {
-        case (stmt_decl(?d, ?nid)) { stmt_decl(fld.fold_decl(d), nid) }
-        case (stmt_expr(?e, ?nid)) { stmt_expr(fld.fold_expr(e), nid) }
-        case (stmt_crate_directive(?cd)) {
-                stmt_crate_directive(fld.fold_crate_directive(cd))
-                    }
-    };
-}
-
-fn noop_fold_arm(&arm a, ast_fold fld) -> arm {
-    ret rec(pat=fld.fold_pat(a.pat), block=fld.fold_block(a.block));
-}
-
-fn noop_fold_pat(&pat_ p, ast_fold fld) -> pat_ {
-    ret alt (p) {
-        case (pat_wild) { p }
-        case (pat_bind(?ident)) { pat_bind(fld.fold_ident(ident))}
-        case (pat_lit(_)) { p }
-        case (pat_tag(?pth, ?pats)) {
-            pat_tag(fld.fold_path(pth), map(fld.fold_pat, pats))
-        }
-    };
-}
-
-fn noop_fold_decl(&decl_ d, ast_fold fld) -> decl_ {
-    ret alt (d) {
-        // local really doesn't need its own fold...
-        case (decl_local(?l)) {
-            decl_local(fld.fold_local(l))
-        }
-        case (decl_item(?it)) { decl_item(fld.fold_item(it)) }
-    }
-}
-
-fn noop_fold_expr(&expr_ e, ast_fold fld) -> expr_ {
-    fn fold_elt_(&elt elt, ast_fold fld) -> elt {
-        ret rec(mut=elt.mut, expr=fld.fold_expr(elt.expr));
-    }
-    auto fold_elt = bind fold_elt_(_,fld);
-    fn fold_field_(&field field, ast_fold fld) -> field {
-        ret rec(node=rec(mut=field.node.mut,
-                         ident=fld.fold_ident(field.node.ident),
-                         expr=fld.fold_expr(field.node.expr)),
-                span=field.span);
-    }
-    auto fold_field = bind fold_field_(_,fld);
-    fn fold_anon_obj_(&anon_obj ao, ast_fold fld) -> anon_obj {
-        fn fold_anon_obj_field_(&anon_obj_field aof, ast_fold fld) 
-            -> anon_obj_field {
-            ret rec(mut=aof.mut, ty=fld.fold_ty(aof.ty), 
-                    expr=fld.fold_expr(aof.expr),
-                    ident=fld.fold_ident(aof.ident), id=aof.id);
-        }
-        auto fold_anon_obj_field = bind fold_anon_obj_field_(_,fld);
-
-        ret rec(fields=alt(ao.fields) {
-                    case (option::none[vec[anon_obj_field]]) { ao.fields }
-                    case (option::some[vec[anon_obj_field]](?v)) {
-                        option::some[vec[anon_obj_field]]
-                            (map(fold_anon_obj_field, v))
-                    }},
-                methods=map(fld.fold_method, ao.methods),
-                with_obj=option::map(fld.fold_expr, ao.with_obj))
-    }
-    auto fold_anon_obj = bind fold_anon_obj_(_,fld);
-    
-
-    ret alt (e) {
-        case (expr_vec(?exprs, ?mut, ?seq_kind)) {
-            expr_vec(map(fld.fold_expr, exprs), mut, seq_kind)
-                }
-        case (expr_tup(?elts)) {
-            expr_tup(map(fold_elt, elts))
-                }
-        case (expr_rec(?fields, ?maybe_expr)) {
-            expr_rec(map(fold_field, fields),
-                     option::map(fld.fold_expr, maybe_expr))
-                }
-        case (expr_call(?f, ?args)) {
-            expr_call(fld.fold_expr(f), map(fld.fold_expr, args))
-                }
-        case (expr_self_method(?id)) {
-            expr_self_method(fld.fold_ident(id))
-                }
-        case (expr_bind(?f, ?args)) {
-            auto opt_map_se = bind option::map(fld.fold_expr,_);
-            expr_bind(fld.fold_expr(f), map(opt_map_se, args))
-                }
-        case (expr_spawn(?spawn_dom, ?name, ?f, ?args)) {
-            expr_spawn(spawn_dom, name, fld.fold_expr(f), 
-                       map(fld.fold_expr, args))
-                }
-        case (expr_binary(?binop, ?lhs, ?rhs)) {
-            expr_binary(binop, fld.fold_expr(lhs), fld.fold_expr(rhs))
-                }
-        case (expr_unary(?binop, ?ohs)) {
-            expr_unary(binop, fld.fold_expr(ohs))
-                }
-        case (expr_lit(_)) { e }
-        case (expr_cast(?expr, ?ty)) {
-            expr_cast(fld.fold_expr(expr), ty)
-        }
-        case (expr_if(?cond, ?tr, ?fl)) {
-            expr_if(fld.fold_expr(cond), fld.fold_block(tr), 
-                    option::map(fld.fold_expr, fl))
-                }
-        case (expr_ternary(?cond, ?tr, ?fl)) {
-            expr_ternary(fld.fold_expr(cond),
-                         fld.fold_expr(tr),
-                         fld.fold_expr(fl))
-                }
-        case (expr_while(?cond, ?body)) {
-            expr_while(fld.fold_expr(cond), fld.fold_block(body))
-                }
-        case (expr_for(?decl, ?expr, ?block)) {
-            expr_for(fld.fold_local(decl), fld.fold_expr(expr), 
-                     fld.fold_block(block))
-                }
-        case (expr_for_each(?decl, ?expr, ?block)) {
-            expr_for_each(fld.fold_local(decl), fld.fold_expr(expr), 
-                          fld.fold_block(block))
-                }
-        case (expr_do_while(?block, ?expr)) {
-            expr_do_while(fld.fold_block(block), fld.fold_expr(expr))
-                }
-        case (expr_alt(?expr, ?arms)) {
-            expr_alt(fld.fold_expr(expr), map(fld.fold_arm, arms))
-                }
-        case (expr_fn(?f)) {
-            expr_fn(fld.fold_fn(f))
-                }
-        case (expr_block(?block)) {
-            expr_block(fld.fold_block(block))
-                }
-        case (expr_move(?el, ?er)) {
-            expr_move(fld.fold_expr(el), fld.fold_expr(er))
-                }
-        case (expr_assign(?el, ?er)) {
-            expr_assign(fld.fold_expr(el), fld.fold_expr(er))
-                }
-        case (expr_swap(?el, ?er)) {
-            expr_swap(fld.fold_expr(el), fld.fold_expr(er))
-                }
-        case (expr_assign_op(?op, ?el, ?er)) {
-            expr_assign_op(op, fld.fold_expr(el), fld.fold_expr(er))
-                }
-        case (expr_send(?el, ?er)) {
-            expr_send(fld.fold_expr(el), fld.fold_expr(er))
-                }
-        case (expr_recv(?el, ?er)) {
-            expr_recv(fld.fold_expr(el), fld.fold_expr(er))
-                }
-        case (expr_field(?el, ?id)) {
-            expr_field(fld.fold_expr(el), fld.fold_ident(id))
-                }
-        case (expr_index(?el, ?er)) {
-            expr_index(fld.fold_expr(el), fld.fold_expr(er))
-                }
-        case (expr_path(?pth)) {
-            expr_path(fld.fold_path(pth))
-                }
-        case (expr_ext(?pth, ?args, ?body, ?expanded)) {
-            expr_ext(fld.fold_path(pth), map(fld.fold_expr, args),
-                     body, fld.fold_expr(expanded))
-                }
-        case (expr_fail(_)) { e }
-        case (expr_break()) { e }
-        case (expr_cont()) { e }
-        case (expr_ret(?e)) { 
-            expr_ret(option::map(fld.fold_expr, e))
-                }
-        case (expr_put(?e)) { 
-            expr_put(option::map(fld.fold_expr, e))
-                }
-        case (expr_be(?e)) { expr_be(fld.fold_expr(e)) }
-        case (expr_log(?lv, ?e)) { expr_log(lv, fld.fold_expr(e)) }
-        case (expr_assert(?e)) { expr_assert(fld.fold_expr(e)) }
-        case (expr_check(?m, ?e)) { expr_check(m, fld.fold_expr(e)) }
-        case (expr_if_check(?cond, ?tr, ?fl)) {
-            expr_if_check(fld.fold_expr(cond), fld.fold_block(tr), 
-                          option::map(fld.fold_expr, fl))
-                }
-        case (expr_port(?ot)) { 
-            expr_port(alt(ot) {
-                    case (option::some(?t)) { option::some(fld.fold_ty(t)) }
-                    case (option::none) { option::none }
-                })
-                }
-        case (expr_chan(?e)) { expr_chan(fld.fold_expr(e)) }
-        case (expr_anon_obj(?ao, ?typms, ?odis)) {
-            expr_anon_obj(fold_anon_obj(ao), typms, odis)
-                }
-    }
-}
-
-fn noop_fold_ty(&ty_ t, ast_fold fld) -> ty_ {
-    //drop in ty::fold_ty here if necessary
-    ret t;
-}
-
-fn noop_fold_constr(&constr_ c, ast_fold fld) -> constr_ {
-    ret rec(path=fld.fold_path(c.path), args=c.args, id=c.id);
-}
-
-// functions just don't get spans, for some reason
-fn noop_fold_fn(&_fn f, ast_fold fld) -> _fn {
-    auto fold_arg = bind fold_arg_(_, fld);
-
-    ret rec(decl= rec(inputs=map(fold_arg, f.decl.inputs),
-                      output=fld.fold_ty(f.decl.output),
-                      purity=f.decl.purity,
-                      cf=f.decl.cf,
-                      constraints=map(fld.fold_constr, f.decl.constraints)),
-            proto = f.proto,
-            body = fld.fold_block(f.body));
-}
-
-// ...nor do modules
-fn noop_fold_mod(&_mod m, ast_fold fld) -> _mod {
-    ret rec(view_items=map(fld.fold_view_item, m.view_items),
-            items=map(fld.fold_item, m.items));
-}
-
-fn noop_fold_native_mod(&native_mod nm, ast_fold fld) -> native_mod {
-    ret rec(native_name=nm.native_name,
-            abi=nm.abi,
-            view_items=map(fld.fold_view_item, nm.view_items),
-            items=map(fld.fold_native_item, nm.items))
-}
-
-fn noop_fold_variant(&variant_ v, ast_fold fld) -> variant_ {
-    fn fold_variant_arg_(&variant_arg va, ast_fold fld) -> variant_arg {
-        ret rec(ty=fld.fold_ty(va.ty), id=va.id);
-    }
-    auto fold_variant_arg = bind fold_variant_arg_(_,fld);
-    ret rec(name=v.name,
-            args=map(fold_variant_arg, v.args),
-            id=v.id);
-}
-
-fn noop_fold_ident(&ident i, ast_fold fld) -> ident {
-    ret i;
-}
-
-fn noop_fold_path(&path_ p, ast_fold fld) -> path_ {
-    ret rec(idents=map(fld.fold_ident, p.idents),
-            types=map(fld.fold_ty, p.types));
-}
-
-fn noop_fold_local(&local_ l, ast_fold fld) -> local_ {
-    ret rec(ty=option::map(fld.fold_ty,l.ty),
-            infer=l.infer,
-            ident=fld.fold_ident(l.ident),
-            init=alt (l.init) {
-                case (option::none[initializer]) { l.init }
-                case (option::some[initializer](?init)) {
-                    option::some[initializer]
-                    (rec(op=init.op, 
-                         expr=fld.fold_expr(init.expr)))
-                }
-            },
-            id=l.id);
-}
-
-
-fn default_ast_fold() -> @ast_fold_precursor {
-    ret @rec(fold_crate = noop_fold_crate,
-             fold_crate_directive = noop_fold_crate_directive,
-             fold_view_item = noop_fold_view_item,
-             fold_native_item = noop_fold_native_item,
-             fold_item = noop_fold_item,
-             fold_item_underscore = noop_fold_item_underscore,
-             fold_method = noop_fold_method,
-             fold_block = noop_fold_block,
-             fold_stmt = noop_fold_stmt,
-             fold_arm = noop_fold_arm,
-             fold_pat = noop_fold_pat,
-             fold_decl = noop_fold_decl,
-             fold_expr = noop_fold_expr,
-             fold_ty = noop_fold_ty,
-             fold_constr = noop_fold_constr,
-             fold_fn = noop_fold_fn,
-             fold_mod = noop_fold_mod,
-             fold_native_mod = noop_fold_native_mod,
-             fold_variant = noop_fold_variant,
-             fold_ident = noop_fold_ident,
-             fold_path = noop_fold_path,
-             fold_local = noop_fold_local);
-}
-
-fn dummy_out(ast_fold a) {
-    *a = rec(fold_crate = nf_crate_dummy,
-                     fold_crate_directive = nf_crate_directive_dummy,
-                     fold_view_item = nf_view_item_dummy,
-                     fold_native_item = nf_native_item_dummy,
-                     fold_item = nf_item_dummy,
-                     fold_item_underscore = nf_item_underscore_dummy,
-                     fold_method = nf_method_dummy,
-                     fold_block = nf_block_dummy,
-                     fold_stmt = nf_stmt_dummy,
-                     fold_arm = nf_arm_dummy,
-                     fold_pat = nf_pat_dummy,
-                     fold_decl = nf_decl_dummy,
-                     fold_expr = nf_expr_dummy,
-                     fold_ty = nf_ty_dummy,
-                     fold_constr = nf_constr_dummy,
-                     fold_fn = nf_fn_dummy,
-                     fold_mod = nf_mod_dummy,
-                     fold_native_mod = nf_native_mod_dummy,
-                     fold_variant = nf_variant_dummy,
-                     fold_ident = nf_ident_dummy,
-                     fold_path = nf_path_dummy,
-                     fold_local = nf_local_dummy);
-}
-
-
-fn make_fold(&ast_fold_precursor afp) -> ast_fold {
-    let ast_fold result = 
-        @mutable rec(fold_crate = nf_crate_dummy,
-                     fold_crate_directive = nf_crate_directive_dummy,
-                     fold_view_item = nf_view_item_dummy,
-                     fold_native_item = nf_native_item_dummy,
-                     fold_item = nf_item_dummy,
-                     fold_item_underscore = nf_item_underscore_dummy,
-                     fold_method = nf_method_dummy,
-                     fold_block = nf_block_dummy,
-                     fold_stmt = nf_stmt_dummy,
-                     fold_arm = nf_arm_dummy,
-                     fold_pat = nf_pat_dummy,
-                     fold_decl = nf_decl_dummy,
-                     fold_expr = nf_expr_dummy,
-                     fold_ty = nf_ty_dummy,
-                     fold_constr = nf_constr_dummy,
-                     fold_fn = nf_fn_dummy,
-                     fold_mod = nf_mod_dummy,
-                     fold_native_mod = nf_native_mod_dummy,
-                     fold_variant = nf_variant_dummy,
-                     fold_ident = nf_ident_dummy,
-                     fold_path = nf_path_dummy,
-                     fold_local = nf_local_dummy);
-
-    /* naturally, a macro to write these would be nice */
-    fn f_crate(&ast_fold_precursor afp, ast_fold f, &crate c) -> crate {
-        ret rec(node=afp.fold_crate(c.node, f),
-                span=c.span);
-    }
-    fn f_crate_directive(&ast_fold_precursor afp, ast_fold f, 
-                         &@crate_directive c) -> @crate_directive {
-        ret @rec(node=afp.fold_crate_directive(c.node, f),
-                 span=c.span);
-    }
-    fn f_view_item(&ast_fold_precursor afp, ast_fold f, &@view_item x)
-        -> @view_item {
-        ret @rec(node=afp.fold_view_item(x.node, f), span=x.span);
-    }
-    fn f_native_item(&ast_fold_precursor afp, ast_fold f, &@native_item x)
-        -> @native_item {
-        ret afp.fold_native_item(x, f);
-    }
-    fn f_item(&ast_fold_precursor afp, ast_fold f, &@item i) -> @item {
-        ret afp.fold_item(i, f);
-    }
-    fn f_item_underscore(&ast_fold_precursor afp, ast_fold f, &item_ i) ->
-        item_ {
-        ret afp.fold_item_underscore(i, f);
-    }
-    fn f_method(&ast_fold_precursor afp, ast_fold f, &@method x) -> @method {
-        ret @rec(node=afp.fold_method(x.node, f), span=x.span);
-    }
-    fn f_block(&ast_fold_precursor afp, ast_fold f, &block x) -> block {
-        ret rec(node=afp.fold_block(x.node, f), span=x.span);
-    }
-    fn f_stmt(&ast_fold_precursor afp, ast_fold f, &@stmt x) -> @stmt {
-        ret @rec(node=afp.fold_stmt(x.node, f), span=x.span);
-    }
-    fn f_arm(&ast_fold_precursor afp, ast_fold f, &arm x) -> arm {
-        ret afp.fold_arm(x, f);
-    }
-    fn f_pat(&ast_fold_precursor afp, ast_fold f, &@pat x) -> @pat {
-        ret @rec(id=x.id, node=afp.fold_pat(x.node, f), span=x.span);
-    }
-    fn f_decl(&ast_fold_precursor afp, ast_fold f, &@decl x) -> @decl {
-        ret @rec(node=afp.fold_decl(x.node, f), span=x.span);
-    }
-    fn f_expr(&ast_fold_precursor afp, ast_fold f, &@expr x) -> @expr {
-        ret @rec(id=x.id, node=afp.fold_expr(x.node, f), span=x.span);
-    }
-    fn f_ty(&ast_fold_precursor afp, ast_fold f, &@ty x) -> @ty {
-        ret @rec(node=afp.fold_ty(x.node, f), span=x.span);
-    }
-    fn f_constr(&ast_fold_precursor afp, ast_fold f, &@constr x) -> @constr {
-        ret @rec(node=afp.fold_constr(x.node, f), span=x.span);
-    }
-    fn f_fn(&ast_fold_precursor afp, ast_fold f, &_fn x) -> _fn {
-        ret afp.fold_fn(x, f);
-    }    
-    fn f_mod(&ast_fold_precursor afp, ast_fold f, &_mod x) -> _mod {
-        ret afp.fold_mod(x, f);
-    }
-    fn f_native_mod(&ast_fold_precursor afp, ast_fold f, &native_mod x) -> 
-        native_mod {
-        ret afp.fold_native_mod(x, f);
-    }    
-    fn f_variant(&ast_fold_precursor afp, ast_fold f, &variant x)
-        -> variant {
-        ret rec(node=afp.fold_variant(x.node, f), span=x.span);
-    }
-    fn f_ident(&ast_fold_precursor afp, ast_fold f, &ident x) -> ident {
-        ret afp.fold_ident(x, f);
-    }
-    fn f_path(&ast_fold_precursor afp, ast_fold f, &path x) -> path {
-        ret rec(node=afp.fold_path(x.node, f), span=x.span);
-    }
-    fn f_local(&ast_fold_precursor afp, ast_fold f, &@local x) -> @local {
-        ret @rec(node=afp.fold_local(x.node, f), span=x.span);
-    }
-
-    *result = rec(fold_crate = bind f_crate(afp,result,_),
-                  fold_crate_directive = bind f_crate_directive(afp,result,_),
-                  fold_view_item = bind f_view_item(afp,result,_),
-                  fold_native_item = bind f_native_item(afp,result,_),
-                  fold_item = bind f_item(afp,result,_),
-                  fold_item_underscore = bind f_item_underscore(afp,result,_),
-                  fold_method = bind f_method(afp,result,_),
-                  fold_block = bind f_block(afp,result,_),
-                  fold_stmt = bind f_stmt(afp,result,_),
-                  fold_arm = bind f_arm(afp, result, _),
-                  fold_pat = bind f_pat(afp,result,_),
-                  fold_decl = bind f_decl(afp,result,_),
-                  fold_expr = bind f_expr(afp,result,_),
-                  fold_ty = bind f_ty(afp,result,_),
-                  fold_constr = bind f_constr(afp,result,_),
-                  fold_fn = bind f_fn(afp,result,_),
-                  fold_mod = bind f_mod(afp,result,_),
-                  fold_native_mod = bind f_native_mod(afp,result,_),
-                  fold_variant = bind f_variant(afp,result,_),
-                  fold_ident = bind f_ident(afp,result,_),
-                  fold_path = bind f_path(afp,result,_),
-                  fold_local = bind f_local(afp,result,_));
-    ret result;
-    /*
-    ret rec(fold_crate = noop_fold_crate,
-          fold_crate_directive = noop_fold_crate_drective,
-          fold_view_item = noop_fold_view_item,
-          fold_native_item = noop_fold_native_item,
-          fold_item = noop_fold_item,
-          fold_method = noop_fold_method,
-          fold_block = noop_fold_block,
-          fold_stmt = noop_fold_stmt,
-          fold_arm = noop_fold_arm,
-          fold_pat = noop_fold_pat,
-          fold_decl = noop_fold_decl,
-          fold_expr = noop_fold_expr,
-          fold_ty = noop_fold_ty,
-          fold_constr = noop_fold_constr,
-          fold_fn = noop_fold_fn);*/
-}
-
-
-//
-// 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/front/lexer.rs b/src/comp/front/lexer.rs
deleted file mode 100644 (file)
index d6bc372..0000000
+++ /dev/null
@@ -1,739 +0,0 @@
-
-import std::io;
-import std::str;
-import std::vec;
-import std::int;
-import std::map;
-import std::map::hashmap;
-import std::option;
-import std::option::some;
-import std::option::none;
-import driver::session::session;
-import util::common;
-import util::common::*;
-import util::data::interner;
-import util::data::interner::intern;
-
-type reader =
-    obj {
-        fn is_eof() -> bool ;
-        fn curr() -> char ;
-        fn next() -> char ;
-        fn init() ;
-        fn bump() ;
-        fn mark() ;
-        fn get_mark_chpos() -> uint ;
-        fn get_mark_str() -> str ;
-        fn get_interner() -> @interner::interner[str] ;
-        fn get_chpos() -> uint ;
-        fn get_col() -> uint ;
-        fn get_filemap() -> codemap::filemap ;
-        fn err(str) ;
-    };
-
-fn new_reader(session sess, io::reader rdr, codemap::filemap filemap,
-              @interner::interner[str] itr) -> reader {
-    obj reader(session sess,
-               str file,
-               uint len,
-               mutable uint col,
-               mutable uint pos,
-               mutable char ch,
-               mutable uint mark_chpos,
-               mutable uint chpos,
-               mutable vec[str] strs,
-               codemap::filemap fm,
-               @interner::interner[str] itr) {
-        fn is_eof() -> bool { ret ch == -1 as char; }
-        fn mark() { mark_chpos = chpos; }
-        fn get_mark_str() -> str { ret str::slice(file, mark_chpos, chpos); }
-        fn get_mark_chpos() -> uint { ret mark_chpos; }
-        fn get_chpos() -> uint { ret chpos; }
-        fn curr() -> char { ret ch; }
-        fn next() -> char {
-            if (pos < len) {
-                ret str::char_at(file, pos);
-            } else { ret -1 as char; }
-        }
-        fn init() {
-            if (pos < len) {
-                auto next = str::char_range_at(file, pos);
-                pos = next._1;
-                ch = next._0;
-            }
-        }
-        fn bump() {
-            if (pos < len) {
-                col += 1u;
-                chpos += 1u;
-                if (ch == '\n') { codemap::next_line(fm, chpos); col = 0u; }
-                auto next = str::char_range_at(file, pos);
-                pos = next._1;
-                ch = next._0;
-            } else { ch = -1 as char; }
-        }
-        fn get_interner() -> @interner::interner[str] { ret itr; }
-        fn get_col() -> uint { ret col; }
-        fn get_filemap() -> codemap::filemap { ret fm; }
-        fn err(str m) { sess.span_fatal(rec(lo=chpos, hi=chpos), m); }
-    }
-    auto file = str::unsafe_from_bytes(rdr.read_whole_stream());
-    let vec[str] strs = [];
-    auto rd =
-        reader(sess, file, str::byte_len(file), 0u, 0u, -1 as char,
-               filemap.start_pos, filemap.start_pos, strs, filemap, itr);
-    rd.init();
-    ret rd;
-}
-
-fn dec_digit_val(char c) -> int { ret (c as int) - ('0' as int); }
-
-fn hex_digit_val(char c) -> int {
-    if (in_range(c, '0', '9')) { ret (c as int) - ('0' as int); }
-    if (in_range(c, 'a', 'f')) { ret (c as int) - ('a' as int) + 10; }
-    if (in_range(c, 'A', 'F')) { ret (c as int) - ('A' as int) + 10; }
-    fail;
-}
-
-fn bin_digit_value(char c) -> int { if (c == '0') { ret 0; } ret 1; }
-
-fn is_whitespace(char c) -> bool {
-    ret c == ' ' || c == '\t' || c == '\r' || c == '\n';
-}
-
-fn consume_whitespace_and_comments(&reader rdr) {
-    while (is_whitespace(rdr.curr())) { rdr.bump(); }
-    be consume_any_line_comment(rdr);
-}
-
-fn consume_any_line_comment(&reader rdr) {
-    if (rdr.curr() == '/') {
-        alt (rdr.next()) {
-            case ('/') {
-                while (rdr.curr() != '\n' && !rdr.is_eof()) { rdr.bump(); }
-                // Restart whitespace munch.
-
-                be consume_whitespace_and_comments(rdr);
-            }
-            case ('*') {
-                rdr.bump();
-                rdr.bump();
-                be consume_block_comment(rdr);
-            }
-            case (_) { ret; }
-        }
-    }
-}
-
-fn consume_block_comment(&reader rdr) {
-    let int level = 1;
-    while (level > 0) {
-        if (rdr.is_eof()) { rdr.err("unterminated block comment"); fail; }
-        if (rdr.curr() == '/' && rdr.next() == '*') {
-            rdr.bump();
-            rdr.bump();
-            level += 1;
-        } else {
-            if (rdr.curr() == '*' && rdr.next() == '/') {
-                rdr.bump();
-                rdr.bump();
-                level -= 1;
-            } else { rdr.bump(); }
-        }
-    }
-    // restart whitespace munch.
-
-    be consume_whitespace_and_comments(rdr);
-}
-
-fn digits_to_string(str s) -> int {
-    let int accum_int = 0;
-    for (u8 c in s) {
-        accum_int *= 10;
-        accum_int += dec_digit_val(c as char);
-    }
-    ret accum_int;
-}
-
-fn scan_exponent(&reader rdr) -> option::t[str] {
-    auto c = rdr.curr();
-    auto rslt = "";
-    if (c == 'e' || c == 'E') {
-        rslt += str::from_bytes([c as u8]);
-        rdr.bump();
-        c = rdr.curr();
-        if (c == '-' || c == '+') {
-            rslt += str::from_bytes([c as u8]);
-            rdr.bump();
-        }
-        auto exponent = scan_dec_digits(rdr);
-        if (str::byte_len(exponent) > 0u) {
-            ret some(rslt + exponent);
-        } else { rdr.err("scan_exponent: bad fp literal"); fail; }
-    } else { ret none[str]; }
-}
-
-fn scan_dec_digits(&reader rdr) -> str {
-    auto c = rdr.curr();
-    let str rslt = "";
-    while (is_dec_digit(c) || c == '_') {
-        if (c != '_') { rslt += str::from_bytes([c as u8]); }
-        rdr.bump();
-        c = rdr.curr();
-    }
-    ret rslt;
-}
-
-fn scan_number(char c, &reader rdr) -> token::token {
-    auto accum_int = 0;
-    let str dec_str = "";
-    let bool is_dec_integer = false;
-    auto n = rdr.next();
-    if (c == '0' && n == 'x') {
-        rdr.bump();
-        rdr.bump();
-        c = rdr.curr();
-        while (is_hex_digit(c) || c == '_') {
-            if (c != '_') { accum_int *= 16; accum_int += hex_digit_val(c); }
-            rdr.bump();
-            c = rdr.curr();
-        }
-    } else if (c == '0' && n == 'b') {
-        rdr.bump();
-        rdr.bump();
-        c = rdr.curr();
-        while (is_bin_digit(c) || c == '_') {
-            if (c != '_') { accum_int *= 2; accum_int += bin_digit_value(c); }
-            rdr.bump();
-            c = rdr.curr();
-        }
-    } else { dec_str = scan_dec_digits(rdr); is_dec_integer = true; }
-    if (is_dec_integer) { accum_int = digits_to_string(dec_str); }
-    c = rdr.curr();
-    n = rdr.next();
-    if (c == 'u' || c == 'i') {
-        let bool signed = c == 'i';
-        rdr.bump();
-        c = rdr.curr();
-        if (c == '8') {
-            rdr.bump();
-            if (signed) {
-                ret token::LIT_MACH_INT(common::ty_i8, accum_int);
-            } else { ret token::LIT_MACH_INT(common::ty_u8, accum_int); }
-        }
-        n = rdr.next();
-        if (c == '1' && n == '6') {
-            rdr.bump();
-            rdr.bump();
-            if (signed) {
-                ret token::LIT_MACH_INT(common::ty_i16, accum_int);
-            } else { ret token::LIT_MACH_INT(common::ty_u16, accum_int); }
-        }
-        if (c == '3' && n == '2') {
-            rdr.bump();
-            rdr.bump();
-            if (signed) {
-                ret token::LIT_MACH_INT(common::ty_i32, accum_int);
-            } else { ret token::LIT_MACH_INT(common::ty_u32, accum_int); }
-        }
-        if (c == '6' && n == '4') {
-            rdr.bump();
-            rdr.bump();
-            if (signed) {
-                ret token::LIT_MACH_INT(common::ty_i64, accum_int);
-            } else { ret token::LIT_MACH_INT(common::ty_u64, accum_int); }
-        }
-        if (signed) {
-            ret token::LIT_INT(accum_int);
-        } else {
-            // FIXME: should cast in the target bit-width.
-
-            ret token::LIT_UINT(accum_int as uint);
-        }
-    }
-    c = rdr.curr();
-    if (c == '.') {
-        // Parse a floating-point number.
-
-        rdr.bump();
-        auto dec_part = scan_dec_digits(rdr);
-        auto float_str = dec_str + "." + dec_part;
-        c = rdr.curr();
-        auto exponent_str = scan_exponent(rdr);
-        alt (exponent_str) {
-            case (some(?s)) { float_str += s; }
-            case (none) { }
-        }
-        c = rdr.curr();
-        if (c == 'f') {
-            rdr.bump();
-            c = rdr.curr();
-            n = rdr.next();
-            if (c == '3' && n == '2') {
-                rdr.bump();
-                rdr.bump();
-                ret token::LIT_MACH_FLOAT(util::common::ty_f32,
-                                          intern(*rdr.get_interner(),
-                                                 float_str));
-            } else if (c == '6' && n == '4') {
-                rdr.bump();
-                rdr.bump();
-                ret token::LIT_MACH_FLOAT(util::common::ty_f64,
-                                          intern(*rdr.get_interner(),
-                                                 float_str));
-                /* FIXME: if this is out of range for either a 32-bit or
-                   64-bit float, it won't be noticed till the back-end */
-
-            }
-        } else {
-            ret token::LIT_FLOAT(interner::intern[str](*rdr.get_interner(),
-                                                       float_str));
-        }
-    }
-    auto maybe_exponent = scan_exponent(rdr);
-    alt (maybe_exponent) {
-        case (some(?s)) {
-            ret token::LIT_FLOAT(interner::intern[str](*rdr.get_interner(),
-                                                       dec_str + s));
-        }
-        case (none) { ret token::LIT_INT(accum_int); }
-    }
-}
-
-fn scan_numeric_escape(&reader rdr, uint n_hex_digits) -> char {
-    auto accum_int = 0;
-    while (n_hex_digits != 0u) {
-        auto n = rdr.curr();
-        rdr.bump();
-        if (!is_hex_digit(n)) {
-            rdr.err(#fmt("illegal numeric character escape: %d", n as int));
-            fail;
-        }
-        accum_int *= 16;
-        accum_int += hex_digit_val(n);
-        n_hex_digits -= 1u;
-    }
-    ret accum_int as char;
-}
-
-fn next_token(&reader rdr) -> token::token {
-    auto accum_str = "";
-    consume_whitespace_and_comments(rdr);
-    if (rdr.is_eof()) { ret token::EOF; }
-    rdr.mark();
-    auto c = rdr.curr();
-    if (is_alpha(c) || c == '_') {
-        while (is_alnum(c) || c == '_') {
-            str::push_char(accum_str, c);
-            rdr.bump();
-            c = rdr.curr();
-        }
-        if (str::eq(accum_str, "_")) { ret token::UNDERSCORE; }
-        auto is_mod_name = c == ':' && rdr.next() == ':';
-        ret token::IDENT(interner::intern[str](*rdr.get_interner(),
-                                               accum_str), is_mod_name);
-    }
-    if (is_dec_digit(c)) { ret scan_number(c, rdr); }
-    fn binop(&reader rdr, token::binop op) -> token::token {
-        rdr.bump();
-        if (rdr.curr() == '=') {
-            rdr.bump();
-            ret token::BINOPEQ(op);
-        } else { ret token::BINOP(op); }
-    }
-    alt (c) {
-        case (
-             // One-byte tokens.
-             '?') {
-            rdr.bump();
-            ret token::QUES;
-        }
-        case (';') { rdr.bump(); ret token::SEMI; }
-        case (',') { rdr.bump(); ret token::COMMA; }
-        case ('.') { rdr.bump(); ret token::DOT; }
-        case ('(') { rdr.bump(); ret token::LPAREN; }
-        case (')') { rdr.bump(); ret token::RPAREN; }
-        case ('{') { rdr.bump(); ret token::LBRACE; }
-        case ('}') { rdr.bump(); ret token::RBRACE; }
-        case ('[') { rdr.bump(); ret token::LBRACKET; }
-        case (']') { rdr.bump(); ret token::RBRACKET; }
-        case ('@') { rdr.bump(); ret token::AT; }
-        case ('#') { rdr.bump(); ret token::POUND; }
-        case ('~') { rdr.bump(); ret token::TILDE; }
-        case (':') {
-            rdr.bump();
-            if (rdr.curr() == ':') {
-                rdr.bump();
-                ret token::MOD_SEP;
-            } else { ret token::COLON; }
-        }
-        case (
-             // Multi-byte tokens.
-             '=') {
-            rdr.bump();
-            if (rdr.curr() == '=') {
-                rdr.bump();
-                ret token::EQEQ;
-            } else { ret token::EQ; }
-        }
-        case ('!') {
-            rdr.bump();
-            if (rdr.curr() == '=') {
-                rdr.bump();
-                ret token::NE;
-            } else { ret token::NOT; }
-        }
-        case ('<') {
-            rdr.bump();
-            alt (rdr.curr()) {
-                case ('=') { rdr.bump(); ret token::LE; }
-                case ('<') { ret binop(rdr, token::LSL); }
-                case ('|') { rdr.bump(); ret token::SEND; }
-                case ('-') {
-                    rdr.bump();
-                    alt (rdr.curr()) {
-                        case ('>') { rdr.bump(); ret token::DARROW; }
-                        case (_) { ret token::LARROW; }
-                    }
-                }
-                case (_) { ret token::LT; }
-            }
-        }
-        case ('>') {
-            rdr.bump();
-            alt (rdr.curr()) {
-                case ('=') { rdr.bump(); ret token::GE; }
-                case ('>') {
-                    if (rdr.next() == '>') {
-                        rdr.bump();
-                        ret binop(rdr, token::ASR);
-                    } else { ret binop(rdr, token::LSR); }
-                }
-                case (_) { ret token::GT; }
-            }
-        }
-        case ('\'') {
-            rdr.bump();
-            auto c2 = rdr.curr();
-            rdr.bump();
-            if (c2 == '\\') {
-                auto escaped = rdr.curr();
-                rdr.bump();
-                alt (escaped) {
-                    case ('n') { c2 = '\n'; }
-                    case ('r') { c2 = '\r'; }
-                    case ('t') { c2 = '\t'; }
-                    case ('\\') { c2 = '\\'; }
-                    case ('\'') { c2 = '\''; }
-                    case ('x') { c2 = scan_numeric_escape(rdr, 2u); }
-                    case ('u') { c2 = scan_numeric_escape(rdr, 4u); }
-                    case ('U') { c2 = scan_numeric_escape(rdr, 8u); }
-                    case (?c2) {
-                        rdr.err(#fmt("unknown character escape: %d",
-                                     c2 as int));
-                        fail;
-                    }
-                }
-            }
-            if (rdr.curr() != '\'') {
-                rdr.err("unterminated character constant");
-                fail;
-            }
-            rdr.bump(); // advance curr past token
-
-            ret token::LIT_CHAR(c2);
-        }
-        case ('"') {
-            rdr.bump();
-            while (rdr.curr() != '"') {
-                auto ch = rdr.curr();
-                rdr.bump();
-                alt (ch) {
-                    case ('\\') {
-                        auto escaped = rdr.curr();
-                        rdr.bump();
-                        alt (escaped) {
-                            case ('n') {
-                                str::push_byte(accum_str, '\n' as u8);
-                            }
-                            case ('r') {
-                                str::push_byte(accum_str, '\r' as u8);
-                            }
-                            case ('t') {
-                                str::push_byte(accum_str, '\t' as u8);
-                            }
-                            case ('\\') {
-                                str::push_byte(accum_str, '\\' as u8);
-                            }
-                            case ('"') {
-                                str::push_byte(accum_str, '"' as u8);
-                            }
-                            case ('\n') { consume_whitespace(rdr); }
-                            case ('x') {
-                                str::push_char(accum_str,
-                                               scan_numeric_escape(rdr, 2u));
-                            }
-                            case ('u') {
-                                str::push_char(accum_str,
-                                               scan_numeric_escape(rdr, 4u));
-                            }
-                            case ('U') {
-                                str::push_char(accum_str,
-                                               scan_numeric_escape(rdr, 8u));
-                            }
-                            case (?c2) {
-                                rdr.err(#fmt("unknown string escape: %d",
-                                             c2 as int));
-                                fail;
-                            }
-                        }
-                    }
-                    case (_) { str::push_char(accum_str, ch); }
-                }
-            }
-            rdr.bump();
-            ret token::LIT_STR(interner::intern[str](*rdr.get_interner(),
-                                                     accum_str));
-        }
-        case ('-') {
-            if (rdr.next() == '>') {
-                rdr.bump();
-                rdr.bump();
-                ret token::RARROW;
-            } else { ret binop(rdr, token::MINUS); }
-        }
-        case ('&') {
-            if (rdr.next() == '&') {
-                rdr.bump();
-                rdr.bump();
-                ret token::ANDAND;
-            } else { ret binop(rdr, token::AND); }
-        }
-        case ('|') {
-            alt (rdr.next()) {
-                case ('|') { rdr.bump(); rdr.bump(); ret token::OROR; }
-                case ('>') { rdr.bump(); rdr.bump(); ret token::RECV; }
-                case (_) { ret binop(rdr, token::OR); }
-            }
-        }
-        case ('+') { ret binop(rdr, token::PLUS); }
-        case ('*') { ret binop(rdr, token::STAR); }
-        case ('/') { ret binop(rdr, token::SLASH); }
-        case ('^') { ret binop(rdr, token::CARET); }
-        case ('%') { ret binop(rdr, token::PERCENT); }
-        case (?c) {
-            rdr.err(#fmt("unkown start of token: %d", c as int));
-            fail;
-        }
-    }
-    fail;
-}
-
-tag cmnt_style {
-    isolated; // No code on either side of each line of the comment
-
-    trailing; // Code exists to the left of the comment
-
-    mixed; // Code before /* foo */ and after the comment
-
-    blank_line; // Just a manual blank linke "\n\n", for layout
-
-}
-
-type cmnt = rec(cmnt_style style, vec[str] lines, uint pos);
-
-fn read_to_eol(&reader rdr) -> str {
-    auto val = "";
-    while (rdr.curr() != '\n' && !rdr.is_eof()) {
-        str::push_char(val, rdr.curr());
-        rdr.bump();
-    }
-    ret val;
-}
-
-fn read_one_line_comment(&reader rdr) -> str {
-    auto val = read_to_eol(rdr);
-    assert (val.(0) == '/' as u8 && val.(1) == '/' as u8);
-    ret val;
-}
-
-fn consume_whitespace(&reader rdr) {
-    while (is_whitespace(rdr.curr()) && !rdr.is_eof()) { rdr.bump(); }
-}
-
-fn consume_non_eol_whitespace(&reader rdr) {
-    while (is_whitespace(rdr.curr()) && rdr.curr() != '\n' && !rdr.is_eof()) {
-        rdr.bump();
-    }
-}
-
-fn consume_whitespace_counting_blank_lines(&reader rdr,
-                                           &mutable vec[cmnt] comments) {
-    while (is_whitespace(rdr.curr()) && !rdr.is_eof()) {
-        if (rdr.curr() == '\n' && rdr.next() == '\n') {
-            log ">>> blank-line comment";
-            let vec[str] v = [];
-            comments += [rec(style=blank_line, lines=v,
-                             pos=rdr.get_chpos())];
-        }
-        rdr.bump();
-    }
-}
-
-fn read_line_comments(&reader rdr, bool code_to_the_left) -> cmnt {
-    log ">>> line comments";
-    auto p = rdr.get_chpos();
-    let vec[str] lines = [];
-    while (rdr.curr() == '/' && rdr.next() == '/') {
-        auto line = read_one_line_comment(rdr);
-        log line;
-        lines += [line];
-        consume_non_eol_whitespace(rdr);
-    }
-    log "<<< line comments";
-    ret rec(style=if (code_to_the_left) { trailing } else { isolated },
-            lines=lines,
-            pos=p);
-}
-
-fn all_whitespace(&str s, uint begin, uint end) -> bool {
-    let uint i = begin;
-    while (i != end) {
-        if (!is_whitespace(s.(i) as char)) { ret false; }
-        i += 1u;
-    }
-    ret true;
-}
-
-fn trim_whitespace_prefix_and_push_line(&mutable vec[str] lines, &str s,
-                                        uint col) {
-    auto s1;
-    if (all_whitespace(s, 0u, col)) {
-        if (col < str::byte_len(s)) {
-            s1 = str::slice(s, col, str::byte_len(s));
-        } else { s1 = ""; }
-    } else { s1 = s; }
-    log "pushing line: " + s1;
-    lines += [s1];
-}
-
-fn read_block_comment(&reader rdr, bool code_to_the_left) -> cmnt {
-    log ">>> block comment";
-    auto p = rdr.get_chpos();
-    let vec[str] lines = [];
-    let uint col = rdr.get_col();
-    rdr.bump();
-    rdr.bump();
-    auto curr_line = "/*";
-    let int level = 1;
-    while (level > 0) {
-        log #fmt("=== block comment level %d", level);
-        if (rdr.is_eof()) { rdr.err("unterminated block comment"); fail; }
-        if (rdr.curr() == '\n') {
-            trim_whitespace_prefix_and_push_line(lines, curr_line, col);
-            curr_line = "";
-            rdr.bump();
-        } else {
-            str::push_char(curr_line, rdr.curr());
-            if (rdr.curr() == '/' && rdr.next() == '*') {
-                rdr.bump();
-                rdr.bump();
-                curr_line += "*";
-                level += 1;
-            } else {
-                if (rdr.curr() == '*' && rdr.next() == '/') {
-                    rdr.bump();
-                    rdr.bump();
-                    curr_line += "/";
-                    level -= 1;
-                } else { rdr.bump(); }
-            }
-        }
-    }
-    if (str::byte_len(curr_line) != 0u) {
-        trim_whitespace_prefix_and_push_line(lines, curr_line, col);
-    }
-    auto style = if (code_to_the_left) { trailing } else { isolated };
-    consume_non_eol_whitespace(rdr);
-    if (!rdr.is_eof() && rdr.curr() != '\n' && vec::len(lines) == 1u) {
-        style = mixed;
-    }
-    log "<<< block comment";
-    ret rec(style=style, lines=lines, pos=p);
-}
-
-fn peeking_at_comment(&reader rdr) -> bool {
-    ret rdr.curr() == '/' && rdr.next() == '/' ||
-            rdr.curr() == '/' && rdr.next() == '*';
-}
-
-fn consume_comment(&reader rdr, bool code_to_the_left,
-                   &mutable vec[cmnt] comments) {
-    log ">>> consume comment";
-    if (rdr.curr() == '/' && rdr.next() == '/') {
-        vec::push[cmnt](comments, read_line_comments(rdr, code_to_the_left));
-    } else if (rdr.curr() == '/' && rdr.next() == '*') {
-        vec::push[cmnt](comments, read_block_comment(rdr, code_to_the_left));
-    } else { fail; }
-    log "<<< consume comment";
-}
-
-fn is_lit(&token::token t) -> bool {
-    ret alt (t) {
-            case (token::LIT_INT(_)) { true }
-            case (token::LIT_UINT(_)) { true }
-            case (token::LIT_MACH_INT(_, _)) { true }
-            case (token::LIT_FLOAT(_)) { true }
-            case (token::LIT_MACH_FLOAT(_, _)) { true }
-            case (token::LIT_STR(_)) { true }
-            case (token::LIT_CHAR(_)) { true }
-            case (token::LIT_BOOL(_)) { true }
-            case (_) { false }
-        }
-}
-
-type lit = rec(str lit, uint pos);
-
-fn gather_comments_and_literals(session sess, str path) ->
-   rec(vec[cmnt] cmnts, vec[lit] lits) {
-    auto srdr = io::file_reader(path);
-    auto itr = @interner::mk[str](str::hash, str::eq);
-    auto rdr = new_reader(sess, srdr, codemap::new_filemap(path, 0u), itr);
-    let vec[cmnt] comments = [];
-    let vec[lit] literals = [];
-    let bool first_read = true;
-    while (!rdr.is_eof()) {
-        while (true) {
-            auto code_to_the_left = !first_read;
-            consume_non_eol_whitespace(rdr);
-            if (rdr.curr() == '\n') {
-                code_to_the_left = false;
-                consume_whitespace_counting_blank_lines(rdr, comments);
-            }
-            while (peeking_at_comment(rdr)) {
-                consume_comment(rdr, code_to_the_left, comments);
-                consume_whitespace_counting_blank_lines(rdr, comments);
-            }
-            break;
-        }
-        auto tok = next_token(rdr);
-        if (is_lit(tok)) {
-            vec::push[lit](literals,
-                           rec(lit=rdr.get_mark_str(),
-                               pos=rdr.get_mark_chpos()));
-        }
-        log "tok: " + token::to_str(rdr, tok);
-        first_read = false;
-    }
-    ret rec(cmnts=comments, lits=literals);
-}
-//
-// 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/front/parser.rs b/src/comp/front/parser.rs
deleted file mode 100644 (file)
index ce68be6..0000000
+++ /dev/null
@@ -1,2465 +0,0 @@
-
-import std::io;
-import std::vec;
-import std::str;
-import std::option;
-import std::option::some;
-import std::option::none;
-import std::either;
-import std::either::left;
-import std::either::right;
-import std::map::hashmap;
-import token::can_begin_expr;
-import driver::session;
-import util::common;
-import util::common::filename;
-import util::common::span;
-import util::common::new_str_hash;
-import util::data::interner;
-import util::common::a_bang;
-import util::common::a_ty;
-
-tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; }
-
-tag file_type { CRATE_FILE; SOURCE_FILE; }
-
-type ty_or_bang = util::common::ty_or_bang[@ast::ty];
-
-type parser =
-    obj {
-        fn peek() -> token::token ;
-        fn bump() ;
-        fn fatal(str) -> !  ;
-        fn restrict(restriction) ;
-        fn get_restriction() -> restriction ;
-        fn get_file_type() -> file_type ;
-        fn get_cfg() -> ast::crate_cfg;
-        fn get_session() -> session::session ;
-        fn get_span() -> common::span ;
-        fn get_lo_pos() -> uint ;
-        fn get_hi_pos() -> uint ;
-        fn get_last_lo_pos() -> uint ;
-        fn get_prec_table() -> vec[op_spec] ;
-        fn get_str(token::str_num) -> str ;
-        fn get_reader() -> lexer::reader ;
-        fn get_filemap() -> codemap::filemap ;
-        fn get_bad_expr_words() -> hashmap[str, ()] ;
-        fn get_syntax_expanders() -> hashmap[str, ext::syntax_extension] ;
-        fn get_chpos() -> uint ;
-        fn get_id() -> ast::node_id ;
-        fn next_id() -> ast::node_id ;
-    };
-
-fn new_parser(session::session sess, ast::crate_cfg cfg,
-              str path, uint pos, ast::node_id next_id) -> parser {
-    obj stdio_parser(session::session sess,
-                     ast::crate_cfg cfg,
-                     file_type ftype,
-                     mutable token::token tok,
-                     mutable uint lo,
-                     mutable uint hi,
-                     mutable uint last_lo,
-                     mutable restriction restr,
-                     lexer::reader rdr,
-                     vec[op_spec] precs,
-                     mutable ast::node_id next_id_var,
-                     hashmap[str, ()] bad_words,
-                     hashmap[str, ext::syntax_extension] syntax_expanders) {
-        fn peek() -> token::token { ret tok; }
-        fn bump() {
-            // log rdr.get_filename()
-            //   + ":" + common::istr(lo.line as int);
-
-            last_lo = lo;
-            tok = lexer::next_token(rdr);
-            lo = rdr.get_mark_chpos();
-            hi = rdr.get_chpos();
-        }
-        fn fatal(str m) -> ! { sess.span_fatal(rec(lo=lo, hi=hi), m); }
-        fn restrict(restriction r) { restr = r; }
-        fn get_restriction() -> restriction { ret restr; }
-        fn get_session() -> session::session { ret sess; }
-        fn get_span() -> common::span { ret rec(lo=lo, hi=hi); }
-        fn get_lo_pos() -> uint { ret lo; }
-        fn get_hi_pos() -> uint { ret hi; }
-        fn get_last_lo_pos() -> uint { ret last_lo; }
-        fn get_file_type() -> file_type { ret ftype; }
-        fn get_cfg() -> ast::crate_cfg { ret cfg; }
-        fn get_prec_table() -> vec[op_spec] { ret precs; }
-        fn get_str(token::str_num i) -> str {
-            ret interner::get(*rdr.get_interner(), i);
-        }
-        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, ext::syntax_extension] {
-            ret syntax_expanders;
-        }
-        fn get_chpos() -> uint { ret rdr.get_chpos(); }
-        fn get_id() -> ast::node_id {
-            auto rv = next_id_var;
-            next_id_var += 1;
-            ret rv;
-        }
-        fn next_id() -> ast::node_id { ret next_id_var; }
-    }
-
-    auto ftype = SOURCE_FILE;
-    if (str::ends_with(path, ".rc")) { ftype = CRATE_FILE; }
-    auto srdr = io::file_reader(path);
-    auto filemap = codemap::new_filemap(path, pos);
-    vec::push(sess.get_codemap().files, filemap);
-    auto itr = @interner::mk(str::hash, str::eq);
-    auto rdr = lexer::new_reader(sess, srdr, filemap, itr);
-    // Make sure npos points at first actual token:
-
-    lexer::consume_whitespace_and_comments(rdr);
-    auto npos = rdr.get_chpos();
-    ret stdio_parser(sess, cfg, ftype, lexer::next_token(rdr),
-                     npos, npos, npos, UNRESTRICTED, rdr,
-                     prec_table(), next_id, bad_expr_word_table(),
-                     ext::syntax_expander_table());
-}
-
-// These are the words that shouldn't be allowed as value identifiers,
-// because, if used at the start of a line, they will cause the line to be
-// interpreted as a specific kind of statement, which would be confusing.
-fn bad_expr_word_table() -> hashmap[str, ()] {
-    auto words = new_str_hash();
-    words.insert("mod", ());
-    words.insert("if", ());
-    words.insert("else", ());
-    words.insert("while", ());
-    words.insert("do", ());
-    words.insert("alt", ());
-    words.insert("for", ());
-    words.insert("break", ());
-    words.insert("cont", ());
-    words.insert("put", ());
-    words.insert("ret", ());
-    words.insert("be", ());
-    words.insert("fail", ());
-    words.insert("type", ());
-    words.insert("resource", ());
-    words.insert("check", ());
-    words.insert("assert", ());
-    words.insert("claim", ());
-    words.insert("prove", ());
-    words.insert("state", ());
-    words.insert("gc", ());
-    words.insert("native", ());
-    words.insert("auto", ());
-    words.insert("fn", ());
-    words.insert("pred", ());
-    words.insert("iter", ());
-    words.insert("import", ());
-    words.insert("export", ());
-    words.insert("let", ());
-    words.insert("const", ());
-    words.insert("log", ());
-    words.insert("log_err", ());
-    words.insert("tag", ());
-    words.insert("obj", ());
-    ret words;
-}
-
-fn unexpected(&parser p, token::token t) -> ! {
-    let str s = "unexpected token: ";
-    s += token::to_str(p.get_reader(), t);
-    p.fatal(s);
-}
-
-fn expect(&parser p, token::token t) {
-    if (p.peek() == t) {
-        p.bump();
-    } else {
-        let str s = "expecting ";
-        s += token::to_str(p.get_reader(), t);
-        s += ", found ";
-        s += token::to_str(p.get_reader(), p.peek());
-        p.fatal(s);
-    }
-}
-
-fn spanned[T](uint lo, uint hi, &T node) -> common::spanned[T] {
-    ret rec(node=node, span=rec(lo=lo, hi=hi));
-}
-
-fn parse_ident(&parser p) -> ast::ident {
-    alt (p.peek()) {
-        case (token::IDENT(?i, _)) { p.bump(); ret p.get_str(i); }
-        case (_) { p.fatal("expecting ident"); fail; }
-    }
-}
-
-fn parse_value_ident(&parser p) -> ast::ident {
-    check_bad_word(p);
-    ret parse_ident(p);
-}
-
-fn is_word(&parser p, &str word) -> bool {
-    ret alt (p.peek()) {
-            case (token::IDENT(?sid, false)) { str::eq(word, p.get_str(sid)) }
-            case (_) { false }
-        };
-}
-
-fn eat_word(&parser p, &str word) -> bool {
-    alt (p.peek()) {
-        case (token::IDENT(?sid, false)) {
-            if (str::eq(word, p.get_str(sid))) {
-                p.bump();
-                ret true;
-            } else { ret false; }
-        }
-        case (_) { ret false; }
-    }
-}
-
-fn expect_word(&parser p, &str word) {
-    if (!eat_word(p, word)) {
-        p.fatal("expecting " + word + ", found " +
-                  token::to_str(p.get_reader(), p.peek()));
-    }
-}
-
-fn check_bad_word(&parser p) {
-    alt (p.peek()) {
-        case (token::IDENT(?sid, false)) {
-            auto w = p.get_str(sid);
-            if (p.get_bad_expr_words().contains_key(w)) {
-                p.fatal("found " + w + " in expression position");
-            }
-        }
-        case (_) { }
-    }
-}
-
-fn parse_ty_fn(ast::proto proto, &parser p, uint lo) -> ast::ty_ {
-    fn parse_fn_input_ty(&parser p) -> ast::ty_arg {
-        auto lo = p.get_lo_pos();
-        auto mode = ast::val;
-        if (p.peek() == token::BINOP(token::AND)) {
-            p.bump();
-            mode = ast::alias(eat_word(p, "mutable"));
-        }
-        auto t = parse_ty(p);
-        alt (p.peek()) {
-            case (token::IDENT(_, _)) { p.bump();/* ignore param name */ }
-            case (_) {/* no param name present */ }
-        }
-        ret spanned(lo, t.span.hi, rec(mode=mode, ty=t));
-    }
-    auto lo = p.get_lo_pos();
-    auto inputs =
-        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
-                  parse_fn_input_ty, p);
-    auto constrs = parse_constrs([], p);
-    let @ast::ty output;
-    auto cf = ast::return;
-    if (p.peek() == token::RARROW) {
-        p.bump();
-        auto tmp = parse_ty_or_bang(p);
-        alt (tmp) {
-            case (a_ty(?t)) { output = t; }
-            case (a_bang) {
-                output = @spanned(lo, inputs.span.hi, ast::ty_bot);
-                cf = ast::noreturn;
-            }
-        }
-    } else { output = @spanned(lo, inputs.span.hi, ast::ty_nil); }
-    ret ast::ty_fn(proto, inputs.node, output, cf, constrs.node);
-}
-
-fn parse_proto(&parser p) -> ast::proto {
-    if (eat_word(p, "iter")) {
-        ret ast::proto_iter;
-    } else if (eat_word(p, "fn")) {
-        ret ast::proto_fn;
-    } else if (eat_word(p, "pred")) {
-        ret ast::proto_fn;
-    } else { unexpected(p, p.peek()); }
-}
-
-fn parse_ty_obj(&parser p, &mutable uint hi) -> ast::ty_ {
-    fn parse_method_sig(&parser p) -> ast::ty_method {
-        auto flo = p.get_lo_pos();
-        let ast::proto proto = parse_proto(p);
-        auto ident = parse_value_ident(p);
-        auto f = parse_ty_fn(proto, p, flo);
-        expect(p, token::SEMI);
-        alt (f) {
-            case (ast::ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
-                ret spanned(flo, output.span.hi,
-                            rec(proto=proto,
-                                ident=ident,
-                                inputs=inputs,
-                                output=output,
-                                cf=cf,
-                                constrs=constrs));
-            }
-        }
-        fail;
-    }
-    auto f = parse_method_sig;
-    auto meths = parse_seq(token::LBRACE, token::RBRACE, none, f, p);
-    hi = meths.span.hi;
-    ret ast::ty_obj(meths.node);
-}
-
-fn parse_mt(&parser p) -> ast::mt {
-    auto mut = parse_mutability(p);
-    auto t = parse_ty(p);
-    ret rec(ty=t, mut=mut);
-}
-
-fn parse_ty_field(&parser p) -> ast::ty_field {
-    auto lo = p.get_lo_pos();
-    auto mt = parse_mt(p);
-    auto id = parse_ident(p);
-    ret spanned(lo, mt.ty.span.hi, rec(ident=id, mt=mt));
-}
-
-
-// if i is the jth ident in args, return j
-// otherwise, fail
-fn ident_index(&parser p, &vec[ast::arg] args, &ast::ident i) -> uint {
-    auto j = 0u;
-    for (ast::arg a in args) { if (a.ident == i) { ret j; } j += 1u; }
-    p.get_session().span_fatal(p.get_span(),
-                             "Unbound variable " + i + " in constraint arg");
-}
-
-fn parse_constr_arg(vec[ast::arg] args, &parser p) -> @ast::constr_arg {
-    auto sp = p.get_span();
-    auto carg = ast::carg_base;
-    if (p.peek() == token::BINOP(token::STAR)) {
-        p.bump();
-    } else {
-        let ast::ident i = parse_value_ident(p);
-        carg = ast::carg_ident(ident_index(p, args, i));
-    }
-    ret @rec(node=carg, span=sp);
-}
-
-fn parse_ty_constr(&vec[ast::arg] fn_args, &parser p) -> @ast::constr {
-    auto lo = p.get_lo_pos();
-    auto path = parse_path(p);
-    auto pf = bind parse_constr_arg(fn_args, _);
-    let rec(vec[@ast::constr_arg] node, span span) args =
-        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), pf, p);
-    // FIXME fix the def_id
-
-    ret @spanned(lo, args.span.hi,
-                 rec(path=path, args=args.node, id=p.get_id()));
-}
-
-
-// Use the args list to translate each bound variable 
-// mentioned in a constraint to an arg index.
-// Seems weird to do this in the parser, but I'm not sure how else to.
-fn parse_constrs(&vec[ast::arg] args, &parser p) ->
-   common::spanned[vec[@ast::constr]] {
-    auto lo = p.get_lo_pos();
-    auto hi = p.get_hi_pos();
-    let vec[@ast::constr] constrs = [];
-    if (p.peek() == token::COLON) {
-        p.bump();
-        while (true) {
-            auto constr = parse_ty_constr(args, p);
-            hi = constr.span.hi;
-            vec::push(constrs, constr);
-            if (p.peek() == token::COMMA) { p.bump(); } else { break; }
-        }
-    }
-    ret spanned(lo, hi, constrs);
-}
-
-fn parse_ty_constrs(@ast::ty t, &parser p) -> @ast::ty {
-    if (p.peek() == token::COLON) {
-        auto constrs = parse_constrs([], p);
-        ret @spanned(t.span.lo, constrs.span.hi,
-                     ast::ty_constr(t, constrs.node));
-    }
-    ret t;
-}
-
-fn parse_ty_postfix(@ast::ty orig_t, &parser p) -> @ast::ty {
-    auto lo = p.get_lo_pos();
-    if (p.peek() == token::LBRACKET) {
-        p.bump();
-
-        auto mut;
-        if (eat_word(p, "mutable")) {
-            if (p.peek() == token::QUES) {
-                p.bump();
-                mut = ast::maybe_mut;
-            } else {
-                mut = ast::mut;
-            }
-        } else {
-            mut = ast::imm;
-        }
-
-        if (mut == ast::imm && p.peek() != token::RBRACKET) {
-            // This is explicit type parameter instantiation.
-            auto seq = parse_seq_to_end(token::RBRACKET, some(token::COMMA),
-                                        parse_ty, p);
-            alt (orig_t.node) {
-                case (ast::ty_path(?pth, ?ann)) {
-                    auto hi = p.get_hi_pos();
-                    ret @spanned(lo, hi,
-                                 ast::ty_path(spanned(lo, hi,
-                                              rec(idents=pth.node.idents,
-                                                  types=seq)),
-                                              ann));
-                }
-                case (_) {
-                    p.fatal("type parameter instantiation only allowed for " +
-                          "paths");
-                }
-            }
-        }
-
-        expect(p, token::RBRACKET);
-        auto hi = p.get_hi_pos();
-        auto t = ast::ty_ivec(rec(ty=orig_t, mut=mut));
-        ret parse_ty_postfix(@spanned(lo, hi, t), p);
-    }
-    ret parse_ty_constrs(orig_t, p);
-}
-
-fn parse_ty_or_bang(&parser p) -> ty_or_bang {
-    alt (p.peek()) {
-        case (token::NOT) { p.bump(); ret a_bang[@ast::ty]; }
-        case (_) { ret a_ty(parse_ty(p)); }
-    }
-}
-
-fn parse_ty(&parser p) -> @ast::ty {
-    auto lo = p.get_lo_pos();
-    auto hi = lo;
-    let ast::ty_ t;
-    // FIXME: do something with this
-
-    parse_layer(p);
-    if (eat_word(p, "bool")) {
-        t = ast::ty_bool;
-    } else if (eat_word(p, "int")) {
-        t = ast::ty_int;
-    } else if (eat_word(p, "uint")) {
-        t = ast::ty_uint;
-    } else if (eat_word(p, "float")) {
-        t = ast::ty_float;
-    } else if (eat_word(p, "str")) {
-        t = ast::ty_str;
-    } else if (eat_word(p, "istr")) {
-        t = ast::ty_istr;
-    } else if (eat_word(p, "char")) {
-        t = ast::ty_char;
-    } else if (eat_word(p, "task")) {
-        t = ast::ty_task;
-    } else if (eat_word(p, "i8")) {
-        t = ast::ty_machine(common::ty_i8);
-    } else if (eat_word(p, "i16")) {
-        t = ast::ty_machine(common::ty_i16);
-    } else if (eat_word(p, "i32")) {
-        t = ast::ty_machine(common::ty_i32);
-    } else if (eat_word(p, "i64")) {
-        t = ast::ty_machine(common::ty_i64);
-    } else if (eat_word(p, "u8")) {
-        t = ast::ty_machine(common::ty_u8);
-    } else if (eat_word(p, "u16")) {
-        t = ast::ty_machine(common::ty_u16);
-    } else if (eat_word(p, "u32")) {
-        t = ast::ty_machine(common::ty_u32);
-    } else if (eat_word(p, "u64")) {
-        t = ast::ty_machine(common::ty_u64);
-    } else if (eat_word(p, "f32")) {
-        t = ast::ty_machine(common::ty_f32);
-    } else if (eat_word(p, "f64")) {
-        t = ast::ty_machine(common::ty_f64);
-    } else if (p.peek() == token::LPAREN) {
-        p.bump();
-        alt (p.peek()) {
-            case (token::RPAREN) {
-                hi = p.get_hi_pos();
-                p.bump();
-                t = ast::ty_nil;
-            }
-            case (_) {
-                t = parse_ty(p).node;
-                hi = p.get_hi_pos();
-                expect(p, token::RPAREN);
-            }
-        }
-    } else if (p.peek() == token::AT) {
-        p.bump();
-        auto mt = parse_mt(p);
-        hi = mt.ty.span.hi;
-        t = ast::ty_box(mt);
-    } else if (p.peek() == token::BINOP(token::STAR)) {
-        p.bump();
-        auto mt = parse_mt(p);
-        hi = mt.ty.span.hi;
-        t = ast::ty_ptr(mt);
-    } else if (eat_word(p, "vec")) {
-        expect(p, token::LBRACKET);
-        t = ast::ty_vec(parse_mt(p));
-        hi = p.get_hi_pos();
-        expect(p, token::RBRACKET);
-    } else if (eat_word(p, "tup")) {
-        auto elems =
-            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
-                      parse_mt, p);
-        hi = elems.span.hi;
-        t = ast::ty_tup(elems.node);
-    } else if (eat_word(p, "rec")) {
-        auto elems =
-            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
-                      parse_ty_field, p);
-        hi = elems.span.hi;
-        t = ast::ty_rec(elems.node);
-    } else if (eat_word(p, "fn")) {
-        auto flo = p.get_last_lo_pos();
-        t = parse_ty_fn(ast::proto_fn, p, flo);
-        alt (t) { case (ast::ty_fn(_, _, ?out, _, _)) { hi = out.span.hi; } }
-    } else if (eat_word(p, "iter")) {
-        auto flo = p.get_last_lo_pos();
-        t = parse_ty_fn(ast::proto_iter, p, flo);
-        alt (t) { case (ast::ty_fn(_, _, ?out, _, _)) { hi = out.span.hi; } }
-    } else if (eat_word(p, "obj")) {
-        t = parse_ty_obj(p, hi);
-    } else if (eat_word(p, "port")) {
-        expect(p, token::LBRACKET);
-        t = ast::ty_port(parse_ty(p));
-        hi = p.get_hi_pos();
-        expect(p, token::RBRACKET);
-    } else if (eat_word(p, "chan")) {
-        expect(p, token::LBRACKET);
-        t = ast::ty_chan(parse_ty(p));
-        hi = p.get_hi_pos();
-        expect(p, token::RBRACKET);
-    } else if (eat_word(p, "mutable")) {
-        p.get_session().span_warn(p.get_span(),
-                                  "ignoring deprecated 'mutable'"
-                                  + " type constructor");
-        auto typ = parse_ty(p);
-        t = typ.node;
-        hi = typ.span.hi;
-    } else if (is_ident(p.peek())) {
-        auto path = parse_path(p);
-        t = ast::ty_path(path, p.get_id());
-        hi = path.span.hi;
-    } else { p.fatal("expecting type"); t = ast::ty_nil; fail; }
-    ret parse_ty_postfix(@spanned(lo, hi, t), p);
-}
-
-fn parse_arg(&parser p) -> ast::arg {
-    let ast::mode m = ast::val;
-    if (p.peek() == token::BINOP(token::AND)) {
-        p.bump();
-        m = ast::alias(eat_word(p, "mutable"));
-    }
-    let @ast::ty t = parse_ty(p);
-    let ast::ident i = parse_value_ident(p);
-    ret rec(mode=m, ty=t, ident=i, id=p.get_id());
-}
-
-fn parse_seq_to_end[T](token::token ket, option::t[token::token] sep,
-                       fn(&parser) -> T  f, &parser p) -> vec[T] {
-    let bool first = true;
-    let vec[T] v = [];
-    while (p.peek() != ket) {
-        alt (sep) {
-            case (some(?t)) {
-                if (first) { first = false; } else { expect(p, t); }
-            }
-            case (_) { }
-        }
-        v += [f(p)];
-    }
-    expect(p, ket);
-    ret v;
-}
-
-fn parse_seq[T](token::token bra, token::token ket,
-                option::t[token::token] sep, fn(&parser) -> T  f, &parser p)
-   -> util::common::spanned[vec[T]] {
-    auto lo = p.get_lo_pos();
-    expect(p, bra);
-    auto result = parse_seq_to_end[T](ket, sep, f, p);
-    auto hi = p.get_hi_pos();
-    ret spanned(lo, hi, result);
-}
-
-fn parse_lit(&parser p) -> ast::lit {
-    auto sp = p.get_span();
-    let ast::lit_ lit = ast::lit_nil;
-    if (eat_word(p, "true")) {
-        lit = ast::lit_bool(true);
-    } else if (eat_word(p, "false")) {
-        lit = ast::lit_bool(false);
-    } else {
-        alt (p.peek()) {
-            case (token::LIT_INT(?i)) { p.bump(); lit = ast::lit_int(i); }
-            case (token::LIT_UINT(?u)) { p.bump(); lit = ast::lit_uint(u); }
-            case (token::LIT_FLOAT(?s)) {
-                p.bump();
-                lit = ast::lit_float(p.get_str(s));
-            }
-            case (token::LIT_MACH_INT(?tm, ?i)) {
-                p.bump();
-                lit = ast::lit_mach_int(tm, i);
-            }
-            case (token::LIT_MACH_FLOAT(?tm, ?s)) {
-                p.bump();
-                lit = ast::lit_mach_float(tm, p.get_str(s));
-            }
-            case (token::LIT_CHAR(?c)) { p.bump(); lit = ast::lit_char(c); }
-            case (token::LIT_STR(?s)) {
-                p.bump();
-                lit = ast::lit_str(p.get_str(s), ast::sk_rc);
-            }
-            case (?t) { unexpected(p, t); }
-        }
-    }
-    ret rec(node=lit, span=sp);
-}
-
-fn is_ident(token::token t) -> bool {
-    alt (t) { case (token::IDENT(_, _)) { ret true; } case (_) { } }
-    ret false;
-}
-
-fn parse_path(&parser p) -> ast::path {
-    auto lo = p.get_lo_pos();
-    auto hi = lo;
-    let vec[ast::ident] ids = [];
-    while (true) {
-        alt (p.peek()) {
-            case (token::IDENT(?i, _)) {
-                hi = p.get_hi_pos();
-                ids += [p.get_str(i)];
-                p.bump();
-                if (p.peek() == token::MOD_SEP) { p.bump(); } else { break; }
-            }
-            case (_) { break; }
-        }
-    }
-    hi = p.get_hi_pos();
-    ret spanned(lo, hi, rec(idents=ids, types=[]));
-}
-
-fn parse_path_and_ty_param_substs(&parser p) -> ast::path {
-    auto lo = p.get_lo_pos();
-    auto path = parse_path(p);
-    if (p.peek() == token::LBRACKET) {
-        auto seq = parse_seq(token::LBRACKET, token::RBRACKET,
-                             some(token::COMMA), parse_ty, p);
-        auto hi = p.get_hi_pos();
-        path = spanned(lo, hi, rec(idents=path.node.idents, types=seq.node));
-    }
-    ret path;
-}
-
-fn parse_mutability(&parser p) -> ast::mutability {
-    if (eat_word(p, "mutable")) {
-        if (p.peek() == token::QUES) { p.bump(); ret ast::maybe_mut; }
-        ret ast::mut;
-    }
-    ret ast::imm;
-}
-
-fn parse_field(&parser p) -> ast::field {
-    auto lo = p.get_lo_pos();
-    auto m = parse_mutability(p);
-    auto i = parse_ident(p);
-    expect(p, token::EQ);
-    auto e = parse_expr(p);
-    ret spanned(lo, e.span.hi, rec(mut=m, ident=i, expr=e));
-}
-
-fn mk_expr(&parser p, uint lo, uint hi, &ast::expr_ node) -> @ast::expr {
-    ret @rec(id=p.get_id(),
-             node=node,
-             span=rec(lo=lo, hi=hi));
-}
-
-fn parse_bottom_expr(&parser p) -> @ast::expr {
-    auto lo = p.get_lo_pos();
-    auto hi = p.get_hi_pos();
-    // FIXME: can only remove this sort of thing when both typestate and
-    // alt-exhaustive-match checking are co-operating.
-
-    auto lit = @spanned(lo, hi, ast::lit_nil);
-    let ast::expr_ ex = ast::expr_lit(lit);
-    if (p.peek() == token::LPAREN) {
-        p.bump();
-        alt (p.peek()) {
-            case (token::RPAREN) {
-                hi = p.get_hi_pos();
-                p.bump();
-                auto lit = @spanned(lo, hi, ast::lit_nil);
-                ret mk_expr(p, lo, hi, ast::expr_lit(lit));
-            }
-            case (_) {/* fall through */ }
-        }
-        auto e = parse_expr(p);
-        hi = p.get_hi_pos();
-        expect(p, token::RPAREN);
-        ret mk_expr(p, lo, hi, e.node);
-    } else if (p.peek() == token::LBRACE) {
-        auto blk = parse_block(p);
-        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
-    } else if (eat_word(p, "if")) {
-        ret parse_if_expr(p);
-    } else if (eat_word(p, "for")) {
-        ret parse_for_expr(p);
-    } else if (eat_word(p, "while")) {
-        ret parse_while_expr(p);
-    } else if (eat_word(p, "do")) {
-        ret parse_do_while_expr(p);
-    } else if (eat_word(p, "alt")) {
-        ret parse_alt_expr(p);
-    } else if (eat_word(p, "spawn")) {
-        ret parse_spawn_expr(p);
-    } else if (eat_word(p, "fn")) {
-        ret parse_fn_expr(p);
-    } else if (eat_word(p, "tup")) {
-        fn parse_elt(&parser p) -> ast::elt {
-            auto m = parse_mutability(p);
-            auto e = parse_expr(p);
-            ret rec(mut=m, expr=e);
-        }
-        auto es =
-            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
-                      parse_elt, p);
-        hi = es.span.hi;
-        ex = ast::expr_tup(es.node);
-    } else if (p.peek() == token::LBRACKET) {
-        p.bump();
-        auto mut = parse_mutability(p);
-        auto es =
-            parse_seq_to_end(token::RBRACKET, some(token::COMMA), parse_expr,
-                             p);
-        ex = ast::expr_vec(es, mut, ast::sk_rc);
-    } else if (p.peek() == token::TILDE) {
-        p.bump();
-        alt (p.peek()) {
-            case (token::LBRACKET) { // unique array (temporary)
-
-                p.bump();
-                auto mut = parse_mutability(p);
-                auto es =
-                    parse_seq_to_end(token::RBRACKET, some(token::COMMA),
-                                     parse_expr, p);
-                ex = ast::expr_vec(es, mut, ast::sk_unique);
-            }
-            case (token::LIT_STR(?s)) {
-                p.bump();
-                auto lit =
-                    @rec(node=ast::lit_str(p.get_str(s), ast::sk_unique),
-                         span=p.get_span());
-                ex = ast::expr_lit(lit);
-            }
-            case (_) {
-                p.get_session().span_unimpl(p.get_span(),
-                                            "unique pointer creation");
-            }
-        }
-    } else if (eat_word(p, "obj")) {
-        // Anonymous object
-
-        // FIXME: Can anonymous objects have ty params?
-        auto ty_params = parse_ty_params(p);
-
-        // Only make people type () if they're actually adding new fields
-        let option::t[vec[ast::anon_obj_field]] fields = none;
-        if (p.peek() == token::LPAREN) {
-            p.bump();
-            fields =
-                some(parse_seq_to_end(token::RPAREN, some(token::COMMA),
-                                      parse_anon_obj_field, p));
-        }
-        let vec[@ast::method] meths = [];
-        let option::t[@ast::expr] with_obj = none;
-        expect(p, token::LBRACE);
-        while (p.peek() != token::RBRACE) {
-            if (eat_word(p, "with")) {
-                with_obj = some(parse_expr(p));
-            } else { vec::push(meths, parse_method(p)); }
-        }
-        hi = p.get_hi_pos();
-        expect(p, token::RBRACE);
-        // fields and methods may be *additional* or *overriding* fields
-        // and methods if there's a with_obj, or they may be the *only*
-        // fields and methods if there's no with_obj.
-
-        // We don't need to pull ".node" out of fields because it's not a
-        // "spanned".
-        let ast::anon_obj ob =
-            rec(fields=fields, methods=meths, with_obj=with_obj);
-        auto odid = rec(ty=p.get_id(), ctor=p.get_id());
-        ex = ast::expr_anon_obj(ob, ty_params, odid);
-    } else if (eat_word(p, "rec")) {
-        expect(p, token::LPAREN);
-        auto fields = [parse_field(p)];
-        auto more = true;
-        auto base = none;
-        while (more) {
-            if (p.peek() == token::RPAREN) {
-                hi = p.get_hi_pos();
-                p.bump();
-                more = false;
-            } else if (eat_word(p, "with")) {
-                base = some(parse_expr(p));
-                hi = p.get_hi_pos();
-                expect(p, token::RPAREN);
-                more = false;
-            } else if (p.peek() == token::COMMA) {
-                p.bump();
-                fields += [parse_field(p)];
-            } else { unexpected(p, p.peek()); }
-        }
-        ex = ast::expr_rec(fields, base);
-    } else if (eat_word(p, "bind")) {
-        auto e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
-        fn parse_expr_opt(&parser p) -> option::t[@ast::expr] {
-            alt (p.peek()) {
-                case (token::UNDERSCORE) { p.bump(); ret none; }
-                case (_) { ret some(parse_expr(p)); }
-            }
-        }
-        auto es =
-            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
-                      parse_expr_opt, p);
-        hi = es.span.hi;
-        ex = ast::expr_bind(e, es.node);
-    } else if (p.peek() == token::POUND) {
-        auto ex_ext = parse_syntax_ext(p);
-        lo = ex_ext.span.lo;
-        ex = ex_ext.node;
-    } else if (eat_word(p, "fail")) {
-        if (can_begin_expr(p.peek())) {
-            auto e = parse_expr(p);
-            hi = e.span.hi;
-            ex = ast::expr_fail(some(e));
-        }
-        else {
-            ex = ast::expr_fail(none);
-        }
-    } else if (eat_word(p, "log")) {
-        auto e = parse_expr(p);
-        ex = ast::expr_log(1, e);
-    } else if (eat_word(p, "log_err")) {
-        auto e = parse_expr(p);
-        ex = ast::expr_log(0, e);
-    } else if (eat_word(p, "assert")) {
-        auto e = parse_expr(p);
-        ex = ast::expr_assert(e);
-    } else if (eat_word(p, "check")) {
-        /* Should be a predicate (pure boolean function) applied to 
-           arguments that are all either slot variables or literals.
-           but the typechecker enforces that. */
-
-        auto e = parse_expr(p);
-        ex = ast::expr_check(ast::checked, e);
-    } else if (eat_word(p, "claim")) {
-        /* Same rules as check, except that if check-claims
-         is enabled (a command-line flag), then the parser turns
-        claims into check */
-        
-        auto e = parse_expr(p);
-        ex = ast::expr_check(ast::unchecked, e);
-    } else if (eat_word(p, "ret")) {
-        alt (p.peek()) {
-            case (token::SEMI) { ex = ast::expr_ret(none); }
-            // Handle ret as the block result expression
-            case (token::RBRACE) { ex = ast::expr_ret(none); }
-            case (_) {
-                auto e = parse_expr(p);
-                hi = e.span.hi;
-                ex = ast::expr_ret(some(e));
-            }
-        }
-    } else if (eat_word(p, "break")) {
-        ex = ast::expr_break;
-    } else if (eat_word(p, "cont")) {
-        ex = ast::expr_cont;
-    } else if (eat_word(p, "put")) {
-        alt (p.peek()) {
-            case (token::SEMI) { ex = ast::expr_put(none); }
-            case (_) {
-                auto e = parse_expr(p);
-                hi = e.span.hi;
-                ex = ast::expr_put(some(e));
-            }
-        }
-    } else if (eat_word(p, "be")) {
-        auto e = parse_expr(p);
-
-        // FIXME: Is this the right place for this check?
-        if (/*check*/ast::is_call_expr(e)) {
-            hi = e.span.hi;
-            ex = ast::expr_be(e);
-        } else { p.fatal("Non-call expression in tail call"); }
-    } else if (eat_word(p, "port")) {
-        auto ty = none;
-        if(token::LBRACKET == p.peek()) {
-            expect(p, token::LBRACKET);
-            ty = some(parse_ty(p));
-            expect(p, token::RBRACKET);
-        }
-        expect(p, token::LPAREN);
-        expect(p, token::RPAREN);
-        hi = p.get_hi_pos();
-        ex = ast::expr_port(ty);
-    } else if (eat_word(p, "chan")) {
-        expect(p, token::LPAREN);
-        auto e = parse_expr(p);
-        hi = e.span.hi;
-        expect(p, token::RPAREN);
-        ex = ast::expr_chan(e);
-    } else if (eat_word(p, "self")) {
-        log "parsing a self-call...";
-        expect(p, token::DOT);
-        // The rest is a call expression.
-
-        let @ast::expr f = parse_self_method(p);
-        auto es =
-            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
-                      parse_expr, p);
-        hi = es.span.hi;
-        ex = ast::expr_call(f, es.node);
-    } else if (is_ident(p.peek()) && !is_word(p, "true") &&
-               !is_word(p, "false")) {
-        check_bad_word(p);
-        auto pth = parse_path_and_ty_param_substs(p);
-        hi = pth.span.hi;
-        ex = ast::expr_path(pth);
-    } else {
-        auto lit = parse_lit(p);
-        hi = lit.span.hi;
-        ex = ast::expr_lit(@lit);
-    }
-    ret mk_expr(p, lo, hi, ex);
-}
-
-fn parse_syntax_ext(&parser p) -> @ast::expr {
-    auto lo = p.get_lo_pos();
-    expect(p, token::POUND);
-    ret parse_syntax_ext_naked(p, lo);
-}
-
-fn parse_syntax_ext_naked(&parser p, uint lo) -> @ast::expr {
-    auto pth = parse_path(p);
-    if (vec::len(pth.node.idents) == 0u) {
-        p.fatal("expected a syntax expander name");
-    }
-    auto es = parse_seq(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, common::span sp, &ast::path path,
-                     vec[@ast::expr] args, option::t[str] body) ->
-   ast::expr_ {
-    assert (vec::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(ext::normal(?ext))) {
-            auto ext_cx = ext::mk_ctxt(p);
-            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(ext::macro_defining(?ext))) {
-            auto ext_cx = ext::mk_ctxt(p);
-            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(vec::empty[ast::elt]());
-        }
-    }
-}
-
-fn parse_self_method(&parser p) -> @ast::expr {
-    auto sp = p.get_span();
-    let ast::ident f_name = parse_ident(p);
-    ret mk_expr(p, sp.lo, sp.hi, ast::expr_self_method(f_name));
-}
-
-fn parse_dot_or_call_expr(&parser p) -> @ast::expr {
-    ret parse_dot_or_call_expr_with(p, parse_bottom_expr(p));
-}
-
-fn parse_dot_or_call_expr_with(&parser p, @ast::expr e) -> @ast::expr {
-    auto lo = e.span.lo;
-    auto hi = e.span.hi;
-    while (true) {
-        alt (p.peek()) {
-            case (token::LPAREN) {
-                if (p.get_restriction() == RESTRICT_NO_CALL_EXPRS) {
-                    ret e;
-                } else {
-                    // Call expr.
-
-                    auto es =
-                        parse_seq(token::LPAREN, token::RPAREN,
-                                  some(token::COMMA), parse_expr, p);
-                    hi = es.span.hi;
-                    e = mk_expr(p, lo, hi, ast::expr_call(e, es.node));
-                }
-            }
-            case (token::DOT) {
-                p.bump();
-                alt (p.peek()) {
-                    case (token::IDENT(?i, _)) {
-                        hi = p.get_hi_pos();
-                        p.bump();
-                        e = mk_expr(p, lo, hi,
-                                    ast::expr_field(e, p.get_str(i)));
-                    }
-                    case (token::LPAREN) {
-                        p.bump();
-                        auto ix = parse_expr(p);
-                        hi = ix.span.hi;
-                        expect(p, token::RPAREN);
-                        e = mk_expr(p, lo, hi, ast::expr_index(e, ix));
-                    }
-                    case (?t) { unexpected(p, t); }
-                }
-            }
-            case (_) { ret e; }
-        }
-    }
-    ret e;
-}
-
-fn parse_prefix_expr(&parser p) -> @ast::expr {
-    if (eat_word(p, "mutable")) {
-        p.get_session().span_warn(p.get_span(),
-                                  "ignoring deprecated 'mutable'"
-                                  + " prefix operator");
-    }
-    auto lo = p.get_lo_pos();
-    auto hi = p.get_hi_pos();
-    // FIXME: can only remove this sort of thing when both typestate and
-    // alt-exhaustive-match checking are co-operating.
-
-    auto lit = @spanned(lo, lo, ast::lit_nil);
-    let ast::expr_ ex = ast::expr_lit(lit);
-    alt (p.peek()) {
-        case (token::NOT) {
-            p.bump();
-            auto e = parse_prefix_expr(p);
-            hi = e.span.hi;
-            ex = ast::expr_unary(ast::not, e);
-        }
-        case (token::BINOP(?b)) {
-            alt (b) {
-                case (token::MINUS) {
-                    p.bump();
-                    auto e = parse_prefix_expr(p);
-                    hi = e.span.hi;
-                    ex = ast::expr_unary(ast::neg, e);
-                }
-                case (token::STAR) {
-                    p.bump();
-                    auto e = parse_prefix_expr(p);
-                    hi = e.span.hi;
-                    ex = ast::expr_unary(ast::deref, e);
-                }
-                case (_) { ret parse_dot_or_call_expr(p); }
-            }
-        }
-        case (token::AT) {
-            p.bump();
-            auto m = parse_mutability(p);
-            auto e = parse_prefix_expr(p);
-            hi = e.span.hi;
-            ex = ast::expr_unary(ast::box(m), e);
-        }
-        case (_) { ret parse_dot_or_call_expr(p); }
-    }
-    ret mk_expr(p, lo, hi, ex);
-}
-
-fn parse_ternary(&parser p) -> @ast::expr {
-    auto cond_expr = parse_binops(p);
-    if (p.peek() == token::QUES) {
-        p.bump();
-        auto then_expr = parse_expr(p);
-        expect(p, token::COLON);
-        auto else_expr = parse_expr(p);
-        ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
-                    ast::expr_ternary(cond_expr, then_expr, else_expr));
-    } else {
-        ret cond_expr;
-    }
-}
-
-type op_spec = rec(token::token tok, ast::binop op, int prec);
-
-
-// FIXME make this a const, don't store it in parser state
-fn prec_table() -> vec[op_spec] {
-    ret [rec(tok=token::BINOP(token::STAR), op=ast::mul, prec=11),
-         rec(tok=token::BINOP(token::SLASH), op=ast::div, prec=11),
-         rec(tok=token::BINOP(token::PERCENT), op=ast::rem, prec=11),
-         rec(tok=token::BINOP(token::PLUS), op=ast::add, prec=10),
-         rec(tok=token::BINOP(token::MINUS), op=ast::sub, prec=10),
-         rec(tok=token::BINOP(token::LSL), op=ast::lsl, prec=9),
-         rec(tok=token::BINOP(token::LSR), op=ast::lsr, prec=9),
-         rec(tok=token::BINOP(token::ASR), op=ast::asr, prec=9),
-         rec(tok=token::BINOP(token::AND), op=ast::bitand, prec=8),
-         rec(tok=token::BINOP(token::CARET), op=ast::bitxor, prec=6),
-         rec(tok=token::BINOP(token::OR), op=ast::bitor, prec=6),
-         // 'as' sits between here with 5
-         rec(tok=token::LT, op=ast::lt, prec=4),
-         rec(tok=token::LE, op=ast::le, prec=4),
-         rec(tok=token::GE, op=ast::ge, prec=4),
-         rec(tok=token::GT, op=ast::gt, prec=4),
-         rec(tok=token::EQEQ, op=ast::eq, prec=3),
-         rec(tok=token::NE, op=ast::ne, prec=3),
-         rec(tok=token::ANDAND, op=ast::and, prec=2),
-         rec(tok=token::OROR, op=ast::or, prec=1)];
-}
-
-fn parse_binops(&parser p) -> @ast::expr {
-    ret parse_more_binops(p, parse_prefix_expr(p), 0);
-}
-
-const int unop_prec = 100;
-
-const int as_prec = 5;
-const int ternary_prec = 0;
-
-fn parse_more_binops(&parser p, @ast::expr lhs, int min_prec) -> @ast::expr {
-    auto peeked = p.peek();
-    for (op_spec cur in p.get_prec_table()) {
-        if (cur.prec > min_prec && cur.tok == peeked) {
-            p.bump();
-            auto rhs = parse_more_binops(p, parse_prefix_expr(p), cur.prec);
-            auto bin = mk_expr(p, lhs.span.lo, rhs.span.hi,
-                               ast::expr_binary(cur.op, lhs, rhs));
-            ret parse_more_binops(p, bin, min_prec);
-        }
-    }
-    if (as_prec > min_prec && eat_word(p, "as")) {
-        auto rhs = parse_ty(p);
-        auto _as = mk_expr(p, lhs.span.lo, rhs.span.hi,
-                           ast::expr_cast(lhs, rhs));
-        ret parse_more_binops(p, _as, min_prec);
-    }
-    ret lhs;
-}
-
-fn parse_assign_expr(&parser p) -> @ast::expr {
-    auto lo = p.get_lo_pos();
-    auto lhs = parse_ternary(p);
-    alt (p.peek()) {
-        case (token::EQ) {
-            p.bump();
-            auto rhs = parse_expr(p);
-            ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign(lhs, rhs));
-        }
-        case (token::BINOPEQ(?op)) {
-            p.bump();
-            auto rhs = parse_expr(p);
-            auto aop = ast::add;
-            alt (op) {
-                case (token::PLUS) { aop = ast::add; }
-                case (token::MINUS) { aop = ast::sub; }
-                case (token::STAR) { aop = ast::mul; }
-                case (token::SLASH) { aop = ast::div; }
-                case (token::PERCENT) { aop = ast::rem; }
-                case (token::CARET) { aop = ast::bitxor; }
-                case (token::AND) { aop = ast::bitand; }
-                case (token::OR) { aop = ast::bitor; }
-                case (token::LSL) { aop = ast::lsl; }
-                case (token::LSR) { aop = ast::lsr; }
-                case (token::ASR) { aop = ast::asr; }
-            }
-            ret mk_expr(p, lo, rhs.span.hi,
-                        ast::expr_assign_op(aop, lhs, rhs));
-        }
-        case (token::LARROW) {
-            p.bump();
-            auto rhs = parse_expr(p);
-            ret mk_expr(p, lo, rhs.span.hi, ast::expr_move(lhs, rhs));
-        }
-        case (token::SEND) {
-            p.bump();
-            auto rhs = parse_expr(p);
-            ret mk_expr(p, lo, rhs.span.hi, ast::expr_send(lhs, rhs));
-        }
-        case (token::RECV) {
-            p.bump();
-            auto rhs = parse_expr(p);
-            ret mk_expr(p, lo, rhs.span.hi, ast::expr_recv(lhs, rhs));
-        }
-        case (token::DARROW) {
-            p.bump();
-            auto rhs = parse_expr(p);
-            ret mk_expr(p, lo, rhs.span.hi, ast::expr_swap(lhs, rhs));
-        }
-        case (_) {/* fall through */ }
-    }
-    ret lhs;
-}
-
-fn parse_if_expr_1(&parser p) -> tup(@ast::expr,
-                                     ast::block, option::t[@ast::expr],
-                                     uint, uint) {
-    auto lo = p.get_last_lo_pos();
-    expect(p, token::LPAREN);
-    auto cond = parse_expr(p);
-    expect(p, token::RPAREN);
-    auto thn = parse_block(p);
-    let option::t[@ast::expr] els = none;
-    auto hi = thn.span.hi;
-    if (eat_word(p, "else")) {
-        auto elexpr = parse_else_expr(p);
-        els = some(elexpr);
-        hi = elexpr.span.hi;
-    }
-    ret tup(cond, thn, els, lo, hi);
-}
-
-fn parse_if_expr(&parser p) -> @ast::expr {
-    if (eat_word(p, "check")) {
-            auto q = parse_if_expr_1(p);
-            ret mk_expr(p, q._3, q._4, ast::expr_if_check(q._0, q._1, q._2));
-    }
-    else {
-        auto q = parse_if_expr_1(p);
-        ret mk_expr(p, q._3, q._4, ast::expr_if(q._0, q._1, q._2));
-    }
-}
-
-fn parse_fn_expr(&parser p) -> @ast::expr {
-    auto lo = p.get_last_lo_pos();
-    auto decl = parse_fn_decl(p, ast::impure_fn);
-    auto body = parse_block(p);
-    auto _fn = rec(decl=decl, proto=ast::proto_fn, body=body);
-    ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
-}
-
-fn parse_else_expr(&parser p) -> @ast::expr {
-    if (eat_word(p, "if")) {
-        ret parse_if_expr(p);
-    } else {
-        auto blk = parse_block(p);
-        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
-    }
-}
-
-fn parse_head_local(&parser p) -> @ast::local {
-    if (is_word(p, "auto")) {
-        ret parse_auto_local(p);
-    } else { 
-        ret parse_typed_local(p);
-    }
-}
-
-fn parse_for_expr(&parser p) -> @ast::expr {
-    auto lo = p.get_last_lo_pos();
-    auto is_each = eat_word(p, "each");
-    expect(p, token::LPAREN);
-    auto decl = parse_head_local(p);
-    expect_word(p, "in");
-    auto seq = parse_expr(p);
-    expect(p, token::RPAREN);
-    auto body = parse_block(p);
-    auto hi = body.span.hi;
-    if (is_each) {
-        ret mk_expr(p, lo, hi, ast::expr_for_each(decl, seq, body));
-    } else {
-        ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
-    }
-}
-
-fn parse_while_expr(&parser p) -> @ast::expr {
-    auto lo = p.get_last_lo_pos();
-    expect(p, token::LPAREN);
-    auto cond = parse_expr(p);
-    expect(p, token::RPAREN);
-    auto body = parse_block(p);
-    auto hi = body.span.hi;
-    ret mk_expr(p, lo, hi, ast::expr_while(cond, body));
-}
-
-fn parse_do_while_expr(&parser p) -> @ast::expr {
-    auto lo = p.get_last_lo_pos();
-    auto body = parse_block(p);
-    expect_word(p, "while");
-    expect(p, token::LPAREN);
-    auto cond = parse_expr(p);
-    expect(p, token::RPAREN);
-    auto hi = cond.span.hi;
-    ret mk_expr(p, lo, hi, ast::expr_do_while(body, cond));
-}
-
-fn parse_alt_expr(&parser p) -> @ast::expr {
-    auto lo = p.get_last_lo_pos();
-    expect(p, token::LPAREN);
-    auto discriminant = parse_expr(p);
-    expect(p, token::RPAREN);
-    expect(p, token::LBRACE);
-    let vec[ast::arm] arms = [];
-    while (p.peek() != token::RBRACE) {
-        if (eat_word(p, "case")) {
-            expect(p, token::LPAREN);
-            auto pat = parse_pat(p);
-            expect(p, token::RPAREN);
-            auto block = parse_block(p);
-            arms += [rec(pat=pat, block=block)];
-        } else if (p.peek() == token::RBRACE) {
-            /* empty */
-
-        } else {
-            p.fatal("expected 'case' or '}' when parsing 'alt' statement " +
-                      "but found " + token::to_str(p.get_reader(), p.peek()));
-        }
-    }
-    auto hi = p.get_hi_pos();
-    p.bump();
-    ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms));
-}
-
-fn parse_spawn_expr(&parser p) -> @ast::expr {
-    auto lo = p.get_last_lo_pos();
-    // FIXME: Parse domain and name
-    // FIXME: why no full expr?
-
-    auto fn_expr = parse_bottom_expr(p);
-    auto es =
-        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
-                  parse_expr, p);
-    auto hi = es.span.hi;
-    ret mk_expr(p, lo, hi, ast::expr_spawn
-                (ast::dom_implicit, option::none, fn_expr, es.node));
-}
-
-fn parse_expr(&parser p) -> @ast::expr {
-    ret parse_expr_res(p, UNRESTRICTED);
-}
-
-fn parse_expr_res(&parser p, restriction r) -> @ast::expr {
-    auto old = p.get_restriction();
-    p.restrict(r);
-    auto e = parse_assign_expr(p);
-    p.restrict(old);
-    ret e;
-}
-
-fn parse_initializer(&parser p) -> option::t[ast::initializer] {
-    alt (p.peek()) {
-        case (token::EQ) {
-            p.bump();
-            ret some(rec(op=ast::init_assign, expr=parse_expr(p)));
-        }
-        case (token::LARROW) {
-            p.bump();
-            ret some(rec(op=ast::init_move, expr=parse_expr(p)));
-        }
-        case (
-             // Now that the the channel is the first argument to receive,
-             // combining it with an initializer doesn't really make sense.
-             // case (token::RECV) {
-             //     p.bump();
-             //     ret some(rec(op = ast::init_recv,
-             //                  expr = parse_expr(p)));
-             // }
-             _) {
-            ret none;
-        }
-    }
-}
-
-fn parse_pat(&parser p) -> @ast::pat {
-    auto lo = p.get_lo_pos();
-    auto hi = p.get_hi_pos();
-    auto pat;
-    alt (p.peek()) {
-        case (token::UNDERSCORE) {
-            p.bump();
-            pat = ast::pat_wild;
-        }
-        case (token::QUES) {
-            p.bump();
-            alt (p.peek()) {
-                case (token::IDENT(?id, _)) {
-                    hi = p.get_hi_pos();
-                    p.bump();
-                    pat = ast::pat_bind(p.get_str(id));
-                }
-                case (?tok) {
-                    p.fatal("expected identifier after '?' in pattern but " +
-                              "found " + token::to_str(p.get_reader(), tok));
-                    fail;
-                }
-            }
-        }
-        case (?tok) {
-            if (!is_ident(tok) || is_word(p, "true") || is_word(p, "false")) {
-                auto lit = parse_lit(p);
-                hi = lit.span.hi;
-                pat = ast::pat_lit(@lit);
-            } else {
-                auto tag_path = parse_path_and_ty_param_substs(p);
-                hi = tag_path.span.hi;
-                let vec[@ast::pat] args;
-                alt (p.peek()) {
-                    case (token::LPAREN) {
-                        auto f = parse_pat;
-                        auto a =
-                            parse_seq(token::LPAREN, token::RPAREN,
-                                      some(token::COMMA), f, p);
-                        args = a.node;
-                        hi = a.span.hi;
-                    }
-                    case (_) { args = []; }
-                }
-                pat = ast::pat_tag(tag_path, args);
-            }
-        }
-    }
-    ret @rec(id=p.get_id(), node=pat, span=rec(lo=lo, hi=hi));
-}
-
-fn parse_local_full(&option::t[@ast::ty] tyopt, &parser p)
-    -> @ast::local {
-    auto lo = p.get_lo_pos();
-    auto ident = parse_value_ident(p);
-    auto init = parse_initializer(p);
-    ret @spanned(lo, p.get_hi_pos(),
-                 rec(ty=tyopt,
-                     infer=false,
-                     ident=ident,
-                     init=init,
-                     id=p.get_id()));
-}
-
-fn parse_typed_local(&parser p) -> @ast::local {
-    auto ty = parse_ty(p);
-    ret parse_local_full(some(ty), p);
-}
-
-fn parse_auto_local(&parser p) -> @ast::local {
-    ret parse_local_full(none, p);
-}
-
-fn parse_let(&parser p) -> @ast::decl {
-    auto lo = p.get_last_lo_pos();
-    auto local = parse_typed_local(p);
-    ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local));
-}
-
-fn parse_auto(&parser p) -> @ast::decl {
-    auto lo = p.get_last_lo_pos();
-    auto local = parse_auto_local(p);
-    ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local));
-}
-
-fn parse_stmt(&parser p) -> @ast::stmt {
-    if (p.get_file_type() == SOURCE_FILE) {
-        ret parse_source_stmt(p);
-    } else { ret parse_crate_stmt(p); }
-}
-
-fn parse_crate_stmt(&parser p) -> @ast::stmt {
-    auto cdir = parse_crate_directive(p, []);
-    ret @spanned(cdir.span.lo, cdir.span.hi,
-                 ast::stmt_crate_directive(@cdir));
-}
-
-fn parse_source_stmt(&parser p) -> @ast::stmt {
-    auto lo = p.get_lo_pos();
-    if (eat_word(p, "let")) {
-        auto decl = parse_let(p);
-        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
-    } else if (eat_word(p, "auto")) {
-        auto decl = parse_auto(p);
-        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
-    } else {
-
-        auto item_attrs;
-        alt (parse_outer_attrs_or_ext(p)) {
-            case (none) {
-                item_attrs = [];
-            }
-            case (some(left(?attrs))) {
-                item_attrs = attrs;
-            }
-            case (some(right(?ext))) {
-                ret @spanned(lo, ext.span.hi,
-                             ast::stmt_expr(ext, p.get_id()));
-            }
-        }
-
-        auto maybe_item = parse_item(p, item_attrs);
-
-        // If we have attributes then we should have an item
-        if (vec::len(item_attrs) > 0u) {
-            alt (maybe_item) {
-                case (got_item(_)) { /* fallthrough */ }
-                case (_) {
-                    ret p.fatal("expected item");
-                }
-            }
-        }
-
-        alt (maybe_item) {
-            case (got_item(?i)) {
-                auto hi = i.span.hi;
-                auto decl = @spanned(lo, hi, ast::decl_item(i));
-                ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_id()));
-            }
-            case (fn_no_item) { // parse_item will have already skipped "fn"
-
-                auto e = parse_fn_expr(p);
-                e = parse_dot_or_call_expr_with(p, e);
-                ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
-            }
-            case (no_item) {
-                // Remainder are line-expr stmts.
-
-                auto e = parse_expr(p);
-                ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
-            }
-        }
-    }
-    p.fatal("expected statement");
-    fail;
-}
-
-fn stmt_to_expr(@ast::stmt stmt) -> option::t[@ast::expr] {
-    ret alt (stmt.node) {
-            case (ast::stmt_expr(?e, _)) { some(e) }
-            case (_) { none }
-        };
-}
-
-fn stmt_ends_with_semi(&ast::stmt stmt) -> bool {
-    alt (stmt.node) {
-        case (ast::stmt_decl(?d, _)) {
-            ret alt (d.node) {
-                case (ast::decl_local(_)) { true }
-                case (ast::decl_item(_)) { false }
-            }
-        }
-        case (ast::stmt_expr(?e, _)) {
-            ret alt (e.node) {
-                case (ast::expr_vec(_, _, _)) { true }
-                case (ast::expr_tup(_)) { true }
-                case (ast::expr_rec(_, _)) { true }
-                case (ast::expr_call(_, _)) { true }
-                case (ast::expr_self_method(_)) { false }
-                case (ast::expr_bind(_, _)) { true }
-                case (ast::expr_spawn(_, _, _, _)) { true }
-                case (ast::expr_binary(_, _, _)) { true }
-                case (ast::expr_unary(_, _)) { true }
-                case (ast::expr_lit(_)) { true }
-                case (ast::expr_cast(_, _)) { true }
-                case (ast::expr_if(_, _, _)) { false }
-                case (ast::expr_ternary(_, _, _)) { true }
-                case (ast::expr_for(_, _, _)) { false }
-                case (ast::expr_for_each(_, _, _)) { false }
-                case (ast::expr_while(_, _)) { false }
-                case (ast::expr_do_while(_, _)) { false }
-                case (ast::expr_alt(_, _)) { false }
-                case (ast::expr_fn(_)) { false }
-                case (ast::expr_block(_)) { false }
-                case (ast::expr_move(_, _)) { true }
-                case (ast::expr_assign(_, _)) { true }
-                case (ast::expr_swap(_, _)) { true }
-                case (ast::expr_assign_op(_, _, _)) { true }
-                case (ast::expr_send(_, _)) { true }
-                case (ast::expr_recv(_, _)) { true }
-                case (ast::expr_field(_, _)) { true }
-                case (ast::expr_index(_, _)) { true }
-                case (ast::expr_path(_)) { true }
-                case (ast::expr_ext(_, _, _, _)) { true }
-                case (ast::expr_fail(_)) { true }
-                case (ast::expr_break) { true }
-                case (ast::expr_cont) { true }
-                case (ast::expr_ret(_)) { true }
-                case (ast::expr_put(_)) { true }
-                case (ast::expr_be(_)) { true }
-                case (ast::expr_log(_, _)) { true }
-                case (ast::expr_check(_, _)) { true }
-                case (ast::expr_if_check(_, _, _)) { false }
-                case (ast::expr_port(_)) { true }
-                case (ast::expr_chan(_)) { true }
-                case (ast::expr_anon_obj(_,_,_)) { false }
-                case (ast::expr_assert(_)) { true }
-            }
-        }
-        // We should not be calling this on a cdir.
-        case (ast::stmt_crate_directive(?cdir)) {
-            fail;
-        }
-    }
-}
-
-fn parse_block(&parser p) -> ast::block {
-    auto lo = p.get_lo_pos();
-    let vec[@ast::stmt] stmts = [];
-    let option::t[@ast::expr] expr = none;
-    expect(p, token::LBRACE);
-    while (p.peek() != token::RBRACE) {
-        alt (p.peek()) {
-            case (token::SEMI) {
-                p.bump(); // empty
-            }
-            case (_) {
-                auto stmt = parse_stmt(p);
-                alt (stmt_to_expr(stmt)) {
-                    case (some(?e)) {
-                        alt (p.peek()) {
-                            case (token::SEMI) { p.bump(); stmts += [stmt]; }
-                            case (token::RBRACE) { expr = some(e); }
-                            case (?t) {
-                                if (stmt_ends_with_semi(*stmt)) {
-                                    p.fatal("expected ';' or '}' after " +
-                                              "expression but found " +
-                                              token::to_str(p.get_reader(),
-                                                            t));
-                                    fail;
-                                }
-                                stmts += [stmt];
-                            }
-                        }
-                    }
-                    case (none) {
-                        // Not an expression statement.
-                        stmts += [stmt];
-
-                        if (p.get_file_type() == SOURCE_FILE
-                            && stmt_ends_with_semi(*stmt)) {
-                            expect(p, token::SEMI);
-                        }
-                    }
-                }
-            }
-        }
-    }
-    auto hi = p.get_hi_pos();
-    p.bump();
-    auto bloc = rec(stmts=stmts, expr=expr, id=p.get_id());
-    ret spanned(lo, hi, bloc);
-}
-
-fn parse_ty_param(&parser p) -> ast::ty_param { ret parse_ident(p); }
-
-fn parse_ty_params(&parser p) -> vec[ast::ty_param] {
-    let vec[ast::ty_param] ty_params = [];
-    if (p.peek() == token::LBRACKET) {
-        ty_params =
-            parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA),
-                      parse_ty_param, p).node;
-    }
-    ret ty_params;
-}
-
-fn parse_fn_decl(&parser p, ast::purity purity) -> ast::fn_decl {
-    let util::common::spanned[vec[ast::arg]] inputs =
-        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_arg,
-                  p);
-    let ty_or_bang rslt;
-    auto constrs = parse_constrs(inputs.node, p).node;
-    if (p.peek() == token::RARROW) {
-        p.bump();
-        rslt = parse_ty_or_bang(p);
-    } else {
-        rslt = a_ty(@spanned(inputs.span.lo, inputs.span.hi, ast::ty_nil));
-    }
-    alt (rslt) {
-        case (a_ty(?t)) {
-            ret rec(inputs=inputs.node,
-                    output=t,
-                    purity=purity,
-                    cf=ast::return,
-                    constraints=constrs);
-        }
-        case (a_bang) {
-            ret rec(inputs=inputs.node,
-                    output=@spanned(p.get_lo_pos(), p.get_hi_pos(),
-                                    ast::ty_bot),
-                    purity=purity,
-                    cf=ast::noreturn,
-                    constraints=constrs);
-        }
-    }
-}
-
-fn parse_fn(&parser p, ast::proto proto, ast::purity purity) -> ast::_fn {
-    auto decl = parse_fn_decl(p, purity);
-    auto body = parse_block(p);
-    ret rec(decl=decl, proto=proto, body=body);
-}
-
-fn parse_fn_header(&parser p) -> tup(ast::ident, vec[ast::ty_param]) {
-    auto id = parse_value_ident(p);
-    auto ty_params = parse_ty_params(p);
-    ret tup(id, ty_params);
-}
-
-fn mk_item(&parser p, uint lo, uint hi, &ast::ident ident, &ast::item_ node,
-           &vec[ast::attribute] attrs) -> @ast::item {
-    ret @rec(ident=ident,
-             attrs=attrs,
-             id=p.get_id(),
-             node=node,
-             span=rec(lo=lo, hi=hi));
-}
-
-fn parse_item_fn_or_iter(&parser p, ast::purity purity, ast::proto proto,
-                         vec[ast::attribute] attrs) -> @ast::item {
-    auto lo = p.get_last_lo_pos();
-    auto t = parse_fn_header(p);
-    auto f = parse_fn(p, proto, purity);
-    ret mk_item(p, lo, f.body.span.hi, t._0, ast::item_fn(f, t._1), attrs);
-}
-
-fn parse_obj_field(&parser p) -> ast::obj_field {
-    auto mut = parse_mutability(p);
-    auto ty = parse_ty(p);
-    auto ident = parse_value_ident(p);
-    ret rec(mut=mut, ty=ty, ident=ident, id=p.get_id());
-}
-
-fn parse_anon_obj_field(&parser p) -> ast::anon_obj_field {
-    auto mut = parse_mutability(p);
-    auto ty = parse_ty(p);
-    auto ident = parse_value_ident(p);
-    expect(p, token::EQ);
-    auto expr = parse_expr(p);
-    ret rec(mut=mut, ty=ty, expr=expr, ident=ident, id=p.get_id());
-}
-
-fn parse_method(&parser p) -> @ast::method {
-    auto lo = p.get_lo_pos();
-    auto proto = parse_proto(p);
-    auto ident = parse_value_ident(p);
-    auto f = parse_fn(p, proto, ast::impure_fn);
-    auto meth = rec(ident=ident, meth=f, id=p.get_id());
-    ret @spanned(lo, f.body.span.hi, meth);
-}
-
-fn parse_dtor(&parser p) -> @ast::method {
-    auto lo = p.get_last_lo_pos();
-    let ast::block b = parse_block(p);
-    let vec[ast::arg] inputs = [];
-    let @ast::ty output = @spanned(lo, lo, ast::ty_nil);
-    let ast::fn_decl d =
-        rec(inputs=inputs,
-            output=output,
-            purity=ast::impure_fn,
-            cf=ast::return,
-
-            // I guess dtors can't have constraints? 
-            constraints=[]);
-    let ast::_fn f = rec(decl=d, proto=ast::proto_fn, body=b);
-    let ast::method_ m =
-        rec(ident="drop", meth=f, id=p.get_id());
-    ret @spanned(lo, f.body.span.hi, m);
-}
-
-fn parse_item_obj(&parser p, ast::layer lyr, vec[ast::attribute] attrs) ->
-   @ast::item {
-    auto lo = p.get_last_lo_pos();
-    auto ident = parse_value_ident(p);
-    auto ty_params = parse_ty_params(p);
-    let util::common::spanned[vec[ast::obj_field]] fields =
-        parse_seq[ast::obj_field](token::LPAREN, token::RPAREN,
-                                  some(token::COMMA), parse_obj_field, p);
-    let vec[@ast::method] meths = [];
-    let option::t[@ast::method] dtor = none;
-    expect(p, token::LBRACE);
-    while (p.peek() != token::RBRACE) {
-        if (eat_word(p, "drop")) {
-            dtor = some(parse_dtor(p));
-        } else { vec::push(meths, parse_method(p)); }
-    }
-    auto hi = p.get_hi_pos();
-    expect(p, token::RBRACE);
-    let ast::_obj ob = rec(fields=fields.node, methods=meths, dtor=dtor);
-    ret mk_item(p, lo, hi, ident, ast::item_obj(ob, ty_params,
-                                                p.get_id()), attrs);
-}
-
-fn parse_item_res(&parser p, ast::layer lyr, vec[ast::attribute] attrs) ->
-   @ast::item {
-    auto lo = p.get_last_lo_pos();
-    auto ident = parse_value_ident(p);
-    auto ty_params = parse_ty_params(p);
-    expect(p, token::LPAREN);
-    auto t = parse_ty(p);
-    auto arg_ident = parse_value_ident(p);
-    expect(p, token::RPAREN);
-    auto dtor = parse_block(p);
-    auto decl = rec(inputs=[rec(mode=ast::alias(false), ty=t, ident=arg_ident,
-                                id=p.get_id())],
-                    output=@spanned(lo, lo, ast::ty_nil),
-                    purity=ast::impure_fn,
-                    cf=ast::return,
-                    constraints=[]);
-    auto f = rec(decl=decl, proto=ast::proto_fn, body=dtor);
-    ret mk_item(p, lo, dtor.span.hi, ident,
-                ast::item_res(f, p.get_id(), ty_params, p.get_id()), attrs);
-}
-
-fn parse_mod_items(&parser p, token::token term,
-                   vec[ast::attribute] first_item_attrs) -> ast::_mod {
-    auto view_items = if (vec::len(first_item_attrs) == 0u) {
-        parse_view(p)
-    } else {
-        // Shouldn't be any view items since we've already parsed an item attr
-        []
-    };
-    let vec[@ast::item] items = [];
-    auto initial_attrs = first_item_attrs;
-    while (p.peek() != term) {
-        auto attrs = initial_attrs + parse_outer_attributes(p);
-        initial_attrs = [];
-        alt (parse_item(p, attrs)) {
-            case (got_item(?i)) { vec::push(items, i); }
-            case (_) {
-                p.fatal("expected item but found " +
-                          token::to_str(p.get_reader(), p.peek()));
-            }
-        }
-    }
-    ret rec(view_items=view_items, items=items);
-}
-
-fn parse_item_const(&parser p, vec[ast::attribute] attrs) -> @ast::item {
-    auto lo = p.get_last_lo_pos();
-    auto ty = parse_ty(p);
-    auto id = parse_value_ident(p);
-    expect(p, token::EQ);
-    auto e = parse_expr(p);
-    auto hi = p.get_hi_pos();
-    expect(p, token::SEMI);
-    ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
-}
-
-fn parse_item_mod(&parser p, vec[ast::attribute] attrs) -> @ast::item {
-    auto lo = p.get_last_lo_pos();
-    auto id = parse_ident(p);
-    expect(p, token::LBRACE);
-    auto inner_attrs = parse_inner_attrs_and_next(p);
-    auto first_item_outer_attrs = inner_attrs._1;
-    auto m = parse_mod_items(p, token::RBRACE,
-                             first_item_outer_attrs);
-    auto hi = p.get_hi_pos();
-    expect(p, token::RBRACE);
-    ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs._0);
-}
-
-fn parse_item_native_type(&parser p) -> @ast::native_item {
-    auto t = parse_type_decl(p);
-    auto hi = p.get_hi_pos();
-    expect(p, token::SEMI);
-    ret @rec(ident=t._1,
-             node=ast::native_item_ty,
-             id=p.get_id(),
-             span=rec(lo=t._0, hi=hi));
-}
-
-fn parse_item_native_fn(&parser p) -> @ast::native_item {
-    auto lo = p.get_last_lo_pos();
-    auto t = parse_fn_header(p);
-    auto decl = parse_fn_decl(p, ast::impure_fn);
-    auto link_name = none;
-    if (p.peek() == token::EQ) {
-        p.bump();
-        link_name = some(parse_str(p));
-    }
-    auto hi = p.get_hi_pos();
-    expect(p, token::SEMI);
-    ret @rec(ident=t._0,
-             node=ast::native_item_fn(link_name, decl, t._1),
-             id=p.get_id(),
-             span=rec(lo=lo, hi=hi));
-}
-
-fn parse_native_item(&parser p) -> @ast::native_item {
-    parse_layer(p);
-    if (eat_word(p, "type")) {
-        ret parse_item_native_type(p);
-    } else if (eat_word(p, "fn")) {
-        ret parse_item_native_fn(p);
-    } else { unexpected(p, p.peek()); fail; }
-}
-
-fn parse_native_mod_items(&parser p, &str native_name, ast::native_abi abi) ->
-   ast::native_mod {
-    let vec[@ast::native_item] items = [];
-    auto view_items = parse_native_view(p);
-    while (p.peek() != token::RBRACE) { items += [parse_native_item(p)]; }
-    ret rec(native_name=native_name,
-            abi=abi,
-            view_items=view_items,
-            items=items);
-}
-
-fn parse_item_native_mod(&parser p, vec[ast::attribute] attrs) -> @ast::item {
-    auto lo = p.get_last_lo_pos();
-    auto abi = ast::native_abi_cdecl;
-    if (!is_word(p, "mod")) {
-        auto t = parse_str(p);
-        if (str::eq(t, "cdecl")) {
-        } else if (str::eq(t, "rust")) {
-            abi = ast::native_abi_rust;
-        } else if (str::eq(t, "llvm")) {
-            abi = ast::native_abi_llvm;
-        } else if (str::eq(t, "rust-intrinsic")) {
-            abi = ast::native_abi_rust_intrinsic;
-        } else { p.fatal("unsupported abi: " + t); fail; }
-    }
-    expect_word(p, "mod");
-    auto id = parse_ident(p);
-    auto native_name;
-    if (p.peek() == token::EQ) {
-        expect(p, token::EQ);
-        native_name = parse_str(p);
-    } else {
-        native_name = id;
-    }
-    expect(p, token::LBRACE);
-    auto m = parse_native_mod_items(p, native_name, abi);
-    auto hi = p.get_hi_pos();
-    expect(p, token::RBRACE);
-    ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs);
-}
-
-fn parse_type_decl(&parser p) -> tup(uint, ast::ident) {
-    auto lo = p.get_last_lo_pos();
-    auto id = parse_ident(p);
-    ret tup(lo, id);
-}
-
-fn parse_item_type(&parser p, vec[ast::attribute] attrs) -> @ast::item {
-    auto t = parse_type_decl(p);
-    auto tps = parse_ty_params(p);
-    expect(p, token::EQ);
-    auto ty = parse_ty(p);
-    auto hi = p.get_hi_pos();
-    expect(p, token::SEMI);
-    ret mk_item(p, t._0, hi, t._1, ast::item_ty(ty, tps), attrs);
-}
-
-fn parse_item_tag(&parser p, vec[ast::attribute] attrs) -> @ast::item {
-    auto lo = p.get_last_lo_pos();
-    auto id = parse_ident(p);
-    auto ty_params = parse_ty_params(p);
-    let vec[ast::variant] variants = [];
-    // Newtype syntax
-    if (p.peek() == token::EQ) {
-        if (p.get_bad_expr_words().contains_key(id)) {
-            p.fatal("found " + id + " in tag constructor position");
-        }
-        p.bump();
-        auto ty = parse_ty(p);
-        expect(p, token::SEMI);
-        auto variant = spanned(ty.span.lo, ty.span.hi,
-                               rec(name=id,
-                                   args=[rec(ty=ty, id=p.get_id())],
-                                   id=p.get_id()));
-        ret mk_item(p, lo, ty.span.hi, id,
-                    ast::item_tag([variant], ty_params), attrs);
-    }
-    expect(p, token::LBRACE);
-    while (p.peek() != token::RBRACE) {
-        auto tok = p.peek();
-        alt (tok) {
-            case (token::IDENT(?name, _)) {
-                check_bad_word(p);
-                auto vlo = p.get_lo_pos();
-                p.bump();
-                let vec[ast::variant_arg] args = [];
-                alt (p.peek()) {
-                    case (token::LPAREN) {
-                        auto arg_tys =
-                            parse_seq(token::LPAREN, token::RPAREN,
-                                      some(token::COMMA), parse_ty, p);
-                        for (@ast::ty ty in arg_tys.node) {
-                            args += [rec(ty=ty, id=p.get_id())];
-                        }
-                    }
-                    case (_) {/* empty */ }
-                }
-                auto vhi = p.get_hi_pos();
-                expect(p, token::SEMI);
-                p.get_id();
-                auto vr =
-                    rec(name=p.get_str(name),
-                        args=args,
-                        id=p.get_id());
-                variants += [spanned(vlo, vhi, vr)];
-            }
-            case (token::RBRACE) {/* empty */ }
-            case (_) {
-                p.fatal("expected name of variant or '}' but found " +
-                          token::to_str(p.get_reader(), tok));
-            }
-        }
-    }
-    auto hi = p.get_hi_pos();
-    p.bump();
-    ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs);
-}
-
-fn parse_layer(&parser p) -> ast::layer {
-    if (eat_word(p, "state")) {
-        ret ast::layer_state;
-    } else if (eat_word(p, "gc")) {
-        ret ast::layer_gc;
-    } else { ret ast::layer_value; }
-    fail;
-}
-
-fn parse_auth(&parser p) -> ast::_auth {
-    if (eat_word(p, "unsafe")) {
-        ret ast::auth_unsafe;
-    } else { unexpected(p, p.peek()); }
-    fail;
-}
-
-tag parsed_item { got_item(@ast::item); no_item; fn_no_item; }
-
-fn parse_item(&parser p, vec[ast::attribute] attrs) -> parsed_item {
-    if (eat_word(p, "const")) {
-        ret got_item(parse_item_const(p, attrs));
-    } else if (eat_word(p, "fn")) {
-        // This is an anonymous function
-
-        if (p.peek() == token::LPAREN) { ret fn_no_item; }
-        ret got_item(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_fn,
-                                           attrs));
-    } else if (eat_word(p, "pred")) {
-        ret got_item(parse_item_fn_or_iter(p, ast::pure_fn, ast::proto_fn,
-                                           attrs));
-    } else if (eat_word(p, "iter")) {
-        ret got_item(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_iter,
-                                           attrs));
-    } else if (eat_word(p, "mod")) {
-        ret got_item(parse_item_mod(p, attrs));
-    } else if (eat_word(p, "native")) {
-        ret got_item(parse_item_native_mod(p, attrs));
-    }
-    auto lyr = parse_layer(p);
-    if (eat_word(p, "type")) {
-        ret got_item(parse_item_type(p, attrs));
-    } else if (eat_word(p, "tag")) {
-        ret got_item(parse_item_tag(p, attrs));
-    } else if (eat_word(p, "obj")) {
-        ret got_item(parse_item_obj(p, lyr, attrs));
-    } else if (eat_word(p, "resource")) {
-        ret got_item(parse_item_res(p, lyr, attrs));
-    } else { ret no_item; }
-}
-
-// A type to distingush between the parsing of item attributes or syntax
-// extensions, which both begin with token.POUND
-type attr_or_ext = option::t[either::t[vec[ast::attribute],
-                                       @ast::expr]];
-
-fn parse_outer_attrs_or_ext(&parser p) -> attr_or_ext {
-    if (p.peek() == token::POUND) {
-        auto lo = p.get_lo_pos();
-        p.bump();
-        if (p.peek() == token::LBRACKET) {
-            auto first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
-            ret some(left([first_attr] + parse_outer_attributes(p)));
-        } else {
-            ret some(right(parse_syntax_ext_naked(p, lo)));
-        }
-    } else {
-        ret none;
-    }
-}
-
-// Parse attributes that appear before an item
-fn parse_outer_attributes(&parser p) -> vec[ast::attribute] {
-    let vec[ast::attribute] attrs = [];
-    while (p.peek() == token::POUND) {
-        attrs += [parse_attribute(p, ast::attr_outer)];
-    }
-    ret attrs;
-}
-
-fn parse_attribute(&parser p, ast::attr_style style) -> ast::attribute {
-    auto lo = p.get_lo_pos();
-    expect(p, token::POUND);
-    ret parse_attribute_naked(p, style, lo);
-}
-
-fn parse_attribute_naked(&parser p, ast::attr_style style,
-                         uint lo) -> ast::attribute {
-    expect(p, token::LBRACKET);
-    auto meta_item = parse_meta_item(p);
-    expect(p, token::RBRACKET);
-    auto hi = p.get_hi_pos();
-    ret spanned(lo, hi, rec(style=style, value=*meta_item));
-}
-
-// Parse attributes that appear after the opening of an item, each terminated
-// by a semicolon. In addition to a vector of inner attributes, this function
-// also returns a vector that may contain the first outer attribute of the
-// next item (since we can't know whether the attribute is an inner attribute
-// of the containing item or an outer attribute of the first contained item
-// until we see the semi).
-fn parse_inner_attrs_and_next(&parser p) -> tup(vec[ast::attribute],
-                                                vec[ast::attribute]) {
-    let vec[ast::attribute] inner_attrs = [];
-    let vec[ast::attribute] next_outer_attrs = [];
-    while (p.peek() == token::POUND) {
-        auto attr = parse_attribute(p, ast::attr_inner);
-        if (p.peek() == token::SEMI) {
-            p.bump();
-            inner_attrs += [attr];
-        } else {
-            // It's not really an inner attribute
-            auto outer_attr = spanned(attr.span.lo,
-                                      attr.span.hi,
-                                      rec(style=ast::attr_outer,
-                                          value=attr.node.value));
-            next_outer_attrs += [outer_attr];
-            break;
-        }
-    }
-    ret tup(inner_attrs, next_outer_attrs);
-}
-
-fn parse_meta_item(&parser p) -> @ast::meta_item {
-    auto lo = p.get_lo_pos();
-    auto ident = parse_ident(p);
-    alt (p.peek()) {
-        case (token::EQ) {
-            p.bump();
-            alt (p.peek()) {
-                case (token::LIT_STR(?s)) {
-                    p.bump();
-                    auto value = p.get_str(s);
-                    auto hi = p.get_hi_pos();
-                    ret @spanned(lo, hi, ast::meta_name_value(ident, value));
-                }
-                case (_) {
-                    p.fatal("Metadata items must be string literals");
-                }
-            }
-        }
-        case (token::LPAREN) {
-            auto inner_items = parse_meta_seq(p);
-            auto hi = p.get_hi_pos();
-            ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
-        }
-        case (_) {
-            auto hi = p.get_hi_pos();
-            ret @spanned(lo, hi, ast::meta_word(ident));
-        }
-    }
-}
-
-fn parse_meta_seq(&parser p) -> vec[@ast::meta_item] {
-    ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
-                  parse_meta_item, p).node;
-}
-
-fn parse_optional_meta(&parser p) -> vec[@ast::meta_item] {
-    alt (p.peek()) {
-        case (token::LPAREN) { ret parse_meta_seq(p); }
-        case (_) { let vec[@ast::meta_item] v = []; ret v; }
-    }
-}
-
-fn parse_use(&parser p) -> @ast::view_item {
-    auto lo = p.get_last_lo_pos();
-    auto ident = parse_ident(p);
-    auto metadata = parse_optional_meta(p);
-    auto hi = p.get_hi_pos();
-    expect(p, token::SEMI);
-    auto use_decl =
-        ast::view_item_use(ident, metadata, p.get_id());
-    ret @spanned(lo, hi, use_decl);
-}
-
-fn parse_rest_import_name(&parser p, ast::ident first,
-                          option::t[ast::ident] def_ident) ->
-   @ast::view_item {
-    auto lo = p.get_lo_pos();
-    let vec[ast::ident] identifiers = [first];
-    let bool glob = false;
-    while (true) {
-        alt (p.peek()) {
-            case (token::SEMI) { p.bump(); break; }
-            case (token::MOD_SEP) {
-                if (glob) { p.fatal("cannot path into a glob"); }
-                p.bump();
-            }
-            case (_) { p.fatal("expecting '::' or ';'"); }
-        }
-        alt (p.peek()) {
-            case (token::IDENT(_, _)) { identifiers += [parse_ident(p)]; }
-            case (
-                 //the lexer can't tell the different kinds of stars apart ) :
-                 token::BINOP(token::STAR)) {
-                glob = true;
-                p.bump();
-            }
-            case (_) { p.fatal("expecting an identifier, or '*'"); }
-        }
-    }
-    auto hi = p.get_hi_pos();
-    auto import_decl;
-    alt (def_ident) {
-        case (some(?i)) {
-            if (glob) { p.fatal("globbed imports can't be renamed"); }
-            import_decl =
-                ast::view_item_import(i, identifiers, p.get_id());
-        }
-        case (_) {
-            if (glob) {
-                import_decl =
-                    ast::view_item_import_glob(identifiers, p.get_id());
-            } else {
-                auto len = vec::len(identifiers);
-                import_decl =
-                    ast::view_item_import(identifiers.(len - 1u), identifiers,
-                                          p.get_id());
-            }
-        }
-    }
-    ret @spanned(lo, hi, import_decl);
-}
-
-fn parse_full_import_name(&parser p, ast::ident def_ident) ->
-   @ast::view_item {
-    alt (p.peek()) {
-        case (token::IDENT(?i, _)) {
-            p.bump();
-            ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
-        }
-        case (_) { p.fatal("expecting an identifier"); }
-    }
-    fail;
-}
-
-fn parse_import(&parser p) -> @ast::view_item {
-    alt (p.peek()) {
-        case (token::IDENT(?i, _)) {
-            p.bump();
-            alt (p.peek()) {
-                case (token::EQ) {
-                    p.bump();
-                    ret parse_full_import_name(p, p.get_str(i));
-                }
-                case (_) {
-                    ret parse_rest_import_name(p, p.get_str(i), none);
-                }
-            }
-        }
-        case (_) { p.fatal("expecting an identifier"); }
-    }
-    fail;
-}
-
-fn parse_export(&parser p) -> @ast::view_item {
-    auto lo = p.get_last_lo_pos();
-    auto id = parse_ident(p);
-    auto hi = p.get_hi_pos();
-    expect(p, token::SEMI);
-    ret @spanned(lo, hi, ast::view_item_export(id, p.get_id()));
-}
-
-fn parse_view_item(&parser p) -> @ast::view_item {
-    if (eat_word(p, "use")) {
-        ret parse_use(p);
-    } else if (eat_word(p, "import")) {
-        ret parse_import(p);
-    } else if (eat_word(p, "export")) { ret parse_export(p); } else { fail; }
-}
-
-fn is_view_item(&parser p) -> bool {
-    alt (p.peek()) {
-        case (token::IDENT(?sid, false)) {
-            auto st = p.get_str(sid);
-            ret str::eq(st, "use") || str::eq(st, "import") ||
-                    str::eq(st, "export");
-        }
-        case (_) { ret false; }
-    }
-    ret false;
-}
-
-fn parse_view(&parser p) -> vec[@ast::view_item] {
-    let vec[@ast::view_item] items = [];
-    while (is_view_item(p)) { items += [parse_view_item(p)]; }
-    ret items;
-}
-
-fn parse_native_view(&parser p) -> vec[@ast::view_item] {
-    let vec[@ast::view_item] items = [];
-    while (is_view_item(p)) { items += [parse_view_item(p)]; }
-    ret items;
-}
-
-fn parse_crate_from_source_file(&parser p) -> @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;
-    auto m = parse_mod_items(p, token::EOF,
-                             first_item_outer_attrs);
-    let vec[@ast::crate_directive] cdirs = [];
-    ret @spanned(lo, p.get_lo_pos(), rec(directives=cdirs,
-                                         module=m,
-                                         attrs=crate_attrs._0,
-                                         config=p.get_cfg()));
-}
-
-fn parse_str(&parser p) -> ast::ident {
-    alt (p.peek()) {
-        case (token::LIT_STR(?s)) {
-            p.bump();
-            ret p.get_str(s);
-        }
-        case (_) { fail; }
-    }
-}
-
-// Logic for parsing crate files (.rc)
-//
-// Each crate file is a sequence of directives.
-//
-// Each directive imperatively extends its environment with 0 or more items.
-fn parse_crate_directive(&parser p, vec[ast::attribute] first_outer_attr)
-    -> ast::crate_directive {
-
-    // Collect the next attributes
-    auto outer_attrs = first_outer_attr
-        + parse_outer_attributes(p);
-    // In a crate file outer attributes are only going to apply to mods
-    auto expect_mod = vec::len(outer_attrs) > 0u;
-
-    auto lo = p.get_lo_pos();
-    if (expect_mod || is_word(p, "mod")) {
-        expect_word(p, "mod");
-        auto id = parse_ident(p);
-        auto file_opt =
-            alt (p.peek()) {
-                case (token::EQ) {
-                    p.bump();
-                    some(parse_str(p))
-                }
-                case (_) { none }
-            };
-        alt (p.peek()) {
-            case (
-                 // mod x = "foo.rs";
-                 token::SEMI) {
-                auto hi = p.get_hi_pos();
-                p.bump();
-                ret spanned(lo, hi, ast::cdir_src_mod(id, file_opt,
-                                                      outer_attrs));
-            }
-            case (
-                 // mod x = "foo_dir" { ...directives... }
-                 token::LBRACE) {
-                p.bump();
-                auto inner_attrs = parse_inner_attrs_and_next(p);
-                auto mod_attrs = outer_attrs + inner_attrs._0;
-                auto next_outer_attr = inner_attrs._1;
-                auto cdirs = parse_crate_directives(p, token::RBRACE,
-                                                    next_outer_attr);
-                auto hi = p.get_hi_pos();
-                expect(p, token::RBRACE);
-                ret spanned(lo, hi, ast::cdir_dir_mod(id, file_opt, cdirs,
-                                                      mod_attrs));
-            }
-            case (?t) { unexpected(p, t); }
-        }
-    } else if (eat_word(p, "auth")) {
-        auto n = parse_path(p);
-        expect(p, token::EQ);
-        auto a = parse_auth(p);
-        auto hi = p.get_hi_pos();
-        expect(p, token::SEMI);
-        ret spanned(lo, hi, ast::cdir_auth(n, a));
-    } else if (is_view_item(p)) {
-        auto vi = parse_view_item(p);
-        ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
-    } else {
-        ret p.fatal("expected crate directive");
-    }
-}
-
-fn parse_crate_directives(&parser p, token::token term,
-                          vec[ast::attribute] first_outer_attr) ->
-   vec[@ast::crate_directive] {
-
-    // This is pretty ugly. If we have an outer attribute then we can't accept
-    // seeing the terminator next, so if we do see it then fail the same way
-    // parse_crate_directive would
-    if (vec::len(first_outer_attr) > 0u && p.peek() == term) {
-        expect_word(p, "mod");
-    }
-
-    let vec[@ast::crate_directive] cdirs = [];
-    while (p.peek() != term) {
-        auto cdir = @parse_crate_directive(p, first_outer_attr);
-        vec::push(cdirs, cdir);
-    }
-    ret cdirs;
-}
-
-fn parse_crate_from_crate_file(&parser p) -> @ast::crate {
-    auto lo = p.get_lo_pos();
-    auto prefix = std::fs::dirname(p.get_filemap().name);
-    auto leading_attrs = parse_inner_attrs_and_next(p);
-    auto crate_attrs = leading_attrs._0;
-    auto first_cdir_attr = leading_attrs._1;
-    auto cdirs = parse_crate_directives(p, token::EOF, first_cdir_attr);
-    let vec[str] deps = [];
-    auto cx =
-        @rec(p=p,
-             mode=eval::mode_parse,
-             mutable deps=deps,
-             sess=p.get_session(),
-             mutable chpos=p.get_chpos(),
-             mutable next_id=p.next_id(),
-             cfg = p.get_cfg());
-    auto m =
-        eval::eval_crate_directives_to_mod(cx, cdirs, prefix);
-    auto hi = p.get_hi_pos();
-    expect(p, token::EOF);
-    ret @spanned(lo, hi, rec(directives=cdirs,
-                             module=m,
-                             attrs=crate_attrs,
-                             config=p.get_cfg()));
-}
-//
-// 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/front/token.rs b/src/comp/front/token.rs
deleted file mode 100644 (file)
index 664a5db..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-
-import util::common::ty_mach;
-import util::common::ty_mach_to_str;
-import util::common::new_str_hash;
-import util::data::interner;
-import std::int;
-import std::uint;
-import std::str;
-
-type str_num = uint;
-
-tag binop {
-    PLUS;
-    MINUS;
-    STAR;
-    SLASH;
-    PERCENT;
-    CARET;
-    AND;
-    OR;
-    LSL;
-    LSR;
-    ASR;
-}
-
-tag token {
-
-    /* Expression-operator symbols. */
-    EQ;
-    LT;
-    LE;
-    EQEQ;
-    NE;
-    GE;
-    GT;
-    ANDAND;
-    OROR;
-    NOT;
-    TILDE;
-    BINOP(binop);
-    BINOPEQ(binop);
-
-    /* Structural symbols */
-    AT;
-    DOT;
-    COMMA;
-    SEMI;
-    COLON;
-    MOD_SEP;
-    QUES;
-    RARROW;
-    SEND;
-    RECV;
-    LARROW;
-    DARROW;
-    LPAREN;
-    RPAREN;
-    LBRACKET;
-    RBRACKET;
-    LBRACE;
-    RBRACE;
-    POUND;
-
-    /* Literals */
-    LIT_INT(int);
-    LIT_UINT(uint);
-    LIT_MACH_INT(ty_mach, int);
-    LIT_FLOAT(str_num);
-    LIT_MACH_FLOAT(ty_mach, str_num);
-    LIT_STR(str_num);
-    LIT_CHAR(char);
-    LIT_BOOL(bool);
-
-    /* Name components */
-    IDENT(str_num, bool);
-    IDX(int);
-    UNDERSCORE;
-    BRACEQUOTE(str_num);
-    EOF;
-}
-
-fn binop_to_str(binop o) -> str {
-    alt (o) {
-        case (PLUS) { ret "+"; }
-        case (MINUS) { ret "-"; }
-        case (STAR) { ret "*"; }
-        case (SLASH) { ret "/"; }
-        case (PERCENT) { ret "%"; }
-        case (CARET) { ret "^"; }
-        case (AND) { ret "&"; }
-        case (OR) { ret "|"; }
-        case (LSL) { ret "<<"; }
-        case (LSR) { ret ">>"; }
-        case (ASR) { ret ">>>"; }
-    }
-}
-
-fn to_str(lexer::reader r, token t) -> str {
-    alt (t) {
-        case (EQ) { ret "="; }
-        case (LT) { ret "<"; }
-        case (LE) { ret "<="; }
-        case (EQEQ) { ret "=="; }
-        case (NE) { ret "!="; }
-        case (GE) { ret ">="; }
-        case (GT) { ret ">"; }
-        case (NOT) { ret "!"; }
-        case (TILDE) { ret "~"; }
-        case (OROR) { ret "||"; }
-        case (ANDAND) { ret "&&"; }
-        case (BINOP(?op)) { ret binop_to_str(op); }
-        case (BINOPEQ(?op)) { ret binop_to_str(op) + "="; }
-        case (
-             /* Structural symbols */
-             AT) {
-            ret "@";
-        }
-        case (DOT) { ret "."; }
-        case (COMMA) { ret ","; }
-        case (SEMI) { ret ";"; }
-        case (COLON) { ret ":"; }
-        case (MOD_SEP) { ret "::"; }
-        case (QUES) { ret "?"; }
-        case (RARROW) { ret "->"; }
-        case (SEND) { ret "<|"; }
-        case (RECV) { ret "|>"; }
-        case (LARROW) { ret "<-"; }
-        case (DARROW) { ret "<->"; }
-        case (LPAREN) { ret "("; }
-        case (RPAREN) { ret ")"; }
-        case (LBRACKET) { ret "["; }
-        case (RBRACKET) { ret "]"; }
-        case (LBRACE) { ret "{"; }
-        case (RBRACE) { ret "}"; }
-        case (POUND) { ret "#"; }
-        case (
-             /* Literals */
-             LIT_INT(?i)) {
-            ret int::to_str(i, 10u);
-        }
-        case (LIT_UINT(?u)) { ret uint::to_str(u, 10u); }
-        case (LIT_MACH_INT(?tm, ?i)) {
-            ret int::to_str(i, 10u) + "_" + ty_mach_to_str(tm);
-        }
-        case (LIT_MACH_FLOAT(?tm, ?s)) {
-            ret interner::get[str](*r.get_interner(), s) + "_" +
-                    ty_mach_to_str(tm);
-        }
-        case (LIT_FLOAT(?s)) { ret interner::get[str](*r.get_interner(), s); }
-        case (LIT_STR(?s)) {
-            // FIXME: escape.
-
-            ret "\"" + interner::get[str](*r.get_interner(), s) + "\"";
-        }
-        case (LIT_CHAR(?c)) {
-            // FIXME: escape.
-
-            auto tmp = "'";
-            str::push_char(tmp, c);
-            str::push_byte(tmp, '\'' as u8);
-            ret tmp;
-        }
-        case (LIT_BOOL(?b)) { if (b) { ret "true"; } else { ret "false"; } }
-        case (
-             /* Name components */
-             IDENT(?s, _)) {
-            ret interner::get[str](*r.get_interner(), s);
-        }
-        case (IDX(?i)) { ret "_" + int::to_str(i, 10u); }
-        case (UNDERSCORE) { ret "_"; }
-        case (BRACEQUOTE(_)) { ret "<bracequote>"; }
-        case (EOF) { ret "<eof>"; }
-    }
-}
-
-
-pred can_begin_expr(token t) -> bool {
-    alt (t) {
-        case (LPAREN) { true }
-        case (LBRACE) { true }
-        case (IDENT(_,_)) { true }
-        case (UNDERSCORE) { true }
-        case (TILDE) { true }
-        case (LIT_INT(_)) { true }
-        case (LIT_UINT(_)) { true }
-        case (LIT_MACH_INT(_,_)) { true }
-        case (LIT_FLOAT(_)) { true }
-        case (LIT_MACH_FLOAT(_,_)) { true }
-        case (LIT_STR(_)) { true }
-        case (LIT_CHAR(_)) { true }
-        case (POUND) { true }
-        case (AT) { true }
-        case (_) { false }
-    }
-}
-// Local Variables:
-// 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:
index 1cbd4c0a98cefa988866836807a6abf0d07ea441..8a9c5aa58570b73a98d16f10b6a5becf19abcab4 100644 (file)
@@ -1457,7 +1457,7 @@ fn get_type(str s) -> TypeRef {
 }
 
 fn mk_type_names() -> type_names {
-    auto nt = util::common::new_str_hash[TypeRef]();
+    auto nt = syntax::_std::new_str_hash[TypeRef]();
 
     fn hash(&TypeRef t) -> uint {
         ret t as uint;
@@ -1519,7 +1519,7 @@ fn tys_str(type_names names,
         case (6) { ret "Label"; }
 
         case (7) {
-            ret "i" + util::common::istr(llvm::LLVMGetIntTypeWidth(ty)
+            ret "i" + syntax::_std::istr(llvm::LLVMGetIntTypeWidth(ty)
                                          as int);
         }
 
@@ -1558,7 +1558,7 @@ fn tys_str(type_names names,
                 i += 1u;
                 if (tout as int == ty as int) {
                     let uint n = vec::len[TypeRef](outer0) - i;
-                    ret "*\\" + util::common::istr(n as int);
+                    ret "*\\" + syntax::_std::istr(n as int);
                 }
             }
             ret "*" + type_to_str_inner(names, outer,
index 5e9cf52a282909cbaaa30b1478171850cfc9d174..5ef08cfd02d06cd45cb6af21d2c8081677a76419 100644 (file)
@@ -1,14 +1,15 @@
 // Extracting metadata from crate files
 
 import driver::session;
-import front::ast;
+import syntax::ast;
 import lib::llvm::False;
 import lib::llvm::llvm;
 import lib::llvm::mk_object_file;
 import lib::llvm::mk_section_iter;
 import front::attr;
 import middle::resolve;
-import middle::walk;
+import syntax::walk;
+import syntax::codemap::span;
 import back::x86;
 import util::common;
 import std::str;
@@ -20,7 +21,7 @@
 import std::option::none;
 import std::option::some;
 import std::map::hashmap;
-import pretty::pprust;
+import syntax::print::pprust;
 import tags::*;
 
 export read_crates;
@@ -129,7 +130,7 @@ fn get_metadata_section(str filename) -> option::t[vec[u8]] {
     ret option::none[vec[u8]];
 }
 
-fn load_library_crate(&session::session sess, common::span span, int cnum,
+fn load_library_crate(&session::session sess, span span, int cnum,
                       &ast::ident ident, vec[@ast::meta_item] metas,
                       &vec[str] library_search_paths) {
     alt (find_library_crate(sess, ident, metas, library_search_paths)) {
@@ -202,7 +203,7 @@ fn read_crates(session::session sess, resolve::crate_map crate_map,
     auto e =
         @rec(sess=sess,
              crate_map=crate_map,
-             crate_cache=@common::new_str_hash[int](),
+             crate_cache=@syntax::_std::new_str_hash[int](),
              library_search_paths=sess.get_opts().library_search_paths,
              mutable next_crate_num=1);
     auto v =
index 9956a46c828c4df6108d35d03730c234c557ba7b..3c1875d07d4be401542fb156ac7928c34d165a3e 100644 (file)
@@ -2,7 +2,7 @@
 
 import std::str;
 import middle::trans;
-import front::ast::crate;
+import syntax::ast::crate;
 import back::x86;
 import lib::llvm::llvm;
 import lib::llvm::llvm::ValueRef;
index 0eda4bbf5af629fbde3cb5ba3a1d9fd90ea45ce2..14d4035185f0b4dde922ae8aba54af890d71844b 100644 (file)
@@ -6,7 +6,7 @@
 import std::str;
 import std::io;
 import std::map::hashmap;
-import front::ast;
+import syntax::ast;
 import front::attr;
 import middle::ty;
 import tags::*;
@@ -14,7 +14,7 @@
 import tydecode::parse_ty_data;
 import driver::session;
 import util::common;
-import pretty::pprust;
+import syntax::print::pprust;
 
 export get_symbol;
 export get_tag_variants;
index c867f483dd34f5d1f6e869789a095f16c63f5f1a..4526e515f7987dce61cd6c70f8ea598fd56bf86d 100644 (file)
@@ -8,7 +8,7 @@
 import std::option::some;
 import std::option::none;
 import std::ebml;
-import front::ast::*;
+import syntax::ast::*;
 import tags::*;
 import middle::trans::crate_ctxt;
 import middle::trans::node_id_type;
index d0ef42f4d14d0882046fee87efbf96da369a631e..b40a84ec30551a384fc6ef06705d66487837944f 100644 (file)
@@ -6,12 +6,9 @@
 import std::option;
 import std::option::none;
 import std::option::some;
-import front::ast;
+import syntax::ast;
+import ast::respan;
 import middle::ty;
-import util::common;
-import util::common::respan;
-import util::common::a_ty;
-import util::common::a_bang;
 
 export parse_def_id;
 export parse_ty_data;
@@ -26,7 +23,7 @@
 type pstate =
     rec(vec[u8] data, int crate, mutable uint pos, uint len, ty::ctxt tcx);
 
-type ty_or_bang = util::common::ty_or_bang[ty::t];
+tag ty_or_bang { a_ty(ty::t); a_bang; }
 
 fn peek(@pstate st) -> u8 { ret st.data.(st.pos); }
 
@@ -63,8 +60,8 @@ fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len, str_def sd,
 
 fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
     alt (peek(st) as char) {
-        case ('!') { next(st); ret a_bang[ty::t]; }
-        case (_) { ret a_ty[ty::t](parse_ty(st, sd)); }
+        case ('!') { next(st); ret a_bang; }
+        case (_) { ret a_ty(parse_ty(st, sd)); }
     }
 }
 
@@ -154,16 +151,16 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
         case ('l') { ret ty::mk_float(st.tcx); }
         case ('M') {
             alt (next(st) as char) {
-                case ('b') { ret ty::mk_mach(st.tcx, common::ty_u8); }
-                case ('w') { ret ty::mk_mach(st.tcx, common::ty_u16); }
-                case ('l') { ret ty::mk_mach(st.tcx, common::ty_u32); }
-                case ('d') { ret ty::mk_mach(st.tcx, common::ty_u64); }
-                case ('B') { ret ty::mk_mach(st.tcx, common::ty_i8); }
-                case ('W') { ret ty::mk_mach(st.tcx, common::ty_i16); }
-                case ('L') { ret ty::mk_mach(st.tcx, common::ty_i32); }
-                case ('D') { ret ty::mk_mach(st.tcx, common::ty_i64); }
-                case ('f') { ret ty::mk_mach(st.tcx, common::ty_f32); }
-                case ('F') { ret ty::mk_mach(st.tcx, common::ty_f64); }
+                case ('b') { ret ty::mk_mach(st.tcx, ast::ty_u8); }
+                case ('w') { ret ty::mk_mach(st.tcx, ast::ty_u16); }
+                case ('l') { ret ty::mk_mach(st.tcx, ast::ty_u32); }
+                case ('d') { ret ty::mk_mach(st.tcx, ast::ty_u64); }
+                case ('B') { ret ty::mk_mach(st.tcx, ast::ty_i8); }
+                case ('W') { ret ty::mk_mach(st.tcx, ast::ty_i16); }
+                case ('L') { ret ty::mk_mach(st.tcx, ast::ty_i32); }
+                case ('D') { ret ty::mk_mach(st.tcx, ast::ty_i64); }
+                case ('f') { ret ty::mk_mach(st.tcx, ast::ty_f32); }
+                case ('F') { ret ty::mk_mach(st.tcx, ast::ty_f64); }
             }
         }
         case ('c') { ret ty::mk_char(st.tcx); }
index a9090c3624c19c01cdd731d9059de2ab81412448..af7f3f67118cb384ec296a87004261c8ba586437 100644 (file)
@@ -5,9 +5,9 @@
 import std::option::some;
 import std::option::none;
 import std::uint;
-import front::ast::*;
+import syntax::ast::*;
 import middle::ty;
-import pretty::ppaux::lit_to_str;
+import syntax::print::pprust::lit_to_str;
 import util::common;
 
 export ctxt;
@@ -105,16 +105,16 @@ fn enc_sty(&io::writer w, &@ctxt cx, &ty::sty st) {
         case (ty::ty_float) { w.write_char('l'); }
         case (ty::ty_machine(?mach)) {
             alt (mach) {
-                case (common::ty_u8) { w.write_str("Mb"); }
-                case (common::ty_u16) { w.write_str("Mw"); }
-                case (common::ty_u32) { w.write_str("Ml"); }
-                case (common::ty_u64) { w.write_str("Md"); }
-                case (common::ty_i8) { w.write_str("MB"); }
-                case (common::ty_i16) { w.write_str("MW"); }
-                case (common::ty_i32) { w.write_str("ML"); }
-                case (common::ty_i64) { w.write_str("MD"); }
-                case (common::ty_f32) { w.write_str("Mf"); }
-                case (common::ty_f64) { w.write_str("MF"); }
+                case (ty_u8) { w.write_str("Mb"); }
+                case (ty_u16) { w.write_str("Mw"); }
+                case (ty_u32) { w.write_str("Ml"); }
+                case (ty_u64) { w.write_str("Md"); }
+                case (ty_i8) { w.write_str("MB"); }
+                case (ty_i16) { w.write_str("MW"); }
+                case (ty_i32) { w.write_str("ML"); }
+                case (ty_i64) { w.write_str("MD"); }
+                case (ty_f32) { w.write_str("Mf"); }
+                case (ty_f64) { w.write_str("MF"); }
             }
         }
         case (ty::ty_char) { w.write_char('c'); }
@@ -182,7 +182,7 @@ fn enc_sty(&io::writer w, &@ctxt cx, &ty::sty st) {
         }
         case (ty::ty_var(?id)) {
             w.write_char('X');
-            w.write_str(common::istr(id));
+            w.write_str(syntax::_std::istr(id));
         }
         case (ty::ty_native(?def)) {
             w.write_char('E');
@@ -191,7 +191,7 @@ fn enc_sty(&io::writer w, &@ctxt cx, &ty::sty st) {
         }
         case (ty::ty_param(?id)) {
             w.write_char('p');
-            w.write_str(common::uistr(id));
+            w.write_str(syntax::_std::uistr(id));
         }
         case (ty::ty_type) { w.write_char('Y'); }
         case (ty::ty_task) { w.write_char('a'); }
index 3c482cc252e7683905cc8572a8beeffddcfed0ad..e419426c969187b44f6fb62f4ac88e3fd3be132c 100644 (file)
@@ -1,10 +1,11 @@
 
-import front::ast;
-import front::ast::ident;
-import front::ast::fn_ident;
-import front::ast::node_id;
-import front::ast::def_id;
-import util::common::span;
+import syntax::ast;
+import ast::ident;
+import ast::fn_ident;
+import ast::node_id;
+import ast::def_id;
+import syntax::codemap::span;
+import syntax::visit;
 import visit::vt;
 import std::vec;
 import std::str;
@@ -44,7 +45,7 @@ fn check_crate(@ty::ctxt tcx, &@ast::crate crate) {
 
              // Stores information about object fields and function
              // arguments that's otherwise not easily available.
-             local_map=util::common::new_int_hash());
+             local_map=syntax::_std::new_int_hash());
     auto v =
         @rec(visit_fn=bind visit_fn(cx, _, _, _, _, _, _, _),
              visit_item=bind visit_item(cx, _, _, _),
@@ -348,7 +349,7 @@ fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq, &ast::block block,
         case (ty::ty_istr) { /* no-op */ }
         case (_) {
             cx.tcx.sess.span_unimpl(seq.span, "unknown seq type " +
-                                    pretty::ppaux::ty_to_str(*cx.tcx, seq_t));
+                                    util::ppaux::ty_to_str(*cx.tcx, seq_t));
         }
     }
     auto new_sc =
index eeee41493458ec76d78120f339e3444e91e06233..9b19e6a9970d35d4dc6c5a7378344507fd94ce6c 100644 (file)
@@ -1,6 +1,7 @@
 import std::smallintmap;
 import std::option;
-import front::ast::*;
+import syntax::ast::*;
+import syntax::visit;
 import visit::vt;
 
 tag ast_node {
index 0fdf92192461d0b08567207947bc75812ce27e13..2e3ed81290053db58ee76ddcd181617ac9813025 100644 (file)
@@ -1,21 +1,22 @@
 
-import front::ast;
-import front::ast::ident;
-import front::ast::fn_ident;
-import front::ast::def;
-import front::ast::def_id;
-import front::ast::node_id;
-import front::ast::local_def;
+import syntax::ast;
+import ast::ident;
+import ast::fn_ident;
+import ast::def;
+import ast::def_id;
+import ast::node_id;
+import ast::local_def;
 
 import metadata::creader;
 import metadata::decoder;
 import driver::session::session;
 import util::common::new_def_hash;
-import util::common::new_int_hash;
-import util::common::new_str_hash;
-import util::common::span;
-import util::common::respan;
+import syntax::_std::new_int_hash;
+import syntax::_std::new_str_hash;
+import syntax::codemap::span;
+import syntax::ast::respan;
 import middle::ty::constr_table;
+import syntax::visit;
 import visit::vt;
 import std::map::hashmap;
 import std::list;
index d05f65d5fd7d4082897e3f55e65cf9264da661bb..f2c00abd6f101af9c2e5c818e927c1e3873e2a3b 100644 (file)
@@ -24,7 +24,8 @@
 import std::option::some;
 import std::option::none;
 import std::fs;
-import front::ast;
+import syntax::ast;
+import syntax::walk;
 import driver::session;
 import middle::ty;
 import back::link;
 import back::abi;
 import back::upcall;
 import middle::ty::pat_ty;
+import syntax::visit;
 import visit::vt;
 import util::common;
-import util::common::istr;
+import syntax::_std::istr;
 import util::common::new_def_hash;
-import util::common::new_int_hash;
-import util::common::new_str_hash;
+import syntax::_std::new_int_hash;
+import syntax::_std::new_str_hash;
 import util::common::local_rhs_span;
-import util::common::span;
+import syntax::codemap::span;
 import lib::llvm::llvm;
 import lib::llvm::builder;
 import lib::llvm::target_data;
 import metadata::tyencode;
 import metadata::creader;
 import metadata::decoder;
-import pretty::ppaux::ty_to_str;
-import pretty::ppaux::ty_to_short_str;
-import pretty::pprust::expr_to_str;
-import pretty::pprust::path_to_str;
+import util::ppaux::ty_to_str;
+import util::ppaux::ty_to_short_str;
+import syntax::print::pprust::expr_to_str;
+import syntax::print::pprust::path_to_str;
 
 obj namegen(mutable int i) {
     fn next(str prefix) -> str { i += 1; ret prefix + istr(i); }
@@ -795,16 +797,16 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
         case (ty::ty_uint) { llty = T_int(); }
         case (ty::ty_machine(?tm)) {
             alt (tm) {
-                case (common::ty_i8) { llty = T_i8(); }
-                case (common::ty_u8) { llty = T_i8(); }
-                case (common::ty_i16) { llty = T_i16(); }
-                case (common::ty_u16) { llty = T_i16(); }
-                case (common::ty_i32) { llty = T_i32(); }
-                case (common::ty_u32) { llty = T_i32(); }
-                case (common::ty_i64) { llty = T_i64(); }
-                case (common::ty_u64) { llty = T_i64(); }
-                case (common::ty_f32) { llty = T_f32(); }
-                case (common::ty_f64) { llty = T_f64(); }
+                case (ast::ty_i8) { llty = T_i8(); }
+                case (ast::ty_u8) { llty = T_i8(); }
+                case (ast::ty_i16) { llty = T_i16(); }
+                case (ast::ty_u16) { llty = T_i16(); }
+                case (ast::ty_i32) { llty = T_i32(); }
+                case (ast::ty_u32) { llty = T_i32(); }
+                case (ast::ty_i64) { llty = T_i64(); }
+                case (ast::ty_u64) { llty = T_i64(); }
+                case (ast::ty_f32) { llty = T_f32(); }
+                case (ast::ty_f64) { llty = T_f64(); }
             }
         }
         case (ty::ty_char) { llty = T_char(); }
@@ -2363,7 +2365,7 @@ fn inner(@block_ctxt last_cx, bool load_inner, ValueRef flag,
     } else {
         // FIXME: compare obj, fn by pointer?
 
-        trans_fail(cx, none[common::span],
+        trans_fail(cx, none[span],
                    "attempt to compare values of type " +
                        ty_to_str(cx.fcx.lcx.ccx.tcx, t));
     }
@@ -2402,7 +2404,7 @@ fn compare_scalar_types(@block_ctxt cx, ValueRef lhs, ValueRef rhs, &ty::t t,
         }
         case (ty::ty_char) { ret f(unsigned_int); }
         case (ty::ty_type) {
-            trans_fail(cx, none[common::span],
+            trans_fail(cx, none[span],
                        "attempt to compare values of type type");
 
             // This is a bit lame, because we return a dummy block to the
@@ -2412,7 +2414,7 @@ fn compare_scalar_types(@block_ctxt cx, ValueRef lhs, ValueRef rhs, &ty::t t,
                      C_bool(false));
         }
         case (ty::ty_native(_)) {
-            trans_fail(cx, none[common::span],
+            trans_fail(cx, none[span],
                        "attempt to compare values of type native");
             ret rslt(new_sub_block_ctxt(cx, "after_fail_dummy"),
                      C_bool(false));
@@ -2752,7 +2754,7 @@ fn iter_variant(@block_ctxt cx, ValueRef a_tup, ValueRef b_tup,
             ret iter_ivec(cx, av, bv, unit_tm.ty, f);
         }
         case (ty::ty_istr) {
-            auto unit_ty = ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8);
+            auto unit_ty = ty::mk_mach(cx.fcx.lcx.ccx.tcx, ast::ty_u8);
             ret iter_ivec(cx, av, bv, unit_ty, f);
         }
         case (_) {
@@ -2858,14 +2860,14 @@ fn iter_sequence_body(@block_ctxt cx, ValueRef v, &ty::t elt_ty,
             ret iter_sequence_body(cx, v, elt.ty, f, false, false);
         }
         case (ty::ty_str) {
-            auto et = ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8);
+            auto et = ty::mk_mach(cx.fcx.lcx.ccx.tcx, ast::ty_u8);
             ret iter_sequence_body(cx, v, et, f, true, false);
         }
         case (ty::ty_ivec(?elt)) {
             ret iter_sequence_body(cx, v, elt.ty, f, false, true);
         }
         case (ty::ty_istr) {
-            auto et = ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8);
+            auto et = ty::mk_mach(cx.fcx.lcx.ccx.tcx, ast::ty_u8);
             ret iter_sequence_body(cx, v, et, f, true, true);
         }
         case (_) {
@@ -3179,7 +3181,7 @@ fn duplicate_heap_parts_if_necessary(&@block_ctxt cx, ValueRef vptr,
       }
       case (ty::ty_istr) {
         ret ivec::duplicate_heap_part(cx, vptr,
-            ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8));
+            ty::mk_mach(cx.fcx.lcx.ccx.tcx, ast::ty_u8));
       }
       case (_) { ret rslt(cx, C_nil()); }
     }
@@ -3276,14 +3278,14 @@ fn trans_lit(&@crate_ctxt cx, &ast::lit lit, ast::node_id id) -> ValueRef {
             auto t = T_int();
             auto s = True;
             alt (tm) {
-                case (common::ty_u8) { t = T_i8(); s = False; }
-                case (common::ty_u16) { t = T_i16(); s = False; }
-                case (common::ty_u32) { t = T_i32(); s = False; }
-                case (common::ty_u64) { t = T_i64(); s = False; }
-                case (common::ty_i8) { t = T_i8(); }
-                case (common::ty_i16) { t = T_i16(); }
-                case (common::ty_i32) { t = T_i32(); }
-                case (common::ty_i64) { t = T_i64(); }
+                case (ast::ty_u8) { t = T_i8(); s = False; }
+                case (ast::ty_u16) { t = T_i16(); s = False; }
+                case (ast::ty_u32) { t = T_i32(); s = False; }
+                case (ast::ty_u64) { t = T_i64(); s = False; }
+                case (ast::ty_i8) { t = T_i8(); }
+                case (ast::ty_i16) { t = T_i16(); }
+                case (ast::ty_i32) { t = T_i32(); }
+                case (ast::ty_i64) { t = T_i64(); }
             }
             ret C_integral(t, i as uint, s);
         }
@@ -3291,8 +3293,8 @@ fn trans_lit(&@crate_ctxt cx, &ast::lit lit, ast::node_id id) -> ValueRef {
         case (ast::lit_mach_float(?tm, ?s)) {
             auto t = T_float();
             alt (tm) {
-                case (common::ty_f32) { t = T_f32(); }
-                case (common::ty_f64) { t = T_f64(); }
+                case (ast::ty_f32) { t = T_f32(); }
+                case (ast::ty_f64) { t = T_f64(); }
             }
             ret C_floating(s, t);
         }
@@ -4768,7 +4770,7 @@ fn trans_alt(&@block_ctxt cx, &@ast::expr expr, &vec[ast::arm] arms,
         this_cx = next_cx;
     }
     auto default_cx = this_cx;
-    trans_fail(default_cx, some[common::span](expr.span),
+    trans_fail(default_cx, some[span](expr.span),
                "non-exhaustive match failure");
     ret rslt(join_branches(cx, arm_results), C_nil());
 }
@@ -5028,7 +5030,7 @@ fn trans_index(&@block_ctxt cx, &span sp, &@ast::expr base, &@ast::expr idx,
     bcx.build.CondBr(bounds_check, next_cx.llbb, fail_cx.llbb);
     // fail: bad bounds check.
 
-    trans_fail(fail_cx, some[common::span](sp), "bounds check");
+    trans_fail(fail_cx, some[span](sp), "bounds check");
     auto body;
     alt (interior_len_and_data) {
         case (some(?lad)) { body = lad._1; }
@@ -6313,11 +6315,11 @@ fn trans_log(int lvl, &@block_ctxt cx, &@ast::expr e) -> result {
         let TypeRef tr;
         let bool is32bit = false;
         alt (ty::struct(cx.fcx.lcx.ccx.tcx, e_ty)) {
-            case (ty::ty_machine(util::common::ty_f32)) {
+            case (ty::ty_machine(ast::ty_f32)) {
                 tr = T_f32();
                 is32bit = true;
             }
-            case (ty::ty_machine(util::common::ty_f64)) { tr = T_f64(); }
+            case (ty::ty_machine(ast::ty_f64)) { tr = T_f64(); }
             case (_) { tr = T_float(); }
         }
         if (is32bit) {
@@ -6366,13 +6368,13 @@ fn trans_check_expr(&@block_ctxt cx, &@ast::expr e, &str s) -> result {
     auto cond_res = trans_expr(cx, e);
     auto expr_str = s + " " + expr_to_str(e) + " failed";
     auto fail_cx = new_sub_block_ctxt(cx, "fail");
-    trans_fail(fail_cx, some[common::span](e.span), expr_str);
+    trans_fail(fail_cx, some[span](e.span), expr_str);
     auto next_cx = new_sub_block_ctxt(cx, "next");
     cond_res.bcx.build.CondBr(cond_res.val, next_cx.llbb, fail_cx.llbb);
     ret rslt(next_cx, C_nil());
 }
 
-fn trans_fail_expr(&@block_ctxt cx, &option::t[common::span] sp_opt,
+fn trans_fail_expr(&@block_ctxt cx, &option::t[span] sp_opt,
                    &option::t[@ast::expr] fail_expr)
         -> result {
     auto bcx = cx;
@@ -6399,13 +6401,13 @@ fn trans_fail_expr(&@block_ctxt cx, &option::t[common::span] sp_opt,
     }
 }
  
-fn trans_fail(&@block_ctxt cx, &option::t[common::span] sp_opt, &str fail_str)
+fn trans_fail(&@block_ctxt cx, &option::t[span] sp_opt, &str fail_str)
    -> result {
     auto V_fail_str = C_cstr(cx.fcx.lcx.ccx, fail_str);
     ret trans_fail_value(cx, sp_opt, V_fail_str);
 }
 
-fn trans_fail_value(&@block_ctxt cx, &option::t[common::span] sp_opt,
+fn trans_fail_value(&@block_ctxt cx, &option::t[span] sp_opt,
                     &ValueRef V_fail_str)
         -> result {
     auto V_filename;
index 882dc4a42f7e7627ebc46050875cf86e411679ad..aa9267656e4517f41537038c02391b1d7a0491b9 100644 (file)
@@ -1,5 +1,4 @@
 
-import front::ast::ident;
 import std::vec;
 import tritv::*;
 
index 3ed1a56928acffd431d1264f2b0f773b83d83ffc..abffc3a97e35719eb67354d89a13abcfd0b0006b 100644 (file)
@@ -3,11 +3,12 @@
 import std::option;
 import std::option::some;
 import std::option::none;
-import front::ast::*;
-import util::common::istr;
-import util::common::uistr;
-import util::common::span;
-import util::common::new_str_hash;
+import syntax::ast::*;
+import syntax::walk;
+import syntax::codemap::span;
+import syntax::_std::istr;
+import syntax::_std::uistr;
+import syntax::_std::new_str_hash;
 import util::common::log_expr_err;
 import util::common::log_block_err;
 import util::common::log_item_err;
index 9aa529c4e416881aff4bc88f0c191cba13beb81a..123f51e7a7022b896adb8fb72105d08217754187 100644 (file)
@@ -7,20 +7,17 @@
 import std::option::none;
 import std::option::some;
 import std::option::maybe;
-import front::ast;
-import front::ast::*;
+import syntax::ast::*;
+import syntax::codemap::span;
 import util::common;
-import util::common::span;
-import util::common::spanned;
-import util::common::respan;
 import util::common::log_block;
-import util::common::new_int_hash;
-import util::common::new_uint_hash;
+import syntax::_std::new_int_hash;
+import syntax::_std::new_uint_hash;
 import util::common::log_expr_err;
-import util::common::istr;
-import util::common::uistr;
+import syntax::_std::istr;
+import syntax::_std::uistr;
 import util::common::lit_eq;
-import pretty::pprust::path_to_str;
+import syntax::print::pprust::path_to_str;
 import tstate::ann::pre_and_post;
 import tstate::ann::pre_and_post_state;
 import tstate::ann::empty_ann;
@@ -42,8 +39,8 @@
 import tstate::ann::clear_in_poststate_;
 import tritv::*;
 
-import pretty::ppaux::constr_args_to_str;
-import pretty::ppaux::lit_to_str;
+import syntax::print::pprust::constr_args_to_str;
+import syntax::print::pprust::lit_to_str;
 
 
 /* logging funs */
@@ -188,10 +185,10 @@ fn print_idents(vec[ident] idents) {
 easier to look up a specific instance.
 
 Both types are in constrast with the constraint type defined in
-front::ast, which is for predicate constraints only, and is what
+syntax::ast, which is for predicate constraints only, and is what
 gets generated by the parser. aux and ast share the same type
 to represent predicate *arguments* however. This type
-(constr_arg_general) is parameterized (see comments in front::ast).
+(constr_arg_general) is parameterized (see comments in syntax::ast).
 
 Both types store an ident and span, for error-logging purposes.
 */
@@ -507,7 +504,7 @@ fn constraints(&fn_ctxt fcx) -> vec[norm_constraint] {
 fn match_args(&fn_ctxt fcx, vec[pred_desc] occs, vec[@constr_arg_use] occ) ->
    uint {
     log "match_args: looking at " +
-        pretty::ppaux::constr_args_to_str(std::util::fst[ident, def_id], occ);
+        constr_args_to_str(std::util::fst[ident, def_id], occ);
     for (pred_desc pd in occs) {
         log "match_args: candidate " + pred_desc_to_str(pd);
         fn eq(&tup(ident, def_id) p, &tup(ident, def_id) q) -> bool {
@@ -594,8 +591,7 @@ fn expr_to_constr(ty::ctxt tcx, &@expr e) -> constr {
 
 fn pred_desc_to_str(&pred_desc p) -> str {
     ret "<" + uistr(p.node.bit_num) + ", " +
-        pretty::ppaux::constr_args_to_str(std::util::fst[ident, def_id],
-                                          p.node.args) + ">";
+        constr_args_to_str(std::util::fst[ident, def_id], p.node.args) + ">";
 }
 
 fn substitute_constr_args(&ty::ctxt cx, &vec[@expr] actuals,
@@ -609,7 +605,7 @@ fn substitute_constr_args(&ty::ctxt cx, &vec[@expr] actuals,
 
 type subst = vec[tup(arg, @expr)];
 
-fn substitute_arg(&ty::ctxt cx, &vec[@expr] actuals, @ast::constr_arg a) ->
+fn substitute_arg(&ty::ctxt cx, &vec[@expr] actuals, @constr_arg a) ->
    @constr_arg_use {
     auto num_actuals = vec::len(actuals);
     alt (a.node) {
index c7e77881e8542f3de926354e03aa14418d1fe334..3dea3cef30dccd55d549d75edc6ffcb822cbc8b5 100644 (file)
@@ -1,5 +1,6 @@
 
-import front::ast::*;
+import syntax::ast::*;
+import syntax::walk;
 import std::option::*;
 import std::vec;
 import std::vec::len;
index 679ac234a7e665c9a6ddb672270e23b25b5de9cc..084a11aa5fd48f6fdacd59f4c58e44d76804c56f 100644 (file)
@@ -1,25 +1,26 @@
 
-import front::ast;
-import front::ast::method;
-import front::ast::item;
-import front::ast::item_fn;
-import front::ast::_fn;
-import front::ast::obj_field;
-import front::ast::_obj;
-import front::ast::stmt;
-import front::ast::ident;
-import front::ast::fn_ident;
-import front::ast::node_id;
-import front::ast::def_id;
-import front::ast::local_def;
-import front::ast::ty_param;
-import front::ast::crate;
-import front::ast::return;
-import front::ast::noreturn;
-import front::ast::expr;
+import syntax::ast;
+import ast::method;
+import ast::item;
+import ast::item_fn;
+import ast::_fn;
+import ast::obj_field;
+import ast::_obj;
+import ast::stmt;
+import ast::ident;
+import ast::fn_ident;
+import ast::node_id;
+import ast::def_id;
+import ast::local_def;
+import ast::ty_param;
+import ast::crate;
+import ast::return;
+import ast::noreturn;
+import ast::expr;
+import syntax::walk;
+import syntax::codemap::span;
 import middle::ty::type_is_nil;
 import middle::ty::ret_ty_of_fn;
-import util::common::span;
 import tstate::ann::ts_ann;
 import tstate::ann::empty_poststate;
 import tstate::ann::true_precond;
@@ -43,7 +44,7 @@
 import std::option::some;
 import std::option::none;
 import aux::*;
-import pretty::pprust::ty_to_str;
+import syntax::print::pprust::ty_to_str;
 import util::common::log_stmt_err;
 import bitvectors::promises;
 import annotate::annotate_crate;
@@ -86,7 +87,7 @@ fn check_states_expr(&fn_ctxt fcx, &@expr e) {
         s +=
             "Unsatisfied precondition constraint (for example, " + diff +
                 ") for expression:\n";
-        s += pretty::pprust::expr_to_str(e);
+        s += syntax::print::pprust::expr_to_str(e);
         s += "\nPrecondition:\n";
         s += tritv_to_str(fcx, prec);
         s += "\nPrestate:\n";
@@ -115,7 +116,7 @@ fn check_states_stmt(&fn_ctxt fcx, &@stmt s) {
         ss +=
             "Unsatisfied precondition constraint (for example, " + diff +
                 ") for statement:\n";
-        ss += pretty::pprust::stmt_to_str(*s);
+        ss += syntax::print::pprust::stmt_to_str(*s);
         ss += "\nPrecondition:\n";
         ss += tritv_to_str(fcx, prec);
         ss += "\nPrestate: \n";
index 2ec43efe0c9b7edb49855b821a33a90b57d3ff42..e3b4f0421d40938616aa6e3cc37f0d76206a6ba6 100644 (file)
@@ -1,13 +1,14 @@
 
 import std::vec;
 import std::vec::plus_option;
-import front::ast;
-import front::ast::*;
-import pretty::ppaux::fn_ident_to_string;
+import syntax::ast::*;
+import util::ppaux::fn_ident_to_string;
 import std::option::*;
-import middle::walk::walk_crate;
-import middle::walk::walk_fn;
-import middle::walk::ast_visitor;
+import syntax::walk;
+import syntax::visit;
+import walk::walk_crate;
+import walk::walk_fn;
+import walk::ast_visitor;
 import aux::cinit;
 import aux::ninit;
 import aux::npred;
 import aux::expr_to_constr;
 import aux::constraints_expr;
 import aux::node_id_to_def_strict;
-import util::common::new_int_hash;
+import syntax::_std::new_int_hash;
 import util::common::new_def_hash;
-import util::common::uistr;
-import util::common::span;
-import util::common::respan;
+import syntax::_std::uistr;
+import syntax::codemap::span;
+import syntax::ast::respan;
 
 type ctxt = rec(@mutable vec[aux::constr] cs, ty::ctxt tcx);
 
@@ -64,7 +65,7 @@ fn do_nothing(&_fn f, &vec[ty_param] tp, &span sp, &fn_ident i,
               node_id iid, &ctxt cx, &visit::vt[ctxt] v) {
 }
  
-fn find_locals(&ty::ctxt tcx, &_fn f, &vec[ast::ty_param] tps,
+fn find_locals(&ty::ctxt tcx, &_fn f, &vec[ty_param] tps,
                &span sp, &fn_ident i, node_id id)
     -> ctxt {
     let ctxt cx = rec(cs=@mutable vec::alloc(0u), tcx=tcx);
@@ -81,7 +82,7 @@ fn find_locals(&ty::ctxt tcx, &_fn f, &vec[ast::ty_param] tps,
 
 fn add_constraint(&ty::ctxt tcx, aux::constr c, uint next, constr_map tbl) ->
    uint {
-    log aux::constraint_to_str(tcx, c) + " |-> " + util::common::uistr(next);
+    log aux::constraint_to_str(tcx, c) + " |-> " + uistr(next);
     alt (c.node.c) {
         case (ninit(?i)) { tbl.insert(c.node.id, cinit(next, c.span, i)); }
         case (npred(?p, ?args)) {
@@ -115,7 +116,7 @@ fn add_constraint(&ty::ctxt tcx, aux::constr c, uint next, constr_map tbl) ->
 
 /* builds a table mapping each local var defined in f
    to a bit number in the precondition/postcondition vectors */
-fn mk_fn_info(&crate_ctxt ccx, &_fn f, &vec[ast::ty_param] tp,
+fn mk_fn_info(&crate_ctxt ccx, &_fn f, &vec[ty_param] tp,
               &span f_sp, &fn_ident f_name,
               node_id id) {
     auto res_map = @new_int_hash[constraint]();
index 25d6fb98a92b40527fc72dd4ccf3f5abdba1e794..9ce0d7ce5eb7253af546e86317398dc962625932 100644 (file)
 import bitvectors::gen_poststate;
 import bitvectors::relax_precond_block;
 import bitvectors::gen;
-import front::ast::*;
-import util::common::new_int_hash;
+import syntax::ast::*;
+import syntax::_std::new_int_hash;
 import util::common::new_def_hash;
-import util::common::uistr;
+import syntax::_std::istr;
+import syntax::_std::uistr;
 import util::common::log_expr;
 import util::common::log_fn;
 import util::common::elt_exprs;
@@ -79,9 +80,8 @@
 import util::common::log_expr_err;
 import util::common::log_block_err;
 import util::common::log_block;
-import util::common::span;
-import util::common::istr;
-import pretty::ppaux::fn_ident_to_string;
+import syntax::codemap::span;
+import util::ppaux::fn_ident_to_string;
 
 fn find_pre_post_mod(&_mod m) -> _mod {
     log "implement find_pre_post_mod!";
index 4e4c3a961d7d54b4d36c9694095be1e63e1cd8b0..ff999c1aa1c6947b7ebb9552075cb0e0cdf26e75 100644 (file)
 import bitvectors::kill_poststate;
 import bitvectors::clear_in_poststate_ident;
 import bitvectors::intersect_states;
-import front::ast;
-import front::ast::*;
+import syntax::ast::*;
 import middle::ty::expr_ty;
 import middle::ty::type_is_nil;
 import middle::ty::type_is_bot;
 import util::common::new_def_hash;
-import util::common::uistr;
+import syntax::_std::uistr;
 import util::common::log_expr;
 import util::common::log_block;
 import util::common::log_block_err;
@@ -171,7 +170,7 @@ fn find_pre_post_state_call(&fn_ctxt fcx, &prestate pres, &@expr a,
           expr_poststate(fcx.ccx, a), id, bs, cf) || changed;
 }
 
-fn find_pre_post_state_exprs(&fn_ctxt fcx, &prestate pres, ast::node_id id,
+fn find_pre_post_state_exprs(&fn_ctxt fcx, &prestate pres, node_id id,
                              &vec[@expr] es, controlflow cf) -> bool {
     auto rs = seq_states(fcx, pres, es);
     auto changed = rs._0 | set_prestate_ann(fcx.ccx, id, pres);
@@ -229,7 +228,7 @@ fn gen_if_local(&fn_ctxt fcx, &poststate p, &@expr e) -> bool {
 }
 
 fn join_then_else(&fn_ctxt fcx, &@expr antec, &block conseq,
-                  &option::t[@expr] maybe_alt, ast::node_id id, &if_ty chk,
+                  &option::t[@expr] maybe_alt, node_id id, &if_ty chk,
                   &prestate pres) -> bool {
     auto changed = set_prestate_ann(fcx.ccx, id, pres) |
         find_pre_post_state_expr(fcx, pres, antec);
index 254fd130681bef9412824ee15c024363d3bac864..760a9b2fa949311706e3144b857b56388993f4de 100644 (file)
 import std::option::some;
 import std::smallintmap;
 import driver::session;
-import front::ast;
-import front::ast::def_id;
-import front::ast::constr_arg_general;
-import front::ast::mutability;
-import front::ast::controlflow;
-import front::ast::path_to_str;
+import syntax::ast;
+import ast::def_id;
+import ast::constr_arg_general;
+import ast::mutability;
+import ast::controlflow;
+import ast::path_to_str;
+import ast::spanned;
+import syntax::codemap::span;
 import metadata::creader;
 import metadata::decoder;
 import util::common::*;
-import util::data::interner;
-import pretty::ppaux::ty_to_str;
-import pretty::ppaux::mode_str_1;
+import syntax::util::interner;
+import util::ppaux::ty_to_str;
+import util::ppaux::mode_str_1;
 
 
 export node_id_to_monotype;
@@ -251,7 +253,7 @@ fn method_ty_to_fn_ty(&ctxt cx, method m) -> t {
     ty_int;
     ty_float;
     ty_uint;
-    ty_machine(ty_mach);
+    ty_machine(ast::ty_mach);
     ty_char;
     ty_str;
     ty_istr;
@@ -360,16 +362,16 @@ fn populate_type_store(&ctxt cx) {
     intern(cx, ty_int, none[str]);
     intern(cx, ty_float, none[str]);
     intern(cx, ty_uint, none[str]);
-    intern(cx, ty_machine(ty_i8), none[str]);
-    intern(cx, ty_machine(ty_i16), none[str]);
-    intern(cx, ty_machine(ty_i32), none[str]);
-    intern(cx, ty_machine(ty_i64), none[str]);
-    intern(cx, ty_machine(ty_u8), none[str]);
-    intern(cx, ty_machine(ty_u16), none[str]);
-    intern(cx, ty_machine(ty_u32), none[str]);
-    intern(cx, ty_machine(ty_u64), none[str]);
-    intern(cx, ty_machine(ty_f32), none[str]);
-    intern(cx, ty_machine(ty_f64), none[str]);
+    intern(cx, ty_machine(ast::ty_i8), none[str]);
+    intern(cx, ty_machine(ast::ty_i16), none[str]);
+    intern(cx, ty_machine(ast::ty_i32), none[str]);
+    intern(cx, ty_machine(ast::ty_i64), none[str]);
+    intern(cx, ty_machine(ast::ty_u8), none[str]);
+    intern(cx, ty_machine(ast::ty_u16), none[str]);
+    intern(cx, ty_machine(ast::ty_u32), none[str]);
+    intern(cx, ty_machine(ast::ty_u64), none[str]);
+    intern(cx, ty_machine(ast::ty_f32), none[str]);
+    intern(cx, ty_machine(ast::ty_f64), none[str]);
     intern(cx, ty_char, none[str]);
     intern(cx, ty_str, none[str]);
     intern(cx, ty_istr, none[str]);
@@ -534,18 +536,18 @@ fn gen_ty_full(&ctxt cx, &sty st, &option::t[str] cname) -> t {
 
 fn mk_uint(&ctxt cx) -> t { ret idx_uint; }
 
-fn mk_mach(&ctxt cx, &ty_mach tm) -> t {
+fn mk_mach(&ctxt cx, &ast::ty_mach tm) -> t {
     alt (tm) {
-        case (ty_u8) { ret idx_u8; }
-        case (ty_u16) { ret idx_u16; }
-        case (ty_u32) { ret idx_u32; }
-        case (ty_u64) { ret idx_u64; }
-        case (ty_i8) { ret idx_i8; }
-        case (ty_i16) { ret idx_i16; }
-        case (ty_i32) { ret idx_i32; }
-        case (ty_i64) { ret idx_i64; }
-        case (ty_f32) { ret idx_f32; }
-        case (ty_f64) { ret idx_f64; }
+        case (ast::ty_u8) { ret idx_u8; }
+        case (ast::ty_u16) { ret idx_u16; }
+        case (ast::ty_u32) { ret idx_u32; }
+        case (ast::ty_u64) { ret idx_u64; }
+        case (ast::ty_i8) { ret idx_i8; }
+        case (ast::ty_i16) { ret idx_i16; }
+        case (ast::ty_i32) { ret idx_i32; }
+        case (ast::ty_i64) { ret idx_i64; }
+        case (ast::ty_f32) { ret idx_f32; }
+        case (ast::ty_f64) { ret idx_f64; }
     }
 }
 
@@ -938,8 +940,8 @@ fn sequence_is_interior(&ctxt cx, &t ty) -> bool {
 
 fn sequence_element_type(&ctxt cx, &t ty) -> t {
     alt (struct(cx, ty)) {
-        case (ty_str) { ret mk_mach(cx, ty_u8); }
-        case (ty_istr) { ret mk_mach(cx, ty_u8); }
+        case (ty_str) { ret mk_mach(cx, ast::ty_u8); }
+        case (ty_istr) { ret mk_mach(cx, ast::ty_u8); }
         case (ty_vec(?mt)) { ret mt.ty; }
         case (ty_ivec(?mt)) { ret mt.ty; }
         case (_) {
@@ -1135,14 +1137,14 @@ fn type_is_integral(&ctxt cx, &t ty) -> bool {
         case (ty_uint) { ret true; }
         case (ty_machine(?m)) {
             alt (m) {
-                case (ty_i8) { ret true; }
-                case (ty_i16) { ret true; }
-                case (ty_i32) { ret true; }
-                case (ty_i64) { ret true; }
-                case (ty_u8) { ret true; }
-                case (ty_u16) { ret true; }
-                case (ty_u32) { ret true; }
-                case (ty_u64) { ret true; }
+                case (ast::ty_i8) { ret true; }
+                case (ast::ty_i16) { ret true; }
+                case (ast::ty_i32) { ret true; }
+                case (ast::ty_i64) { ret true; }
+                case (ast::ty_u8) { ret true; }
+                case (ast::ty_u16) { ret true; }
+                case (ast::ty_u32) { ret true; }
+                case (ast::ty_u64) { ret true; }
                 case (_) { ret false; }
             }
         }
@@ -1155,8 +1157,8 @@ fn type_is_fp(&ctxt cx, &t ty) -> bool {
     alt (struct(cx, ty)) {
         case (ty_machine(?tm)) {
             alt (tm) {
-                case (ty_f32) { ret true; }
-                case (ty_f64) { ret true; }
+                case (ast::ty_f32) { ret true; }
+                case (ast::ty_f64) { ret true; }
                 case (_) { ret false; }
             }
         }
@@ -1170,10 +1172,10 @@ fn type_is_signed(&ctxt cx, &t ty) -> bool {
         case (ty_int) { ret true; }
         case (ty_machine(?tm)) {
             alt (tm) {
-                case (ty_i8) { ret true; }
-                case (ty_i16) { ret true; }
-                case (ty_i32) { ret true; }
-                case (ty_i64) { ret true; }
+                case (ast::ty_i8) { ret true; }
+                case (ast::ty_i16) { ret true; }
+                case (ast::ty_i32) { ret true; }
+                case (ast::ty_i64) { ret true; }
                 case (_) { ret false; }
             }
         }
@@ -1322,16 +1324,16 @@ fn hash_fn(uint id, &arg[] args, &t rty) -> uint {
         case (ty_uint) { ret 4u; }
         case (ty_machine(?tm)) {
             alt (tm) {
-                case (ty_i8) { ret 5u; }
-                case (ty_i16) { ret 6u; }
-                case (ty_i32) { ret 7u; }
-                case (ty_i64) { ret 8u; }
-                case (ty_u8) { ret 9u; }
-                case (ty_u16) { ret 10u; }
-                case (ty_u32) { ret 11u; }
-                case (ty_u64) { ret 12u; }
-                case (ty_f32) { ret 13u; }
-                case (ty_f64) { ret 14u; }
+                case (ast::ty_i8) { ret 5u; }
+                case (ast::ty_i16) { ret 6u; }
+                case (ast::ty_i32) { ret 7u; }
+                case (ast::ty_i64) { ret 8u; }
+                case (ast::ty_u8) { ret 9u; }
+                case (ast::ty_u16) { ret 10u; }
+                case (ast::ty_u32) { ret 11u; }
+                case (ast::ty_u64) { ret 12u; }
+                case (ast::ty_f32) { ret 13u; }
+                case (ast::ty_f64) { ret 14u; }
             }
         }
         case (ty_char) { ret 15u; }
@@ -2644,7 +2646,7 @@ fn dump_var_bindings(ty_ctxt tcx, @var_bindings vb) {
             alt (smallintmap::find[t](vb.types, i)) {
                 case (none[t]) { typespec = ""; }
                 case (some[t](?typ)) {
-                    typespec = " =" + pretty::ppaux::ty_to_str(tcx, typ);
+                    typespec = " =" + ty_to_str(tcx, typ);
                 }
             }
             log_err #fmt("set %u:%s%s", i, typespec, sets);
@@ -2948,17 +2950,17 @@ fn tycat(&ctxt cx, t ty) -> int {
             case (ty_bool) { tycat_bool }
             case (ty_int) { tycat_int }
             case (ty_uint) { tycat_int }
-            case (ty_machine(ty_i8)) { tycat_int }
-            case (ty_machine(ty_i16)) { tycat_int }
-            case (ty_machine(ty_i32)) { tycat_int }
-            case (ty_machine(ty_i64)) { tycat_int }
-            case (ty_machine(ty_u8)) { tycat_int }
-            case (ty_machine(ty_u16)) { tycat_int }
-            case (ty_machine(ty_u32)) { tycat_int }
-            case (ty_machine(ty_u64)) { tycat_int }
+            case (ty_machine(ast::ty_i8)) { tycat_int }
+            case (ty_machine(ast::ty_i16)) { tycat_int }
+            case (ty_machine(ast::ty_i32)) { tycat_int }
+            case (ty_machine(ast::ty_i64)) { tycat_int }
+            case (ty_machine(ast::ty_u8)) { tycat_int }
+            case (ty_machine(ast::ty_u16)) { tycat_int }
+            case (ty_machine(ast::ty_u32)) { tycat_int }
+            case (ty_machine(ast::ty_u64)) { tycat_int }
             case (ty_float) { tycat_float }
-            case (ty_machine(ty_f32)) { tycat_float }
-            case (ty_machine(ty_f64)) { tycat_float }
+            case (ty_machine(ast::ty_f32)) { tycat_float }
+            case (ty_machine(ast::ty_f64)) { tycat_float }
             case (ty_char) { tycat_int }
             case (ty_ptr(_)) { tycat_int }
             case (ty_str) { tycat_str }
index 785393e13c907ba2347d6b41a257f799e41e980c..5c4e4f1572b19a71448485abf6f4ea44294cf6e0 100644 (file)
@@ -1,14 +1,15 @@
 
-import front::ast;
-import front::ast::mutability;
-import front::ast::local_def;
-import front::ast::path_to_str;
+import syntax::ast;
+import ast::mutability;
+import ast::local_def;
+import ast::path_to_str;
+import ast::respan;
+import syntax::walk;
 import metadata::decoder;
 import driver::session;
 import util::common;
-import util::common::span;
-import util::common::respan;
-import util::common::new_int_hash;
+import syntax::codemap::span;
+import syntax::_std::new_int_hash;
 import util::common::new_def_hash;
 import util::common::log_expr_err;
 import middle::ty;
@@ -24,7 +25,7 @@
 import middle::ty::node_type_table;
 import middle::ty::pat_ty;
 import middle::ty::ty_param_substs_opt_and_ty;
-import pretty::ppaux::ty_to_str;
+import util::ppaux::ty_to_str;
 import middle::ty::ty_param_count_and_ty;
 import middle::ty::ty_nil;
 import middle::ty::unify::ures_ok;
@@ -537,7 +538,7 @@ fn getter(@ctxt cx, &ast::def_id id) -> ty::ty_param_count_and_ty {
             }
             case (_) {
                 cx.tcx.sess.fatal("internal error " +
-                                  util::common::istr(id._1));
+                                  syntax::_std::istr(id._1));
             }
         }
         ret tpt;
@@ -1375,7 +1376,7 @@ fn require_pure_call(@crate_ctxt ccx, &ast::purity caller_purity,
 
 fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
     // fcx.ccx.tcx.sess.span_warn(expr.span, "typechecking expr " +
-    //                                pretty::pprust::expr_to_str(expr));
+    //                            syntax::print::pprust::expr_to_str(expr));
 
     // A generic function to factor out common logic from call and bind
     // expressions.
@@ -1545,7 +1546,7 @@ fn check_then_else(&@fn_ctxt fcx, &ast::block thn,
     }
 
     // Checks the compatibility 
-    fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
+    fn check_binop_type_compat(&@fn_ctxt fcx, span span,
                                ty::t ty, ast::binop binop) {
         auto resolved_t = resolve_type_vars_if_possible(fcx, ty);
         if (!ty::is_binopable(fcx.ccx.tcx, resolved_t, binop)) {
@@ -1794,11 +1795,11 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
             alt (structure_of(fcx, expr.span, ety)) {
                 case (ty::ty_vec(?vec_elt_ty)) { elt_ty = vec_elt_ty.ty; }
                 case (ty::ty_str) {
-                    elt_ty = ty::mk_mach(fcx.ccx.tcx, util::common::ty_u8);
+                    elt_ty = ty::mk_mach(fcx.ccx.tcx, ast::ty_u8);
                 }
                 case (ty::ty_ivec(?vec_elt_ty)) { elt_ty = vec_elt_ty.ty; }
                 case (ty::ty_istr) {
-                    elt_ty = ty::mk_mach(fcx.ccx.tcx, util::common::ty_u8);
+                    elt_ty = ty::mk_mach(fcx.ccx.tcx, ast::ty_u8);
                 }
                 case (_) {
                     fcx.ccx.tcx.sess.span_fatal(expr.span,
@@ -2150,11 +2151,11 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
                     write::ty_only_fixup(fcx, id, mt.ty);
                 }
                 case (ty::ty_str) {
-                    auto typ = ty::mk_mach(fcx.ccx.tcx, common::ty_u8);
+                    auto typ = ty::mk_mach(fcx.ccx.tcx, ast::ty_u8);
                     write::ty_only_fixup(fcx, id, typ);
                 }
                 case (ty::ty_istr) {
-                    auto typ = ty::mk_mach(fcx.ccx.tcx, common::ty_u8);
+                    auto typ = ty::mk_mach(fcx.ccx.tcx, ast::ty_u8);
                     write::ty_only_fixup(fcx, id, typ);
                 }
                 case (_) {
diff --git a/src/comp/middle/visit.rs b/src/comp/middle/visit.rs
deleted file mode 100644 (file)
index c87373c..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-
-import front::ast::*;
-import std::option;
-import std::option::some;
-import std::option::none;
-import util::common::span;
-import util::common::respan;
-
-
-// Context-passing AST walker. Each overridden visit method has full control
-// over what happens with its node, it can do its own traversal of the node's
-// children (potentially passing in different contexts to each), call
-// visit::visit_* to apply the default traversal algorithm (again, it can
-// override the context), or prevent deeper traversal by doing nothing.
-
-// Lots of redundant indirection and refcounting. Our typesystem doesn't do
-// circular types, so the visitor record can not hold functions that take
-// visitors. A vt tag is used to break the cycle.
-tag vt[E] { vtor(visitor[E]); }
-
-fn vt[E](&vt[E] x) -> visitor[E] { alt (x) { case (vtor(?v)) { ret v; } } }
-
-type visitor[E] =
-    @rec(fn(&_mod, &span, &E, &vt[E])  visit_mod,
-         fn(&@view_item, &E, &vt[E])  visit_view_item,
-         fn(&@native_item, &E, &vt[E])  visit_native_item,
-         fn(&@item, &E, &vt[E])  visit_item,
-         fn(&@local, &E, &vt[E])  visit_local,
-         fn(&block, &E, &vt[E])  visit_block,
-         fn(&@stmt, &E, &vt[E])  visit_stmt,
-         fn(&arm, &E, &vt[E])  visit_arm,
-         fn(&@pat, &E, &vt[E])  visit_pat,
-         fn(&@decl, &E, &vt[E])  visit_decl,
-         fn(&@expr, &E, &vt[E])  visit_expr,
-         fn(&@ty, &E, &vt[E])  visit_ty,
-         fn(&@constr, &E, &vt[E])  visit_constr,
-         fn(&_fn, &vec[ty_param], &span, &fn_ident, node_id, &E, &vt[E])
-             visit_fn);
-
-fn default_visitor[E]() -> visitor[E] {
-    ret @rec(visit_mod=bind visit_mod[E](_, _, _, _),
-             visit_view_item=bind visit_view_item[E](_, _, _),
-             visit_native_item=bind visit_native_item[E](_, _, _),
-             visit_item=bind visit_item[E](_, _, _),
-             visit_local=bind visit_local[E](_, _, _),
-             visit_block=bind visit_block[E](_, _, _),
-             visit_stmt=bind visit_stmt[E](_, _, _),
-             visit_arm=bind visit_arm[E](_, _, _),
-             visit_pat=bind visit_pat[E](_, _, _),
-             visit_decl=bind visit_decl[E](_, _, _),
-             visit_expr=bind visit_expr[E](_, _, _),
-             visit_ty=bind visit_ty[E](_, _, _),
-             visit_constr=bind visit_constr[E](_, _, _),
-             visit_fn=bind visit_fn[E](_, _, _, _, _, _, _));
-}
-
-fn visit_crate[E](&crate c, &E e, &vt[E] v) {
-    vt(v).visit_mod(c.node.module, c.span, e, v);
-}
-
-fn visit_crate_directive[E](&@crate_directive cd, &E e, &vt[E] v) {
-    alt (cd.node) {
-        case (cdir_src_mod(_, _, _)) { }
-        case (cdir_dir_mod(_, _, ?cdirs, _)) {
-            for (@crate_directive cdir in cdirs) {
-                visit_crate_directive(cdir, e, v);
-            }
-        }
-        case (cdir_view_item(?vi)) { vt(v).visit_view_item(vi, e, v); }
-        case (cdir_syntax(_)) { }
-        case (cdir_auth(_, _)) { }
-    }
-}
-
-fn visit_mod[E](&_mod m, &span sp, &E e, &vt[E] v) {
-    for (@view_item vi in m.view_items) { vt(v).visit_view_item(vi, e, v); }
-    for (@item i in m.items) { vt(v).visit_item(i, e, v); }
-}
-
-fn visit_view_item[E](&@view_item vi, &E e, &vt[E] v) { }
-
-fn visit_local[E](&@local loc, &E e, &vt[E] v) {
-    alt (loc.node.ty) {
-        case (none) { }
-        case (some(?t)) { vt(v).visit_ty(t, e, v); }
-    }
-    alt (loc.node.init) {
-        case (none) { }
-        case (some(?i)) { vt(v).visit_expr(i.expr, e, v); }
-    }
-}
-
-fn visit_item[E](&@item i, &E e, &vt[E] v) {
-    alt (i.node) {
-        case (item_const(?t, ?ex)) {
-            vt(v).visit_ty(t, e, v);
-            vt(v).visit_expr(ex, e, v);
-        }
-        case (item_fn(?f, ?tp)) {
-            vt(v).visit_fn(f, tp, i.span, some(i.ident), i.id, e, v);
-        }
-        case (item_mod(?m)) { vt(v).visit_mod(m, i.span, e, v); }
-        case (item_native_mod(?nm)) {
-            for (@view_item vi in nm.view_items) {
-                vt(v).visit_view_item(vi, e, v);
-            }
-            for (@native_item ni in nm.items) {
-                vt(v).visit_native_item(ni, e, v);
-            }
-        }
-        case (item_ty(?t, _)) { vt(v).visit_ty(t, e, v); }
-        case (item_res(?f, ?dtor_id, ?tps, _)) {
-            vt(v).visit_fn(f, tps, i.span, some(i.ident), dtor_id, e, v);
-        }
-        case (item_tag(?variants, _)) {
-            for (variant vr in variants) {
-                for (variant_arg va in vr.node.args) {
-                    vt(v).visit_ty(va.ty, e, v);
-                }
-            }
-        }
-        case (item_obj(?ob, _, _)) {
-            for (obj_field f in ob.fields) { vt(v).visit_ty(f.ty, e, v); }
-            for (@method m in ob.methods) {
-                vt(v).visit_fn(m.node.meth, [], m.span, some(m.node.ident),
-                               m.node.id, e, v);
-            }
-            alt (ob.dtor) {
-                case (none) { }
-                case (some(?m)) {
-                    vt(v).visit_fn(m.node.meth, [], m.span,
-                                   some(m.node.ident),
-                                   m.node.id, e, v);
-                }
-            }
-        }
-    }
-}
-
-fn visit_ty[E](&@ty t, &E e, &vt[E] v) {
-    alt (t.node) {
-        case (ty_nil)           { /* no-op */ }
-        case (ty_bot)           { /* no-op */ }
-        case (ty_bool)          { /* no-op */ }
-        case (ty_int)           { /* no-op */ }
-        case (ty_float)         { /* no-op */ }
-        case (ty_uint)          { /* no-op */ }
-        case (ty_machine(_))    { /* no-op */ }
-        case (ty_char)          { /* no-op */ }
-        case (ty_str)           { /* no-op */ }
-        case (ty_istr)          { /* no-op */ }
-        case (ty_box(?mt))      { vt(v).visit_ty(mt.ty, e, v); }
-        case (ty_vec(?mt))      { vt(v).visit_ty(mt.ty, e, v); }
-        case (ty_ivec(?mt))     { vt(v).visit_ty(mt.ty, e, v); }
-        case (ty_ptr(?mt))      { vt(v).visit_ty(mt.ty, e, v); }
-        case (ty_port(?t))      { vt(v).visit_ty(t, e, v); }
-        case (ty_chan(?t))      { vt(v).visit_ty(t, e, v); }
-        case (ty_task)          { /* no-op */ }
-        case (ty_tup(?mts)) {
-            for (mt mt in mts) { vt(v).visit_ty(mt.ty, e, v); }
-        }
-        case (ty_rec(?flds)) {
-            for (ty_field f in flds) { vt(v).visit_ty(f.node.mt.ty, e, v); }
-        }
-        case (ty_fn(_, ?args, ?out, _, ?constrs)) {
-            for (ty_arg a in args) { vt(v).visit_ty(a.node.ty, e, v); }
-            for (@constr c in constrs) { vt(v).visit_constr(c, e, v); }
-            vt(v).visit_ty(out, e, v);
-        }
-        case (ty_obj(?tmeths)) {
-            for (ty_method m in tmeths) {
-                for (ty_arg a in m.node.inputs) {
-                    vt(v).visit_ty(a.node.ty, e, v);
-                }
-                vt(v).visit_ty(m.node.output, e, v);
-            }
-        }
-        case (ty_path(?p, _)) {
-            for (@ty tp in p.node.types) { vt(v).visit_ty(tp, e, v); }
-        }
-        case (ty_type)          { /* no-op */ }
-        case (ty_constr(?t, _)) { vt(v).visit_ty(t, e, v); }
-    }
-}
-
-fn visit_constr[E](&@constr c, &E e, &vt[E] v) {
-    // default
-
-}
-
-fn visit_pat[E](&@pat p, &E e, &vt[E] v) {
-    alt (p.node) {
-        case (pat_tag(?path, ?children)) {
-            for (@ty tp in path.node.types) { vt(v).visit_ty(tp, e, v); }
-            for (@pat child in children) { vt(v).visit_pat(child, e, v); }
-        }
-        case (_) { }
-    }
-}
-
-fn visit_native_item[E](&@native_item ni, &E e, &vt[E] v) {
-    alt (ni.node) {
-        case (native_item_fn(_, ?fd, _)) { visit_fn_decl(fd, e, v); }
-        case (native_item_ty) { }
-    }
-}
-
-fn visit_fn_decl[E](&fn_decl fd, &E e, &vt[E] v) {
-    for (arg a in fd.inputs) { vt(v).visit_ty(a.ty, e, v); }
-    for (@constr c in fd.constraints) { vt(v).visit_constr(c, e, v); }
-    vt(v).visit_ty(fd.output, e, v);
-}
-
-fn visit_fn[E](&_fn f, &vec[ty_param] tp, &span sp, &fn_ident i,
-               node_id id, &E e, &vt[E] v) {
-    visit_fn_decl(f.decl, e, v);
-    vt(v).visit_block(f.body, e, v);
-}
-
-fn visit_block[E](&block b, &E e, &vt[E] v) {
-    for (@stmt s in b.node.stmts) { vt(v).visit_stmt(s, e, v); }
-    visit_expr_opt(b.node.expr, e, v);
-}
-
-fn visit_stmt[E](&@stmt s, &E e, &vt[E] v) {
-    alt (s.node) {
-        case (stmt_decl(?d, _)) { vt(v).visit_decl(d, e, v); }
-        case (stmt_expr(?ex, _)) { vt(v).visit_expr(ex, e, v); }
-        case (stmt_crate_directive(?cd)) { visit_crate_directive(cd, e, v); }
-    }
-}
-
-fn visit_decl[E](&@decl d, &E e, &vt[E] v) {
-    alt (d.node) {
-        case (decl_local(?loc)) {
-            vt(v).visit_local(loc, e, v);
-        }
-        case (decl_item(?it)) { vt(v).visit_item(it, e, v); }
-    }
-}
-
-fn visit_expr_opt[E](option::t[@expr] eo, &E e, &vt[E] v) {
-    alt (eo) {
-        case (none) { }
-        case (some(?ex)) { vt(v).visit_expr(ex, e, v); }
-    }
-}
-
-fn visit_exprs[E](vec[@expr] exprs, &E e, &vt[E] v) {
-    for (@expr ex in exprs) { vt(v).visit_expr(ex, e, v); }
-}
-
-fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
-    alt (ex.node) {
-        case (expr_vec(?es, _, _)) { visit_exprs(es, e, v); }
-        case (expr_tup(?elts)) {
-            for (elt el in elts) { vt(v).visit_expr(el.expr, e, v); }
-        }
-        case (expr_rec(?flds, ?base)) {
-            for (field f in flds) { vt(v).visit_expr(f.node.expr, e, v); }
-            visit_expr_opt(base, e, v);
-        }
-        case (expr_call(?callee, ?args)) {
-            vt(v).visit_expr(callee, e, v);
-            visit_exprs(args, e, v);
-        }
-        case (expr_self_method(_)) { }
-        case (expr_bind(?callee, ?args)) {
-            vt(v).visit_expr(callee, e, v);
-            for (option::t[@expr] eo in args) { visit_expr_opt(eo, e, v); }
-        }
-        case (expr_spawn(_, _, ?callee, ?args)) {
-            vt(v).visit_expr(callee, e, v);
-            visit_exprs(args, e, v);
-        }
-        case (expr_binary(_, ?a, ?b)) {
-            vt(v).visit_expr(a, e, v);
-            vt(v).visit_expr(b, e, v);
-        }
-        case (expr_unary(_, ?a)) { vt(v).visit_expr(a, e, v); }
-        case (expr_lit(_)) { }
-        case (expr_cast(?x, ?t)) {
-            vt(v).visit_expr(x, e, v);
-            vt(v).visit_ty(t, e, v);
-        }
-        case (expr_if(?x, ?b, ?eo)) {
-            vt(v).visit_expr(x, e, v);
-            vt(v).visit_block(b, e, v);
-            visit_expr_opt(eo, e, v);
-        }
-        case (expr_if_check(?x, ?b, ?eo)) {
-            vt(v).visit_expr(x, e, v);
-            vt(v).visit_block(b, e, v);
-            visit_expr_opt(eo, e, v);
-        }
-        case (expr_ternary(?c, ?t, ?el)) {
-            vt(v).visit_expr(c, e, v);
-            vt(v).visit_expr(t, e, v);
-            vt(v).visit_expr(el, e, v);
-        }
-        case (expr_while(?x, ?b)) {
-            vt(v).visit_expr(x, e, v);
-            vt(v).visit_block(b, e, v);
-        }
-        case (expr_for(?dcl, ?x, ?b)) {
-            vt(v).visit_local(dcl, e, v);
-            vt(v).visit_expr(x, e, v);
-            vt(v).visit_block(b, e, v);
-        }
-        case (expr_for_each(?dcl, ?x, ?b)) {
-            vt(v).visit_local(dcl, e, v);
-            vt(v).visit_expr(x, e, v);
-            vt(v).visit_block(b, e, v);
-        }
-        case (expr_do_while(?b, ?x)) {
-            vt(v).visit_block(b, e, v);
-            vt(v).visit_expr(x, e, v);
-        }
-        case (expr_alt(?x, ?arms)) {
-            vt(v).visit_expr(x, e, v);
-            for (arm a in arms) { vt(v).visit_arm(a, e, v); }
-        }
-        case (expr_fn(?f)) {
-            vt(v).visit_fn(f, [], ex.span, none, ex.id, e, v);
-        }
-        case (expr_block(?b)) { vt(v).visit_block(b, e, v); }
-        case (expr_assign(?a, ?b)) {
-            vt(v).visit_expr(b, e, v);
-            vt(v).visit_expr(a, e, v);
-        }
-        case (expr_move(?a, ?b)) {
-            vt(v).visit_expr(b, e, v);
-            vt(v).visit_expr(a, e, v);
-        }
-        case (expr_swap(?a, ?b)) {
-            vt(v).visit_expr(a, e, v);
-            vt(v).visit_expr(b, e, v);
-        }
-        case (expr_assign_op(_, ?a, ?b)) {
-            vt(v).visit_expr(b, e, v);
-            vt(v).visit_expr(a, e, v);
-        }
-        case (expr_send(?a, ?b)) {
-            vt(v).visit_expr(a, e, v);
-            vt(v).visit_expr(b, e, v);
-        }
-        case (expr_recv(?a, ?b)) {
-            vt(v).visit_expr(a, e, v);
-            vt(v).visit_expr(b, e, v);
-        }
-        case (expr_field(?x, _)) { vt(v).visit_expr(x, e, v); }
-        case (expr_index(?a, ?b)) {
-            vt(v).visit_expr(a, e, v);
-            vt(v).visit_expr(b, e, v);
-        }
-        case (expr_path(?p)) {
-            for (@ty tp in p.node.types) { vt(v).visit_ty(tp, e, v); }
-        }
-        case (expr_ext(_, _, _, ?expansion)) {
-            vt(v).visit_expr(expansion, e, v);
-        }
-        case (expr_fail(?eo)) {
-            visit_expr_opt(eo, e, v);
-        }
-        case (expr_break) { }
-        case (expr_cont) { }
-        case (expr_ret(?eo)) { visit_expr_opt(eo, e, v); }
-        case (expr_put(?eo)) { visit_expr_opt(eo, e, v); }
-        case (expr_be(?x)) { vt(v).visit_expr(x, e, v); }
-        case (expr_log(_, ?x)) { vt(v).visit_expr(x, e, v); }
-        case (expr_check(_, ?x)) { vt(v).visit_expr(x, e, v); }
-        case (expr_assert(?x)) { vt(v).visit_expr(x, e, v); }
-        case (expr_port(_)) { }
-        case (expr_chan(?x)) { vt(v).visit_expr(x, e, v); }
-        case (expr_anon_obj(?anon_obj, _, _)) {
-            alt (anon_obj.fields) {
-                case (none) { }
-                case (some(?fields)) {
-                    for (anon_obj_field f in fields) {
-                        vt(v).visit_ty(f.ty, e, v);
-                        vt(v).visit_expr(f.expr, e, v);
-                    }
-                }
-            }
-            alt (anon_obj.with_obj) {
-                case (none) { }
-                case (some(?ex)) { vt(v).visit_expr(ex, e, v); }
-            }
-            for (@method m in anon_obj.methods) {
-                vt(v).visit_fn(m.node.meth, [], m.span, some(m.node.ident),
-                               m.node.id, e, v);
-            }
-        }
-    }
-}
-
-fn visit_arm[E](&arm a, &E e, &vt[E] v) {
-    vt(v).visit_pat(a.pat, e, v);
-    vt(v).visit_block(a.block, e, v);
-}
-// 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/middle/walk.rs b/src/comp/middle/walk.rs
deleted file mode 100644 (file)
index 598c6d6..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-
-import front::ast;
-import middle::ty::ty_param;
-import std::option;
-import std::option::some;
-import std::option::none;
-import util::common::span;
-import util::common::respan;
-
-type ast_visitor =
-    rec(fn() -> bool  keep_going,
-        fn() -> bool  want_crate_directives,
-        fn(&ast::crate)  visit_crate_pre,
-        fn(&ast::crate)  visit_crate_post,
-        fn(&@ast::crate_directive)  visit_crate_directive_pre,
-        fn(&@ast::crate_directive)  visit_crate_directive_post,
-        fn(&@ast::view_item)  visit_view_item_pre,
-        fn(&@ast::view_item)  visit_view_item_post,
-        fn(&@ast::native_item)  visit_native_item_pre,
-        fn(&@ast::native_item)  visit_native_item_post,
-        fn(&@ast::item)  visit_item_pre,
-        fn(&@ast::item)  visit_item_post,
-        fn(&@ast::method)  visit_method_pre,
-        fn(&@ast::method)  visit_method_post,
-        fn(&ast::block)  visit_block_pre,
-        fn(&ast::block)  visit_block_post,
-        fn(&@ast::stmt)  visit_stmt_pre,
-        fn(&@ast::stmt)  visit_stmt_post,
-        fn(&ast::arm)  visit_arm_pre,
-        fn(&ast::arm)  visit_arm_post,
-        fn(&@ast::pat)  visit_pat_pre,
-        fn(&@ast::pat)  visit_pat_post,
-        fn(&@ast::decl)  visit_decl_pre,
-        fn(&@ast::decl)  visit_decl_post,
-        fn(&@ast::local)  visit_local_pre,
-        fn(&@ast::local)  visit_local_post,
-        fn(&@ast::expr)  visit_expr_pre,
-        fn(&@ast::expr)  visit_expr_post,
-        fn(&@ast::ty)  visit_ty_pre,
-        fn(&@ast::ty)  visit_ty_post,
-        fn(&@ast::constr)  visit_constr,
-        fn(&ast::_fn, &vec[ast::ty_param], &span, &ast::fn_ident,
-           ast::node_id) visit_fn_pre,
-        fn(&ast::_fn, &vec[ast::ty_param], &span, &ast::fn_ident,
-           ast::node_id) visit_fn_post);
-
-fn walk_crate(&ast_visitor v, &ast::crate c) {
-    if (!v.keep_going()) { ret; }
-    v.visit_crate_pre(c);
-    walk_mod(v, c.node.module);
-    v.visit_crate_post(c);
-}
-
-fn walk_crate_directive(&ast_visitor v, @ast::crate_directive cd) {
-    if (!v.keep_going()) { ret; }
-    if (!v.want_crate_directives()) { ret; }
-    v.visit_crate_directive_pre(cd);
-    alt (cd.node) {
-        case (ast::cdir_src_mod(_, _, _)) { }
-        case (ast::cdir_dir_mod(_, _, ?cdirs, _)) {
-            for (@ast::crate_directive cdir in cdirs) {
-                walk_crate_directive(v, cdir);
-            }
-        }
-        case (ast::cdir_view_item(?vi)) { walk_view_item(v, vi); }
-        case (ast::cdir_syntax(_)) { }
-        case (ast::cdir_auth(_, _)) { }
-    }
-    v.visit_crate_directive_post(cd);
-}
-
-fn walk_mod(&ast_visitor v, &ast::_mod m) {
-    if (!v.keep_going()) { ret; }
-    for (@ast::view_item vi in m.view_items) { walk_view_item(v, vi); }
-    for (@ast::item i in m.items) { walk_item(v, i); }
-}
-
-fn walk_view_item(&ast_visitor v, @ast::view_item vi) {
-    if (!v.keep_going()) { ret; }
-    v.visit_view_item_pre(vi);
-    v.visit_view_item_post(vi);
-}
-
-fn walk_local(&ast_visitor v, @ast::local loc) {
-    v.visit_local_pre(loc);
-    alt (loc.node.ty) { case (none) { } case (some(?t)) { walk_ty(v, t); } }
-    alt (loc.node.init) {
-        case (none) { }
-        case (some(?i)) { walk_expr(v, i.expr); }
-    }
-    v.visit_local_post(loc);
-}
-
-fn walk_item(&ast_visitor v, @ast::item i) {
-    if (!v.keep_going()) { ret; }
-    v.visit_item_pre(i);
-    alt (i.node) {
-        case (ast::item_const(?t, ?e)) { walk_ty(v, t); walk_expr(v, e); }
-        case (ast::item_fn(?f, ?tps)) {
-            walk_fn(v, f, tps, i.span, some(i.ident), i.id);
-        }
-        case (ast::item_mod(?m)) { walk_mod(v, m); }
-        case (ast::item_native_mod(?nm)) { walk_native_mod(v, nm); }
-        case (ast::item_ty(?t, _)) { walk_ty(v, t); }
-        case (ast::item_res(?f, ?dtor_id, ?tps, _)) {
-            walk_fn(v, f, tps, i.span, some(i.ident), dtor_id);
-        }
-        case (ast::item_tag(?variants, _)) {
-            for (ast::variant vr in variants) {
-                for (ast::variant_arg va in vr.node.args) {
-                    walk_ty(v, va.ty);
-                }
-            }
-        }
-        case (ast::item_obj(?ob, _, _)) {
-            for (ast::obj_field f in ob.fields) { walk_ty(v, f.ty); }
-            for (@ast::method m in ob.methods) {
-                v.visit_method_pre(m);
-                // Methods don't have ty params?
-                walk_fn(v, m.node.meth, [], m.span,
-                        some(m.node.ident), m.node.id);
-                v.visit_method_post(m);
-            }
-            alt (ob.dtor) {
-                case (none) { }
-                case (some(?m)) {
-                    walk_fn(v, m.node.meth, [], m.span,
-                            some(m.node.ident), m.node.id);
-                }
-            }
-        }
-    }
-    v.visit_item_post(i);
-}
-
-fn walk_ty(&ast_visitor v, @ast::ty t) {
-    if (!v.keep_going()) { ret; }
-    v.visit_ty_pre(t);
-    alt (t.node) {
-        case (ast::ty_nil) { }
-        case (ast::ty_bot) { }
-        case (ast::ty_bool) { }
-        case (ast::ty_int) { }
-        case (ast::ty_uint) { }
-        case (ast::ty_float) { }
-        case (ast::ty_machine(_)) { }
-        case (ast::ty_char) { }
-        case (ast::ty_str) { }
-        case (ast::ty_istr) { }
-        case (ast::ty_box(?mt)) { walk_ty(v, mt.ty); }
-        case (ast::ty_vec(?mt)) { walk_ty(v, mt.ty); }
-        case (ast::ty_ivec(?mt)) { walk_ty(v, mt.ty); }
-        case (ast::ty_ptr(?mt)) { walk_ty(v, mt.ty); }
-        case (ast::ty_task) { }
-        case (ast::ty_port(?t)) { walk_ty(v, t); }
-        case (ast::ty_chan(?t)) { walk_ty(v, t); }
-        case (ast::ty_tup(?mts)) {
-            for (ast::mt mt in mts) { walk_ty(v, mt.ty); }
-        }
-        case (ast::ty_rec(?flds)) {
-            for (ast::ty_field f in flds) { walk_ty(v, f.node.mt.ty); }
-        }
-        case (ast::ty_fn(_, ?args, ?out, _, ?constrs)) {
-            for (ast::ty_arg a in args) { walk_ty(v, a.node.ty); }
-            for (@ast::constr c in constrs) { v.visit_constr(c); }
-            walk_ty(v, out);
-        }
-        case (ast::ty_obj(?tmeths)) {
-            for (ast::ty_method m in tmeths) {
-                for (ast::ty_arg a in m.node.inputs) {
-                    walk_ty(v, a.node.ty);
-                }
-                walk_ty(v, m.node.output);
-            }
-        }
-        case (ast::ty_path(?p, _)) {
-            for (@ast::ty tp in p.node.types) { walk_ty(v, tp); }
-        }
-        case (ast::ty_type) { }
-        case (ast::ty_constr(?t, _)) { walk_ty(v, t); }
-    }
-    v.visit_ty_post(t);
-}
-
-fn walk_pat(&ast_visitor v, &@ast::pat p) {
-    v.visit_pat_pre(p);
-    alt (p.node) {
-        case (ast::pat_tag(?path, ?children)) {
-            for (@ast::ty tp in path.node.types) { walk_ty(v, tp); }
-            for (@ast::pat child in children) { walk_pat(v, child); }
-        }
-        case (_) { }
-    }
-    v.visit_pat_post(p);
-}
-
-fn walk_native_mod(&ast_visitor v, &ast::native_mod nm) {
-    if (!v.keep_going()) { ret; }
-    for (@ast::view_item vi in nm.view_items) { walk_view_item(v, vi); }
-    for (@ast::native_item ni in nm.items) { walk_native_item(v, ni); }
-}
-
-fn walk_native_item(&ast_visitor v, @ast::native_item ni) {
-    if (!v.keep_going()) { ret; }
-    v.visit_native_item_pre(ni);
-    alt (ni.node) {
-        case (ast::native_item_fn(_, ?fd, _)) {
-            walk_fn_decl(v, fd);
-        }
-        case (ast::native_item_ty) { }
-    }
-    v.visit_native_item_post(ni);
-}
-
-fn walk_fn_decl(&ast_visitor v, &ast::fn_decl fd) {
-    for (ast::arg a in fd.inputs) { walk_ty(v, a.ty); }
-    for (@ast::constr c in fd.constraints) { v.visit_constr(c); }
-    walk_ty(v, fd.output);
-}
-
-fn walk_fn(&ast_visitor v, &ast::_fn f, &vec[ast::ty_param] tps,
-           &span sp, &ast::fn_ident i, ast::node_id d) {
-    if (!v.keep_going()) { ret; }
-    v.visit_fn_pre(f, tps, sp, i, d);
-    walk_fn_decl(v, f.decl);
-    walk_block(v, f.body);
-    v.visit_fn_post(f, tps, sp, i, d);
-}
-
-fn walk_block(&ast_visitor v, &ast::block b) {
-    if (!v.keep_going()) { ret; }
-    v.visit_block_pre(b);
-    for (@ast::stmt s in b.node.stmts) { walk_stmt(v, s); }
-    walk_expr_opt(v, b.node.expr);
-    v.visit_block_post(b);
-}
-
-fn walk_stmt(&ast_visitor v, @ast::stmt s) {
-    if (!v.keep_going()) { ret; }
-    v.visit_stmt_pre(s);
-    alt (s.node) {
-        case (ast::stmt_decl(?d, _)) { walk_decl(v, d); }
-        case (ast::stmt_expr(?e, _)) { walk_expr(v, e); }
-        case (ast::stmt_crate_directive(?cdir)) {
-            walk_crate_directive(v, cdir);
-        }
-    }
-    v.visit_stmt_post(s);
-}
-
-fn walk_decl(&ast_visitor v, @ast::decl d) {
-    if (!v.keep_going()) { ret; }
-    v.visit_decl_pre(d);
-    alt (d.node) {
-        case (ast::decl_local(?loc)) { walk_local(v, loc); }
-        case (ast::decl_item(?it)) { walk_item(v, it); }
-    }
-    v.visit_decl_post(d);
-}
-
-fn walk_expr_opt(&ast_visitor v, option::t[@ast::expr] eo) {
-    alt (eo) { case (none) { } case (some(?e)) { walk_expr(v, e); } }
-}
-
-fn walk_exprs(&ast_visitor v, vec[@ast::expr] exprs) {
-    for (@ast::expr e in exprs) { walk_expr(v, e); }
-}
-
-fn walk_expr(&ast_visitor v, @ast::expr e) {
-    if (!v.keep_going()) { ret; }
-    v.visit_expr_pre(e);
-    alt (e.node) {
-        case (ast::expr_vec(?es, _, _)) { walk_exprs(v, es); }
-        case (ast::expr_tup(?elts)) {
-            for (ast::elt e in elts) { walk_expr(v, e.expr); }
-        }
-        case (ast::expr_rec(?flds, ?base)) {
-            for (ast::field f in flds) { walk_expr(v, f.node.expr); }
-            walk_expr_opt(v, base);
-        }
-        case (ast::expr_call(?callee, ?args)) {
-            walk_expr(v, callee);
-            walk_exprs(v, args);
-        }
-        case (ast::expr_self_method(_)) { }
-        case (ast::expr_bind(?callee, ?args)) {
-            walk_expr(v, callee);
-            for (option::t[@ast::expr] eo in args) { walk_expr_opt(v, eo); }
-        }
-        case (ast::expr_spawn(_, _, ?callee, ?args)) {
-            walk_expr(v, callee);
-            walk_exprs(v, args);
-        }
-        case (ast::expr_binary(_, ?a, ?b)) {
-            walk_expr(v, a);
-            walk_expr(v, b);
-        }
-        case (ast::expr_unary(_, ?a)) { walk_expr(v, a); }
-        case (ast::expr_lit(_)) { }
-        case (ast::expr_cast(?x, ?t)) { walk_expr(v, x); walk_ty(v, t); }
-        case (ast::expr_if(?x, ?b, ?eo)) {
-            walk_expr(v, x);
-            walk_block(v, b);
-            walk_expr_opt(v, eo);
-        }
-        case (ast::expr_if_check(?x, ?b, ?eo)) {
-            walk_expr(v, x);
-            walk_block(v, b);
-            walk_expr_opt(v, eo);
-        }
-        case (ast::expr_ternary(?c, ?t, ?e)) {
-            walk_expr(v, c);
-            walk_expr(v, t);
-            walk_expr(v, e);
-        }
-        case (ast::expr_while(?x, ?b)) {
-            walk_expr(v, x);
-            walk_block(v, b);
-        }
-        case (ast::expr_for(?dcl, ?x, ?b)) {
-            walk_local(v, dcl);
-            walk_expr(v, x);
-            walk_block(v, b);
-        }
-        case (ast::expr_for_each(?dcl, ?x, ?b)) {
-            walk_local(v, dcl);
-            walk_expr(v, x);
-            walk_block(v, b);
-        }
-        case (ast::expr_do_while(?b, ?x)) {
-            walk_block(v, b);
-            walk_expr(v, x);
-        }
-        case (ast::expr_alt(?x, ?arms)) {
-            walk_expr(v, x);
-            for (ast::arm a in arms) {
-                walk_pat(v, a.pat);
-                v.visit_arm_pre(a);
-                walk_block(v, a.block);
-                v.visit_arm_post(a);
-            }
-        }
-        case (ast::expr_fn(?f)) {
-            walk_fn(v, f, [], e.span, none, e.id);
-        }
-        case (ast::expr_block(?b)) { walk_block(v, b); }
-        case (ast::expr_assign(?a, ?b)) {
-            walk_expr(v, a);
-            walk_expr(v, b);
-        }
-        case (ast::expr_move(?a, ?b)) { walk_expr(v, a); walk_expr(v, b); }
-        case (ast::expr_swap(?a, ?b)) { walk_expr(v, a); walk_expr(v, b); }
-        case (ast::expr_assign_op(_, ?a, ?b)) {
-            walk_expr(v, a);
-            walk_expr(v, b);
-        }
-        case (ast::expr_send(?a, ?b)) { walk_expr(v, a); walk_expr(v, b); }
-        case (ast::expr_recv(?a, ?b)) { walk_expr(v, a); walk_expr(v, b); }
-        case (ast::expr_field(?x, _)) { walk_expr(v, x); }
-        case (ast::expr_index(?a, ?b)) {
-            walk_expr(v, a);
-            walk_expr(v, b);
-        }
-        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_fail(?eo)) { walk_expr_opt(v, eo); }
-        case (ast::expr_break) { }
-        case (ast::expr_cont) { }
-        case (ast::expr_ret(?eo)) { walk_expr_opt(v, eo); }
-        case (ast::expr_put(?eo)) { walk_expr_opt(v, eo); }
-        case (ast::expr_be(?x)) { walk_expr(v, x); }
-        case (ast::expr_log(_, ?x)) { walk_expr(v, x); }
-        case (ast::expr_check(_, ?x)) { walk_expr(v, x); }
-        case (ast::expr_assert(?x)) { walk_expr(v, x); }
-        case (ast::expr_port(_)) { }
-        case (ast::expr_chan(?x)) { walk_expr(v, x); }
-        case (ast::expr_anon_obj(?anon_obj, _, _)) {
-            // Fields
-
-            alt (anon_obj.fields) {
-                case (none) { }
-                case (some(?fields)) {
-                    for (ast::anon_obj_field f in fields) { 
-                        walk_ty(v, f.ty);
-                        walk_expr(v, f.expr);
-                    }
-                }
-            }
-            // with_obj
-
-            alt (anon_obj.with_obj) {
-                case (none) { }
-                case (some(?e)) { walk_expr(v, e); }
-            }
-
-            // Methods
-            for (@ast::method m in anon_obj.methods) {
-                v.visit_method_pre(m);
-                walk_fn(v, m.node.meth, [], m.span, some(m.node.ident),
-                        m.node.id);
-                v.visit_method_post(m);
-            }
-        }
-    }
-    v.visit_expr_post(e);
-}
-
-fn def_keep_going() -> bool { ret true; }
-
-fn def_want_crate_directives() -> bool { ret false; }
-
-fn def_visit_crate(&ast::crate c) { }
-
-fn def_visit_crate_directive(&@ast::crate_directive c) { }
-
-fn def_visit_view_item(&@ast::view_item vi) { }
-
-fn def_visit_native_item(&@ast::native_item ni) { }
-
-fn def_visit_item(&@ast::item i) { }
-
-fn def_visit_method(&@ast::method m) { }
-
-fn def_visit_block(&ast::block b) { }
-
-fn def_visit_stmt(&@ast::stmt s) { }
-
-fn def_visit_arm(&ast::arm a) { }
-
-fn def_visit_pat(&@ast::pat p) { }
-
-fn def_visit_decl(&@ast::decl d) { }
-
-fn def_visit_local(&@ast::local l) { }
-
-fn def_visit_expr(&@ast::expr e) { }
-
-fn def_visit_ty(&@ast::ty t) { }
-
-fn def_visit_constr(&@ast::constr c) { }
-
-fn def_visit_fn(&ast::_fn f, &vec[ast::ty_param] tps,
-  &span sp, &ast::fn_ident i, ast::node_id d) { }
-
-fn default_visitor() -> ast_visitor {
-    ret rec(keep_going=def_keep_going,
-            want_crate_directives=def_want_crate_directives,
-            visit_crate_pre=def_visit_crate,
-            visit_crate_post=def_visit_crate,
-            visit_crate_directive_pre=def_visit_crate_directive,
-            visit_crate_directive_post=def_visit_crate_directive,
-            visit_view_item_pre=def_visit_view_item,
-            visit_view_item_post=def_visit_view_item,
-            visit_native_item_pre=def_visit_native_item,
-            visit_native_item_post=def_visit_native_item,
-            visit_item_pre=def_visit_item,
-            visit_item_post=def_visit_item,
-            visit_method_pre=def_visit_method,
-            visit_method_post=def_visit_method,
-            visit_block_pre=def_visit_block,
-            visit_block_post=def_visit_block,
-            visit_stmt_pre=def_visit_stmt,
-            visit_stmt_post=def_visit_stmt,
-            visit_arm_pre=def_visit_arm,
-            visit_arm_post=def_visit_arm,
-            visit_pat_pre=def_visit_pat,
-            visit_pat_post=def_visit_pat,
-            visit_decl_pre=def_visit_decl,
-            visit_decl_post=def_visit_decl,
-            visit_local_pre=def_visit_local,
-            visit_local_post=def_visit_local,
-            visit_expr_pre=def_visit_expr,
-            visit_expr_post=def_visit_expr,
-            visit_ty_pre=def_visit_ty,
-            visit_ty_post=def_visit_ty,
-            visit_constr=def_visit_constr,
-            visit_fn_pre=def_visit_fn,
-            visit_fn_post=def_visit_fn);
-}
-//
-// 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/pretty/pp.rs b/src/comp/pretty/pp.rs
deleted file mode 100644 (file)
index ef3a875..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-
-import std::io;
-import std::vec;
-import std::str;
-
-
-/*
- * This pretty-printer is a direct reimplementation of Philip Karlton's
- * Mesa pretty-printer, as described in appendix A of
- *
- *     STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen.
- *     Stanford Department of Computer Science, 1979.
- *
- * The algorithm's aim is to break a stream into as few lines as possible
- * while respecting the indentation-consistency requirements of the enclosing
- * block, and avoiding breaking at silly places on block boundaries, for
- * example, between "x" and ")" in "x)".
- *
- * I am implementing this algorithm because it comes with 20 pages of
- * documentation explaining its theory, and because it addresses the set of
- * concerns I've seen other pretty-printers fall down on. Weirdly. Even though
- * it's 32 years old and not written in Haskell. What can I say?
- *
- * Despite some redundancies and quirks in the way it's implemented in that
- * paper, I've opted to keep the implementation here as similar as I can,
- * changing only what was blatantly wrong, a typo, or sufficiently
- * non-idiomatic rust that it really stuck out.
- *
- * In particular you'll see a certain amount of churn related to INTEGER vs.
- * CARDINAL in the Mesa implementation. Mesa apparently interconverts the two
- * somewhat readily? In any case, I've used uint for indices-in-buffers and
- * ints for character-sizes-and-indentation-offsets. This respects the need
- * for ints to "go negative" while carrying a pending-calculation balance, and
- * helps differentiate all the numbers flying around internally (slightly).
- *
- * I also inverted the indentation arithmetic used in the print stack, since
- * the Mesa implementation (somewhat randomly) stores the offset on the print
- * stack in terms of margin-col rather than col itself. I store col.
- *
- * I also implemented a small change in the STRING token, in that I store an
- * explicit length for the string. For most tokens this is just the length of
- * the accompanying string. But it's necessary to permit it to differ, for
- * encoding things that are supposed to "go on their own line" -- certain
- * classes of comment and blank-line -- where relying on adjacent
- * hardbreak-like BREAK tokens with long blankness indication doesn't actually
- * work. To see why, consider when there is a "thing that should be on its own
- * line" between two long blocks, say functions. If you put a hardbreak after
- * each function (or before each) and the breaking algorithm decides to break
- * there anyways (because the functions themselves are long) you wind up with
- * extra blank lines. If you don't put hardbreaks you can wind up with the
- * "thing which should be on its own line" not getting its own line in the
- * rare case of "really small functions" or such. This re-occurs with comments
- * and explicit blank lines. So in those cases we use a string with a payload
- * we want isolated to a line and an explicit length that's huge, surrounded
- * by two zero-length breaks. The algorithm will try its best to fit it on a
- * line (which it can't) and so naturally place the content on its own line to
- * avoid combining it with other lines and making matters even worse.
- */
-tag breaks { consistent; inconsistent; }
-
-type break_t = rec(int offset, int blank_space);
-
-type begin_t = rec(int offset, breaks breaks);
-
-tag token { STRING(str, int); BREAK(break_t); BEGIN(begin_t); END; EOF; }
-
-fn tok_str(token t) -> str {
-    alt (t) {
-        case (STRING(?s, ?len)) { ret #fmt("STR(%s,%d)", s, len); }
-        case (BREAK(_)) { ret "BREAK"; }
-        case (BEGIN(_)) { ret "BEGIN"; }
-        case (END) { ret "END"; }
-        case (EOF) { ret "EOF"; }
-    }
-}
-
-fn buf_str(vec[mutable token] toks, vec[mutable int] szs, uint left,
-           uint right, uint lim) -> str {
-    auto n = vec::len(toks);
-    assert (n == vec::len(szs));
-    auto i = left;
-    auto L = lim;
-    auto s = "[";
-    while (i != right && L != 0u) {
-        L -= 1u;
-        if (i != left) { s += ", "; }
-        s += #fmt("%d=%s", szs.(i), tok_str(toks.(i)));
-        i += 1u;
-        i %= n;
-    }
-    s += "]";
-    ret s;
-}
-
-tag print_stack_break { fits; broken(breaks); }
-
-type print_stack_elt = rec(int offset, print_stack_break pbreak);
-
-const int size_infinity = 0xffff;
-
-fn mk_printer(io::writer out, uint linewidth) -> printer {
-    // Yes 3, it makes the ring buffers big enough to never
-    // fall behind.
-
-    let uint n = 3u * linewidth;
-    log #fmt("mk_printer %u", linewidth);
-    let vec[mutable token] token = vec::init_elt_mut(EOF, n);
-    let vec[mutable int] size = vec::init_elt_mut(0, n);
-    let vec[mutable uint] scan_stack = vec::init_elt_mut(0u, n);
-    let vec[print_stack_elt] print_stack = [];
-    ret printer(out, n, linewidth as int, // margin
-                 linewidth as int, // space
-                 0u, // left
-                 0u, // right
-                 token, size, 0, // left_total
-                 0, // right_total
-                 scan_stack, true, // scan_stack_empty
-                 0u, // top
-                 0u, // bottom
-                 print_stack, 0);
-}
-
-
-/*
- * In case you do not have the paper, here is an explanation of what's going
- * on.
- *
- * There is a stream of input tokens flowing through this printer.
- *
- * The printer buffers up to 3N tokens inside itself, where N is linewidth.
- * Yes, linewidth is chars and tokens are multi-char, but in the worst
- * case every token worth buffering is 1 char long, so it's ok.
- *
- * Tokens are STRING, BREAK, and BEGIN/END to delimit blocks.
- *
- * BEGIN tokens can carry an offset, saying "how far to indent when you break
- * inside here", as well as a flag indicating "consistent" or "inconsistent"
- * breaking. Consistent breaking means that after the first break, no attempt
- * will be made to flow subsequent breaks together onto lines. Inconsistent
- * is the opposite. Inconsistent breaking example would be, say:
- *
- *  foo(hello, there, good, friends)
- *
- * breaking inconsistently to become
- *
- *  foo(hello, there
- *      good, friends);
- *
- * whereas a consistent breaking would yield:
- *
- *  foo(hello,
- *      there
- *      good,
- *      friends);
- *
- * That is, in the consistent-break blocks we value vertical alignment
- * more than the ability to cram stuff onto a line. But in all cases if it
- * can make a block a one-liner, it'll do so.
- *
- * Carrying on with high-level logic:
- *
- * The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and
- * 'right' indices denote the active portion of the ring buffer as well as
- * describing hypothetical points-in-the-infinite-stream at most 3N tokens
- * apart (i.e. "not wrapped to ring-buffer boundaries"). The paper will switch
- * between using 'left' and 'right' terms to denote the wrapepd-to-ring-buffer
- * and point-in-infinite-stream senses freely.
- *
- * There is a parallel ring buffer, 'size', that holds the calculated size of
- * each token. Why calculated? Because for BEGIN/END pairs, the "size"
- * includes everything betwen the pair. That is, the "size" of BEGIN is
- * actually the sum of the sizes of everything between BEGIN and the paired
- * END that follows. Since that is arbitrarily far in the future, 'size' is
- * being rewritten regularly while the printer runs; in fact most of the
- * machinery is here to work out 'size' entries on the fly (and give up when
- * they're so obviously over-long that "infinity" is a good enough
- * approximation for purposes of line breaking).
- *
- * The "input side" of the printer is managed as an abstract process called
- * SCAN, which uses 'scan_stack', 'scan_stack_empty', 'top' and 'bottom', to
- * manage calculating 'size'. SCAN is, in other words, the process of
- * calculating 'size' entries.
- *
- * The "output side" of the printer is managed by an abstract process called
- * PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to
- * do with each token/size pair it consumes as it goes. It's trying to consume
- * the entire buffered window, but can't output anything until the size is >=
- * 0 (sizes are set to negative while they're pending calculation).
- *
- * So SCAN takeks input and buffers tokens and pending calculations, while
- * PRINT gobbles up completed calculations and tokens from the buffer. The
- * theory is that the two can never get more than 3N tokens apart, because
- * once there's "obviously" too much data to fit on a line, in a size
- * calculation, SCAN will write "infinity" to the size and let PRINT consume
- * it.
- *
- * In this implementation (following the paper, again) the SCAN process is
- * the method called 'pretty_print', and the 'PRINT' process is the method
- * called 'print'.
- */
-obj printer(io::writer out,
-            uint buf_len,
-            mutable int margin, // width of lines we're constrained to
-
-            mutable int space, // number of spaces left on line
-
-            mutable uint left, // index of left side of input stream
-
-            mutable uint right, // index of right side of input stream
-
-            mutable vec[mutable token] token,
-             // ring-buffr stream goes through
-            mutable vec[mutable int] size, // ring-buffer of calculated sizes
-
-            mutable int left_total, // running size of stream "...left"
-
-            mutable int right_total, // running size of stream "...right"
-
-             // pseudo-stack, really a ring too. Holds the
-             // primary-ring-buffers index of the BEGIN that started the
-             // current block, possibly with the most recent BREAK after that
-             // BEGIN (if there is any) on top of it. Stuff is flushed off the
-             // bottom as it becomes irrelevant due to the primary ring-buffer
-             // advancing.
-             mutable vec[mutable uint] scan_stack,
-            mutable bool scan_stack_empty, // top==bottom disambiguator
-
-            mutable uint top, // index of top of scan_stack
-
-            mutable uint bottom, // index of bottom of scan_stack
-
-             // stack of blocks-in-progress being flushed by print
-            mutable vec[print_stack_elt] print_stack,
-
-            // buffered indentation to avoid writing trailing whitespace
-            mutable int pending_indentation) {
-
-    fn last_token() -> token {
-        ret token.(right);
-    }
-
-    fn pretty_print(token t) {
-        log #fmt("pp [%u,%u]", left, right);
-        alt (t) {
-            case (EOF) {
-                if (!scan_stack_empty) {
-                    self.check_stack(0);
-                    self.advance_left(token.(left), size.(left));
-                }
-                self.indent(0);
-            }
-            case (BEGIN(?b)) {
-                if (scan_stack_empty) {
-                    left_total = 1;
-                    right_total = 1;
-                    left = 0u;
-                    right = 0u;
-                } else { self.advance_right(); }
-                log #fmt("pp BEGIN/buffer [%u,%u]", left, right);
-                token.(right) = t;
-                size.(right) = -right_total;
-                self.scan_push(right);
-            }
-            case (END) {
-                if (scan_stack_empty) {
-                    log #fmt("pp END/print [%u,%u]", left, right);
-                    self.print(t, 0);
-                } else {
-                    log #fmt("pp END/buffer [%u,%u]", left, right);
-                    self.advance_right();
-                    token.(right) = t;
-                    size.(right) = -1;
-                    self.scan_push(right);
-                }
-            }
-            case (BREAK(?b)) {
-                if (scan_stack_empty) {
-                    left_total = 1;
-                    right_total = 1;
-                    left = 0u;
-                    right = 0u;
-                } else { self.advance_right(); }
-                log #fmt("pp BREAK/buffer [%u,%u]", left, right);
-                self.check_stack(0);
-                self.scan_push(right);
-                token.(right) = t;
-                size.(right) = -right_total;
-                right_total += b.blank_space;
-            }
-            case (STRING(?s, ?len)) {
-                if (scan_stack_empty) {
-                    log #fmt("pp STRING/print [%u,%u]", left, right);
-                    self.print(t, len);
-                } else {
-                    log #fmt("pp STRING/buffer [%u,%u]", left, right);
-                    self.advance_right();
-                    token.(right) = t;
-                    size.(right) = len;
-                    right_total += len;
-                    self.check_stream();
-                }
-            }
-        }
-    }
-    fn check_stream() {
-        log #fmt("check_stream [%u, %u] with left_total=%d, right_total=%d",
-                 left, right, left_total, right_total);
-        if (right_total - left_total > space) {
-            log #fmt("scan window is %d, longer than space on line (%d)",
-                     right_total - left_total, space);
-            if (!scan_stack_empty) {
-                if (left == scan_stack.(bottom)) {
-                    log #fmt("setting %u to infinity and popping", left);
-                    size.(self.scan_pop_bottom()) = size_infinity;
-                }
-            }
-            self.advance_left(token.(left), size.(left));
-            if (left != right) { self.check_stream(); }
-        }
-    }
-    fn scan_push(uint x) {
-        log #fmt("scan_push %u", x);
-        if (scan_stack_empty) {
-            scan_stack_empty = false;
-        } else { top += 1u; top %= buf_len; assert (top != bottom); }
-        scan_stack.(top) = x;
-    }
-    fn scan_pop() -> uint {
-        assert (!scan_stack_empty);
-        auto x = scan_stack.(top);
-        if (top == bottom) {
-            scan_stack_empty = true;
-        } else { top += buf_len - 1u; top %= buf_len; }
-        ret x;
-    }
-    fn scan_top() -> uint {
-        assert (!scan_stack_empty);
-        ret scan_stack.(top);
-    }
-    fn scan_pop_bottom() -> uint {
-        assert (!scan_stack_empty);
-        auto x = scan_stack.(bottom);
-        if (top == bottom) {
-            scan_stack_empty = true;
-        } else { bottom += 1u; bottom %= buf_len; }
-        ret x;
-    }
-    fn advance_right() {
-        right += 1u;
-        right %= buf_len;
-        assert (right != left);
-    }
-    fn advance_left(token x, int L) {
-        log #fmt("advnce_left [%u,%u], sizeof(%u)=%d", left, right, left, L);
-        if (L >= 0) {
-            self.print(x, L);
-            alt (x) {
-                case (BREAK(?b)) { left_total += b.blank_space; }
-                case (STRING(_, ?len)) {
-                    assert (len == L);
-                    left_total += len;
-                }
-                case (_) { }
-            }
-            if (left != right) {
-                left += 1u;
-                left %= buf_len;
-                self.advance_left(token.(left), size.(left));
-            }
-        }
-    }
-    fn check_stack(int k) {
-        if (!scan_stack_empty) {
-            auto x = self.scan_top();
-            alt (token.(x)) {
-                case (BEGIN(?b)) {
-                    if (k > 0) {
-                        size.(self.scan_pop()) = size.(x) + right_total;
-                        self.check_stack(k - 1);
-                    }
-                }
-                case (END) {
-                    // paper says + not =, but that makes no sense.
-
-                    size.(self.scan_pop()) = 1;
-                    self.check_stack(k + 1);
-                }
-                case (_) {
-                    size.(self.scan_pop()) = size.(x) + right_total;
-                    if (k > 0) { self.check_stack(k); }
-                }
-            }
-        }
-    }
-    fn print_newline(int amount) {
-        log #fmt("NEWLINE %d", amount);
-        out.write_str("\n");
-        pending_indentation = 0;
-        self.indent(amount);
-    }
-    fn indent(int amount) {
-        log #fmt("INDENT %d", amount);
-        pending_indentation += amount;
-    }
-    fn top() -> print_stack_elt {
-        auto n = vec::len(print_stack);
-        let print_stack_elt top = rec(offset=0, pbreak=broken(inconsistent));
-        if (n != 0u) { top = print_stack.(n - 1u); }
-        ret top;
-    }
-    fn write_str(str s) {
-        while (pending_indentation > 0) {
-            out.write_str(" ");
-            pending_indentation -= 1;
-        }
-        out.write_str(s);
-    }
-    fn print(token x, int L) {
-        log #fmt("print %s %d (remaining line space=%d)", tok_str(x), L,
-                 space);
-        log buf_str(token, size, left, right, 6u);
-        alt (x) {
-            case (BEGIN(?b)) {
-                if (L > space) {
-                    auto col = margin - space + b.offset;
-                    log #fmt("print BEGIN -> push broken block at col %d",
-                             col);
-                    vec::push(print_stack,
-                              rec(offset=col, pbreak=broken(b.breaks)));
-                } else {
-                    log "print BEGIN -> push fitting block";
-                    vec::push(print_stack, rec(offset=0, pbreak=fits));
-                }
-            }
-            case (END) {
-                log "print END -> pop END";
-                assert (vec::len(print_stack) != 0u);
-                vec::pop(print_stack);
-            }
-            case (BREAK(?b)) {
-                auto top = self.top();
-                alt (top.pbreak) {
-                    case (fits) {
-                        log "print BREAK in fitting block";
-                        space -= b.blank_space;
-                        self.indent(b.blank_space);
-                    }
-                    case (broken(consistent)) {
-                        log "print BREAK in consistent block";
-                        self.print_newline(top.offset + b.offset);
-                        space = margin - (top.offset + b.offset);
-                    }
-                    case (broken(inconsistent)) {
-                        if (L > space) {
-                            log "print BREAK w/ newline in inconsistent";
-                            self.print_newline(top.offset + b.offset);
-                            space = margin - (top.offset + b.offset);
-                        } else {
-                            log "print BREAK w/o newline in inconsistent";
-                            self.indent(b.blank_space);
-                            space -= b.blank_space;
-                        }
-                    }
-                }
-            }
-            case (STRING(?s, ?len)) {
-                log "print STRING";
-                assert (L == len);
-                // assert L <= space;
-
-                space -= len;
-                self.write_str(s);
-            }
-            case (EOF) {
-                // EOF should never get here.
-
-                fail;
-            }
-        }
-    }
-}
-
-
-// Convenience functions to talk to the printer.
-fn box(printer p, uint indent, breaks b) {
-    p.pretty_print(BEGIN(rec(offset=indent as int, breaks=b)));
-}
-
-fn ibox(printer p, uint indent) { box(p, indent, inconsistent); }
-
-fn cbox(printer p, uint indent) { box(p, indent, consistent); }
-
-fn break_offset(printer p, uint n, int off) {
-    p.pretty_print(BREAK(rec(offset=off, blank_space=n as int)));
-}
-
-fn end(printer p) { p.pretty_print(END); }
-
-fn eof(printer p) { p.pretty_print(EOF); }
-
-fn word(printer p, str wrd) {
-    p.pretty_print(STRING(wrd, str::char_len(wrd) as int));
-}
-
-fn huge_word(printer p, str wrd) {
-    p.pretty_print(STRING(wrd, size_infinity));
-}
-
-fn zero_word(printer p, str wrd) { p.pretty_print(STRING(wrd, 0)); }
-
-fn spaces(printer p, uint n) { break_offset(p, n, 0); }
-
-fn zerobreak(printer p) { spaces(p, 0u); }
-
-fn space(printer p) { spaces(p, 1u); }
-
-fn hardbreak(printer p) { spaces(p, size_infinity as uint); }
-
-fn hardbreak_tok() -> token {
-    ret BREAK(rec(offset=0, blank_space=size_infinity));
-}
-
-//
-// 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/pretty/ppaux.rs b/src/comp/pretty/ppaux.rs
deleted file mode 100644 (file)
index ea41361..0000000
+++ /dev/null
@@ -1,433 +0,0 @@
-
-import std::io;
-import std::vec;
-import std::str;
-import std::option;
-import std::option::none;
-import std::option::some;
-import middle::ty;
-import middle::ty::*;
-import front::lexer;
-import front::ast;
-import pp::word;
-import pp::eof;
-import pp::zerobreak;
-import pp::hardbreak;
-import front::codemap;
-import front::codemap::codemap;
-import util::common::istr;
-import util::common::uistr;
-import util::common::ty_mach_to_str;
-
-fn mode_str(&ty::mode m) -> str {
-    alt (m) {
-        case (mo_val) { "" }
-        case (mo_alias(false)) { "&" }
-        case (mo_alias(true)) { "&mutable " }
-    }
-}
-
-fn mode_str_1(&ty::mode m) -> str {
-    alt (m) {
-        case (mo_val) { "val" }
-        case (_)      { mode_str(m) }
-    }
-}
-
-fn fn_ident_to_string(ast::node_id id, &ast::fn_ident i) -> str {
-    ret alt (i) {
-        case (none) { "anon" + istr(id) }
-        case (some(?s)) { s }
-    };
-}
-
-fn ty_to_str(&ctxt cx, &t typ) -> str {
-    fn fn_input_to_str(&ctxt cx, &rec(middle::ty::mode mode, t ty) input) ->
-       str {
-        auto s = mode_str(input.mode);
-        ret s + ty_to_str(cx, input.ty);
-    }
-    fn fn_to_str(&ctxt cx, ast::proto proto, option::t[ast::ident] ident,
-                 &arg[] inputs, t output, ast::controlflow cf,
-                 &vec[@constr_def] constrs) -> str {
-        auto s;
-        alt (proto) {
-            case (ast::proto_iter) { s = "iter"; }
-            case (ast::proto_fn) { s = "fn"; }
-        }
-        alt (ident) { case (some(?i)) { s += " "; s += i; } case (_) { } }
-        s += "(";
-        auto strs = [];
-        for (arg a in inputs) { strs += [fn_input_to_str(cx, a)]; }
-        s += str::connect(strs, ", ");
-        s += ")";
-        if (struct(cx, output) != ty_nil) {
-            alt (cf) {
-                case (ast::noreturn) { s += " -> !"; }
-                case (ast::return) { s += " -> " + ty_to_str(cx, output); }
-            }
-        }
-        s += constrs_str(constrs);
-        ret s;
-    }
-    fn method_to_str(&ctxt cx, &method m) -> str {
-        ret fn_to_str(cx, m.proto, some[ast::ident](m.ident), m.inputs,
-                      m.output, m.cf, m.constrs) + ";";
-    }
-    fn field_to_str(&ctxt cx, &field f) -> str {
-        ret mt_to_str(cx, f.mt) + " " + f.ident;
-    }
-    fn mt_to_str(&ctxt cx, &mt m) -> str {
-        auto mstr;
-        alt (m.mut) {
-            case (ast::mut) { mstr = "mutable "; }
-            case (ast::imm) { mstr = ""; }
-            case (ast::maybe_mut) { mstr = "mutable? "; }
-        }
-        ret mstr + ty_to_str(cx, m.ty);
-    }
-    alt (cname(cx, typ)) { case (some(?cs)) { ret cs; } case (_) { } }
-    auto s = "";
-    alt (struct(cx, typ)) {
-        case (ty_native(_)) { s += "native"; }
-        case (ty_nil) { s += "()"; }
-        case (ty_bot) { s += "_|_"; }
-        case (ty_bool) { s += "bool"; }
-        case (ty_int) { s += "int"; }
-        case (ty_float) { s += "float"; }
-        case (ty_uint) { s += "uint"; }
-        case (ty_machine(?tm)) { s += ty_mach_to_str(tm); }
-        case (ty_char) { s += "char"; }
-        case (ty_str) { s += "str"; }
-        case (ty_istr) { s += "istr"; }
-        case (ty_box(?tm)) { s += "@" + mt_to_str(cx, tm); }
-        case (ty_vec(?tm)) { s += "vec[" + mt_to_str(cx, tm) + "]"; }
-        case (ty_ivec(?tm)) { s += "ivec[" + mt_to_str(cx, tm) + "]"; }
-        case (ty_port(?t)) { s += "port[" + ty_to_str(cx, t) + "]"; }
-        case (ty_chan(?t)) { s += "chan[" + ty_to_str(cx, t) + "]"; }
-        case (ty_type) { s += "type"; }
-        case (ty_task) { s += "task"; }
-        case (ty_tup(?elems)) {
-            let vec[str] strs = [];
-            for (mt tm in elems) { strs += [mt_to_str(cx, tm)]; }
-            s += "tup(" + str::connect(strs, ",") + ")";
-        }
-        case (ty_rec(?elems)) {
-            let vec[str] strs = [];
-            for (field fld in elems) { strs += [field_to_str(cx, fld)]; }
-            s += "rec(" + str::connect(strs, ",") + ")";
-        }
-        case (ty_tag(?id, ?tps)) {
-            // The user should never see this if the cname is set properly!
-
-            s += "<tag#" + istr(id._0) + ":" + istr(id._1) + ">";
-            if (vec::len[t](tps) > 0u) {
-                auto f = bind ty_to_str(cx, _);
-                auto strs = vec::map[t, str](f, tps);
-                s += "[" + str::connect(strs, ",") + "]";
-            }
-        }
-        case (ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
-            s += fn_to_str(cx, proto, none, inputs, output, cf, constrs);
-        }
-        case (ty_native_fn(_, ?inputs, ?output)) {
-            s += fn_to_str(cx, ast::proto_fn, none, inputs, output,
-                           ast::return, []);
-        }
-        case (ty_obj(?meths)) {
-            auto f = bind method_to_str(cx, _);
-            auto m = vec::map[method, str](f, meths);
-            s += "obj {\n\t" + str::connect(m, "\n\t") + "\n}";
-        }
-        case (ty_res(?id, _, _)) {
-            s += "<resource#" + istr(id._0) + ":" + istr(id._1) + ">";
-        }
-        case (ty_var(?v)) { s += "<T" + istr(v) + ">"; }
-        case (ty_param(?id)) {
-            s += "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)]);
-        }
-        case (_) { s += ty_to_short_str(cx, typ); }
-    }
-    ret s;
-}
-
-fn ty_to_short_str(&ctxt cx, t typ) -> str {
-    auto f = def_to_str;
-    auto ecx = @rec(ds=f, tcx=cx, abbrevs=metadata::tyencode::ac_no_abbrevs);
-    auto s = metadata::tyencode::ty_str(ecx, typ);
-    if (str::byte_len(s) >= 32u) { s = str::substr(s, 0u, 32u); }
-    ret s;
-}
-
-fn constr_arg_to_str[T](fn(&T) -> str  f, &ast::constr_arg_general_[T] c) ->
-   str {
-    alt (c) {
-        case (ast::carg_base) { ret "*"; }
-        case (ast::carg_ident(?i)) { ret f(i); }
-        case (ast::carg_lit(?l)) { ret lit_to_str(l); }
-    }
-}
-
-fn constr_arg_to_str_1(&front::ast::constr_arg_general_[str] c) -> str {
-    alt (c) {
-        case (ast::carg_base) { ret "*"; }
-        case (ast::carg_ident(?i)) { ret i; }
-        case (ast::carg_lit(?l)) { ret lit_to_str(l); }
-    }
-}
-
-fn constr_args_to_str[T](fn(&T) -> str  f,
-                         &vec[@ast::constr_arg_general[T]] args) -> str {
-    auto comma = false;
-    auto s = "(";
-    for (@ast::constr_arg_general[T] a in args) {
-        if (comma) { s += ", "; } else { comma = true; }
-        s += constr_arg_to_str[T](f, a.node);
-    }
-    s += ")";
-    ret s;
-}
-
-fn print_literal(&ps s, &@front::ast::lit lit) {
-    maybe_print_comment(s, lit.span.lo);
-    alt (next_lit(s)) {
-        case (some(?lt)) {
-            if (lt.pos == lit.span.lo) {
-                word(s.s, lt.lit);
-                s.cur_lit += 1u;
-                ret;
-            }
-        }
-        case (_) { }
-    }
-    alt (lit.node) {
-        case (ast::lit_str(?st, ?kind)) {
-            if (kind == ast::sk_unique) { word(s.s, "~"); }
-            print_string(s, st);
-        }
-        case (ast::lit_char(?ch)) {
-            word(s.s,
-                 "'" + escape_str(str::from_bytes([ch as u8]), '\'') + "'");
-        }
-        case (ast::lit_int(?val)) { word(s.s, istr(val)); }
-        case (ast::lit_uint(?val)) { word(s.s, uistr(val) + "u"); }
-        case (ast::lit_float(?fstr)) { word(s.s, fstr); }
-        case (ast::lit_mach_int(?mach, ?val)) {
-            word(s.s, istr(val as int));
-            word(s.s, ty_mach_to_str(mach));
-        }
-        case (ast::lit_mach_float(?mach, ?val)) {
-            // val is already a str
-
-            word(s.s, val);
-            word(s.s, ty_mach_to_str(mach));
-        }
-        case (ast::lit_nil) { word(s.s, "()"); }
-        case (ast::lit_bool(?val)) {
-            if (val) { word(s.s, "true"); } else { word(s.s, "false"); }
-        }
-    }
-}
-
-fn lit_to_str(&@front::ast::lit l) -> str { be to_str(l, print_literal); }
-
-fn next_lit(&ps s) -> option::t[lexer::lit] {
-    alt (s.literals) {
-        case (some(?lits)) {
-            if (s.cur_lit < vec::len(lits)) {
-                ret some(lits.(s.cur_lit));
-            } else { ret none[lexer::lit]; }
-        }
-        case (_) { ret none[lexer::lit]; }
-    }
-}
-
-fn maybe_print_comment(&ps s, uint pos) {
-    while (true) {
-        alt (next_comment(s)) {
-            case (some(?cmnt)) {
-                if (cmnt.pos < pos) {
-                    print_comment(s, cmnt);
-                    s.cur_cmnt += 1u;
-                } else { break; }
-            }
-            case (_) { break; }
-        }
-    }
-}
-
-fn print_comment(&ps s, lexer::cmnt cmnt) {
-    alt (cmnt.style) {
-        case (lexer::mixed) {
-            assert (vec::len(cmnt.lines) == 1u);
-            zerobreak(s.s);
-            word(s.s, cmnt.lines.(0));
-            zerobreak(s.s);
-        }
-        case (lexer::isolated) {
-            pprust::hardbreak_if_not_bol(s);
-            for (str line in cmnt.lines) { word(s.s, line); hardbreak(s.s); }
-        }
-        case (lexer::trailing) {
-            word(s.s, " ");
-            if (vec::len(cmnt.lines) == 1u) {
-                word(s.s, cmnt.lines.(0));
-                hardbreak(s.s);
-            } else {
-                ibox(s, 0u);
-                for (str line in cmnt.lines) {
-                    word(s.s, line);
-                    hardbreak(s.s);
-                }
-                end(s);
-            }
-        }
-        case (lexer::blank_line) {
-            // We need to do at least one, possibly two hardbreaks.
-            pprust::hardbreak_if_not_bol(s);
-            hardbreak(s.s);
-        }
-    }
-}
-
-fn print_string(&ps s, &str st) {
-    word(s.s, "\"");
-    word(s.s, escape_str(st, '"'));
-    word(s.s, "\"");
-}
-
-fn escape_str(str st, char to_escape) -> str {
-    let str out = "";
-    auto len = str::byte_len(st);
-    auto i = 0u;
-    while (i < len) {
-        alt (st.(i) as char) {
-            case ('\n') { out += "\\n"; }
-            case ('\t') { out += "\\t"; }
-            case ('\r') { out += "\\r"; }
-            case ('\\') { out += "\\\\"; }
-            case (?cur) {
-                if (cur == to_escape) { out += "\\"; }
-                // FIXME some (or all?) non-ascii things should be escaped
-
-                str::push_char(out, cur);
-            }
-        }
-        i += 1u;
-    }
-    ret out;
-}
-
-fn to_str[T](&T t, fn(&ps, &T)  f) -> str {
-    auto writer = io::string_writer();
-    auto s = rust_printer(writer.get_writer());
-    f(s, t);
-    eof(s.s);
-    ret writer.get_str();
-}
-
-fn next_comment(&ps s) -> option::t[lexer::cmnt] {
-    alt (s.comments) {
-        case (some(?cmnts)) {
-            if (s.cur_cmnt < vec::len(cmnts)) {
-                ret some(cmnts.(s.cur_cmnt));
-            } else { ret none[lexer::cmnt]; }
-        }
-        case (_) { ret none[lexer::cmnt]; }
-    }
-}
-
-// The ps is stored here to prevent recursive type.
-// FIXME use a nominal tag instead
-tag ann_node {
-    node_block(ps, ast::block);
-    node_item(ps, @ast::item);
-    node_expr(ps, @ast::expr);
-    node_pat(ps, @ast::pat);
-}
-type pp_ann = rec(fn(&ann_node node) pre,
-                  fn(&ann_node node) post);
-
-fn no_ann() -> pp_ann {
-    fn ignore(&ann_node node) {}
-    ret rec(pre=ignore, post=ignore);
-}
-
-type ps =
-    @rec(pp::printer s,
-         option::t[codemap] cm,
-         option::t[vec[lexer::cmnt]] comments,
-         option::t[vec[lexer::lit]] literals,
-         mutable uint cur_cmnt,
-         mutable uint cur_lit,
-         mutable vec[pp::breaks] boxes,
-         pp_ann ann);
-
-fn ibox(&ps s, uint u) {
-    vec::push(s.boxes, pp::inconsistent);
-    pp::ibox(s.s, u);
-}
-
-fn end(&ps s) { vec::pop(s.boxes); pp::end(s.s); }
-
-fn rust_printer(io::writer writer) -> ps {
-    let vec[pp::breaks] boxes = [];
-    ret @rec(s=pp::mk_printer(writer, default_columns),
-             cm=none[codemap],
-             comments=none[vec[lexer::cmnt]],
-             literals=none[vec[lexer::lit]],
-             mutable cur_cmnt=0u,
-             mutable cur_lit=0u,
-             mutable boxes=boxes,
-             ann=no_ann());
-}
-
-const uint indent_unit = 4u;
-
-const uint default_columns = 78u;
-
-
-// needed b/c constr_args_to_str needs
-// something that takes an alias
-// (argh)
-fn uint_to_str(&uint i) -> str { ret uistr(i); }
-
-fn constr_to_str(&@constr_def c) -> str {
-    ret ast::path_to_str(c.node.path) +
-            constr_args_to_str(uint_to_str, c.node.args);
-}
-
-fn ast_constr_to_str(&@front::ast::constr c) -> str {
-    ret ast::path_to_str(c.node.path) +
-            constr_args_to_str(uint_to_str, c.node.args);
-}
-
-fn constrs_str(&vec[@constr_def] constrs) -> str {
-    auto s = "";
-    auto colon = true;
-    for (@constr_def c in constrs) {
-        if (colon) { s += " : "; colon = false; } else { s += ", "; }
-        s += constr_to_str(c);
-    }
-    ret s;
-}
-
-fn ast_constrs_str(&vec[@ast::constr] constrs) -> str {
-    auto s = "";
-    auto colon = true;
-    for (@ast::constr c in constrs) {
-        if (colon) { s += " : "; colon = false; } else { s += ", "; }
-        s += ast_constr_to_str(c);
-    }
-    ret s;
-}
-//
-// 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/pretty/pprust.rs b/src/comp/pretty/pprust.rs
deleted file mode 100644 (file)
index 104362a..0000000
+++ /dev/null
@@ -1,1233 +0,0 @@
-
-import std::uint;
-import std::int;
-import std::vec;
-import std::str;
-import std::io;
-import std::option;
-import driver::session::session;
-import front::lexer;
-import front::codemap;
-import front::codemap::codemap;
-import front::ast;
-import util::common;
-import option::some;
-import option::none;
-import pp::printer;
-import pp::break_offset;
-import pp::word;
-import pp::huge_word;
-import pp::zero_word;
-import pp::space;
-import pp::zerobreak;
-import pp::hardbreak;
-import pp::breaks;
-import pp::consistent;
-import pp::inconsistent;
-import pp::eof;
-import ppaux::*;
-
-fn print_crate(session sess, @ast::crate crate, str filename,
-               io::writer out, &pp_ann ann) {
-    let vec[pp::breaks] boxes = [];
-    auto r = lexer::gather_comments_and_literals(sess, filename);
-    auto s =
-        @rec(s=pp::mk_printer(out, default_columns),
-             cm=some(sess.get_codemap()),
-             comments=some(r.cmnts),
-             literals=some(r.lits),
-             mutable cur_cmnt=0u,
-             mutable cur_lit=0u,
-             mutable boxes=boxes,
-             ann=ann);
-    print_mod(s, crate.node.module, crate.node.attrs);
-    eof(s.s);
-}
-
-fn ty_to_str(&ast::ty ty) -> str { be to_str(ty, print_type); }
-
-fn pat_to_str(&@ast::pat pat) -> str { be to_str(pat, print_pat); }
-
-fn expr_to_str(&@ast::expr e) -> str { be to_str(e, print_expr); }
-
-fn stmt_to_str(&ast::stmt s) -> str { be to_str(s, print_stmt); }
-
-fn item_to_str(&@ast::item i) -> str { be to_str(i, print_item); }
-
-fn path_to_str(&ast::path p) -> str { be to_str(p, print_path); }
-
-fn fun_to_str(&ast::_fn f, str name, vec[ast::ty_param] params) -> str {
-    auto writer = io::string_writer();
-    auto s = rust_printer(writer.get_writer());
-    print_fn(s, f.decl, f.proto, name, params);
-    eof(s.s);
-    ret writer.get_str();
-}
-
-fn block_to_str(&ast::block blk) -> str {
-    auto writer = io::string_writer();
-    auto s = rust_printer(writer.get_writer());
-    // containing cbox, will be closed by print-block at }
-
-    cbox(s, indent_unit);
-    // head-ibox, will be closed by print-block after {
-
-    ibox(s, 0u);
-    print_block(s, blk);
-    eof(s.s);
-    ret writer.get_str();
-}
-
-fn meta_item_to_str(&ast::meta_item mi) -> str {
-    ret to_str(@mi, print_meta_item);
-}
-
-fn attribute_to_str(&ast::attribute attr) -> str {
-    be to_str(attr, print_attribute);
-}
-
-fn cbox(&ps s, uint u) {
-    vec::push(s.boxes, pp::consistent);
-    pp::cbox(s.s, u);
-}
-
-fn box(&ps s, uint u, pp::breaks b) {
-    vec::push(s.boxes, b);
-    pp::box(s.s, u, b);
-}
-
-fn word_nbsp(&ps s, str w) { word(s.s, w); word(s.s, " "); }
-
-fn word_space(&ps s, str w) { word(s.s, w); space(s.s); }
-
-fn popen(&ps s) { word(s.s, "("); }
-
-fn pclose(&ps s) { word(s.s, ")"); }
-
-fn head(&ps s, str w) {
-    // outer-box is consistent
-    cbox(s, indent_unit);
-    // head-box is inconsistent
-    ibox(s, str::char_len(w) + 1u);
-    // keyword that starts the head
-    word_nbsp(s, w);
-}
-
-fn bopen(&ps s) {
-    word(s.s, "{");
-    end(s); // close the head-box
-
-}
-
-fn bclose(&ps s, common::span span) {
-    maybe_print_comment(s, span.hi);
-    break_offset(s.s, 1u, -(indent_unit as int));
-    word(s.s, "}");
-    end(s); // close the outer-box
-
-}
-
-fn hardbreak_if_not_bol(&ps s) {
-    if (s.s.last_token() != pp::EOF &&
-        s.s.last_token() != pp::hardbreak_tok()) {
-        hardbreak(s.s);
-    }
-}
-
-fn space_if_not_hardbreak(&ps s) {
-    if (s.s.last_token() != pp::hardbreak_tok()) {
-        space(s.s);
-    }
-}
-
-// Synthesizes a comment that was not textually present in the original source
-// file.
-fn synth_comment(&ps s, str text) {
-    word(s.s, "/*");
-    space(s.s);
-    word(s.s, text);
-    space(s.s);
-    word(s.s, "*/");
-}
-
-fn commasep[IN](&ps s, breaks b, vec[IN] elts, fn(&ps, &IN)  op) {
-    box(s, 0u, b);
-    auto first = true;
-    for (IN elt in elts) {
-        if (first) { first = false; } else { word_space(s, ","); }
-        op(s, elt);
-    }
-    end(s);
-}
-
-fn commasep_cmnt[IN](&ps s, breaks b, vec[IN] elts, fn(&ps, &IN)  op,
-                     fn(&IN) -> common::span  get_span) {
-    box(s, 0u, b);
-    auto len = vec::len[IN](elts);
-    auto i = 0u;
-    for (IN elt in elts) {
-        maybe_print_comment(s, get_span(elt).hi);
-        op(s, elt);
-        i += 1u;
-        if (i < len) {
-            word(s.s, ",");
-            maybe_print_trailing_comment(s, get_span(elt),
-                                         some(get_span(elts.(i)).hi));
-            space_if_not_hardbreak(s);
-        }
-    }
-    end(s);
-}
-
-fn commasep_exprs(&ps s, breaks b, vec[@ast::expr] exprs) {
-    fn expr_span(&@ast::expr expr) -> common::span { ret expr.span; }
-    commasep_cmnt(s, b, exprs, print_expr, expr_span);
-}
-
-fn print_mod(&ps s, ast::_mod _mod, &vec[ast::attribute] attrs) {
-    print_inner_attributes(s, attrs);
-    for (@ast::view_item vitem in _mod.view_items) {
-        print_view_item(s, vitem);
-    }
-    for (@ast::item item in _mod.items) {
-        hardbreak_if_not_bol(s);
-        print_item(s, item);
-    }
-    print_remaining_comments(s);
-}
-
-fn print_boxed_type(&ps s, &@ast::ty ty) { print_type(s, *ty); }
-
-fn print_type(&ps s, &ast::ty ty) {
-    maybe_print_comment(s, ty.span.lo);
-    ibox(s, 0u);
-    alt (ty.node) {
-        case (ast::ty_nil) { word(s.s, "()"); }
-        case (ast::ty_bool) { word(s.s, "bool"); }
-        case (ast::ty_bot) { word(s.s, "!"); }
-        case (ast::ty_int) { word(s.s, "int"); }
-        case (ast::ty_uint) { word(s.s, "uint"); }
-        case (ast::ty_float) { word(s.s, "float"); }
-        case (ast::ty_machine(?tm)) { word(s.s, common::ty_mach_to_str(tm)); }
-        case (ast::ty_char) { word(s.s, "char"); }
-        case (ast::ty_str) { word(s.s, "str"); }
-        case (ast::ty_istr) { word(s.s, "istr"); }
-        case (ast::ty_box(?mt)) { word(s.s, "@"); print_mt(s, mt); }
-        case (ast::ty_vec(?mt)) {
-            word(s.s, "vec[");
-            print_mt(s, mt);
-            word(s.s, "]");
-        }
-        case (ast::ty_ivec(?mt)) {
-            print_type(s, *mt.ty);
-            word(s.s, "[");
-            print_mutability(s, mt.mut);
-            word(s.s, "]");
-        }
-        case (ast::ty_ptr(?mt)) {
-            word(s.s, "*");
-            print_mt(s, mt);
-        }
-        case (ast::ty_task) {
-            word(s.s, "task");
-        }
-        case (ast::ty_port(?t)) {
-            word(s.s, "port[");
-            print_type(s, *t);
-            word(s.s, "]");
-        }
-        case (ast::ty_chan(?t)) {
-            word(s.s, "chan[");
-            print_type(s, *t);
-            word(s.s, "]");
-        }
-        case (ast::ty_tup(?elts)) {
-            word(s.s, "tup");
-            popen(s);
-            commasep(s, inconsistent, elts, print_mt);
-            pclose(s);
-        }
-        case (ast::ty_rec(?fields)) {
-            word(s.s, "rec");
-            popen(s);
-            fn print_field(&ps s, &ast::ty_field f) {
-                cbox(s, indent_unit);
-                print_mt(s, f.node.mt);
-                space(s.s);
-                word(s.s, f.node.ident);
-                end(s);
-            }
-            fn get_span(&ast::ty_field f) -> common::span { ret f.span; }
-            commasep_cmnt(s, consistent, fields, print_field, get_span);
-            pclose(s);
-        }
-        case (ast::ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
-            print_ty_fn(s, proto, none[str], inputs, output, cf, constrs);
-        }
-        case (ast::ty_obj(?methods)) {
-            head(s, "obj");
-            bopen(s);
-            for (ast::ty_method m in methods) {
-                hardbreak_if_not_bol(s);
-                cbox(s, indent_unit);
-                maybe_print_comment(s, m.span.lo);
-                print_ty_fn(s, m.node.proto, some(m.node.ident),
-                            m.node.inputs, m.node.output, m.node.cf,
-                            m.node.constrs);
-                word(s.s, ";");
-                end(s);
-            }
-            bclose(s, ty.span);
-        }
-        case (ast::ty_path(?path, _)) { print_path(s, path); }
-        case (ast::ty_type) { word(s.s, "type"); }
-        case (ast::ty_constr(?t, ?cs)) {
-            print_type(s, *t);
-            space(s.s);
-            word(s.s, ":");
-            space(s.s);
-            word(s.s, ast_constrs_str(cs));
-        }
-    }
-    end(s);
-}
-
-fn print_item(&ps s, &@ast::item item) {
-    hardbreak_if_not_bol(s);
-    maybe_print_comment(s, item.span.lo);
-    print_outer_attributes(s, item.attrs);
-    auto ann_node = node_item(s, item);
-    s.ann.pre(ann_node);
-    alt (item.node) {
-        case (ast::item_const(?ty, ?expr)) {
-            head(s, "const");
-            print_type(s, *ty);
-            space(s.s);
-            word_space(s, item.ident);
-            end(s); // end the head-ibox
-
-            word_space(s, "=");
-            print_expr(s, expr);
-            word(s.s, ";");
-            end(s); // end the outer cbox
-
-        }
-        case (ast::item_fn(?_fn, ?typarams)) {
-            print_fn(s, _fn.decl, _fn.proto, item.ident, typarams);
-            word(s.s, " ");
-            print_block(s, _fn.body);
-        }
-        case (ast::item_mod(?_mod)) {
-            head(s, "mod");
-            word_nbsp(s, item.ident);
-            bopen(s);
-            print_mod(s, _mod, item.attrs);
-            bclose(s, item.span);
-        }
-        case (ast::item_native_mod(?nmod)) {
-            head(s, "native");
-            alt (nmod.abi) {
-                case (ast::native_abi_rust) { word_nbsp(s, "\"rust\""); }
-                case (ast::native_abi_cdecl) { word_nbsp(s, "\"cdecl\""); }
-                case (ast::native_abi_rust_intrinsic) {
-                    word_nbsp(s, "\"rust-intrinsic\"");
-                }
-            }
-            word_nbsp(s, "mod");
-            word_nbsp(s, item.ident);
-            bopen(s);
-            for (@ast::native_item item in nmod.items) {
-                hardbreak_if_not_bol(s);
-                ibox(s, indent_unit);
-                maybe_print_comment(s, item.span.lo);
-                alt (item.node) {
-                    case (ast::native_item_ty) {
-                        word_nbsp(s, "type");
-                        word(s.s, item.ident);
-                    }
-                    case (ast::native_item_fn(?lname, ?decl, ?typarams)) {
-                        print_fn(s, decl, ast::proto_fn, item.ident,
-                                 typarams);
-                        alt (lname) {
-                            case (none) { }
-                            case (some(?ss)) {
-                                space(s.s);
-                                word_space(s, "=");
-                                print_string(s, ss);
-                            }
-                        }
-                        end(s); // end head-ibox
-
-                        end(s); // end the outer fn box
-
-                    }
-                }
-                word(s.s, ";");
-                end(s);
-            }
-            bclose(s, item.span);
-        }
-        case (ast::item_ty(?ty, ?params)) {
-            ibox(s, indent_unit);
-            ibox(s, 0u);
-            word_nbsp(s, "type");
-            word(s.s, item.ident);
-            print_type_params(s, params);
-            end(s); // end the inner ibox
-
-            space(s.s);
-            word_space(s, "=");
-            print_type(s, *ty);
-            word(s.s, ";");
-            end(s); // end the outer ibox
-
-            break_offset(s.s, 0u, 0);
-        }
-        case (ast::item_tag(?variants, ?params)) {
-            auto newtype = vec::len(variants) == 1u &&
-                str::eq(item.ident, variants.(0).node.name) &&
-                vec::len(variants.(0).node.args) == 1u;
-            if (newtype) {
-                ibox(s, indent_unit);
-                word_space(s, "tag");
-            } else {
-                head(s, "tag");
-            }
-            word(s.s, item.ident);
-            print_type_params(s, params);
-            space(s.s);
-            if (newtype) {
-                word_space(s, "=");
-                print_type(s, *variants.(0).node.args.(0).ty);
-                word(s.s, ";");
-                end(s);
-            } else {
-                bopen(s);
-                for (ast::variant v in variants) {
-                    space(s.s);
-                    maybe_print_comment(s, v.span.lo);
-                    word(s.s, v.node.name);
-                    if (vec::len(v.node.args) > 0u) {
-                        popen(s);
-                        fn print_variant_arg(&ps s, &ast::variant_arg arg) {
-                            print_type(s, *arg.ty);
-                        }
-                        commasep(s, consistent, v.node.args,
-                                 print_variant_arg);
-                        pclose(s);
-                    }
-                    word(s.s, ";");
-                    maybe_print_trailing_comment(s, v.span, none[uint]);
-                }
-                bclose(s, item.span);
-            }
-        }
-        case (ast::item_obj(?_obj, ?params, _)) {
-            head(s, "obj");
-            word(s.s, item.ident);
-            print_type_params(s, params);
-            popen(s);
-            fn print_field(&ps s, &ast::obj_field field) {
-                ibox(s, indent_unit);
-                print_mutability(s, field.mut);
-                print_type(s, *field.ty);
-                space(s.s);
-                word(s.s, field.ident);
-                end(s);
-            }
-            fn get_span(&ast::obj_field f) -> common::span { ret f.ty.span; }
-            commasep_cmnt(s, consistent, _obj.fields, print_field, get_span);
-            pclose(s);
-            space(s.s);
-            bopen(s);
-            for (@ast::method meth in _obj.methods) {
-                let vec[ast::ty_param] typarams = [];
-                hardbreak_if_not_bol(s);
-                maybe_print_comment(s, meth.span.lo);
-                print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
-                         meth.node.ident, typarams);
-                word(s.s, " ");
-                print_block(s, meth.node.meth.body);
-            }
-            alt (_obj.dtor) {
-                case (some(?dtor)) {
-                    head(s, "drop");
-                    print_block(s, dtor.node.meth.body);
-                }
-                case (_) { }
-            }
-            bclose(s, item.span);
-        }
-        case (ast::item_res(?dt, ?dt_id, ?tps, ?ct_id)) {
-            head(s, "resource");
-            word(s.s, item.ident);
-            print_type_params(s, tps);
-            popen(s);
-            print_type(s, *dt.decl.inputs.(0).ty);
-            space(s.s);
-            word(s.s, dt.decl.inputs.(0).ident);
-            pclose(s);
-            space(s.s);
-            print_block(s, dt.body);
-        }
-    }
-    s.ann.post(ann_node);
-}
-
-fn print_outer_attributes(&ps s, vec[ast::attribute] attrs) {
-    auto count = 0;
-    for (ast::attribute attr in attrs) {
-        alt (attr.node.style) {
-            case (ast::attr_outer) { print_attribute(s, attr); count += 1; }
-            case (_) {/* fallthrough */ }
-        }
-    }
-    if (count > 0) { hardbreak_if_not_bol(s); }
-}
-
-fn print_inner_attributes(&ps s, vec[ast::attribute] attrs) {
-    auto count = 0;
-    for (ast::attribute attr in attrs) {
-        alt (attr.node.style) {
-            case (ast::attr_inner) {
-                print_attribute(s, attr);
-                word(s.s, ";");
-                count += 1;
-            }
-            case (_) { /* fallthrough */ }
-        }
-    }
-    if (count > 0) { hardbreak_if_not_bol(s); }
-}
-
-fn print_attribute(&ps s, &ast::attribute attr) {
-    hardbreak_if_not_bol(s);
-    maybe_print_comment(s, attr.span.lo);
-    word(s.s, "#[");
-    print_meta_item(s, @attr.node.value);
-    word(s.s, "]");
-}
-
-fn print_stmt(&ps s, &ast::stmt st) {
-    maybe_print_comment(s, st.span.lo);
-    alt (st.node) {
-        case (ast::stmt_decl(?decl, _)) { print_decl(s, decl); }
-        case (ast::stmt_expr(?expr, _)) {
-            space_if_not_hardbreak(s);
-            print_expr(s, expr);
-        }
-    }
-    if (front::parser::stmt_ends_with_semi(st)) { word(s.s, ";"); }
-    maybe_print_trailing_comment(s, st.span, none[uint]);
-}
-
-fn print_block(&ps s, ast::block blk) {
-    maybe_print_comment(s, blk.span.lo);
-    auto ann_node = node_block(s, blk);
-    s.ann.pre(ann_node);
-    bopen(s);
-    for (@ast::stmt st in blk.node.stmts) { print_stmt(s, *st) }
-    alt (blk.node.expr) {
-        case (some(?expr)) {
-            space_if_not_hardbreak(s);
-            print_expr(s, expr);
-            maybe_print_trailing_comment(s, expr.span, some(blk.span.hi));
-        }
-        case (_) { }
-    }
-    bclose(s, blk.span);
-    s.ann.post(ann_node);
-}
-
-fn print_if(&ps s, &@ast::expr test, &ast::block block,
-            &option::t[@ast::expr] elseopt, bool chk) {
-    head(s, "if");
-    if (chk) {
-        word_nbsp(s, "check");
-    }
-    popen(s);
-    print_expr(s, test);
-    pclose(s);
-    space(s.s);
-    print_block(s, block);
-    fn do_else(&ps s, option::t[@ast::expr] els) {
-        alt (els) {
-            case (some(?_else)) {
-                alt (_else.node) {
-                    // "another else-if"
-                    case (ast::expr_if(?i, ?t, ?e)) {
-                        cbox(s, indent_unit - 1u);
-                        ibox(s, 0u);
-                        word(s.s, " else if ");
-                        popen(s);
-                        print_expr(s, i);
-                        pclose(s);
-                        space(s.s);
-                        print_block(s, t);
-                        do_else(s, e);
-                    }
-                    // "final else"
-                    case (ast::expr_block(?b)) {
-                        cbox(s, indent_unit - 1u);
-                        ibox(s, 0u);
-                        word(s.s, " else ");
-                        print_block(s, b);
-                    }
-                }
-            }
-            case (_) {/* fall through */ }
-        }
-    }
-    do_else(s, elseopt);
-}
-
-fn print_expr(&ps s, &@ast::expr expr) {
-    maybe_print_comment(s, expr.span.lo);
-    ibox(s, indent_unit);
-    auto ann_node = node_expr(s, expr);
-    s.ann.pre(ann_node);
-    alt (expr.node) {
-        case (ast::expr_vec(?exprs, ?mut, ?kind)) {
-            ibox(s, indent_unit);
-            alt (kind) {
-                case (ast::sk_rc) { word(s.s, "["); }
-                case (ast::sk_unique) { word(s.s, "~["); }
-            }
-            if (mut == ast::mut) { word_nbsp(s, "mutable"); }
-            commasep_exprs(s, inconsistent, exprs);
-            word(s.s, "]");
-            end(s);
-        }
-        case (ast::expr_tup(?exprs)) {
-            fn printElt(&ps s, &ast::elt elt) {
-                ibox(s, indent_unit);
-                if (elt.mut == ast::mut) { word_nbsp(s, "mutable"); }
-                print_expr(s, elt.expr);
-                end(s);
-            }
-            fn get_span(&ast::elt elt) -> common::span { ret elt.expr.span; }
-            word(s.s, "tup");
-            popen(s);
-            commasep_cmnt(s, inconsistent, exprs, printElt, get_span);
-            pclose(s);
-        }
-        case (ast::expr_rec(?fields, ?wth)) {
-            fn print_field(&ps s, &ast::field field) {
-                ibox(s, indent_unit);
-                if (field.node.mut == ast::mut) { word_nbsp(s, "mutable"); }
-                word(s.s, field.node.ident);
-                word(s.s, "=");
-                print_expr(s, field.node.expr);
-                end(s);
-            }
-            fn get_span(&ast::field field) -> common::span { ret field.span; }
-            word(s.s, "rec");
-            popen(s);
-            commasep_cmnt(s, consistent, fields, print_field, get_span);
-            alt (wth) {
-                case (some(?expr)) {
-                    if (vec::len(fields) > 0u) { space(s.s); }
-                    ibox(s, indent_unit);
-                    word_space(s, "with");
-                    print_expr(s, expr);
-                    end(s);
-                }
-                case (_) { }
-            }
-            pclose(s);
-        }
-        case (ast::expr_call(?func, ?args)) {
-            print_expr(s, func);
-            popen(s);
-            commasep_exprs(s, inconsistent, args);
-            pclose(s);
-        }
-        case (ast::expr_self_method(?ident)) {
-            word(s.s, "self.");
-            print_ident(s, ident);
-        }
-        case (ast::expr_bind(?func, ?args)) {
-            fn print_opt(&ps s, &option::t[@ast::expr] expr) {
-                alt (expr) {
-                    case (some(?expr)) { print_expr(s, expr); }
-                    case (_) { word(s.s, "_"); }
-                }
-            }
-            word_nbsp(s, "bind");
-            print_expr(s, func);
-            popen(s);
-            commasep(s, inconsistent, args, print_opt);
-            pclose(s);
-        }
-        case (ast::expr_spawn(_, _, ?e, ?es)) {
-            word_nbsp(s, "spawn");
-            print_expr(s, e);
-            popen(s);
-            commasep_exprs(s, inconsistent, es);
-            pclose(s);
-        }
-        case (ast::expr_binary(?op, ?lhs, ?rhs)) {
-            auto prec = operator_prec(op);
-            print_maybe_parens(s, lhs, prec);
-            space(s.s);
-            word_space(s, ast::binop_to_str(op));
-            print_maybe_parens(s, rhs, prec + 1);
-        }
-        case (ast::expr_unary(?op, ?expr)) {
-            word(s.s, ast::unop_to_str(op));
-            print_maybe_parens(s, expr, front::parser::unop_prec);
-        }
-        case (ast::expr_lit(?lit)) { print_literal(s, lit); }
-        case (ast::expr_cast(?expr, ?ty)) {
-            print_maybe_parens(s, expr, front::parser::as_prec);
-            space(s.s);
-            word_space(s, "as");
-            print_type(s, *ty);
-        }
-        case (ast::expr_if(?test, ?block, ?elseopt)) {
-            print_if(s, test, block, elseopt, false);
-        }
-        case (ast::expr_if_check(?test, ?block, ?elseopt)) {
-            print_if(s, test, block, elseopt, true);
-        }
-        case (ast::expr_ternary(?test, ?then, ?els)) {
-            print_expr(s, test);
-            space(s.s);
-            word_space(s, "?");
-            print_expr(s, then);
-            space(s.s);
-            word_space(s, ":");
-            print_expr(s, els);
-        }
-        case (ast::expr_while(?test, ?block)) {
-            head(s, "while");
-            popen(s);
-            print_expr(s, test);
-            pclose(s);
-            space(s.s);
-            print_block(s, block);
-        }
-        case (ast::expr_for(?decl, ?expr, ?block)) {
-            head(s, "for");
-            popen(s);
-            print_for_decl(s, decl);
-            space(s.s);
-            word_space(s, "in");
-            print_expr(s, expr);
-            pclose(s);
-            space(s.s);
-            print_block(s, block);
-        }
-        case (ast::expr_for_each(?decl, ?expr, ?block)) {
-            head(s, "for each");
-            popen(s);
-            print_for_decl(s, decl);
-            space(s.s);
-            word_space(s, "in");
-            print_expr(s, expr);
-            pclose(s);
-            space(s.s);
-            print_block(s, block);
-        }
-        case (ast::expr_do_while(?block, ?expr)) {
-            head(s, "do");
-            space(s.s);
-            print_block(s, block);
-            space(s.s);
-            word_space(s, "while");
-            popen(s);
-            print_expr(s, expr);
-            pclose(s);
-        }
-        case (ast::expr_alt(?expr, ?arms)) {
-            head(s, "alt");
-            popen(s);
-            print_expr(s, expr);
-            pclose(s);
-            space(s.s);
-            bopen(s);
-            for (ast::arm arm in arms) {
-                space(s.s);
-                head(s, "case");
-                popen(s);
-                print_pat(s, arm.pat);
-                pclose(s);
-                space(s.s);
-                print_block(s, arm.block);
-            }
-            bclose(s, expr.span);
-        }
-        case (ast::expr_fn(?f)) {
-            head(s, "fn");
-            print_fn_args_and_ret(s, f.decl);
-            space(s.s);
-            print_block(s, f.body);
-        }
-        case (ast::expr_block(?block)) {
-            // containing cbox, will be closed by print-block at }
-
-            cbox(s, indent_unit);
-            // head-box, will be closed by print-block after {
-
-            ibox(s, 0u);
-            print_block(s, block);
-        }
-        case (ast::expr_move(?lhs, ?rhs)) {
-            print_expr(s, lhs);
-            space(s.s);
-            word_space(s, "<-");
-            print_expr(s, rhs);
-        }
-        case (ast::expr_assign(?lhs, ?rhs)) {
-            print_expr(s, lhs);
-            space(s.s);
-            word_space(s, "=");
-            print_expr(s, rhs);
-        }
-        case (ast::expr_swap(?lhs, ?rhs)) {
-            print_expr(s, lhs);
-            space(s.s);
-            word_space(s, "<->");
-            print_expr(s, rhs);
-        }
-        case (ast::expr_assign_op(?op, ?lhs, ?rhs)) {
-            print_expr(s, lhs);
-            space(s.s);
-            word(s.s, ast::binop_to_str(op));
-            word_space(s, "=");
-            print_expr(s, rhs);
-        }
-        case (ast::expr_send(?lhs, ?rhs)) {
-            print_expr(s, lhs);
-            space(s.s);
-            word_space(s, "<|");
-            print_expr(s, rhs);
-        }
-        case (ast::expr_recv(?lhs, ?rhs)) {
-            print_expr(s, lhs);
-            space(s.s);
-            word_space(s, "|>");
-            print_expr(s, rhs);
-        }
-        case (ast::expr_field(?expr, ?id)) {
-            print_expr(s, expr);
-            word(s.s, ".");
-            word(s.s, id);
-        }
-        case (ast::expr_index(?expr, ?index)) {
-            print_expr(s, expr);
-            word(s.s, ".");
-            popen(s);
-            print_expr(s, index);
-            pclose(s);
-        }
-        case (ast::expr_path(?path)) { print_path(s, path); }
-        case (ast::expr_fail(?maybe_fail_val)) {
-            word(s.s, "fail");
-            alt (maybe_fail_val) {
-                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
-                case (_) { }
-            }
-        }
-        case (ast::expr_break) { word(s.s, "break"); }
-        case (ast::expr_cont) { word(s.s, "cont"); }
-        case (ast::expr_ret(?result)) {
-            word(s.s, "ret");
-            alt (result) {
-                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
-                case (_) { }
-            }
-        }
-        case (ast::expr_put(?result)) {
-            word(s.s, "put");
-            alt (result) {
-                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
-                case (_) { }
-            }
-        }
-        case (ast::expr_be(?result)) {
-            word_nbsp(s, "be");
-            print_expr(s, result);
-        }
-        case (ast::expr_log(?lvl, ?expr)) {
-            alt (lvl) {
-                case (1) { word_nbsp(s, "log"); }
-                case (0) { word_nbsp(s, "log_err"); }
-            }
-            print_expr(s, expr);
-        }
-        case (ast::expr_check(?m, ?expr)) {
-            alt (m) {
-                case (ast::unchecked) {
-                    word_nbsp(s, "claim");
-                }
-                case (ast::checked) {
-                    word_nbsp(s, "check");
-                }
-            }
-            popen(s);
-            print_expr(s, expr);
-            pclose(s);
-        }
-        case (ast::expr_assert(?expr)) {
-            word_nbsp(s, "assert");
-            popen(s);
-            print_expr(s, expr);
-            pclose(s);
-        }
-        case (ast::expr_ext(?path, ?args, ?body, _)) {
-            word(s.s, "#");
-            print_path(s, path);
-            if (vec::len(args) > 0u) {
-                popen(s);
-                commasep_exprs(s, inconsistent, args);
-                pclose(s);
-            }
-            // FIXME: extension 'body'
-
-        }
-        case (ast::expr_port(?ot)) {
-            word(s.s, "port");
-            alt(ot) {
-                case(some(?t)) {
-                    word(s.s, "[");
-                    print_type(s, *t);
-                    word(s.s, "]");
-                }
-                case(none) {}
-            }
-            popen(s); pclose(s);
-        }
-        case (ast::expr_chan(?expr)) {
-            word(s.s, "chan");
-            popen(s);
-            print_expr(s, expr);
-            pclose(s);
-        }
-        case (ast::expr_anon_obj(_, _, _)) {
-            word(s.s, "anon obj");
-            // FIXME (issue #499): nicer pretty-printing of anon objs
-
-        }
-    }
-    s.ann.post(ann_node);
-    end(s);
-}
-
-fn print_decl(&ps s, &@ast::decl decl) {
-    maybe_print_comment(s, decl.span.lo);
-    alt (decl.node) {
-        case (ast::decl_local(?loc)) {
-            space_if_not_hardbreak(s);
-            ibox(s, indent_unit);
-            alt (loc.node.ty) {
-                case (some(?ty)) {
-                    word_nbsp(s, "let");
-                    print_type(s, *ty);
-                    space(s.s);
-                }
-                case (_) {
-                    word_nbsp(s, "auto");
-                }
-            }
-            word(s.s, loc.node.ident);
-            alt (loc.node.init) {
-                case (some(?init)) {
-                    space(s.s);
-                    alt (init.op) {
-                        case (ast::init_assign) { word_space(s, "="); }
-                        case (ast::init_move) { word_space(s, "<-"); }
-                        case (ast::init_recv) { word_space(s, "|>"); }
-                    }
-                    print_expr(s, init.expr);
-                }
-                case (_) { }
-            }
-            end(s);
-        }
-        case (ast::decl_item(?item)) { print_item(s, item); }
-    }
-}
-
-fn print_ident(&ps s, &ast::ident ident) { word(s.s, ident); }
-
-fn print_for_decl(&ps s, @ast::local loc) {
-    print_type(s, *option::get(loc.node.ty));
-    space(s.s);
-    word(s.s, loc.node.ident);
-}
-
-fn print_path(&ps s, &ast::path path) {
-    maybe_print_comment(s, path.span.lo);
-    auto first = true;
-    for (str id in path.node.idents) {
-        if (first) { first = false; } else { word(s.s, "::"); }
-        word(s.s, id);
-    }
-    if (vec::len(path.node.types) > 0u) {
-        word(s.s, "[");
-        commasep(s, inconsistent, path.node.types, print_boxed_type);
-        word(s.s, "]");
-    }
-}
-
-fn print_pat(&ps s, &@ast::pat pat) {
-    maybe_print_comment(s, pat.span.lo);
-    auto ann_node = node_pat(s, pat);
-    s.ann.pre(ann_node);
-    alt (pat.node) {
-        case (ast::pat_wild) { word(s.s, "_"); }
-        case (ast::pat_bind(?id)) { word(s.s, "?" + id); }
-        case (ast::pat_lit(?lit)) { print_literal(s, lit); }
-        case (ast::pat_tag(?path, ?args)) {
-            print_path(s, path);
-            if (vec::len(args) > 0u) {
-                popen(s);
-                commasep(s, inconsistent, args, print_pat);
-                pclose(s);
-            }
-        }
-    }
-    s.ann.post(ann_node);
-}
-
-fn print_fn(&ps s, ast::fn_decl decl, ast::proto proto, str name,
-            vec[ast::ty_param] typarams) {
-    alt (decl.purity) {
-        case (ast::impure_fn) {
-            if (proto == ast::proto_iter) {
-                head(s, "iter");
-            } else { head(s, "fn"); }
-        }
-        case (_) { head(s, "pred"); }
-    }
-    word(s.s, name);
-    print_type_params(s, typarams);
-    print_fn_args_and_ret(s, decl);
-}
-
-fn print_fn_args_and_ret(&ps s, &ast::fn_decl decl) {
-    popen(s);
-    fn print_arg(&ps s, &ast::arg x) {
-        ibox(s, indent_unit);
-        print_alias(s, x.mode);
-        print_type(s, *x.ty);
-        space(s.s);
-        word(s.s, x.ident);
-        end(s);
-    }
-    commasep(s, inconsistent, decl.inputs, print_arg);
-    pclose(s);
-    maybe_print_comment(s, decl.output.span.lo);
-    if (decl.output.node != ast::ty_nil) {
-        space_if_not_hardbreak(s);
-        word_space(s, "->");
-        print_type(s, *decl.output);
-    }
-}
-
-fn print_alias(&ps s, ast::mode m) {
-    alt (m) {
-        case (ast::alias(true)) { word_space(s, "&mutable"); }
-        case (ast::alias(false)) { word(s.s, "&"); }
-        case (ast::val) { }
-    }
-}
-
-fn print_type_params(&ps s, &vec[ast::ty_param] params) {
-    if (vec::len(params) > 0u) {
-        word(s.s, "[");
-        fn printParam(&ps s, &ast::ty_param param) { word(s.s, param); }
-        commasep(s, inconsistent, params, printParam);
-        word(s.s, "]");
-    }
-}
-
-fn print_meta_item(&ps s, &@ast::meta_item item) {
-    ibox(s, indent_unit);
-    alt (item.node) {
-        case (ast::meta_word(?name)) {
-            word(s.s, name);
-        }
-        case (ast::meta_name_value(?name, ?value)) {
-            word_space(s, name);
-            word_space(s, "=");
-            print_string(s, value);
-        }
-        case (ast::meta_list(?name, ?items)) {
-            word(s.s, name);
-            popen(s);
-            commasep(s, consistent, items, print_meta_item);
-            pclose(s);
-        }
-    }
-    end(s);
-}
-
-fn print_view_item(&ps s, &@ast::view_item item) {
-    hardbreak_if_not_bol(s);
-    maybe_print_comment(s, item.span.lo);
-    alt (item.node) {
-        case (ast::view_item_use(?id, ?mta, _)) {
-            head(s, "use");
-            word(s.s, id);
-            if (vec::len(mta) > 0u) {
-                popen(s);
-                commasep(s, consistent, mta, print_meta_item);
-                pclose(s);
-            }
-        }
-        case (ast::view_item_import(?id, ?ids, _)) {
-            head(s, "import");
-            if (!str::eq(id, ids.(vec::len(ids) - 1u))) {
-                word_space(s, id);
-                word_space(s, "=");
-            }
-            auto first = true;
-            for (str elt in ids) {
-                if (first) { first = false; } else { word(s.s, "::"); }
-                word(s.s, elt);
-            }
-        }
-        case (ast::view_item_import_glob(?ids, _)) {
-            head(s, "import");
-            auto first = true;
-            for (str elt in ids) {
-                if (first) { first = false; } else { word(s.s, "::"); }
-                word(s.s, elt);
-            }
-            word(s.s, "::*");
-        }
-        case (ast::view_item_export(?id, _)) {
-            head(s, "export");
-            word(s.s, id);
-        }
-    }
-    word(s.s, ";");
-    end(s); // end inner head-block
-
-    end(s); // end outer head-block
-
-}
-
-
-// FIXME: The fact that this builds up the table anew for every call is
-// not good. Eventually, table should be a const.
-fn operator_prec(ast::binop op) -> int {
-    for (front::parser::op_spec spec in front::parser::prec_table()) {
-        if (spec.op == op) { ret spec.prec; }
-    }
-    fail;
-}
-
-fn print_maybe_parens(&ps s, &@ast::expr expr, int outer_prec) {
-    auto add_them;
-    alt (expr.node) {
-        case (ast::expr_binary(?op, _, _)) {
-            add_them = operator_prec(op) < outer_prec;
-        }
-        case (ast::expr_cast(_, _)) {
-            add_them = front::parser::as_prec < outer_prec;
-        }
-        case (ast::expr_ternary(_, _, _)) {
-            add_them = front::parser::ternary_prec < outer_prec;
-        }
-        case (_) { add_them = false; }
-    }
-    if (add_them) { popen(s); }
-    print_expr(s, expr);
-    if (add_them) { pclose(s); }
-}
-
-fn print_mutability(&ps s, &ast::mutability mut) {
-    alt (mut) {
-        case (ast::mut) { word_nbsp(s, "mutable"); }
-        case (ast::maybe_mut) { word_nbsp(s, "mutable?"); }
-        case (ast::imm) {/* nothing */ }
-    }
-}
-
-fn print_mt(&ps s, &ast::mt mt) {
-    print_mutability(s, mt.mut);
-    print_type(s, *mt.ty);
-}
-
-fn print_ty_fn(&ps s, &ast::proto proto, &option::t[str] id,
-               &vec[ast::ty_arg] inputs, &@ast::ty output,
-               &ast::controlflow cf, &vec[@ast::constr] constrs) {
-    ibox(s, indent_unit);
-    if (proto == ast::proto_fn) {
-        word(s.s, "fn");
-    } else { word(s.s, "iter"); }
-    alt (id) {
-        case (some(?id)) { word(s.s, " "); word(s.s, id); }
-        case (_) { }
-    }
-    zerobreak(s.s);
-    popen(s);
-    fn print_arg(&ps s, &ast::ty_arg input) {
-        print_alias(s, input.node.mode);
-        print_type(s, *input.node.ty);
-    }
-    commasep(s, inconsistent, inputs, print_arg);
-    pclose(s);
-    maybe_print_comment(s, output.span.lo);
-    if (output.node != ast::ty_nil) {
-        space_if_not_hardbreak(s);
-        ibox(s, indent_unit);
-        word_space(s, "->");
-        alt (cf) {
-            case (ast::return) { print_type(s, *output); }
-            case (ast::noreturn) { word_nbsp(s, "!"); }
-        }
-        end(s);
-    }
-    word_space(s, ast_constrs_str(constrs));
-    end(s);
-}
-
-fn maybe_print_trailing_comment(&ps s, common::span span,
-                                option::t[uint] next_pos) {
-    auto cm;
-    alt (s.cm) { case (some(?ccm)) { cm = ccm; } case (_) { ret; } }
-    alt (next_comment(s)) {
-        case (some(?cmnt)) {
-            if (cmnt.style != lexer::trailing) { ret; }
-            auto span_line = codemap::lookup_pos(cm, span.hi);
-            auto comment_line = codemap::lookup_pos(cm, cmnt.pos);
-            auto next = cmnt.pos + 1u;
-            alt (next_pos) { case (none) { } case (some(?p)) { next = p; } }
-            if (span.hi < cmnt.pos && cmnt.pos < next &&
-                span_line.line == comment_line.line) {
-                print_comment(s, cmnt);
-                s.cur_cmnt += 1u;
-            }
-        }
-        case (_) { }
-    }
-}
-
-fn print_remaining_comments(&ps s) {
-    while (true) {
-        alt (next_comment(s)) {
-            case (some(?cmnt)) { print_comment(s, cmnt); s.cur_cmnt += 1u; }
-            case (_) { break; }
-        }
-    }
-}
-
-fn in_cbox(&ps s) -> bool {
-    auto len = vec::len(s.boxes);
-    if (len == 0u) { ret false; }
-    ret s.boxes.(len - 1u) == pp::consistent;
-}
-//
-// 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:
-//
index 0fb9f2332559a7a0e14b3906eb7ea67c0ab4ec3c..d79c221013a01202dedb8f11d8aed290adbba950 100644 (file)
@@ -17,8 +17,6 @@ use std (name = "std",
 mod middle {
     mod trans;
     mod ty;
-    mod walk;
-    mod visit;
     mod ast_map;
     mod resolve;
     mod typeck;
@@ -38,25 +36,36 @@ mod middle {
 }
 
 
-mod pretty {
-    mod pprust;
-    mod pp;
-    mod ppaux;
+mod syntax {
+    mod _std; // FIXME remove
+    mod ast;
+    mod fold;
+    mod walk;
+    mod visit;
+    mod codemap;
+    mod parse {
+        mod lexer;
+        mod parser;
+        mod token;
+        mod eval;
+    }
+    mod ext {
+        mod base;
+        mod fmt;
+        mod env;
+        mod simplext;
+    }
+    mod print {
+        mod pprust;
+        mod pp;
+    }
+    mod util {
+        mod interner;
+    }
 }
 
 mod front {
-    mod ast;
     mod attr;
-    mod ext;
-    mod extfmt;
-    mod extenv;
-    mod extsimplext;
-    mod fold;
-    mod codemap;
-    mod lexer;
-    mod parser;
-    mod token;
-    mod eval;
     mod config;
 }
 
@@ -88,11 +97,9 @@ mod driver {
 
 mod util {
     mod common;
-    mod data;
+    mod ppaux;
 }
 
-auth front::creader::load_crate = unsafe;
-auth front::creader::get_metadata_section = unsafe;
 auth middle::metadata = unsafe;
 auth middle::trans = unsafe;
 auth lib::llvm = unsafe;
diff --git a/src/comp/syntax/_std.rs b/src/comp/syntax/_std.rs
new file mode 100644 (file)
index 0000000..fb4d144
--- /dev/null
@@ -0,0 +1,29 @@
+// FIXME all this stuff should be in the standard lib, and in fact is,
+// but due to the way our snapshots currently work, rustc can't use it
+// until after the next snapshot.
+
+fn new_str_hash[V]() -> std::map::hashmap[str, V] {
+    let std::map::hashfn[str] hasher = std::str::hash;
+    let std::map::eqfn[str] eqer = std::str::eq;
+    ret std::map::mk_hashmap[str, V](hasher, eqer);
+}
+
+fn new_int_hash[V]() -> std::map::hashmap[int, V] {
+    fn hash_int(&int x) -> uint { ret x as uint; }
+    fn eq_int(&int a, &int b) -> bool { ret a == b; }
+    auto hasher = hash_int;
+    auto eqer = eq_int;
+    ret std::map::mk_hashmap[int, V](hasher, eqer);
+}
+
+fn new_uint_hash[V]() -> std::map::hashmap[uint, V] {
+    fn hash_uint(&uint x) -> uint { ret x; }
+    fn eq_uint(&uint a, &uint b) -> bool { ret a == b; }
+    auto hasher = hash_uint;
+    auto eqer = eq_uint;
+    ret std::map::mk_hashmap[uint, V](hasher, eqer);
+}
+
+fn istr(int i) -> str { ret std::int::to_str(i, 10u); }
+
+fn uistr(uint i) -> str { ret std::uint::to_str(i, 10u); }
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs
new file mode 100644 (file)
index 0000000..0b05d21
--- /dev/null
@@ -0,0 +1,654 @@
+
+import std::option;
+import std::str;
+import std::vec;
+import codemap::span;
+import codemap::filename;
+
+type spanned[T] = rec(T node, span span);
+fn respan[T](&span sp, &T t) -> spanned[T] { ret rec(node=t, span=sp); }
+
+type ident = str;
+// Functions may or may not have names.
+type fn_ident = option::t[ident];
+
+// FIXME: with typestate constraint, could say
+// idents and types are the same length, and are
+// non-empty
+type path_ = rec(vec[ident] idents, vec[@ty] types);
+
+type path = spanned[path_];
+
+fn path_name(&path p) -> str { ret str::connect(p.node.idents, "::"); }
+
+type crate_num = int;
+type node_id = int;
+type def_id = tup(crate_num, node_id);
+
+const crate_num local_crate = 0;
+fn local_def(node_id id) -> def_id {
+    ret tup(local_crate, id);
+}
+
+type ty_param = ident;
+
+tag def {
+    def_fn(def_id, purity);
+    def_obj_field(def_id);
+    def_mod(def_id);
+    def_native_mod(def_id);
+    def_const(def_id);
+    def_arg(def_id);
+    def_local(def_id);
+    def_variant(def_id, /* tag */def_id);
+
+    /* variant */
+    def_ty(def_id);
+    def_ty_arg(uint);
+    def_binding(def_id);
+    def_use(def_id);
+    def_native_ty(def_id);
+    def_native_fn(def_id);
+}
+
+fn variant_def_ids(&def d) -> tup(def_id, def_id) {
+    alt (d) {
+        case (def_variant(?tag_id, ?var_id)) { ret tup(tag_id, var_id); }
+    }
+}
+
+fn def_id_of_def(def d) -> def_id {
+    alt (d) {
+        case (def_fn(?id,_)) { ret id; }
+        case (def_obj_field(?id)) { ret id; }
+        case (def_mod(?id)) { ret id; }
+        case (def_native_mod(?id)) { ret id; }
+        case (def_const(?id)) { ret id; }
+        case (def_arg(?id)) { ret id; }
+        case (def_local(?id)) { ret id; }
+        case (def_variant(_, ?id)) { ret id; }
+        case (def_ty(?id)) { ret id; }
+        case (def_ty_arg(_)) { fail; }
+        case (def_binding(?id)) { ret id; }
+        case (def_use(?id)) { ret id; }
+        case (def_native_ty(?id)) { ret id; }
+        case (def_native_fn(?id)) { ret id; }
+    }
+    fail;
+}
+
+// The set of meta_items that define the compilation environment of the crate,
+// used to drive conditional compilation
+type crate_cfg = vec[@meta_item];
+
+type crate = spanned[crate_];
+
+type crate_ = rec(vec[@crate_directive] directives,
+                  _mod module,
+                  vec[attribute] attrs,
+                  crate_cfg config);
+
+tag crate_directive_ {
+    cdir_src_mod(ident, option::t[filename], vec[attribute]);
+    cdir_dir_mod(ident, option::t[filename],
+                 vec[@crate_directive], vec[attribute]);
+    cdir_view_item(@view_item);
+    cdir_syntax(path);
+    cdir_auth(path, _auth);
+}
+
+type crate_directive = spanned[crate_directive_];
+
+type meta_item = spanned[meta_item_];
+
+tag meta_item_ {
+    meta_word(ident);
+    meta_list(ident, vec[@meta_item]);
+    meta_name_value(ident, str);
+}
+
+type block = spanned[block_];
+
+type block_ = rec(vec[@stmt] stmts, option::t[@expr] expr, node_id id);
+
+type pat = rec(node_id id,
+               pat_ node,
+               span span);
+
+tag pat_ {
+    pat_wild;
+    pat_bind(ident);
+    pat_lit(@lit);
+    pat_tag(path, vec[@pat]);
+}
+
+tag mutability { mut; imm; maybe_mut; }
+
+tag layer { layer_value; layer_state; layer_gc; }
+
+tag _auth { auth_unsafe; }
+
+tag proto { proto_iter; proto_fn; }
+
+tag binop {
+    add;
+    sub;
+    mul;
+    div;
+    rem;
+    and;
+    or;
+    bitxor;
+    bitand;
+    bitor;
+    lsl;
+    lsr;
+    asr;
+    eq;
+    lt;
+    le;
+    ne;
+    ge;
+    gt;
+}
+
+fn binop_to_str(binop op) -> str {
+    alt (op) {
+        case (add) { ret "+"; }
+        case (sub) { ret "-"; }
+        case (mul) { ret "*"; }
+        case (div) { ret "/"; }
+        case (rem) { ret "%"; }
+        case (and) { ret "&&"; }
+        case (or) { ret "||"; }
+        case (bitxor) { ret "^"; }
+        case (bitand) { ret "&"; }
+        case (bitor) { ret "|"; }
+        case (lsl) { ret "<<"; }
+        case (lsr) { ret ">>"; }
+        case (asr) { ret ">>>"; }
+        case (eq) { ret "=="; }
+        case (lt) { ret "<"; }
+        case (le) { ret "<="; }
+        case (ne) { ret "!="; }
+        case (ge) { ret ">="; }
+        case (gt) { ret ">"; }
+    }
+}
+
+pred lazy_binop(binop b) -> bool {
+    alt (b) {
+        case (and) { true }
+        case (or)  { true }
+        case (_)   { false }
+    }
+}
+
+tag unop { box(mutability); deref; not; neg; }
+
+fn unop_to_str(unop op) -> str {
+    alt (op) {
+        case (box(?mt)) { if (mt == mut) { ret "@mutable "; } ret "@"; }
+        case (deref) { ret "*"; }
+        case (not) { ret "!"; }
+        case (neg) { ret "-"; }
+    }
+}
+
+tag mode { val; alias(bool); }
+
+type stmt = spanned[stmt_];
+
+tag stmt_ {
+    stmt_decl(@decl, node_id);
+    stmt_expr(@expr, node_id);
+
+    // These only exist in crate-level blocks.
+    stmt_crate_directive(@crate_directive);
+}
+
+tag init_op { init_assign; init_recv; init_move; }
+
+type initializer = rec(init_op op, @expr expr);
+
+type local_ =
+    rec(option::t[@ty] ty,
+        bool infer,
+        ident ident,
+        option::t[initializer] init,
+        node_id id);
+
+type local = spanned[local_];
+
+type decl = spanned[decl_];
+
+tag decl_ { decl_local(@local); decl_item(@item); }
+
+type arm = rec(@pat pat, block block);
+
+type elt = rec(mutability mut, @expr expr);
+
+type field_ = rec(mutability mut, ident ident, @expr expr);
+
+type field = spanned[field_];
+
+tag spawn_dom { dom_implicit; dom_thread; }
+
+tag check_mode { checked; unchecked; }
+
+// FIXME: temporary
+tag seq_kind { sk_unique; sk_rc; }
+
+type expr = rec(node_id id,
+                expr_ node,
+                span span);
+
+tag expr_ {
+    expr_vec(vec[@expr], mutability, seq_kind);
+    expr_tup(vec[elt]);
+    expr_rec(vec[field], option::t[@expr]);
+    expr_call(@expr, vec[@expr]);
+    expr_self_method(ident);
+    expr_bind(@expr, vec[option::t[@expr]]);
+    expr_spawn(spawn_dom, option::t[str], @expr, vec[@expr]);
+    expr_binary(binop, @expr, @expr);
+    expr_unary(unop, @expr);
+    expr_lit(@lit);
+    expr_cast(@expr, @ty);
+    expr_if(@expr, block, option::t[@expr]);
+    expr_ternary(@expr, @expr, @expr);
+    expr_while(@expr, block);
+    expr_for(@local, @expr, block);
+    expr_for_each(@local, @expr, block);
+    expr_do_while(block, @expr);
+    expr_alt(@expr, vec[arm]);
+    expr_fn(_fn);
+    expr_block(block);
+    /*
+     * FIXME: many of these @exprs should be constrained with
+     * is_lval once we have constrained types working.
+     */
+    expr_move(@expr, @expr);
+    expr_assign(@expr,@expr);
+    expr_swap(@expr, @expr);
+    expr_assign_op(binop, @expr, @expr);
+    expr_send(@expr, @expr);
+    expr_recv(@expr, @expr);
+    expr_field(@expr, ident);
+    expr_index(@expr, @expr);
+    expr_path(path);
+    expr_ext(path, vec[@expr], option::t[str], @expr);
+    expr_fail(option::t[@expr]);
+    expr_break;
+    expr_cont;
+    expr_ret(option::t[@expr]);
+    expr_put(option::t[@expr]);
+    expr_be(@expr);
+    expr_log(int, @expr);
+
+    /* just an assert, no significance to typestate */
+    expr_assert(@expr);
+
+    /* preds that typestate is aware of */
+    expr_check(check_mode, @expr);
+   /* FIXME Would be nice if expr_check desugared
+      to expr_if_check. */
+    expr_if_check(@expr, block, option::t[@expr]);
+    expr_port(option::t[@ty]);
+    expr_chan(@expr);
+    expr_anon_obj(anon_obj, vec[ty_param], obj_def_ids);
+}
+
+type lit = spanned[lit_];
+
+tag lit_ {
+    lit_str(str, seq_kind);
+    lit_char(char);
+    lit_int(int);
+    lit_uint(uint);
+    lit_mach_int(ty_mach, int);
+    lit_float(str);
+    lit_mach_float(ty_mach, str);
+    lit_nil;
+    lit_bool(bool);
+}
+
+fn is_path(&@expr e) -> bool {
+    ret alt (e.node) {
+        case (expr_path(_)) { true }
+        case (_) { false }
+    };
+}
+
+
+// NB: If you change this, you'll probably want to change the corresponding
+// type structure in middle/ty.rs as well.
+type mt = rec(@ty ty, mutability mut);
+
+type ty_field_ = rec(ident ident, mt mt);
+
+type ty_arg_ = rec(mode mode, @ty ty);
+
+type ty_method_ =
+    rec(proto proto,
+        ident ident,
+        vec[ty_arg] inputs,
+        @ty output,
+        controlflow cf,
+        vec[@constr] constrs);
+
+type ty_field = spanned[ty_field_];
+
+type ty_arg = spanned[ty_arg_];
+
+type ty_method = spanned[ty_method_];
+
+tag ty_mach {
+    ty_i8;
+    ty_i16;
+    ty_i32;
+    ty_i64;
+    ty_u8;
+    ty_u16;
+    ty_u32;
+    ty_u64;
+    ty_f32;
+    ty_f64;
+}
+
+fn ty_mach_to_str(ty_mach tm) -> str {
+    alt (tm) {
+        case (ty_u8) { ret "u8"; }
+        case (ty_u16) { ret "u16"; }
+        case (ty_u32) { ret "u32"; }
+        case (ty_u64) { ret "u64"; }
+        case (ty_i8) { ret "i8"; }
+        case (ty_i16) { ret "i16"; }
+        case (ty_i32) { ret "i32"; }
+        case (ty_i64) { ret "i64"; }
+        case (ty_f32) { ret "f32"; }
+        case (ty_f64) { ret "f64"; }
+    }
+}
+
+type ty = spanned[ty_];
+
+tag ty_ {
+    ty_nil;
+    ty_bot; /* return type of ! functions and type of
+             ret/fail/break/cont. there is no syntax
+             for this type. */
+
+     /* bot represents the value of functions that don't return a value
+        locally to their context. in contrast, things like log that do
+        return, but don't return a meaningful value, have result type nil. */
+    ty_bool;
+    ty_int;
+    ty_uint;
+    ty_float;
+    ty_machine(ty_mach);
+    ty_char;
+    ty_str;
+    ty_istr; // interior string
+
+    ty_box(mt);
+    ty_vec(mt);
+    ty_ivec(mt); // interior vector
+
+    ty_ptr(mt);
+    ty_task;
+    ty_port(@ty);
+    ty_chan(@ty);
+    ty_tup(vec[mt]);
+    ty_rec(vec[ty_field]);
+    ty_fn(proto, vec[ty_arg], @ty, controlflow, vec[@constr]);
+    ty_obj(vec[ty_method]);
+    ty_path(path, node_id);
+    ty_type;
+    ty_constr(@ty, vec[@constr]);
+}
+
+
+/*
+A constraint arg that's a function argument is referred to by its position
+rather than name.  This is so we could have higher-order functions that have
+constraints (potentially -- right now there's no way to write that), and also
+so that the typestate pass doesn't have to map a function name onto its decl.
+So, the constr_arg type is parameterized: it's instantiated with uint for
+declarations, and ident for uses.
+*/
+tag constr_arg_general_[T] { carg_base; carg_ident(T); carg_lit(@lit); }
+
+type constr_arg = constr_arg_general[uint];
+
+type constr_arg_general[T] = spanned[constr_arg_general_[T]];
+
+type constr_ = rec(path path,
+                   vec[@constr_arg_general[uint]] args,
+                   node_id id);
+
+type constr = spanned[constr_];
+
+
+/* The parser generates ast::constrs; resolve generates
+ a mapping from each function to a list of ty::constr_defs,
+ corresponding to these. */
+type arg = rec(mode mode, @ty ty, ident ident, node_id id);
+
+type fn_decl =
+    rec(vec[arg] inputs,
+        @ty output,
+        purity purity,
+        controlflow cf,
+        vec[@constr] constraints);
+
+tag purity {
+    pure_fn; // declared with "pred"
+
+    impure_fn; // declared with "fn"
+
+}
+
+tag controlflow {
+    noreturn; // functions with return type _|_ that always
+              // raise an error or exit (i.e. never return to the caller)
+
+    return; // everything else
+
+}
+
+type _fn = rec(fn_decl decl, proto proto, block body);
+
+type method_ = rec(ident ident, _fn meth, node_id id);
+
+type method = spanned[method_];
+
+type obj_field = rec(mutability mut, @ty ty, ident ident, node_id id);
+type anon_obj_field = rec(mutability mut, @ty ty, @expr expr, ident ident,
+                          node_id id);
+
+type _obj =
+    rec(vec[obj_field] fields, vec[@method] methods, option::t[@method] dtor);
+
+type anon_obj =
+    rec(
+        // New fields and methods, if they exist.
+        option::t[vec[anon_obj_field]] fields,
+        vec[@method] methods,
+
+        // with_obj: the original object being extended, if it exists.
+        option::t[@expr] with_obj);
+
+type _mod = rec(vec[@view_item] view_items, vec[@item] items);
+
+tag native_abi {
+    native_abi_rust;
+    native_abi_cdecl;
+    native_abi_llvm;
+    native_abi_rust_intrinsic;
+}
+
+type native_mod =
+    rec(str native_name,
+        native_abi abi,
+        vec[@view_item] view_items,
+        vec[@native_item] items);
+
+type variant_arg = rec(@ty ty, node_id id);
+
+type variant_ = rec(str name, vec[variant_arg] args, node_id id);
+
+type variant = spanned[variant_];
+
+type view_item = spanned[view_item_];
+
+tag view_item_ {
+    view_item_use(ident, vec[@meta_item], node_id);
+    view_item_import(ident, vec[ident], node_id);
+    view_item_import_glob(vec[ident], node_id);
+    view_item_export(ident, node_id);
+}
+
+type obj_def_ids = rec(node_id ty, node_id ctor);
+
+
+// Meta-data associated with an item
+type attribute = spanned[attribute_];
+
+
+// Distinguishes between attributes that decorate items and attributes that
+// are contained as statements within items. These two cases need to be
+// distinguished for pretty-printing.
+tag attr_style { attr_outer; attr_inner; }
+
+type attribute_ = rec(attr_style style, meta_item value);
+
+type item = rec(ident ident,
+                vec[attribute] attrs,
+                node_id id, // For objs and resources, this is the type def_id
+                item_ node,
+                span span);
+
+tag item_ {
+    item_const(@ty, @expr);
+    item_fn(_fn, vec[ty_param]);
+    item_mod(_mod);
+    item_native_mod(native_mod);
+    item_ty(@ty, vec[ty_param]);
+    item_tag(vec[variant], vec[ty_param]);
+    item_obj(_obj, vec[ty_param], node_id /* constructor id */);
+    item_res(_fn /* dtor */, node_id /* dtor id */,
+             vec[ty_param], node_id /* ctor id */);
+}
+
+type native_item = rec(ident ident,
+                       native_item_ node,
+                       node_id id,
+                       span span);
+
+tag native_item_ {
+    native_item_ty;
+    native_item_fn(option::t[str], fn_decl, vec[ty_param]);
+}
+
+fn is_exported(ident i, _mod m) -> bool {
+    auto nonlocal = true;
+    for (@ast::item it in m.items) {
+        if (it.ident == i) { nonlocal = false; }
+        alt (it.node) {
+            case (item_tag(?variants, _)) {
+                for (variant v in variants) {
+                    if (v.node.name == i) { nonlocal = false; }
+                }
+            }
+            case (_) { }
+        }
+        if (!nonlocal) { break; }
+    }
+    auto count = 0u;
+    for (@ast::view_item vi in m.view_items) {
+        alt (vi.node) {
+            case (ast::view_item_export(?id, _)) {
+                if (str::eq(i, id)) {
+                    // even if it's nonlocal (since it's explicit)
+
+                    ret true;
+                }
+                count += 1u;
+            }
+            case (_) {/* fall through */ }
+        }
+    }
+    // If there are no declared exports then 
+    // everything not imported is exported
+
+    ret count == 0u && !nonlocal;
+}
+
+fn is_call_expr(@expr e) -> bool {
+    alt (e.node) {
+        case (expr_call(_, _)) { ret true; }
+        case (_) { ret false; }
+    }
+}
+
+fn is_constraint_arg(@expr e) -> bool {
+    alt (e.node) {
+        case (expr_lit(_)) { ret true; }
+        case (expr_path(_)) { ret true; }
+        case (_) { ret false; }
+    }
+}
+
+fn eq_ty(&@ty a, &@ty b) -> bool { ret std::box::ptr_eq(a, b); }
+
+fn hash_ty(&@ty t) -> uint { ret t.span.lo << 16u + t.span.hi; }
+
+fn block_from_expr(@expr e) -> block {
+    let block_ blk_ =
+        rec(stmts=[],
+            expr=option::some[@expr](e),
+            id=e.id);
+    ret rec(node=blk_, span=e.span);
+}
+
+// This is a convenience function to transfor ternary expressions to if
+// expressions so that they can be treated the same
+fn ternary_to_if(&@expr e) -> @ast::expr {
+    alt (e.node) {
+        case (expr_ternary(?cond, ?then, ?els)) {
+            auto then_blk = block_from_expr(then);
+            auto els_blk = block_from_expr(els);
+            auto els_expr = @rec(id=els.id, node=expr_block(els_blk),
+                                 span=els.span);
+            ret @rec(id=e.id,
+                     node=expr_if(cond, then_blk, option::some(els_expr)),
+                     span=e.span);
+        }
+        case (_) { fail; }
+    }
+}
+
+// Path stringification
+fn path_to_str(&ast::path pth) -> str {
+    auto result = str::connect(pth.node.idents, "::");
+    if (vec::len[@ast::ty](pth.node.types) > 0u) {
+        fn f(&@ast::ty t) -> str { ret print::pprust::ty_to_str(*t); }
+        result += "[";
+        result += str::connect(vec::map(f, pth.node.types), ",");
+        result += "]";
+    }
+    ret result;
+}
+
+
+//
+// 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/codemap.rs b/src/comp/syntax/codemap.rs
new file mode 100644 (file)
index 0000000..b1f0e7e
--- /dev/null
@@ -0,0 +1,96 @@
+
+import std::vec;
+import std::term;
+import std::io;
+import std::option;
+import std::option::some;
+import std::option::none;
+
+type filename = str;
+
+/* A codemap is a thing that maps uints to file/line/column positions
+ * in a crate. This to make it possible to represent the positions
+ * with single-word things, rather than passing records all over the
+ * compiler.
+ */
+type filemap = @rec(filename name, uint start_pos, mutable vec[uint] lines);
+
+type codemap = @rec(mutable vec[filemap] files);
+
+type loc = rec(filename filename, uint line, uint col);
+
+fn new_codemap() -> codemap {
+    let vec[filemap] files = [];
+    ret @rec(mutable files=files);
+}
+
+fn new_filemap(filename filename, uint start_pos) -> filemap {
+    ret @rec(name=filename, start_pos=start_pos, mutable lines=[0u]);
+}
+
+fn next_line(filemap file, uint pos) { vec::push[uint](file.lines, pos); }
+
+fn lookup_pos(codemap map, uint pos) -> loc {
+    auto a = 0u;
+    auto b = vec::len[filemap](map.files);
+    while (b - a > 1u) {
+        auto m = (a + b) / 2u;
+        if (map.files.(m).start_pos > pos) { b = m; } else { a = m; }
+    }
+    auto f = map.files.(a);
+    a = 0u;
+    b = vec::len[uint](f.lines);
+    while (b - a > 1u) {
+        auto m = (a + b) / 2u;
+        if (f.lines.(m) > pos) { b = m; } else { a = m; }
+    }
+    ret rec(filename=f.name, line=a + 1u, col=pos - f.lines.(a));
+}
+
+type span = rec(uint lo, uint hi);
+
+fn span_to_str(&span sp, &codemap cm) -> str {
+    auto lo = lookup_pos(cm, sp.lo);
+    auto hi = lookup_pos(cm, sp.hi);
+    ret #fmt("%s:%u:%u:%u:%u", lo.filename, lo.line, lo.col, hi.line, hi.col);
+}
+
+fn emit_diagnostic(&option::t[span] sp, &str msg, &str kind, u8 color,
+                   &codemap cm) {
+    auto ss = "<input>:0:0:0:0";
+    alt (sp) {
+        case (some(?ssp)) { ss = span_to_str(ssp, cm); }
+        case (none) { }
+    }
+    io::stdout().write_str(ss + ": ");
+    if (term::color_supported()) {
+        term::fg(io::stdout().get_buf_writer(), color);
+    }
+    io::stdout().write_str(#fmt("%s:", kind));
+    if (term::color_supported()) {
+        term::reset(io::stdout().get_buf_writer());
+    }
+    io::stdout().write_str(#fmt(" %s\n", msg));
+}
+
+fn emit_warning(&option::t[span] sp, &str msg, &codemap cm) {
+    emit_diagnostic(sp, msg, "warning", 11u8, cm);
+}
+fn emit_error(&option::t[span] sp, &str msg, &codemap cm) {
+    emit_diagnostic(sp, msg, "error", 9u8, cm);
+}
+fn emit_note(&option::t[span] sp, &str msg, &codemap cm) {
+    emit_diagnostic(sp, msg, "note", 10u8, cm);
+}
+
+
+//
+// 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/base.rs b/src/comp/syntax/ext/base.rs
new file mode 100644 (file)
index 0000000..719e96f
--- /dev/null
@@ -0,0 +1,98 @@
+import std::vec;
+import std::option;
+import std::map::hashmap;
+import parse::parser::parse_sess;
+import codemap::span;
+import syntax::_std::new_str_hash;
+import codemap;
+
+type syntax_expander = 
+    fn(&ext_ctxt, span, &vec[@ast::expr], option::t[str]) -> @ast::expr;
+type macro_definer = fn(&ext_ctxt, span, &vec[@ast::expr],
+                        option::t[str]) -> tup(str, syntax_extension);
+
+tag syntax_extension {
+    normal(syntax_expander);
+    macro_defining(macro_definer);
+}
+
+// A temporary hard-coded map of methods for expanding syntax extension
+// AST nodes into full ASTs
+fn syntax_expander_table() -> hashmap[str, syntax_extension] {
+    auto syntax_expanders = new_str_hash[syntax_extension]();
+    syntax_expanders.insert("fmt", normal(ext::fmt::expand_syntax_ext));
+    syntax_expanders.insert("env", normal(ext::env::expand_syntax_ext));
+    syntax_expanders.insert("macro",    
+                            macro_defining(ext::simplext::add_new_extension));
+    ret syntax_expanders;
+}
+
+type span_msg_fn = fn(span, str) -> !  ;
+
+type next_id_fn = fn() -> ast::node_id ;
+
+
+// Provides a limited set of services necessary for syntax extensions
+// to do their thing
+type ext_ctxt =
+    rec(span_msg_fn span_fatal,
+        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);
+        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);
+        fail;
+    }
+    auto ext_span_unimpl = bind ext_span_unimpl_(sess.cm, _, _);
+    auto ext_next_id = bind parse::parser::next_node_id(sess);
+    ret rec(span_fatal=ext_span_fatal,
+            span_unimpl=ext_span_unimpl,
+            next_id=ext_next_id);
+}
+
+fn expr_to_str(&ext_ctxt cx, @ast::expr expr, str error) -> str {
+    alt (expr.node) {
+        case (ast::expr_lit(?l)) {
+            alt (l.node) {
+                case (ast::lit_str(?s, _)) { ret s; }
+                case (_) { cx.span_fatal(l.span, error); }
+            }
+        }
+        case (_) { cx.span_fatal(expr.span, error); }
+    }
+}
+
+fn expr_to_ident(&ext_ctxt cx, @ast::expr expr, str error) -> ast::ident {
+    alt(expr.node) {
+        case (ast::expr_path(?p)) {
+            if (vec::len(p.node.types) > 0u 
+                || vec::len(p.node.idents) != 1u) {
+                cx.span_fatal(expr.span, error);
+            } else {
+                ret p.node.idents.(0);
+            }
+        }
+        case (_) {
+            cx.span_fatal(expr.span, error);
+        }
+    }
+}
+
+
+
+//
+// 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/env.rs b/src/comp/syntax/ext/env.rs
new file mode 100644 (file)
index 0000000..7b12c04
--- /dev/null
@@ -0,0 +1,47 @@
+
+
+/*
+ * The compiler code necessary to support the #env extension.  Eventually this
+ * should all get sucked into either the compiler syntax extension plugin
+ * interface.
+ */
+import std::str;
+import std::vec;
+import std::option;
+import std::generic_os;
+import base::*;
+export expand_syntax_ext;
+
+fn expand_syntax_ext(&ext_ctxt cx, codemap::span sp, &vec[@ast::expr] args,
+                     option::t[str] body) -> @ast::expr {
+    if (vec::len[@ast::expr](args) != 1u) {
+        cx.span_fatal(sp, "malformed #env call");
+    }
+    // FIXME: if this was more thorough it would manufacture an
+    // option::t[str] rather than just an maybe-empty string.
+
+    auto var = expr_to_str(cx, args.(0), "#env requires a string");
+    alt (generic_os::getenv(var)) {
+        case (option::none) { ret make_new_str(cx, sp, ""); }
+        case (option::some(?s)) { ret make_new_str(cx, sp, s); }
+    }
+}
+
+fn make_new_lit(&ext_ctxt cx, codemap::span sp, ast::lit_ lit) -> @ast::expr {
+    auto sp_lit = @rec(node=lit, span=sp);
+    ret @rec(id=cx.next_id(), node=ast::expr_lit(sp_lit), span=sp);
+}
+
+fn make_new_str(&ext_ctxt cx, codemap::span sp, str s) -> @ast::expr {
+    ret make_new_lit(cx, sp, ast::lit_str(s, ast::sk_rc));
+}
+//
+// 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/fmt.rs b/src/comp/syntax/ext/fmt.rs
new file mode 100644 (file)
index 0000000..1ea2d69
--- /dev/null
@@ -0,0 +1,372 @@
+
+
+/*
+ * The compiler code necessary to support the #fmt extension.  Eventually this
+ * should all get sucked into either the standard library extfmt module or the
+ * compiler syntax extension plugin interface.
+ */
+import std::str;
+import std::vec;
+import std::option;
+import std::option::none;
+import std::option::some;
+import std::extfmt::ct::*;
+import base::*;
+import codemap::span;
+export expand_syntax_ext;
+
+fn expand_syntax_ext(&ext_ctxt cx, span sp, &vec[@ast::expr] args,
+                     option::t[str] body) -> @ast::expr {
+    if (vec::len[@ast::expr](args) == 0u) {
+        cx.span_fatal(sp, "#fmt requires a format string");
+    }
+    auto fmt = expr_to_str(cx, args.(0), "first argument to #fmt must be a "
+                           + "string literal.");
+    auto fmtspan = args.(0).span;
+    log "Format string:";
+    log fmt;
+    fn parse_fmt_err_(&ext_ctxt cx, span sp, str msg) -> ! {
+        cx.span_fatal(sp, msg);
+    }
+    auto parse_fmt_err = bind parse_fmt_err_(cx, fmtspan, _);
+    auto pieces = parse_fmt_string(fmt, parse_fmt_err);
+    ret pieces_to_expr(cx, sp, pieces, args);
+}
+
+// FIXME: A lot of these functions for producing expressions can probably
+// be factored out in common with other code that builds expressions.
+// FIXME: Cleanup the naming of these functions
+fn pieces_to_expr(&ext_ctxt cx, span sp, vec[piece] pieces,
+                  vec[@ast::expr] args) -> @ast::expr {
+    fn make_new_lit(&ext_ctxt cx, span sp, ast::lit_ lit) ->
+       @ast::expr {
+        auto sp_lit = @rec(node=lit, span=sp);
+        ret @rec(id=cx.next_id(), node=ast::expr_lit(sp_lit), span=sp);
+    }
+    fn make_new_str(&ext_ctxt cx, span sp, str s) -> @ast::expr {
+        auto lit = ast::lit_str(s, ast::sk_rc);
+        ret make_new_lit(cx, sp, lit);
+    }
+    fn make_new_int(&ext_ctxt cx, span sp, int i) -> @ast::expr {
+        auto lit = ast::lit_int(i);
+        ret make_new_lit(cx, sp, lit);
+    }
+    fn make_new_uint(&ext_ctxt cx, span sp, uint u) -> @ast::expr {
+        auto lit = ast::lit_uint(u);
+        ret make_new_lit(cx, sp, lit);
+    }
+    fn make_add_expr(&ext_ctxt cx, span sp, @ast::expr lhs,
+                     @ast::expr rhs) -> @ast::expr {
+        auto binexpr = ast::expr_binary(ast::add, lhs, rhs);
+        ret @rec(id=cx.next_id(), node=binexpr, span=sp);
+    }
+    fn make_path_expr(&ext_ctxt cx, span sp, vec[ast::ident] idents)
+       -> @ast::expr {
+        let vec[@ast::ty] types = [];
+        auto path = rec(idents=idents, types=types);
+        auto sp_path = rec(node=path, span=sp);
+        auto pathexpr = ast::expr_path(sp_path);
+        ret @rec(id=cx.next_id(), node=pathexpr, span=sp);
+    }
+    fn make_vec_expr(&ext_ctxt cx, span sp, vec[@ast::expr] exprs) ->
+       @ast::expr {
+        auto vecexpr = ast::expr_vec(exprs, ast::imm, ast::sk_rc);
+        ret @rec(id=cx.next_id(), node=vecexpr, span=sp);
+    }
+    fn make_call(&ext_ctxt cx, span sp, vec[ast::ident] fn_path,
+                 vec[@ast::expr] args) -> @ast::expr {
+        auto pathexpr = make_path_expr(cx, sp, fn_path);
+        auto callexpr = ast::expr_call(pathexpr, args);
+        ret @rec(id=cx.next_id(), node=callexpr, span=sp);
+    }
+    fn make_rec_expr(&ext_ctxt cx, span sp,
+                     vec[tup(ast::ident, @ast::expr)] fields) -> @ast::expr {
+        let vec[ast::field] astfields = [];
+        for (tup(ast::ident, @ast::expr) field in fields) {
+            auto ident = field._0;
+            auto val = field._1;
+            auto astfield =
+                rec(node=rec(mut=ast::imm, ident=ident, expr=val), span=sp);
+            astfields += [astfield];
+        }
+        auto recexpr = ast::expr_rec(astfields, option::none[@ast::expr]);
+        ret @rec(id=cx.next_id(), node=recexpr, span=sp);
+    }
+    fn make_path_vec(str ident) -> vec[str] {
+        // FIXME: #fmt can't currently be used from within std
+        // because we're explicitly referencing the 'std' crate here
+
+        ret ["std", "extfmt", "rt", ident];
+    }
+    fn make_rt_path_expr(&ext_ctxt cx, span sp, str ident) ->
+       @ast::expr {
+        auto path = make_path_vec(ident);
+        ret make_path_expr(cx, sp, path);
+    }
+    // Produces an AST expression that represents a RT::conv record,
+    // which tells the RT::conv* functions how to perform the conversion
+
+    fn make_rt_conv_expr(&ext_ctxt cx, span sp, &conv cnv) ->
+       @ast::expr {
+        fn make_flags(&ext_ctxt cx, span sp, vec[flag] flags) ->
+           @ast::expr {
+            let vec[@ast::expr] flagexprs = [];
+            for (flag f in flags) {
+                auto fstr;
+                alt (f) {
+                    case (flag_left_justify) { fstr = "flag_left_justify"; }
+                    case (flag_left_zero_pad) { fstr = "flag_left_zero_pad"; }
+                    case (flag_space_for_sign) {
+                        fstr = "flag_space_for_sign";
+                    }
+                    case (flag_sign_always) { fstr = "flag_sign_always"; }
+                    case (flag_alternate) { fstr = "flag_alternate"; }
+                }
+                flagexprs += [make_rt_path_expr(cx, sp, fstr)];
+            }
+            // FIXME: 0-length vectors can't have their type inferred
+            // through the rec that these flags are a member of, so
+            // this is a hack placeholder flag
+
+            if (vec::len[@ast::expr](flagexprs) == 0u) {
+                flagexprs += [make_rt_path_expr(cx, sp, "flag_none")];
+            }
+            ret make_vec_expr(cx, sp, flagexprs);
+        }
+        fn make_count(&ext_ctxt cx, span sp, &count cnt) ->
+           @ast::expr {
+            alt (cnt) {
+                case (count_implied) {
+                    ret make_rt_path_expr(cx, sp, "count_implied");
+                }
+                case (count_is(?c)) {
+                    auto count_lit = make_new_int(cx, sp, c);
+                    auto count_is_path = make_path_vec("count_is");
+                    auto count_is_args = [count_lit];
+                    ret make_call(cx, sp, count_is_path, count_is_args);
+                }
+                case (_) {
+                    cx.span_unimpl(sp, "unimplemented #fmt conversion");
+                }
+            }
+        }
+        fn make_ty(&ext_ctxt cx, span sp, &ty t) -> @ast::expr {
+            auto rt_type;
+            alt (t) {
+                case (ty_hex(?c)) {
+                    alt (c) {
+                        case (case_upper) { rt_type = "ty_hex_upper"; }
+                        case (case_lower) { rt_type = "ty_hex_lower"; }
+                    }
+                }
+                case (ty_bits) { rt_type = "ty_bits"; }
+                case (ty_octal) { rt_type = "ty_octal"; }
+                case (_) { rt_type = "ty_default"; }
+            }
+            ret make_rt_path_expr(cx, sp, rt_type);
+        }
+        fn make_conv_rec(&ext_ctxt cx, span sp, @ast::expr flags_expr,
+                         @ast::expr width_expr, @ast::expr precision_expr,
+                         @ast::expr ty_expr) -> @ast::expr {
+            ret make_rec_expr(cx, sp,
+                              [tup("flags", flags_expr),
+                               tup("width", width_expr),
+                               tup("precision", precision_expr),
+                               tup("ty", ty_expr)]);
+        }
+        auto rt_conv_flags = make_flags(cx, sp, cnv.flags);
+        auto rt_conv_width = make_count(cx, sp, cnv.width);
+        auto rt_conv_precision = make_count(cx, sp, cnv.precision);
+        auto rt_conv_ty = make_ty(cx, sp, cnv.ty);
+        ret make_conv_rec(cx, sp, rt_conv_flags, rt_conv_width,
+                          rt_conv_precision, rt_conv_ty);
+    }
+    fn make_conv_call(&ext_ctxt cx, span sp, str conv_type, &conv cnv,
+                      @ast::expr arg) -> @ast::expr {
+        auto fname = "conv_" + conv_type;
+        auto path = make_path_vec(fname);
+        auto cnv_expr = make_rt_conv_expr(cx, sp, cnv);
+        auto args = [cnv_expr, arg];
+        ret make_call(cx, arg.span, path, args);
+    }
+    fn make_new_conv(&ext_ctxt cx, span sp, conv cnv, @ast::expr arg)
+       -> @ast::expr {
+        // FIXME: Extract all this validation into extfmt::ct
+
+        fn is_signed_type(conv cnv) -> bool {
+            alt (cnv.ty) {
+                case (ty_int(?s)) {
+                    alt (s) {
+                        case (signed) { ret true; }
+                        case (unsigned) { ret false; }
+                    }
+                }
+                case (_) { ret false; }
+            }
+        }
+        auto unsupported = "conversion not supported in #fmt string";
+        alt (cnv.param) {
+            case (option::none) { }
+            case (_) { cx.span_unimpl(sp, unsupported); }
+        }
+        for (flag f in cnv.flags) {
+            alt (f) {
+                case (flag_left_justify) { }
+                case (flag_sign_always) {
+                    if (!is_signed_type(cnv)) {
+                        cx.span_fatal(sp,
+                                    "+ flag only valid in " +
+                                        "signed #fmt conversion");
+                    }
+                }
+                case (flag_space_for_sign) {
+                    if (!is_signed_type(cnv)) {
+                        cx.span_fatal(sp,
+                                    "space flag only valid in " +
+                                        "signed #fmt conversions");
+                    }
+                }
+                case (flag_left_zero_pad) { }
+                case (_) { cx.span_unimpl(sp, unsupported); }
+            }
+        }
+        alt (cnv.width) {
+            case (count_implied) { }
+            case (count_is(_)) { }
+            case (_) { cx.span_unimpl(sp, unsupported); }
+        }
+        alt (cnv.precision) {
+            case (count_implied) { }
+            case (count_is(_)) { }
+            case (_) { cx.span_unimpl(sp, unsupported); }
+        }
+        alt (cnv.ty) {
+            case (ty_str) {
+                ret make_conv_call(cx, arg.span, "str", cnv, arg);
+            }
+            case (ty_int(?sign)) {
+                alt (sign) {
+                    case (signed) {
+                        ret make_conv_call(cx, arg.span, "int", cnv, arg);
+                    }
+                    case (unsigned) {
+                        ret make_conv_call(cx, arg.span, "uint", cnv, arg);
+                    }
+                }
+            }
+            case (ty_bool) {
+                ret make_conv_call(cx, arg.span, "bool", cnv, arg);
+            }
+            case (ty_char) {
+                ret make_conv_call(cx, arg.span, "char", cnv, arg);
+            }
+            case (ty_hex(_)) {
+                ret make_conv_call(cx, arg.span, "uint", cnv, arg);
+            }
+            case (ty_bits) {
+                ret make_conv_call(cx, arg.span, "uint", cnv, arg);
+            }
+            case (ty_octal) {
+                ret make_conv_call(cx, arg.span, "uint", cnv, arg);
+            }
+            case (_) { cx.span_unimpl(sp, unsupported); }
+        }
+    }
+    fn log_conv(conv c) {
+        alt (c.param) {
+            case (some(?p)) { log "param: " + std::int::to_str(p, 10u); }
+            case (_) { log "param: none"; }
+        }
+        for (flag f in c.flags) {
+            alt (f) {
+                case (flag_left_justify) { log "flag: left justify"; }
+                case (flag_left_zero_pad) { log "flag: left zero pad"; }
+                case (flag_space_for_sign) { log "flag: left space pad"; }
+                case (flag_sign_always) { log "flag: sign always"; }
+                case (flag_alternate) { log "flag: alternate"; }
+            }
+        }
+        alt (c.width) {
+            case (count_is(?i)) {
+                log "width: count is " + std::int::to_str(i, 10u);
+            }
+            case (count_is_param(?i)) {
+                log "width: count is param " + std::int::to_str(i, 10u);
+            }
+            case (count_is_next_param) { log "width: count is next param"; }
+            case (count_implied) { log "width: count is implied"; }
+        }
+        alt (c.precision) {
+            case (count_is(?i)) {
+                log "prec: count is " + std::int::to_str(i, 10u);
+            }
+            case (count_is_param(?i)) {
+                log "prec: count is param " + std::int::to_str(i, 10u);
+            }
+            case (count_is_next_param) { log "prec: count is next param"; }
+            case (count_implied) { log "prec: count is implied"; }
+        }
+        alt (c.ty) {
+            case (ty_bool) { log "type: bool"; }
+            case (ty_str) { log "type: str"; }
+            case (ty_char) { log "type: char"; }
+            case (ty_int(?s)) {
+                alt (s) {
+                    case (signed) { log "type: signed"; }
+                    case (unsigned) { log "type: unsigned"; }
+                }
+            }
+            case (ty_bits) { log "type: bits"; }
+            case (ty_hex(?cs)) {
+                alt (cs) {
+                    case (case_upper) { log "type: uhex"; }
+                    case (case_lower) { log "type: lhex"; }
+                }
+            }
+            case (ty_octal) { log "type: octal"; }
+        }
+    }
+    auto fmt_sp = args.(0).span;
+    auto n = 0u;
+    auto tmp_expr = make_new_str(cx, sp, "");
+    auto nargs = vec::len[@ast::expr](args);
+    for (piece pc in pieces) {
+        alt (pc) {
+            case (piece_string(?s)) {
+                auto s_expr = make_new_str(cx, fmt_sp, s);
+                tmp_expr = make_add_expr(cx, fmt_sp, tmp_expr, s_expr);
+            }
+            case (piece_conv(?conv)) {
+                n += 1u;
+                if (n >= nargs) {
+                    cx.span_fatal(sp,
+                                "not enough arguments to #fmt " +
+                                    "for the given format string");
+                }
+                log "Building conversion:";
+                log_conv(conv);
+                auto arg_expr = args.(n);
+                auto c_expr = make_new_conv(cx, fmt_sp, conv, arg_expr);
+                tmp_expr = make_add_expr(cx, fmt_sp, tmp_expr, c_expr);
+            }
+        }
+    }
+    auto expected_nargs = n + 1u; // n conversions + the fmt string
+
+    if (expected_nargs < nargs) {
+        cx.span_fatal(sp,
+                    #fmt("too many arguments to #fmt. found %u, expected %u",
+                         nargs, expected_nargs));
+    }
+    ret tmp_expr;
+}
+//
+// 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
new file mode 100644 (file)
index 0000000..e214524
--- /dev/null
@@ -0,0 +1,144 @@
+use std;
+
+import codemap::span;
+import std::vec;
+import std::option;
+import vec::map;
+import vec::len;
+import option::some;
+import option::none;
+
+import base::syntax_extension;
+import base::ext_ctxt;
+import base::normal;
+import base::expr_to_str;
+import base::expr_to_ident;
+
+import fold::*;
+import ast::ident;
+import ast::path_;
+import ast::expr_path;
+
+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;
+    }
+    ret none[uint];
+}
+
+// substitute, in a position that's required to be an ident
+fn subst_ident(&ext_ctxt cx, &vec[@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.");
+        }
+        case (none[uint]) {
+            ret i;
+        }
+    }
+}
+
+fn subst_path(&ext_ctxt cx, &vec[@ast::expr] args, 
+              @vec[ident] param_names, &path_ p, ast_fold fld) -> path_ {
+    // Don't substitute into qualified names.
+    if (len(p.types) > 0u || 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.");
+                }
+            }
+        }
+        case (none[uint]) { ret p; }
+    }
+}
+
+
+fn subst_expr(&ext_ctxt cx, &vec[@ast::expr] args, @vec[ident] param_names, 
+              &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 (len(p.node.types) > 0u || len(p.node.idents) != 1u) { e }
+            alt (position(p.node.idents.(0), *param_names)) {
+                case (some[uint](?idx)) {
+                    args.(idx).node
+                }
+                case (none[uint]) { e }
+            }
+        }
+        case (_) { orig(e,fld) }
+    }
+}
+
+
+fn add_new_extension(&ext_ctxt cx, span sp, &vec[@ast::expr] args,
+                     option::t[str] body) -> tup(str, syntax_extension) {
+    if (len(args) < 2u) {
+        cx.span_fatal(sp, "malformed extension description");
+    }
+
+    fn generic_extension(&ext_ctxt cx, span sp, &vec[@ast::expr] args,
+                         option::t[str] body, @vec[ident] param_names,
+                         @ast::expr dest_form) -> @ast::expr {
+        if (len(args) != len(*param_names)) {
+            cx.span_fatal(sp, #fmt("extension expects %u arguments, got %u",
+                                 len(*param_names), len(args)));
+        }
+
+        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)
+                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 < len(args)) {
+        param_names +=
+            [expr_to_ident(cx, args.(idx),
+                           "this parameter name must be an identifier.")];
+        idx += 1u;
+    }
+
+    ret tup(expr_to_str(cx, args.(0), "first arg must be a literal string."),
+            normal(bind generic_extension(_,_,_,_,@param_names,
+                                          args.(len(args)-1u))));
+}
+
+
+
+//
+// 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/fold.rs b/src/comp/syntax/fold.rs
new file mode 100644 (file)
index 0000000..5cf447a
--- /dev/null
@@ -0,0 +1,708 @@
+import syntax::codemap::span;
+import ast::*;
+
+import std::vec;
+import std::option;
+import vec::map;
+
+export ast_fold_precursor;
+export ast_fold;
+export default_ast_fold;
+export make_fold;
+export dummy_out;
+
+type ast_fold = @mutable a_f;
+
+// We may eventually want to be able to fold over type parameters, too
+
+type ast_fold_precursor = 
+    rec(fn (&crate_ c, ast_fold) -> crate_                fold_crate,
+        fn (&crate_directive_ cd, ast_fold) -> crate_directive_ 
+                                                 fold_crate_directive,
+        fn (&view_item_ i, ast_fold) -> view_item_        fold_view_item,
+        fn (&@native_item i, ast_fold) -> @native_item    fold_native_item,
+        fn (&@item i, ast_fold) -> @item                  fold_item,
+        //unlike the others, item_ is non-trivial
+        fn (&item_ i, ast_fold) -> item_        fold_item_underscore,
+        fn (&method_ m, ast_fold) -> method_              fold_method,
+        fn (&block_ b, ast_fold) -> block_                fold_block,
+        fn (&stmt_ s, ast_fold) -> stmt_                  fold_stmt,
+        fn (&arm a, ast_fold) -> arm                      fold_arm,
+        fn (&pat_ p, ast_fold) -> pat_                    fold_pat,
+        fn (&decl_ d, ast_fold) -> decl_                  fold_decl,
+        fn (&expr_ e, ast_fold) -> expr_                  fold_expr,
+        fn (&ty_ t, ast_fold) -> ty_                      fold_ty,
+        fn (&constr_ c, ast_fold) -> constr_              fold_constr,
+        fn (&_fn f, ast_fold) -> _fn                      fold_fn,
+        fn (&_mod m, ast_fold) -> _mod                    fold_mod,
+        fn (&native_mod, ast_fold) -> native_mod          fold_native_mod,
+        fn (&variant_, ast_fold) -> variant_              fold_variant,
+        fn (&ident, ast_fold) -> ident                    fold_ident,
+        fn (&path_, ast_fold) -> path_                    fold_path,
+        fn (&local_, ast_fold) -> local_                  fold_local
+        );
+
+type a_f =
+    rec(fn (&crate c) -> crate                        fold_crate,
+        fn (&@crate_directive cd) -> @crate_directive fold_crate_directive,
+        fn (&@view_item i) -> @view_item              fold_view_item,
+        fn (&@native_item i) -> @native_item          fold_native_item,
+        fn (&@item i) -> @item                        fold_item,
+        fn (&item_ i) -> item_                        fold_item_underscore,
+        fn (&@method m) -> @method                    fold_method,
+        fn (&block b) -> block                        fold_block,
+        fn (&@stmt s) -> @stmt                        fold_stmt,
+        fn (&arm a) -> arm                            fold_arm,
+        fn (&@pat p) -> @pat                          fold_pat,
+        fn (&@decl d) -> @decl                        fold_decl,
+        fn (&@expr e) -> @expr                        fold_expr,
+        fn (&@ty t) -> @ty                            fold_ty,
+        fn (&@constr c) -> @constr                    fold_constr,
+        fn (&_fn f) -> _fn                            fold_fn,
+        fn (&_mod m) -> _mod                          fold_mod,
+        fn (&native_mod) -> native_mod                fold_native_mod,
+        fn (&variant) -> variant                      fold_variant,
+        fn (&ident) -> ident                          fold_ident,
+        fn (&path) -> path                            fold_path,
+        fn (&@local) -> @local                        fold_local
+        );
+
+//fn nf_dummy[T](&T node) -> T { fail; }
+fn nf_crate_dummy(&crate c) -> crate { fail; }
+fn nf_crate_directive_dummy(&@crate_directive c) 
+    -> @crate_directive { fail; }
+fn nf_view_item_dummy(&@view_item v) -> @view_item { fail; } 
+fn nf_native_item_dummy(&@native_item n) -> @native_item { fail; } 
+fn nf_item_dummy(&@item i) -> @item { fail; } 
+fn nf_item_underscore_dummy(&item_ i) -> item_ { fail; } 
+fn nf_method_dummy(&@method m) -> @method { fail; } 
+fn nf_block_dummy(&block b) -> block { fail; } 
+fn nf_stmt_dummy(&@stmt s) -> @stmt { fail; } 
+fn nf_arm_dummy(&arm a) -> arm { fail; } 
+fn nf_pat_dummy(&@pat p) -> @pat { fail; } 
+fn nf_decl_dummy(&@decl d) -> @decl { fail; } 
+fn nf_expr_dummy(&@expr e) -> @expr { fail; } 
+fn nf_ty_dummy(&@ty t) -> @ty { fail; } 
+fn nf_constr_dummy(&@constr c) -> @constr { fail; } 
+fn nf_fn_dummy(&_fn f) -> _fn { fail; } 
+fn nf_mod_dummy(&_mod m) -> _mod { fail; } 
+fn nf_native_mod_dummy(&native_mod n) -> native_mod { fail; } 
+fn nf_variant_dummy(&variant v) -> variant { fail; } 
+fn nf_ident_dummy(&ident i) -> ident { fail; } 
+fn nf_path_dummy(&path p) -> path { fail; } 
+fn nf_obj_field_dummy(&obj_field o) -> obj_field { fail; }
+fn nf_local_dummy(&@local o) -> @local { fail; }
+
+/* some little folds that probably aren't useful to have in ast_fold itself*/
+
+//used in noop_fold_item and noop_fold_crate and noop_fold_crate_directive
+fn fold_meta_item_(&@meta_item mi, ast_fold fld) -> @meta_item {
+    ret @rec(node=
+             alt (mi.node) {
+                 case (meta_word(?id)) { meta_word(fld.fold_ident(id)) }
+                 case (meta_list(?id, ?mis)) {
+                     auto fold_meta_item = bind fold_meta_item_(_,fld);
+                     meta_list(id, map(fold_meta_item, mis))
+                 }
+                 case (meta_name_value(?id,?s)) {
+                     meta_name_value(fld.fold_ident(id),s)
+                 }
+             },
+             span=mi.span);
+}
+//used in noop_fold_item and noop_fold_crate
+fn fold_attribute_(&attribute at, fn(&@meta_item) -> @meta_item fmi) 
+    -> attribute {
+    ret rec(node=rec(style=at.node.style,
+                     value=*fmi(@at.node.value)),
+            span=at.span);
+}
+//used in noop_fold_native_item and noop_fold_fn
+fn fold_arg_(&arg a, ast_fold fld) -> arg {
+    ret rec(mode=a.mode, ty=fld.fold_ty(a.ty), 
+            ident=fld.fold_ident(a.ident), id=a.id);
+}
+
+
+
+
+fn noop_fold_crate(&crate_ c, ast_fold fld) -> crate_ {
+    auto fold_meta_item = bind fold_meta_item_(_,fld);
+    auto fold_attribute = bind fold_attribute_(_,fold_meta_item);
+
+    ret rec(directives=map(fld.fold_crate_directive, c.directives),
+            module=fld.fold_mod(c.module),
+            attrs=map(fold_attribute, c.attrs),
+            config=map(fold_meta_item, c.config));
+}
+
+fn noop_fold_crate_directive(&crate_directive_ cd, ast_fold fld) 
+    -> crate_directive_ {
+    ret alt(cd) {
+        case(cdir_src_mod(?id,?fname,?attrs)) { 
+            cdir_src_mod(fld.fold_ident(id), fname, attrs)
+                }
+        case(cdir_dir_mod(?id,?fname,?cds,?attrs)) {
+            cdir_dir_mod(fld.fold_ident(id),fname,
+                         map(fld.fold_crate_directive, cds), attrs)
+                }
+        case(cdir_view_item(?vi)) { 
+            cdir_view_item(fld.fold_view_item(vi))
+                }
+        case(cdir_syntax(_)) { cd }
+        case(cdir_auth(_,_)) { cd }
+    }
+}
+
+fn noop_fold_view_item(&view_item_ vi, ast_fold fld) -> view_item_ {
+    ret vi;
+}
+
+
+fn noop_fold_native_item(&@native_item ni, ast_fold fld) -> @native_item {
+    auto fold_arg = bind fold_arg_(_, fld);
+
+    ret @rec(ident=fld.fold_ident(ni.ident),
+             node=alt (ni.node) {
+                 case (native_item_ty) { native_item_ty }
+                 case (native_item_fn(?st, ?fdec, ?typms)) {
+                     native_item_fn(st, 
+                                    rec(inputs=map(fold_arg, fdec.inputs),
+                                        output=fld.fold_ty(fdec.output),
+                                        purity=fdec.purity, cf=fdec.cf,
+                                        constraints=map(fld.fold_constr,
+                                                        fdec.constraints)),
+                                    typms)
+                 }
+             },
+             id=ni.id,
+             span=ni.span);
+}
+
+fn noop_fold_item(&@item i, ast_fold fld) -> @item {
+    auto fold_meta_item = bind fold_meta_item_(_,fld);
+    auto fold_attribute = bind fold_attribute_(_,fold_meta_item);
+
+    ret @rec(ident=fld.fold_ident(i.ident),
+             attrs=map(fold_attribute,i.attrs),
+             id=i.id, node=fld.fold_item_underscore(i.node),
+             span=i.span);
+}
+
+fn noop_fold_item_underscore(&item_ i, ast_fold fld) -> item_ {
+    fn fold_obj_field_(&obj_field of, ast_fold fld) -> obj_field {
+        ret rec(mut=of.mut, ty=fld.fold_ty(of.ty), 
+                ident=fld.fold_ident(of.ident), id=of.id);
+    }
+    auto fold_obj_field = bind fold_obj_field_(_,fld);
+
+    ret alt(i) {
+        case (item_const(?t, ?e)) {
+            item_const(fld.fold_ty(t), fld.fold_expr(e))
+        }
+        case (item_fn(?f, ?typms)) {
+            item_fn(fld.fold_fn(f), typms)
+        }
+        case (item_mod(?m)) { item_mod(fld.fold_mod(m)) }
+        case (item_native_mod(?nm)) {
+            item_native_mod(fld.fold_native_mod(nm))
+                }
+        case (item_ty(?t, ?typms)) {
+            item_ty(fld.fold_ty(t), typms)
+                }
+        case (item_tag(?variants, ?typms)) {
+            item_tag(map(fld.fold_variant, variants), typms)
+                }
+        case (item_obj(?o, ?typms, ?d)) {
+            item_obj(rec(fields=map(fold_obj_field,o.fields),
+                         methods=map(fld.fold_method,o.methods),
+                         dtor=option::map(fld.fold_method,o.dtor)),
+                     typms, d)
+                }
+        case (item_res(?dtor, ?did, ?typms, ?cid)) {
+            item_res(fld.fold_fn(dtor), did, typms, cid)
+        }
+    };
+}
+
+fn noop_fold_method(&method_ m, ast_fold fld) -> method_ {
+    ret rec(ident=fld.fold_ident(m.ident),
+            meth=fld.fold_fn(m.meth), id=m.id); 
+}
+
+
+fn noop_fold_block(&block_ b, ast_fold fld) -> block_ {
+    ret rec(stmts=map(fld.fold_stmt, b.stmts),
+            expr=option::map(fld.fold_expr, b.expr), id=b.id);
+}
+
+fn noop_fold_stmt(&stmt_ s, ast_fold fld) -> stmt_ {
+    ret alt(s) {
+        case (stmt_decl(?d, ?nid)) { stmt_decl(fld.fold_decl(d), nid) }
+        case (stmt_expr(?e, ?nid)) { stmt_expr(fld.fold_expr(e), nid) }
+        case (stmt_crate_directive(?cd)) {
+                stmt_crate_directive(fld.fold_crate_directive(cd))
+                    }
+    };
+}
+
+fn noop_fold_arm(&arm a, ast_fold fld) -> arm {
+    ret rec(pat=fld.fold_pat(a.pat), block=fld.fold_block(a.block));
+}
+
+fn noop_fold_pat(&pat_ p, ast_fold fld) -> pat_ {
+    ret alt (p) {
+        case (pat_wild) { p }
+        case (pat_bind(?ident)) { pat_bind(fld.fold_ident(ident))}
+        case (pat_lit(_)) { p }
+        case (pat_tag(?pth, ?pats)) {
+            pat_tag(fld.fold_path(pth), map(fld.fold_pat, pats))
+        }
+    };
+}
+
+fn noop_fold_decl(&decl_ d, ast_fold fld) -> decl_ {
+    ret alt (d) {
+        // local really doesn't need its own fold...
+        case (decl_local(?l)) {
+            decl_local(fld.fold_local(l))
+        }
+        case (decl_item(?it)) { decl_item(fld.fold_item(it)) }
+    }
+}
+
+fn noop_fold_expr(&expr_ e, ast_fold fld) -> expr_ {
+    fn fold_elt_(&elt elt, ast_fold fld) -> elt {
+        ret rec(mut=elt.mut, expr=fld.fold_expr(elt.expr));
+    }
+    auto fold_elt = bind fold_elt_(_,fld);
+    fn fold_field_(&field field, ast_fold fld) -> field {
+        ret rec(node=rec(mut=field.node.mut,
+                         ident=fld.fold_ident(field.node.ident),
+                         expr=fld.fold_expr(field.node.expr)),
+                span=field.span);
+    }
+    auto fold_field = bind fold_field_(_,fld);
+    fn fold_anon_obj_(&anon_obj ao, ast_fold fld) -> anon_obj {
+        fn fold_anon_obj_field_(&anon_obj_field aof, ast_fold fld) 
+            -> anon_obj_field {
+            ret rec(mut=aof.mut, ty=fld.fold_ty(aof.ty), 
+                    expr=fld.fold_expr(aof.expr),
+                    ident=fld.fold_ident(aof.ident), id=aof.id);
+        }
+        auto fold_anon_obj_field = bind fold_anon_obj_field_(_,fld);
+
+        ret rec(fields=alt(ao.fields) {
+                    case (option::none[vec[anon_obj_field]]) { ao.fields }
+                    case (option::some[vec[anon_obj_field]](?v)) {
+                        option::some[vec[anon_obj_field]]
+                            (map(fold_anon_obj_field, v))
+                    }},
+                methods=map(fld.fold_method, ao.methods),
+                with_obj=option::map(fld.fold_expr, ao.with_obj))
+    }
+    auto fold_anon_obj = bind fold_anon_obj_(_,fld);
+    
+
+    ret alt (e) {
+        case (expr_vec(?exprs, ?mut, ?seq_kind)) {
+            expr_vec(map(fld.fold_expr, exprs), mut, seq_kind)
+                }
+        case (expr_tup(?elts)) {
+            expr_tup(map(fold_elt, elts))
+                }
+        case (expr_rec(?fields, ?maybe_expr)) {
+            expr_rec(map(fold_field, fields),
+                     option::map(fld.fold_expr, maybe_expr))
+                }
+        case (expr_call(?f, ?args)) {
+            expr_call(fld.fold_expr(f), map(fld.fold_expr, args))
+                }
+        case (expr_self_method(?id)) {
+            expr_self_method(fld.fold_ident(id))
+                }
+        case (expr_bind(?f, ?args)) {
+            auto opt_map_se = bind option::map(fld.fold_expr,_);
+            expr_bind(fld.fold_expr(f), map(opt_map_se, args))
+                }
+        case (expr_spawn(?spawn_dom, ?name, ?f, ?args)) {
+            expr_spawn(spawn_dom, name, fld.fold_expr(f), 
+                       map(fld.fold_expr, args))
+                }
+        case (expr_binary(?binop, ?lhs, ?rhs)) {
+            expr_binary(binop, fld.fold_expr(lhs), fld.fold_expr(rhs))
+                }
+        case (expr_unary(?binop, ?ohs)) {
+            expr_unary(binop, fld.fold_expr(ohs))
+                }
+        case (expr_lit(_)) { e }
+        case (expr_cast(?expr, ?ty)) {
+            expr_cast(fld.fold_expr(expr), ty)
+        }
+        case (expr_if(?cond, ?tr, ?fl)) {
+            expr_if(fld.fold_expr(cond), fld.fold_block(tr), 
+                    option::map(fld.fold_expr, fl))
+                }
+        case (expr_ternary(?cond, ?tr, ?fl)) {
+            expr_ternary(fld.fold_expr(cond),
+                         fld.fold_expr(tr),
+                         fld.fold_expr(fl))
+                }
+        case (expr_while(?cond, ?body)) {
+            expr_while(fld.fold_expr(cond), fld.fold_block(body))
+                }
+        case (expr_for(?decl, ?expr, ?block)) {
+            expr_for(fld.fold_local(decl), fld.fold_expr(expr), 
+                     fld.fold_block(block))
+                }
+        case (expr_for_each(?decl, ?expr, ?block)) {
+            expr_for_each(fld.fold_local(decl), fld.fold_expr(expr), 
+                          fld.fold_block(block))
+                }
+        case (expr_do_while(?block, ?expr)) {
+            expr_do_while(fld.fold_block(block), fld.fold_expr(expr))
+                }
+        case (expr_alt(?expr, ?arms)) {
+            expr_alt(fld.fold_expr(expr), map(fld.fold_arm, arms))
+                }
+        case (expr_fn(?f)) {
+            expr_fn(fld.fold_fn(f))
+                }
+        case (expr_block(?block)) {
+            expr_block(fld.fold_block(block))
+                }
+        case (expr_move(?el, ?er)) {
+            expr_move(fld.fold_expr(el), fld.fold_expr(er))
+                }
+        case (expr_assign(?el, ?er)) {
+            expr_assign(fld.fold_expr(el), fld.fold_expr(er))
+                }
+        case (expr_swap(?el, ?er)) {
+            expr_swap(fld.fold_expr(el), fld.fold_expr(er))
+                }
+        case (expr_assign_op(?op, ?el, ?er)) {
+            expr_assign_op(op, fld.fold_expr(el), fld.fold_expr(er))
+                }
+        case (expr_send(?el, ?er)) {
+            expr_send(fld.fold_expr(el), fld.fold_expr(er))
+                }
+        case (expr_recv(?el, ?er)) {
+            expr_recv(fld.fold_expr(el), fld.fold_expr(er))
+                }
+        case (expr_field(?el, ?id)) {
+            expr_field(fld.fold_expr(el), fld.fold_ident(id))
+                }
+        case (expr_index(?el, ?er)) {
+            expr_index(fld.fold_expr(el), fld.fold_expr(er))
+                }
+        case (expr_path(?pth)) {
+            expr_path(fld.fold_path(pth))
+                }
+        case (expr_ext(?pth, ?args, ?body, ?expanded)) {
+            expr_ext(fld.fold_path(pth), map(fld.fold_expr, args),
+                     body, fld.fold_expr(expanded))
+                }
+        case (expr_fail(_)) { e }
+        case (expr_break()) { e }
+        case (expr_cont()) { e }
+        case (expr_ret(?e)) { 
+            expr_ret(option::map(fld.fold_expr, e))
+                }
+        case (expr_put(?e)) { 
+            expr_put(option::map(fld.fold_expr, e))
+                }
+        case (expr_be(?e)) { expr_be(fld.fold_expr(e)) }
+        case (expr_log(?lv, ?e)) { expr_log(lv, fld.fold_expr(e)) }
+        case (expr_assert(?e)) { expr_assert(fld.fold_expr(e)) }
+        case (expr_check(?m, ?e)) { expr_check(m, fld.fold_expr(e)) }
+        case (expr_if_check(?cond, ?tr, ?fl)) {
+            expr_if_check(fld.fold_expr(cond), fld.fold_block(tr), 
+                          option::map(fld.fold_expr, fl))
+                }
+        case (expr_port(?ot)) { 
+            expr_port(alt(ot) {
+                    case (option::some(?t)) { option::some(fld.fold_ty(t)) }
+                    case (option::none) { option::none }
+                })
+                }
+        case (expr_chan(?e)) { expr_chan(fld.fold_expr(e)) }
+        case (expr_anon_obj(?ao, ?typms, ?odis)) {
+            expr_anon_obj(fold_anon_obj(ao), typms, odis)
+                }
+    }
+}
+
+fn noop_fold_ty(&ty_ t, ast_fold fld) -> ty_ {
+    //drop in ty::fold_ty here if necessary
+    ret t;
+}
+
+fn noop_fold_constr(&constr_ c, ast_fold fld) -> constr_ {
+    ret rec(path=fld.fold_path(c.path), args=c.args, id=c.id);
+}
+
+// functions just don't get spans, for some reason
+fn noop_fold_fn(&_fn f, ast_fold fld) -> _fn {
+    auto fold_arg = bind fold_arg_(_, fld);
+
+    ret rec(decl= rec(inputs=map(fold_arg, f.decl.inputs),
+                      output=fld.fold_ty(f.decl.output),
+                      purity=f.decl.purity,
+                      cf=f.decl.cf,
+                      constraints=map(fld.fold_constr, f.decl.constraints)),
+            proto = f.proto,
+            body = fld.fold_block(f.body));
+}
+
+// ...nor do modules
+fn noop_fold_mod(&_mod m, ast_fold fld) -> _mod {
+    ret rec(view_items=map(fld.fold_view_item, m.view_items),
+            items=map(fld.fold_item, m.items));
+}
+
+fn noop_fold_native_mod(&native_mod nm, ast_fold fld) -> native_mod {
+    ret rec(native_name=nm.native_name,
+            abi=nm.abi,
+            view_items=map(fld.fold_view_item, nm.view_items),
+            items=map(fld.fold_native_item, nm.items))
+}
+
+fn noop_fold_variant(&variant_ v, ast_fold fld) -> variant_ {
+    fn fold_variant_arg_(&variant_arg va, ast_fold fld) -> variant_arg {
+        ret rec(ty=fld.fold_ty(va.ty), id=va.id);
+    }
+    auto fold_variant_arg = bind fold_variant_arg_(_,fld);
+    ret rec(name=v.name,
+            args=map(fold_variant_arg, v.args),
+            id=v.id);
+}
+
+fn noop_fold_ident(&ident i, ast_fold fld) -> ident {
+    ret i;
+}
+
+fn noop_fold_path(&path_ p, ast_fold fld) -> path_ {
+    ret rec(idents=map(fld.fold_ident, p.idents),
+            types=map(fld.fold_ty, p.types));
+}
+
+fn noop_fold_local(&local_ l, ast_fold fld) -> local_ {
+    ret rec(ty=option::map(fld.fold_ty,l.ty),
+            infer=l.infer,
+            ident=fld.fold_ident(l.ident),
+            init=alt (l.init) {
+                case (option::none[initializer]) { l.init }
+                case (option::some[initializer](?init)) {
+                    option::some[initializer]
+                    (rec(op=init.op, 
+                         expr=fld.fold_expr(init.expr)))
+                }
+            },
+            id=l.id);
+}
+
+
+fn default_ast_fold() -> @ast_fold_precursor {
+    ret @rec(fold_crate = noop_fold_crate,
+             fold_crate_directive = noop_fold_crate_directive,
+             fold_view_item = noop_fold_view_item,
+             fold_native_item = noop_fold_native_item,
+             fold_item = noop_fold_item,
+             fold_item_underscore = noop_fold_item_underscore,
+             fold_method = noop_fold_method,
+             fold_block = noop_fold_block,
+             fold_stmt = noop_fold_stmt,
+             fold_arm = noop_fold_arm,
+             fold_pat = noop_fold_pat,
+             fold_decl = noop_fold_decl,
+             fold_expr = noop_fold_expr,
+             fold_ty = noop_fold_ty,
+             fold_constr = noop_fold_constr,
+             fold_fn = noop_fold_fn,
+             fold_mod = noop_fold_mod,
+             fold_native_mod = noop_fold_native_mod,
+             fold_variant = noop_fold_variant,
+             fold_ident = noop_fold_ident,
+             fold_path = noop_fold_path,
+             fold_local = noop_fold_local);
+}
+
+fn dummy_out(ast_fold a) {
+    *a = rec(fold_crate = nf_crate_dummy,
+                     fold_crate_directive = nf_crate_directive_dummy,
+                     fold_view_item = nf_view_item_dummy,
+                     fold_native_item = nf_native_item_dummy,
+                     fold_item = nf_item_dummy,
+                     fold_item_underscore = nf_item_underscore_dummy,
+                     fold_method = nf_method_dummy,
+                     fold_block = nf_block_dummy,
+                     fold_stmt = nf_stmt_dummy,
+                     fold_arm = nf_arm_dummy,
+                     fold_pat = nf_pat_dummy,
+                     fold_decl = nf_decl_dummy,
+                     fold_expr = nf_expr_dummy,
+                     fold_ty = nf_ty_dummy,
+                     fold_constr = nf_constr_dummy,
+                     fold_fn = nf_fn_dummy,
+                     fold_mod = nf_mod_dummy,
+                     fold_native_mod = nf_native_mod_dummy,
+                     fold_variant = nf_variant_dummy,
+                     fold_ident = nf_ident_dummy,
+                     fold_path = nf_path_dummy,
+                     fold_local = nf_local_dummy);
+}
+
+
+fn make_fold(&ast_fold_precursor afp) -> ast_fold {
+    let ast_fold result = 
+        @mutable rec(fold_crate = nf_crate_dummy,
+                     fold_crate_directive = nf_crate_directive_dummy,
+                     fold_view_item = nf_view_item_dummy,
+                     fold_native_item = nf_native_item_dummy,
+                     fold_item = nf_item_dummy,
+                     fold_item_underscore = nf_item_underscore_dummy,
+                     fold_method = nf_method_dummy,
+                     fold_block = nf_block_dummy,
+                     fold_stmt = nf_stmt_dummy,
+                     fold_arm = nf_arm_dummy,
+                     fold_pat = nf_pat_dummy,
+                     fold_decl = nf_decl_dummy,
+                     fold_expr = nf_expr_dummy,
+                     fold_ty = nf_ty_dummy,
+                     fold_constr = nf_constr_dummy,
+                     fold_fn = nf_fn_dummy,
+                     fold_mod = nf_mod_dummy,
+                     fold_native_mod = nf_native_mod_dummy,
+                     fold_variant = nf_variant_dummy,
+                     fold_ident = nf_ident_dummy,
+                     fold_path = nf_path_dummy,
+                     fold_local = nf_local_dummy);
+
+    /* naturally, a macro to write these would be nice */
+    fn f_crate(&ast_fold_precursor afp, ast_fold f, &crate c) -> crate {
+        ret rec(node=afp.fold_crate(c.node, f),
+                span=c.span);
+    }
+    fn f_crate_directive(&ast_fold_precursor afp, ast_fold f, 
+                         &@crate_directive c) -> @crate_directive {
+        ret @rec(node=afp.fold_crate_directive(c.node, f),
+                 span=c.span);
+    }
+    fn f_view_item(&ast_fold_precursor afp, ast_fold f, &@view_item x)
+        -> @view_item {
+        ret @rec(node=afp.fold_view_item(x.node, f), span=x.span);
+    }
+    fn f_native_item(&ast_fold_precursor afp, ast_fold f, &@native_item x)
+        -> @native_item {
+        ret afp.fold_native_item(x, f);
+    }
+    fn f_item(&ast_fold_precursor afp, ast_fold f, &@item i) -> @item {
+        ret afp.fold_item(i, f);
+    }
+    fn f_item_underscore(&ast_fold_precursor afp, ast_fold f, &item_ i) ->
+        item_ {
+        ret afp.fold_item_underscore(i, f);
+    }
+    fn f_method(&ast_fold_precursor afp, ast_fold f, &@method x) -> @method {
+        ret @rec(node=afp.fold_method(x.node, f), span=x.span);
+    }
+    fn f_block(&ast_fold_precursor afp, ast_fold f, &block x) -> block {
+        ret rec(node=afp.fold_block(x.node, f), span=x.span);
+    }
+    fn f_stmt(&ast_fold_precursor afp, ast_fold f, &@stmt x) -> @stmt {
+        ret @rec(node=afp.fold_stmt(x.node, f), span=x.span);
+    }
+    fn f_arm(&ast_fold_precursor afp, ast_fold f, &arm x) -> arm {
+        ret afp.fold_arm(x, f);
+    }
+    fn f_pat(&ast_fold_precursor afp, ast_fold f, &@pat x) -> @pat {
+        ret @rec(id=x.id, node=afp.fold_pat(x.node, f), span=x.span);
+    }
+    fn f_decl(&ast_fold_precursor afp, ast_fold f, &@decl x) -> @decl {
+        ret @rec(node=afp.fold_decl(x.node, f), span=x.span);
+    }
+    fn f_expr(&ast_fold_precursor afp, ast_fold f, &@expr x) -> @expr {
+        ret @rec(id=x.id, node=afp.fold_expr(x.node, f), span=x.span);
+    }
+    fn f_ty(&ast_fold_precursor afp, ast_fold f, &@ty x) -> @ty {
+        ret @rec(node=afp.fold_ty(x.node, f), span=x.span);
+    }
+    fn f_constr(&ast_fold_precursor afp, ast_fold f, &@constr x) -> @constr {
+        ret @rec(node=afp.fold_constr(x.node, f), span=x.span);
+    }
+    fn f_fn(&ast_fold_precursor afp, ast_fold f, &_fn x) -> _fn {
+        ret afp.fold_fn(x, f);
+    }    
+    fn f_mod(&ast_fold_precursor afp, ast_fold f, &_mod x) -> _mod {
+        ret afp.fold_mod(x, f);
+    }
+    fn f_native_mod(&ast_fold_precursor afp, ast_fold f, &native_mod x) -> 
+        native_mod {
+        ret afp.fold_native_mod(x, f);
+    }    
+    fn f_variant(&ast_fold_precursor afp, ast_fold f, &variant x)
+        -> variant {
+        ret rec(node=afp.fold_variant(x.node, f), span=x.span);
+    }
+    fn f_ident(&ast_fold_precursor afp, ast_fold f, &ident x) -> ident {
+        ret afp.fold_ident(x, f);
+    }
+    fn f_path(&ast_fold_precursor afp, ast_fold f, &path x) -> path {
+        ret rec(node=afp.fold_path(x.node, f), span=x.span);
+    }
+    fn f_local(&ast_fold_precursor afp, ast_fold f, &@local x) -> @local {
+        ret @rec(node=afp.fold_local(x.node, f), span=x.span);
+    }
+
+    *result = rec(fold_crate = bind f_crate(afp,result,_),
+                  fold_crate_directive = bind f_crate_directive(afp,result,_),
+                  fold_view_item = bind f_view_item(afp,result,_),
+                  fold_native_item = bind f_native_item(afp,result,_),
+                  fold_item = bind f_item(afp,result,_),
+                  fold_item_underscore = bind f_item_underscore(afp,result,_),
+                  fold_method = bind f_method(afp,result,_),
+                  fold_block = bind f_block(afp,result,_),
+                  fold_stmt = bind f_stmt(afp,result,_),
+                  fold_arm = bind f_arm(afp, result, _),
+                  fold_pat = bind f_pat(afp,result,_),
+                  fold_decl = bind f_decl(afp,result,_),
+                  fold_expr = bind f_expr(afp,result,_),
+                  fold_ty = bind f_ty(afp,result,_),
+                  fold_constr = bind f_constr(afp,result,_),
+                  fold_fn = bind f_fn(afp,result,_),
+                  fold_mod = bind f_mod(afp,result,_),
+                  fold_native_mod = bind f_native_mod(afp,result,_),
+                  fold_variant = bind f_variant(afp,result,_),
+                  fold_ident = bind f_ident(afp,result,_),
+                  fold_path = bind f_path(afp,result,_),
+                  fold_local = bind f_local(afp,result,_));
+    ret result;
+    /*
+    ret rec(fold_crate = noop_fold_crate,
+          fold_crate_directive = noop_fold_crate_drective,
+          fold_view_item = noop_fold_view_item,
+          fold_native_item = noop_fold_native_item,
+          fold_item = noop_fold_item,
+          fold_method = noop_fold_method,
+          fold_block = noop_fold_block,
+          fold_stmt = noop_fold_stmt,
+          fold_arm = noop_fold_arm,
+          fold_pat = noop_fold_pat,
+          fold_decl = noop_fold_decl,
+          fold_expr = noop_fold_expr,
+          fold_ty = noop_fold_ty,
+          fold_constr = noop_fold_constr,
+          fold_fn = noop_fold_fn);*/
+}
+
+
+//
+// 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/parse/eval.rs b/src/comp/syntax/parse/eval.rs
new file mode 100644 (file)
index 0000000..89f6ac5
--- /dev/null
@@ -0,0 +1,124 @@
+
+import std::vec;
+import std::str;
+import std::option;
+import std::option::some;
+import std::option::none;
+import syntax::ast;
+import syntax::parse::token;
+import syntax::parse::parser::parser;
+import syntax::parse::parser::new_parser;
+import syntax::parse::parser::parse_inner_attrs_and_next;
+import syntax::parse::parser::parse_mod_items;
+
+export eval_crate_directives_to_mod;
+export mode_parse;
+
+tag eval_mode { mode_depend; mode_parse; }
+
+type ctx =
+    @rec(parser p,
+         eval_mode mode,
+         mutable vec[str] deps,
+         parser::parse_sess sess,
+         mutable uint chpos,
+         ast::crate_cfg cfg);
+
+fn eval_crate_directives(ctx cx, vec[@ast::crate_directive] cdirs,
+                         str prefix, &mutable vec[@ast::view_item] view_items,
+                         &mutable vec[@ast::item] items) {
+    for (@ast::crate_directive sub_cdir in cdirs) {
+        eval_crate_directive(cx, sub_cdir, prefix, view_items, items);
+    }
+}
+
+fn eval_crate_directives_to_mod(ctx cx,
+                                vec[@ast::crate_directive] cdirs, str prefix)
+   -> ast::_mod {
+    let vec[@ast::view_item] view_items = [];
+    let vec[@ast::item] items = [];
+    eval_crate_directives(cx, cdirs, prefix, view_items, items);
+    ret rec(view_items=view_items, items=items);
+}
+
+fn eval_crate_directive_block(ctx cx, &ast::block blk, str prefix,
+                              &mutable vec[@ast::view_item] view_items,
+                              &mutable vec[@ast::item] items) {
+    for (@ast::stmt s in blk.node.stmts) {
+        alt (s.node) {
+            case (ast::stmt_crate_directive(?cdir)) {
+                eval_crate_directive(cx, cdir, prefix, view_items, items);
+            }
+            case (_) {
+                codemap::emit_warning
+                   (some(s.span), "unsupported stmt in crate-directive block",
+                    cx.sess.cm);
+            }
+        }
+    }
+}
+
+fn eval_crate_directive(ctx cx, @ast::crate_directive cdir, str prefix,
+                        &mutable vec[@ast::view_item] view_items,
+                        &mutable vec[@ast::item] items) {
+    alt (cdir.node) {
+        case (ast::cdir_src_mod(?id, ?file_opt, ?attrs)) {
+            auto file_path = id + ".rs";
+            alt (file_opt) {
+                case (some(?f)) { file_path = f; }
+                case (none) { }
+            }
+            auto full_path = if (std::fs::path_is_absolute(file_path)) {
+                file_path
+            } else {
+                prefix + std::fs::path_sep() + file_path
+            };
+            if (cx.mode == mode_depend) { cx.deps += [full_path]; ret; }
+            auto p0 =
+                new_parser(cx.sess, cx.cfg, full_path, cx.chpos);
+            auto inner_attrs = parse_inner_attrs_and_next(p0);
+            auto mod_attrs = attrs + inner_attrs._0;
+            auto first_item_outer_attrs = inner_attrs._1;
+            auto m0 = parse_mod_items(p0, token::EOF, first_item_outer_attrs);
+
+            auto i = syntax::parse::parser::mk_item
+                (p0, cdir.span.lo, cdir.span.hi, id, ast::item_mod(m0),
+                 mod_attrs);
+            // Thread defids and chpos through the parsers
+            cx.chpos = p0.get_chpos();
+            vec::push[@ast::item](items, i);
+        }
+        case (ast::cdir_dir_mod(?id, ?dir_opt, ?cdirs, ?attrs)) {
+            auto path = id;
+            alt (dir_opt) { case (some(?d)) { path = d; } case (none) { } }
+            auto full_path = if (std::fs::path_is_absolute(path)) {
+                path
+            } else {
+                prefix + std::fs::path_sep() + path
+            };
+            auto m0 = eval_crate_directives_to_mod(cx, cdirs, full_path);
+            auto i = @rec(ident=id,
+                          attrs=attrs,
+                          id=cx.sess.next_id,
+                          node=ast::item_mod(m0),
+                          span=cdir.span);
+            cx.sess.next_id += 1;
+            vec::push[@ast::item](items, i);
+        }
+        case (ast::cdir_view_item(?vi)) {
+            vec::push[@ast::view_item](view_items, vi);
+        }
+        case (ast::cdir_syntax(?pth)) { }
+        case (ast::cdir_auth(?pth, ?eff)) { }
+    }
+}
+//
+// 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/parse/lexer.rs b/src/comp/syntax/parse/lexer.rs
new file mode 100644 (file)
index 0000000..ffc83bc
--- /dev/null
@@ -0,0 +1,758 @@
+
+import std::io;
+import std::str;
+import std::vec;
+import std::int;
+import std::map;
+import std::map::hashmap;
+import std::option;
+import std::option::some;
+import std::option::none;
+import util::interner;
+import util::interner::intern;
+import codemap;
+
+type reader =
+    obj {
+        fn is_eof() -> bool ;
+        fn curr() -> char ;
+        fn next() -> char ;
+        fn init() ;
+        fn bump() ;
+        fn mark() ;
+        fn get_mark_chpos() -> uint ;
+        fn get_mark_str() -> str ;
+        fn get_interner() -> @interner::interner[str] ;
+        fn get_chpos() -> uint ;
+        fn get_col() -> uint ;
+        fn get_filemap() -> codemap::filemap ;
+        fn err(str) ;
+    };
+
+fn new_reader(&codemap::codemap cm, io::reader rdr, codemap::filemap filemap,
+              @interner::interner[str] itr) -> reader {
+    obj reader(codemap::codemap cm,
+               str file,
+               uint len,
+               mutable uint col,
+               mutable uint pos,
+               mutable char ch,
+               mutable uint mark_chpos,
+               mutable uint chpos,
+               mutable vec[str] strs,
+               codemap::filemap fm,
+               @interner::interner[str] itr) {
+        fn is_eof() -> bool { ret ch == -1 as char; }
+        fn mark() { mark_chpos = chpos; }
+        fn get_mark_str() -> str { ret str::slice(file, mark_chpos, chpos); }
+        fn get_mark_chpos() -> uint { ret mark_chpos; }
+        fn get_chpos() -> uint { ret chpos; }
+        fn curr() -> char { ret ch; }
+        fn next() -> char {
+            if (pos < len) {
+                ret str::char_at(file, pos);
+            } else { ret -1 as char; }
+        }
+        fn init() {
+            if (pos < len) {
+                auto next = str::char_range_at(file, pos);
+                pos = next._1;
+                ch = next._0;
+            }
+        }
+        fn bump() {
+            if (pos < len) {
+                col += 1u;
+                chpos += 1u;
+                if (ch == '\n') { codemap::next_line(fm, chpos); col = 0u; }
+                auto next = str::char_range_at(file, pos);
+                pos = next._1;
+                ch = next._0;
+            } else { ch = -1 as char; }
+        }
+        fn get_interner() -> @interner::interner[str] { ret itr; }
+        fn get_col() -> uint { ret col; }
+        fn get_filemap() -> codemap::filemap { ret fm; }
+        fn err(str m) {
+            codemap::emit_error(some(rec(lo=chpos, hi=chpos)), m, cm);
+        }
+    }
+    auto file = str::unsafe_from_bytes(rdr.read_whole_stream());
+    let vec[str] strs = [];
+    auto rd =
+        reader(cm, file, str::byte_len(file), 0u, 0u, -1 as char,
+               filemap.start_pos, filemap.start_pos, strs, filemap, itr);
+    rd.init();
+    ret rd;
+}
+
+fn dec_digit_val(char c) -> int { ret (c as int) - ('0' as int); }
+
+fn hex_digit_val(char c) -> int {
+    if (in_range(c, '0', '9')) { ret (c as int) - ('0' as int); }
+    if (in_range(c, 'a', 'f')) { ret (c as int) - ('a' as int) + 10; }
+    if (in_range(c, 'A', 'F')) { ret (c as int) - ('A' as int) + 10; }
+    fail;
+}
+
+fn bin_digit_value(char c) -> int { if (c == '0') { ret 0; } ret 1; }
+
+fn is_whitespace(char c) -> bool {
+    ret c == ' ' || c == '\t' || c == '\r' || c == '\n';
+}
+
+fn may_begin_ident(char c) -> bool { ret is_alpha(c) || c == '_'; }
+
+fn in_range(char c, char lo, char hi) -> bool { ret lo <= c && c <= hi; }
+
+fn is_alpha(char c) -> bool {
+    ret in_range(c, 'a', 'z') || in_range(c, 'A', 'Z');
+}
+
+fn is_dec_digit(char c) -> bool { ret in_range(c, '0', '9'); }
+
+fn is_alnum(char c) -> bool { ret is_alpha(c) || is_dec_digit(c); }
+
+fn is_hex_digit(char c) -> bool {
+    ret in_range(c, '0', '9') || in_range(c, 'a', 'f') ||
+            in_range(c, 'A', 'F');
+}
+
+fn is_bin_digit(char c) -> bool { ret c == '0' || c == '1'; }
+
+fn consume_whitespace_and_comments(&reader rdr) {
+    while (is_whitespace(rdr.curr())) { rdr.bump(); }
+    be consume_any_line_comment(rdr);
+}
+
+fn consume_any_line_comment(&reader rdr) {
+    if (rdr.curr() == '/') {
+        alt (rdr.next()) {
+            case ('/') {
+                while (rdr.curr() != '\n' && !rdr.is_eof()) { rdr.bump(); }
+                // Restart whitespace munch.
+
+                be consume_whitespace_and_comments(rdr);
+            }
+            case ('*') {
+                rdr.bump();
+                rdr.bump();
+                be consume_block_comment(rdr);
+            }
+            case (_) { ret; }
+        }
+    }
+}
+
+fn consume_block_comment(&reader rdr) {
+    let int level = 1;
+    while (level > 0) {
+        if (rdr.is_eof()) { rdr.err("unterminated block comment"); fail; }
+        if (rdr.curr() == '/' && rdr.next() == '*') {
+            rdr.bump();
+            rdr.bump();
+            level += 1;
+        } else {
+            if (rdr.curr() == '*' && rdr.next() == '/') {
+                rdr.bump();
+                rdr.bump();
+                level -= 1;
+            } else { rdr.bump(); }
+        }
+    }
+    // restart whitespace munch.
+
+    be consume_whitespace_and_comments(rdr);
+}
+
+fn digits_to_string(str s) -> int {
+    let int accum_int = 0;
+    for (u8 c in s) {
+        accum_int *= 10;
+        accum_int += dec_digit_val(c as char);
+    }
+    ret accum_int;
+}
+
+fn scan_exponent(&reader rdr) -> option::t[str] {
+    auto c = rdr.curr();
+    auto rslt = "";
+    if (c == 'e' || c == 'E') {
+        rslt += str::from_bytes([c as u8]);
+        rdr.bump();
+        c = rdr.curr();
+        if (c == '-' || c == '+') {
+            rslt += str::from_bytes([c as u8]);
+            rdr.bump();
+        }
+        auto exponent = scan_dec_digits(rdr);
+        if (str::byte_len(exponent) > 0u) {
+            ret some(rslt + exponent);
+        } else { rdr.err("scan_exponent: bad fp literal"); fail; }
+    } else { ret none[str]; }
+}
+
+fn scan_dec_digits(&reader rdr) -> str {
+    auto c = rdr.curr();
+    let str rslt = "";
+    while (is_dec_digit(c) || c == '_') {
+        if (c != '_') { rslt += str::from_bytes([c as u8]); }
+        rdr.bump();
+        c = rdr.curr();
+    }
+    ret rslt;
+}
+
+fn scan_number(char c, &reader rdr) -> token::token {
+    auto accum_int = 0;
+    let str dec_str = "";
+    let bool is_dec_integer = false;
+    auto n = rdr.next();
+    if (c == '0' && n == 'x') {
+        rdr.bump();
+        rdr.bump();
+        c = rdr.curr();
+        while (is_hex_digit(c) || c == '_') {
+            if (c != '_') { accum_int *= 16; accum_int += hex_digit_val(c); }
+            rdr.bump();
+            c = rdr.curr();
+        }
+    } else if (c == '0' && n == 'b') {
+        rdr.bump();
+        rdr.bump();
+        c = rdr.curr();
+        while (is_bin_digit(c) || c == '_') {
+            if (c != '_') { accum_int *= 2; accum_int += bin_digit_value(c); }
+            rdr.bump();
+            c = rdr.curr();
+        }
+    } else { dec_str = scan_dec_digits(rdr); is_dec_integer = true; }
+    if (is_dec_integer) { accum_int = digits_to_string(dec_str); }
+    c = rdr.curr();
+    n = rdr.next();
+    if (c == 'u' || c == 'i') {
+        let bool signed = c == 'i';
+        rdr.bump();
+        c = rdr.curr();
+        if (c == '8') {
+            rdr.bump();
+            if (signed) {
+                ret token::LIT_MACH_INT(ast::ty_i8, accum_int);
+            } else { ret token::LIT_MACH_INT(ast::ty_u8, accum_int); }
+        }
+        n = rdr.next();
+        if (c == '1' && n == '6') {
+            rdr.bump();
+            rdr.bump();
+            if (signed) {
+                ret token::LIT_MACH_INT(ast::ty_i16, accum_int);
+            } else { ret token::LIT_MACH_INT(ast::ty_u16, accum_int); }
+        }
+        if (c == '3' && n == '2') {
+            rdr.bump();
+            rdr.bump();
+            if (signed) {
+                ret token::LIT_MACH_INT(ast::ty_i32, accum_int);
+            } else { ret token::LIT_MACH_INT(ast::ty_u32, accum_int); }
+        }
+        if (c == '6' && n == '4') {
+            rdr.bump();
+            rdr.bump();
+            if (signed) {
+                ret token::LIT_MACH_INT(ast::ty_i64, accum_int);
+            } else { ret token::LIT_MACH_INT(ast::ty_u64, accum_int); }
+        }
+        if (signed) {
+            ret token::LIT_INT(accum_int);
+        } else {
+            // FIXME: should cast in the target bit-width.
+
+            ret token::LIT_UINT(accum_int as uint);
+        }
+    }
+    c = rdr.curr();
+    if (c == '.') {
+        // Parse a floating-point number.
+
+        rdr.bump();
+        auto dec_part = scan_dec_digits(rdr);
+        auto float_str = dec_str + "." + dec_part;
+        c = rdr.curr();
+        auto exponent_str = scan_exponent(rdr);
+        alt (exponent_str) {
+            case (some(?s)) { float_str += s; }
+            case (none) { }
+        }
+        c = rdr.curr();
+        if (c == 'f') {
+            rdr.bump();
+            c = rdr.curr();
+            n = rdr.next();
+            if (c == '3' && n == '2') {
+                rdr.bump();
+                rdr.bump();
+                ret token::LIT_MACH_FLOAT(ast::ty_f32,
+                                          intern(*rdr.get_interner(),
+                                                 float_str));
+            } else if (c == '6' && n == '4') {
+                rdr.bump();
+                rdr.bump();
+                ret token::LIT_MACH_FLOAT(ast::ty_f64,
+                                          intern(*rdr.get_interner(),
+                                                 float_str));
+                /* FIXME: if this is out of range for either a 32-bit or
+                   64-bit float, it won't be noticed till the back-end */
+
+            }
+        } else {
+            ret token::LIT_FLOAT(interner::intern[str](*rdr.get_interner(),
+                                                       float_str));
+        }
+    }
+    auto maybe_exponent = scan_exponent(rdr);
+    alt (maybe_exponent) {
+        case (some(?s)) {
+            ret token::LIT_FLOAT(interner::intern[str](*rdr.get_interner(),
+                                                       dec_str + s));
+        }
+        case (none) { ret token::LIT_INT(accum_int); }
+    }
+}
+
+fn scan_numeric_escape(&reader rdr, uint n_hex_digits) -> char {
+    auto accum_int = 0;
+    while (n_hex_digits != 0u) {
+        auto n = rdr.curr();
+        rdr.bump();
+        if (!is_hex_digit(n)) {
+            rdr.err(#fmt("illegal numeric character escape: %d", n as int));
+            fail;
+        }
+        accum_int *= 16;
+        accum_int += hex_digit_val(n);
+        n_hex_digits -= 1u;
+    }
+    ret accum_int as char;
+}
+
+fn next_token(&reader rdr) -> token::token {
+    auto accum_str = "";
+    consume_whitespace_and_comments(rdr);
+    if (rdr.is_eof()) { ret token::EOF; }
+    rdr.mark();
+    auto c = rdr.curr();
+    if (is_alpha(c) || c == '_') {
+        while (is_alnum(c) || c == '_') {
+            str::push_char(accum_str, c);
+            rdr.bump();
+            c = rdr.curr();
+        }
+        if (str::eq(accum_str, "_")) { ret token::UNDERSCORE; }
+        auto is_mod_name = c == ':' && rdr.next() == ':';
+        ret token::IDENT(interner::intern[str](*rdr.get_interner(),
+                                               accum_str), is_mod_name);
+    }
+    if (is_dec_digit(c)) { ret scan_number(c, rdr); }
+    fn binop(&reader rdr, token::binop op) -> token::token {
+        rdr.bump();
+        if (rdr.curr() == '=') {
+            rdr.bump();
+            ret token::BINOPEQ(op);
+        } else { ret token::BINOP(op); }
+    }
+    alt (c) {
+        case (
+             // One-byte tokens.
+             '?') {
+            rdr.bump();
+            ret token::QUES;
+        }
+        case (';') { rdr.bump(); ret token::SEMI; }
+        case (',') { rdr.bump(); ret token::COMMA; }
+        case ('.') { rdr.bump(); ret token::DOT; }
+        case ('(') { rdr.bump(); ret token::LPAREN; }
+        case (')') { rdr.bump(); ret token::RPAREN; }
+        case ('{') { rdr.bump(); ret token::LBRACE; }
+        case ('}') { rdr.bump(); ret token::RBRACE; }
+        case ('[') { rdr.bump(); ret token::LBRACKET; }
+        case (']') { rdr.bump(); ret token::RBRACKET; }
+        case ('@') { rdr.bump(); ret token::AT; }
+        case ('#') { rdr.bump(); ret token::POUND; }
+        case ('~') { rdr.bump(); ret token::TILDE; }
+        case (':') {
+            rdr.bump();
+            if (rdr.curr() == ':') {
+                rdr.bump();
+                ret token::MOD_SEP;
+            } else { ret token::COLON; }
+        }
+        case (
+             // Multi-byte tokens.
+             '=') {
+            rdr.bump();
+            if (rdr.curr() == '=') {
+                rdr.bump();
+                ret token::EQEQ;
+            } else { ret token::EQ; }
+        }
+        case ('!') {
+            rdr.bump();
+            if (rdr.curr() == '=') {
+                rdr.bump();
+                ret token::NE;
+            } else { ret token::NOT; }
+        }
+        case ('<') {
+            rdr.bump();
+            alt (rdr.curr()) {
+                case ('=') { rdr.bump(); ret token::LE; }
+                case ('<') { ret binop(rdr, token::LSL); }
+                case ('|') { rdr.bump(); ret token::SEND; }
+                case ('-') {
+                    rdr.bump();
+                    alt (rdr.curr()) {
+                        case ('>') { rdr.bump(); ret token::DARROW; }
+                        case (_) { ret token::LARROW; }
+                    }
+                }
+                case (_) { ret token::LT; }
+            }
+        }
+        case ('>') {
+            rdr.bump();
+            alt (rdr.curr()) {
+                case ('=') { rdr.bump(); ret token::GE; }
+                case ('>') {
+                    if (rdr.next() == '>') {
+                        rdr.bump();
+                        ret binop(rdr, token::ASR);
+                    } else { ret binop(rdr, token::LSR); }
+                }
+                case (_) { ret token::GT; }
+            }
+        }
+        case ('\'') {
+            rdr.bump();
+            auto c2 = rdr.curr();
+            rdr.bump();
+            if (c2 == '\\') {
+                auto escaped = rdr.curr();
+                rdr.bump();
+                alt (escaped) {
+                    case ('n') { c2 = '\n'; }
+                    case ('r') { c2 = '\r'; }
+                    case ('t') { c2 = '\t'; }
+                    case ('\\') { c2 = '\\'; }
+                    case ('\'') { c2 = '\''; }
+                    case ('x') { c2 = scan_numeric_escape(rdr, 2u); }
+                    case ('u') { c2 = scan_numeric_escape(rdr, 4u); }
+                    case ('U') { c2 = scan_numeric_escape(rdr, 8u); }
+                    case (?c2) {
+                        rdr.err(#fmt("unknown character escape: %d",
+                                     c2 as int));
+                        fail;
+                    }
+                }
+            }
+            if (rdr.curr() != '\'') {
+                rdr.err("unterminated character constant");
+                fail;
+            }
+            rdr.bump(); // advance curr past token
+
+            ret token::LIT_CHAR(c2);
+        }
+        case ('"') {
+            rdr.bump();
+            while (rdr.curr() != '"') {
+                auto ch = rdr.curr();
+                rdr.bump();
+                alt (ch) {
+                    case ('\\') {
+                        auto escaped = rdr.curr();
+                        rdr.bump();
+                        alt (escaped) {
+                            case ('n') {
+                                str::push_byte(accum_str, '\n' as u8);
+                            }
+                            case ('r') {
+                                str::push_byte(accum_str, '\r' as u8);
+                            }
+                            case ('t') {
+                                str::push_byte(accum_str, '\t' as u8);
+                            }
+                            case ('\\') {
+                                str::push_byte(accum_str, '\\' as u8);
+                            }
+                            case ('"') {
+                                str::push_byte(accum_str, '"' as u8);
+                            }
+                            case ('\n') { consume_whitespace(rdr); }
+                            case ('x') {
+                                str::push_char(accum_str,
+                                               scan_numeric_escape(rdr, 2u));
+                            }
+                            case ('u') {
+                                str::push_char(accum_str,
+                                               scan_numeric_escape(rdr, 4u));
+                            }
+                            case ('U') {
+                                str::push_char(accum_str,
+                                               scan_numeric_escape(rdr, 8u));
+                            }
+                            case (?c2) {
+                                rdr.err(#fmt("unknown string escape: %d",
+                                             c2 as int));
+                                fail;
+                            }
+                        }
+                    }
+                    case (_) { str::push_char(accum_str, ch); }
+                }
+            }
+            rdr.bump();
+            ret token::LIT_STR(interner::intern[str](*rdr.get_interner(),
+                                                     accum_str));
+        }
+        case ('-') {
+            if (rdr.next() == '>') {
+                rdr.bump();
+                rdr.bump();
+                ret token::RARROW;
+            } else { ret binop(rdr, token::MINUS); }
+        }
+        case ('&') {
+            if (rdr.next() == '&') {
+                rdr.bump();
+                rdr.bump();
+                ret token::ANDAND;
+            } else { ret binop(rdr, token::AND); }
+        }
+        case ('|') {
+            alt (rdr.next()) {
+                case ('|') { rdr.bump(); rdr.bump(); ret token::OROR; }
+                case ('>') { rdr.bump(); rdr.bump(); ret token::RECV; }
+                case (_) { ret binop(rdr, token::OR); }
+            }
+        }
+        case ('+') { ret binop(rdr, token::PLUS); }
+        case ('*') { ret binop(rdr, token::STAR); }
+        case ('/') { ret binop(rdr, token::SLASH); }
+        case ('^') { ret binop(rdr, token::CARET); }
+        case ('%') { ret binop(rdr, token::PERCENT); }
+        case (?c) {
+            rdr.err(#fmt("unkown start of token: %d", c as int));
+            fail;
+        }
+    }
+    fail;
+}
+
+tag cmnt_style {
+    isolated; // No code on either side of each line of the comment
+
+    trailing; // Code exists to the left of the comment
+
+    mixed; // Code before /* foo */ and after the comment
+
+    blank_line; // Just a manual blank linke "\n\n", for layout
+
+}
+
+type cmnt = rec(cmnt_style style, vec[str] lines, uint pos);
+
+fn read_to_eol(&reader rdr) -> str {
+    auto val = "";
+    while (rdr.curr() != '\n' && !rdr.is_eof()) {
+        str::push_char(val, rdr.curr());
+        rdr.bump();
+    }
+    ret val;
+}
+
+fn read_one_line_comment(&reader rdr) -> str {
+    auto val = read_to_eol(rdr);
+    assert (val.(0) == '/' as u8 && val.(1) == '/' as u8);
+    ret val;
+}
+
+fn consume_whitespace(&reader rdr) {
+    while (is_whitespace(rdr.curr()) && !rdr.is_eof()) { rdr.bump(); }
+}
+
+fn consume_non_eol_whitespace(&reader rdr) {
+    while (is_whitespace(rdr.curr()) && rdr.curr() != '\n' && !rdr.is_eof()) {
+        rdr.bump();
+    }
+}
+
+fn consume_whitespace_counting_blank_lines(&reader rdr,
+                                           &mutable vec[cmnt] comments) {
+    while (is_whitespace(rdr.curr()) && !rdr.is_eof()) {
+        if (rdr.curr() == '\n' && rdr.next() == '\n') {
+            log ">>> blank-line comment";
+            let vec[str] v = [];
+            comments += [rec(style=blank_line, lines=v,
+                             pos=rdr.get_chpos())];
+        }
+        rdr.bump();
+    }
+}
+
+fn read_line_comments(&reader rdr, bool code_to_the_left) -> cmnt {
+    log ">>> line comments";
+    auto p = rdr.get_chpos();
+    let vec[str] lines = [];
+    while (rdr.curr() == '/' && rdr.next() == '/') {
+        auto line = read_one_line_comment(rdr);
+        log line;
+        lines += [line];
+        consume_non_eol_whitespace(rdr);
+    }
+    log "<<< line comments";
+    ret rec(style=if (code_to_the_left) { trailing } else { isolated },
+            lines=lines,
+            pos=p);
+}
+
+fn all_whitespace(&str s, uint begin, uint end) -> bool {
+    let uint i = begin;
+    while (i != end) {
+        if (!is_whitespace(s.(i) as char)) { ret false; }
+        i += 1u;
+    }
+    ret true;
+}
+
+fn trim_whitespace_prefix_and_push_line(&mutable vec[str] lines, &str s,
+                                        uint col) {
+    auto s1;
+    if (all_whitespace(s, 0u, col)) {
+        if (col < str::byte_len(s)) {
+            s1 = str::slice(s, col, str::byte_len(s));
+        } else { s1 = ""; }
+    } else { s1 = s; }
+    log "pushing line: " + s1;
+    lines += [s1];
+}
+
+fn read_block_comment(&reader rdr, bool code_to_the_left) -> cmnt {
+    log ">>> block comment";
+    auto p = rdr.get_chpos();
+    let vec[str] lines = [];
+    let uint col = rdr.get_col();
+    rdr.bump();
+    rdr.bump();
+    auto curr_line = "/*";
+    let int level = 1;
+    while (level > 0) {
+        log #fmt("=== block comment level %d", level);
+        if (rdr.is_eof()) { rdr.err("unterminated block comment"); fail; }
+        if (rdr.curr() == '\n') {
+            trim_whitespace_prefix_and_push_line(lines, curr_line, col);
+            curr_line = "";
+            rdr.bump();
+        } else {
+            str::push_char(curr_line, rdr.curr());
+            if (rdr.curr() == '/' && rdr.next() == '*') {
+                rdr.bump();
+                rdr.bump();
+                curr_line += "*";
+                level += 1;
+            } else {
+                if (rdr.curr() == '*' && rdr.next() == '/') {
+                    rdr.bump();
+                    rdr.bump();
+                    curr_line += "/";
+                    level -= 1;
+                } else { rdr.bump(); }
+            }
+        }
+    }
+    if (str::byte_len(curr_line) != 0u) {
+        trim_whitespace_prefix_and_push_line(lines, curr_line, col);
+    }
+    auto style = if (code_to_the_left) { trailing } else { isolated };
+    consume_non_eol_whitespace(rdr);
+    if (!rdr.is_eof() && rdr.curr() != '\n' && vec::len(lines) == 1u) {
+        style = mixed;
+    }
+    log "<<< block comment";
+    ret rec(style=style, lines=lines, pos=p);
+}
+
+fn peeking_at_comment(&reader rdr) -> bool {
+    ret rdr.curr() == '/' && rdr.next() == '/' ||
+            rdr.curr() == '/' && rdr.next() == '*';
+}
+
+fn consume_comment(&reader rdr, bool code_to_the_left,
+                   &mutable vec[cmnt] comments) {
+    log ">>> consume comment";
+    if (rdr.curr() == '/' && rdr.next() == '/') {
+        vec::push[cmnt](comments, read_line_comments(rdr, code_to_the_left));
+    } else if (rdr.curr() == '/' && rdr.next() == '*') {
+        vec::push[cmnt](comments, read_block_comment(rdr, code_to_the_left));
+    } else { fail; }
+    log "<<< consume comment";
+}
+
+fn is_lit(&token::token t) -> bool {
+    ret alt (t) {
+            case (token::LIT_INT(_)) { true }
+            case (token::LIT_UINT(_)) { true }
+            case (token::LIT_MACH_INT(_, _)) { true }
+            case (token::LIT_FLOAT(_)) { true }
+            case (token::LIT_MACH_FLOAT(_, _)) { true }
+            case (token::LIT_STR(_)) { true }
+            case (token::LIT_CHAR(_)) { true }
+            case (token::LIT_BOOL(_)) { true }
+            case (_) { false }
+        }
+}
+
+type lit = rec(str lit, uint pos);
+
+fn gather_comments_and_literals(&codemap::codemap cm, str path) ->
+   rec(vec[cmnt] cmnts, vec[lit] lits) {
+    auto srdr = io::file_reader(path);
+    auto itr = @interner::mk[str](str::hash, str::eq);
+    auto rdr = new_reader(cm, srdr, codemap::new_filemap(path, 0u), itr);
+    let vec[cmnt] comments = [];
+    let vec[lit] literals = [];
+    let bool first_read = true;
+    while (!rdr.is_eof()) {
+        while (true) {
+            auto code_to_the_left = !first_read;
+            consume_non_eol_whitespace(rdr);
+            if (rdr.curr() == '\n') {
+                code_to_the_left = false;
+                consume_whitespace_counting_blank_lines(rdr, comments);
+            }
+            while (peeking_at_comment(rdr)) {
+                consume_comment(rdr, code_to_the_left, comments);
+                consume_whitespace_counting_blank_lines(rdr, comments);
+            }
+            break;
+        }
+        auto tok = next_token(rdr);
+        if (is_lit(tok)) {
+            vec::push[lit](literals,
+                           rec(lit=rdr.get_mark_str(),
+                               pos=rdr.get_mark_chpos()));
+        }
+        log "tok: " + token::to_str(rdr, tok);
+        first_read = false;
+    }
+    ret rec(cmnts=comments, lits=literals);
+}
+//
+// 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/parse/parser.rs b/src/comp/syntax/parse/parser.rs
new file mode 100644 (file)
index 0000000..48213c1
--- /dev/null
@@ -0,0 +1,2468 @@
+
+import std::io;
+import std::vec;
+import std::str;
+import std::option;
+import std::option::some;
+import std::option::none;
+import std::either;
+import std::either::left;
+import std::either::right;
+import std::map::hashmap;
+import token::can_begin_expr;
+import ex=ext::base;
+import codemap::span;
+import _std::new_str_hash;
+import util::interner;
+
+tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; }
+
+tag file_type { CRATE_FILE; SOURCE_FILE; }
+
+tag ty_or_bang { a_ty(@ast::ty); a_bang; }
+
+type parse_sess = @rec(codemap::codemap cm,
+                       mutable ast::node_id next_id);
+
+fn next_node_id(&parse_sess sess) -> ast::node_id {
+    auto rv = sess.next_id;
+    sess.next_id += 1;
+    ret rv;
+}
+
+type parser =
+    obj {
+        fn peek() -> token::token ;
+        fn bump() ;
+        fn fatal(str) -> !  ;
+        fn warn(str);
+        fn restrict(restriction) ;
+        fn get_restriction() -> restriction ;
+        fn get_file_type() -> file_type ;
+        fn get_cfg() -> ast::crate_cfg;
+        fn get_span() -> span ;
+        fn get_lo_pos() -> uint ;
+        fn get_hi_pos() -> uint ;
+        fn get_last_lo_pos() -> uint ;
+        fn get_prec_table() -> vec[op_spec] ;
+        fn get_str(token::str_num) -> str ;
+        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;
+    };
+
+fn new_parser(parse_sess sess, ast::crate_cfg cfg,
+              str path, uint pos) -> parser {
+    obj stdio_parser(parse_sess sess,
+                     ast::crate_cfg cfg,
+                     file_type ftype,
+                     mutable token::token tok,
+                     mutable uint lo,
+                     mutable uint hi,
+                     mutable uint last_lo,
+                     mutable restriction restr,
+                     lexer::reader rdr,
+                     vec[op_spec] precs,
+                     hashmap[str, ()] bad_words,
+                     hashmap[str, ex::syntax_extension] syntax_expanders) {
+        fn peek() -> token::token { ret tok; }
+        fn bump() {
+            // log rdr.get_filename()
+            //   + ":" + common::istr(lo.line as int);
+
+            last_lo = lo;
+            tok = lexer::next_token(rdr);
+            lo = rdr.get_mark_chpos();
+            hi = rdr.get_chpos();
+        }
+        fn fatal(str m) -> ! {
+            codemap::emit_error(some(self.get_span()), m, sess.cm);
+            fail;
+        }
+        fn warn(str m) {
+            codemap::emit_warning(some(self.get_span()), m, sess.cm);
+        }
+        fn restrict(restriction r) { restr = r; }
+        fn get_restriction() -> restriction { ret restr; }
+        fn get_span() -> span { ret rec(lo=lo, hi=hi); }
+        fn get_lo_pos() -> uint { ret lo; }
+        fn get_hi_pos() -> uint { ret hi; }
+        fn get_last_lo_pos() -> uint { ret last_lo; }
+        fn get_file_type() -> file_type { ret ftype; }
+        fn get_cfg() -> ast::crate_cfg { ret cfg; }
+        fn get_prec_table() -> vec[op_spec] { ret precs; }
+        fn get_str(token::str_num i) -> str {
+            ret interner::get(*rdr.get_interner(), i);
+        }
+        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; }
+    }
+
+    auto ftype = SOURCE_FILE;
+    if (str::ends_with(path, ".rc")) { ftype = CRATE_FILE; }
+    auto srdr = io::file_reader(path);
+    auto filemap = codemap::new_filemap(path, pos);
+    vec::push(sess.cm.files, filemap);
+    auto itr = @interner::mk(str::hash, str::eq);
+    auto rdr = lexer::new_reader(sess.cm, srdr, filemap, itr);
+    // Make sure npos points at first actual token:
+
+    lexer::consume_whitespace_and_comments(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());
+}
+
+// These are the words that shouldn't be allowed as value identifiers,
+// because, if used at the start of a line, they will cause the line to be
+// interpreted as a specific kind of statement, which would be confusing.
+fn bad_expr_word_table() -> hashmap[str, ()] {
+    auto words = new_str_hash();
+    words.insert("mod", ());
+    words.insert("if", ());
+    words.insert("else", ());
+    words.insert("while", ());
+    words.insert("do", ());
+    words.insert("alt", ());
+    words.insert("for", ());
+    words.insert("break", ());
+    words.insert("cont", ());
+    words.insert("put", ());
+    words.insert("ret", ());
+    words.insert("be", ());
+    words.insert("fail", ());
+    words.insert("type", ());
+    words.insert("resource", ());
+    words.insert("check", ());
+    words.insert("assert", ());
+    words.insert("claim", ());
+    words.insert("prove", ());
+    words.insert("state", ());
+    words.insert("gc", ());
+    words.insert("native", ());
+    words.insert("auto", ());
+    words.insert("fn", ());
+    words.insert("pred", ());
+    words.insert("iter", ());
+    words.insert("import", ());
+    words.insert("export", ());
+    words.insert("let", ());
+    words.insert("const", ());
+    words.insert("log", ());
+    words.insert("log_err", ());
+    words.insert("tag", ());
+    words.insert("obj", ());
+    ret words;
+}
+
+fn unexpected(&parser p, token::token t) -> ! {
+    let str s = "unexpected token: ";
+    s += token::to_str(p.get_reader(), t);
+    p.fatal(s);
+}
+
+fn expect(&parser p, token::token t) {
+    if (p.peek() == t) {
+        p.bump();
+    } else {
+        let str s = "expecting ";
+        s += token::to_str(p.get_reader(), t);
+        s += ", found ";
+        s += token::to_str(p.get_reader(), p.peek());
+        p.fatal(s);
+    }
+}
+
+fn spanned[T](uint lo, uint hi, &T node) -> ast::spanned[T] {
+    ret rec(node=node, span=rec(lo=lo, hi=hi));
+}
+
+fn parse_ident(&parser p) -> ast::ident {
+    alt (p.peek()) {
+        case (token::IDENT(?i, _)) { p.bump(); ret p.get_str(i); }
+        case (_) { p.fatal("expecting ident"); fail; }
+    }
+}
+
+fn parse_value_ident(&parser p) -> ast::ident {
+    check_bad_word(p);
+    ret parse_ident(p);
+}
+
+fn is_word(&parser p, &str word) -> bool {
+    ret alt (p.peek()) {
+            case (token::IDENT(?sid, false)) { str::eq(word, p.get_str(sid)) }
+            case (_) { false }
+        };
+}
+
+fn eat_word(&parser p, &str word) -> bool {
+    alt (p.peek()) {
+        case (token::IDENT(?sid, false)) {
+            if (str::eq(word, p.get_str(sid))) {
+                p.bump();
+                ret true;
+            } else { ret false; }
+        }
+        case (_) { ret false; }
+    }
+}
+
+fn expect_word(&parser p, &str word) {
+    if (!eat_word(p, word)) {
+        p.fatal("expecting " + word + ", found " +
+                  token::to_str(p.get_reader(), p.peek()));
+    }
+}
+
+fn check_bad_word(&parser p) {
+    alt (p.peek()) {
+        case (token::IDENT(?sid, false)) {
+            auto w = p.get_str(sid);
+            if (p.get_bad_expr_words().contains_key(w)) {
+                p.fatal("found " + w + " in expression position");
+            }
+        }
+        case (_) { }
+    }
+}
+
+fn parse_ty_fn(ast::proto proto, &parser p, uint lo) -> ast::ty_ {
+    fn parse_fn_input_ty(&parser p) -> ast::ty_arg {
+        auto lo = p.get_lo_pos();
+        auto mode = ast::val;
+        if (p.peek() == token::BINOP(token::AND)) {
+            p.bump();
+            mode = ast::alias(eat_word(p, "mutable"));
+        }
+        auto t = parse_ty(p);
+        alt (p.peek()) {
+            case (token::IDENT(_, _)) { p.bump();/* ignore param name */ }
+            case (_) {/* no param name present */ }
+        }
+        ret spanned(lo, t.span.hi, rec(mode=mode, ty=t));
+    }
+    auto lo = p.get_lo_pos();
+    auto inputs =
+        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
+                  parse_fn_input_ty, p);
+    auto constrs = parse_constrs([], p);
+    let @ast::ty output;
+    auto cf = ast::return;
+    if (p.peek() == token::RARROW) {
+        p.bump();
+        auto tmp = parse_ty_or_bang(p);
+        alt (tmp) {
+            case (a_ty(?t)) { output = t; }
+            case (a_bang) {
+                output = @spanned(lo, inputs.span.hi, ast::ty_bot);
+                cf = ast::noreturn;
+            }
+        }
+    } else { output = @spanned(lo, inputs.span.hi, ast::ty_nil); }
+    ret ast::ty_fn(proto, inputs.node, output, cf, constrs.node);
+}
+
+fn parse_proto(&parser p) -> ast::proto {
+    if (eat_word(p, "iter")) {
+        ret ast::proto_iter;
+    } else if (eat_word(p, "fn")) {
+        ret ast::proto_fn;
+    } else if (eat_word(p, "pred")) {
+        ret ast::proto_fn;
+    } else { unexpected(p, p.peek()); }
+}
+
+fn parse_ty_obj(&parser p, &mutable uint hi) -> ast::ty_ {
+    fn parse_method_sig(&parser p) -> ast::ty_method {
+        auto flo = p.get_lo_pos();
+        let ast::proto proto = parse_proto(p);
+        auto ident = parse_value_ident(p);
+        auto f = parse_ty_fn(proto, p, flo);
+        expect(p, token::SEMI);
+        alt (f) {
+            case (ast::ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
+                ret spanned(flo, output.span.hi,
+                            rec(proto=proto,
+                                ident=ident,
+                                inputs=inputs,
+                                output=output,
+                                cf=cf,
+                                constrs=constrs));
+            }
+        }
+        fail;
+    }
+    auto f = parse_method_sig;
+    auto meths = parse_seq(token::LBRACE, token::RBRACE, none, f, p);
+    hi = meths.span.hi;
+    ret ast::ty_obj(meths.node);
+}
+
+fn parse_mt(&parser p) -> ast::mt {
+    auto mut = parse_mutability(p);
+    auto t = parse_ty(p);
+    ret rec(ty=t, mut=mut);
+}
+
+fn parse_ty_field(&parser p) -> ast::ty_field {
+    auto lo = p.get_lo_pos();
+    auto mt = parse_mt(p);
+    auto id = parse_ident(p);
+    ret spanned(lo, mt.ty.span.hi, rec(ident=id, mt=mt));
+}
+
+
+// if i is the jth ident in args, return j
+// otherwise, fail
+fn ident_index(&parser p, &vec[ast::arg] args, &ast::ident i) -> uint {
+    auto j = 0u;
+    for (ast::arg a in args) { if (a.ident == i) { ret j; } j += 1u; }
+    p.fatal("Unbound variable " + i + " in constraint arg");
+}
+
+fn parse_constr_arg(vec[ast::arg] args, &parser p) -> @ast::constr_arg {
+    auto sp = p.get_span();
+    auto carg = ast::carg_base;
+    if (p.peek() == token::BINOP(token::STAR)) {
+        p.bump();
+    } else {
+        let ast::ident i = parse_value_ident(p);
+        carg = ast::carg_ident(ident_index(p, args, i));
+    }
+    ret @rec(node=carg, span=sp);
+}
+
+fn parse_ty_constr(&vec[ast::arg] fn_args, &parser p) -> @ast::constr {
+    auto lo = p.get_lo_pos();
+    auto path = parse_path(p);
+    auto pf = bind parse_constr_arg(fn_args, _);
+    let rec(vec[@ast::constr_arg] node, span span) args =
+        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), pf, p);
+    // FIXME fix the def_id
+
+    ret @spanned(lo, args.span.hi,
+                 rec(path=path, args=args.node, id=p.get_id()));
+}
+
+
+// Use the args list to translate each bound variable 
+// mentioned in a constraint to an arg index.
+// Seems weird to do this in the parser, but I'm not sure how else to.
+fn parse_constrs(&vec[ast::arg] args, &parser p) ->
+    ast::spanned[vec[@ast::constr]] {
+    auto lo = p.get_lo_pos();
+    auto hi = p.get_hi_pos();
+    let vec[@ast::constr] constrs = [];
+    if (p.peek() == token::COLON) {
+        p.bump();
+        while (true) {
+            auto constr = parse_ty_constr(args, p);
+            hi = constr.span.hi;
+            vec::push(constrs, constr);
+            if (p.peek() == token::COMMA) { p.bump(); } else { break; }
+        }
+    }
+    ret spanned(lo, hi, constrs);
+}
+
+fn parse_ty_constrs(@ast::ty t, &parser p) -> @ast::ty {
+    if (p.peek() == token::COLON) {
+        auto constrs = parse_constrs([], p);
+        ret @spanned(t.span.lo, constrs.span.hi,
+                     ast::ty_constr(t, constrs.node));
+    }
+    ret t;
+}
+
+fn parse_ty_postfix(@ast::ty orig_t, &parser p) -> @ast::ty {
+    auto lo = p.get_lo_pos();
+    if (p.peek() == token::LBRACKET) {
+        p.bump();
+
+        auto mut;
+        if (eat_word(p, "mutable")) {
+            if (p.peek() == token::QUES) {
+                p.bump();
+                mut = ast::maybe_mut;
+            } else {
+                mut = ast::mut;
+            }
+        } else {
+            mut = ast::imm;
+        }
+
+        if (mut == ast::imm && p.peek() != token::RBRACKET) {
+            // This is explicit type parameter instantiation.
+            auto seq = parse_seq_to_end(token::RBRACKET, some(token::COMMA),
+                                        parse_ty, p);
+            alt (orig_t.node) {
+                case (ast::ty_path(?pth, ?ann)) {
+                    auto hi = p.get_hi_pos();
+                    ret @spanned(lo, hi,
+                                 ast::ty_path(spanned(lo, hi,
+                                              rec(idents=pth.node.idents,
+                                                  types=seq)),
+                                              ann));
+                }
+                case (_) {
+                    p.fatal("type parameter instantiation only allowed for " +
+                          "paths");
+                }
+            }
+        }
+
+        expect(p, token::RBRACKET);
+        auto hi = p.get_hi_pos();
+        auto t = ast::ty_ivec(rec(ty=orig_t, mut=mut));
+        ret parse_ty_postfix(@spanned(lo, hi, t), p);
+    }
+    ret parse_ty_constrs(orig_t, p);
+}
+
+fn parse_ty_or_bang(&parser p) -> ty_or_bang {
+    alt (p.peek()) {
+        case (token::NOT) { p.bump(); ret a_bang; }
+        case (_) { ret a_ty(parse_ty(p)); }
+    }
+}
+
+fn parse_ty(&parser p) -> @ast::ty {
+    auto lo = p.get_lo_pos();
+    auto hi = lo;
+    let ast::ty_ t;
+    // FIXME: do something with this
+
+    parse_layer(p);
+    if (eat_word(p, "bool")) {
+        t = ast::ty_bool;
+    } else if (eat_word(p, "int")) {
+        t = ast::ty_int;
+    } else if (eat_word(p, "uint")) {
+        t = ast::ty_uint;
+    } else if (eat_word(p, "float")) {
+        t = ast::ty_float;
+    } else if (eat_word(p, "str")) {
+        t = ast::ty_str;
+    } else if (eat_word(p, "istr")) {
+        t = ast::ty_istr;
+    } else if (eat_word(p, "char")) {
+        t = ast::ty_char;
+    } else if (eat_word(p, "task")) {
+        t = ast::ty_task;
+    } else if (eat_word(p, "i8")) {
+        t = ast::ty_machine(ast::ty_i8);
+    } else if (eat_word(p, "i16")) {
+        t = ast::ty_machine(ast::ty_i16);
+    } else if (eat_word(p, "i32")) {
+        t = ast::ty_machine(ast::ty_i32);
+    } else if (eat_word(p, "i64")) {
+        t = ast::ty_machine(ast::ty_i64);
+    } else if (eat_word(p, "u8")) {
+        t = ast::ty_machine(ast::ty_u8);
+    } else if (eat_word(p, "u16")) {
+        t = ast::ty_machine(ast::ty_u16);
+    } else if (eat_word(p, "u32")) {
+        t = ast::ty_machine(ast::ty_u32);
+    } else if (eat_word(p, "u64")) {
+        t = ast::ty_machine(ast::ty_u64);
+    } else if (eat_word(p, "f32")) {
+        t = ast::ty_machine(ast::ty_f32);
+    } else if (eat_word(p, "f64")) {
+        t = ast::ty_machine(ast::ty_f64);
+    } else if (p.peek() == token::LPAREN) {
+        p.bump();
+        alt (p.peek()) {
+            case (token::RPAREN) {
+                hi = p.get_hi_pos();
+                p.bump();
+                t = ast::ty_nil;
+            }
+            case (_) {
+                t = parse_ty(p).node;
+                hi = p.get_hi_pos();
+                expect(p, token::RPAREN);
+            }
+        }
+    } else if (p.peek() == token::AT) {
+        p.bump();
+        auto mt = parse_mt(p);
+        hi = mt.ty.span.hi;
+        t = ast::ty_box(mt);
+    } else if (p.peek() == token::BINOP(token::STAR)) {
+        p.bump();
+        auto mt = parse_mt(p);
+        hi = mt.ty.span.hi;
+        t = ast::ty_ptr(mt);
+    } else if (eat_word(p, "vec")) {
+        expect(p, token::LBRACKET);
+        t = ast::ty_vec(parse_mt(p));
+        hi = p.get_hi_pos();
+        expect(p, token::RBRACKET);
+    } else if (eat_word(p, "tup")) {
+        auto elems =
+            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
+                      parse_mt, p);
+        hi = elems.span.hi;
+        t = ast::ty_tup(elems.node);
+    } else if (eat_word(p, "rec")) {
+        auto elems =
+            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
+                      parse_ty_field, p);
+        hi = elems.span.hi;
+        t = ast::ty_rec(elems.node);
+    } else if (eat_word(p, "fn")) {
+        auto flo = p.get_last_lo_pos();
+        t = parse_ty_fn(ast::proto_fn, p, flo);
+        alt (t) { case (ast::ty_fn(_, _, ?out, _, _)) { hi = out.span.hi; } }
+    } else if (eat_word(p, "iter")) {
+        auto flo = p.get_last_lo_pos();
+        t = parse_ty_fn(ast::proto_iter, p, flo);
+        alt (t) { case (ast::ty_fn(_, _, ?out, _, _)) { hi = out.span.hi; } }
+    } else if (eat_word(p, "obj")) {
+        t = parse_ty_obj(p, hi);
+    } else if (eat_word(p, "port")) {
+        expect(p, token::LBRACKET);
+        t = ast::ty_port(parse_ty(p));
+        hi = p.get_hi_pos();
+        expect(p, token::RBRACKET);
+    } else if (eat_word(p, "chan")) {
+        expect(p, token::LBRACKET);
+        t = ast::ty_chan(parse_ty(p));
+        hi = p.get_hi_pos();
+        expect(p, token::RBRACKET);
+    } else if (eat_word(p, "mutable")) {
+        p.warn("ignoring deprecated 'mutable' type constructor");
+        auto typ = parse_ty(p);
+        t = typ.node;
+        hi = typ.span.hi;
+    } else if (is_ident(p.peek())) {
+        auto path = parse_path(p);
+        t = ast::ty_path(path, p.get_id());
+        hi = path.span.hi;
+    } else { p.fatal("expecting type"); t = ast::ty_nil; fail; }
+    ret parse_ty_postfix(@spanned(lo, hi, t), p);
+}
+
+fn parse_arg(&parser p) -> ast::arg {
+    let ast::mode m = ast::val;
+    if (p.peek() == token::BINOP(token::AND)) {
+        p.bump();
+        m = ast::alias(eat_word(p, "mutable"));
+    }
+    let @ast::ty t = parse_ty(p);
+    let ast::ident i = parse_value_ident(p);
+    ret rec(mode=m, ty=t, ident=i, id=p.get_id());
+}
+
+fn parse_seq_to_end[T](token::token ket, option::t[token::token] sep,
+                       fn(&parser) -> T  f, &parser p) -> vec[T] {
+    let bool first = true;
+    let vec[T] v = [];
+    while (p.peek() != ket) {
+        alt (sep) {
+            case (some(?t)) {
+                if (first) { first = false; } else { expect(p, t); }
+            }
+            case (_) { }
+        }
+        v += [f(p)];
+    }
+    expect(p, ket);
+    ret v;
+}
+
+fn parse_seq[T](token::token bra, token::token ket,
+                option::t[token::token] sep, fn(&parser) -> T  f, &parser p)
+   -> ast::spanned[vec[T]] {
+    auto lo = p.get_lo_pos();
+    expect(p, bra);
+    auto result = parse_seq_to_end[T](ket, sep, f, p);
+    auto hi = p.get_hi_pos();
+    ret spanned(lo, hi, result);
+}
+
+fn parse_lit(&parser p) -> ast::lit {
+    auto sp = p.get_span();
+    let ast::lit_ lit = ast::lit_nil;
+    if (eat_word(p, "true")) {
+        lit = ast::lit_bool(true);
+    } else if (eat_word(p, "false")) {
+        lit = ast::lit_bool(false);
+    } else {
+        alt (p.peek()) {
+            case (token::LIT_INT(?i)) { p.bump(); lit = ast::lit_int(i); }
+            case (token::LIT_UINT(?u)) { p.bump(); lit = ast::lit_uint(u); }
+            case (token::LIT_FLOAT(?s)) {
+                p.bump();
+                lit = ast::lit_float(p.get_str(s));
+            }
+            case (token::LIT_MACH_INT(?tm, ?i)) {
+                p.bump();
+                lit = ast::lit_mach_int(tm, i);
+            }
+            case (token::LIT_MACH_FLOAT(?tm, ?s)) {
+                p.bump();
+                lit = ast::lit_mach_float(tm, p.get_str(s));
+            }
+            case (token::LIT_CHAR(?c)) { p.bump(); lit = ast::lit_char(c); }
+            case (token::LIT_STR(?s)) {
+                p.bump();
+                lit = ast::lit_str(p.get_str(s), ast::sk_rc);
+            }
+            case (?t) { unexpected(p, t); }
+        }
+    }
+    ret rec(node=lit, span=sp);
+}
+
+fn is_ident(token::token t) -> bool {
+    alt (t) { case (token::IDENT(_, _)) { ret true; } case (_) { } }
+    ret false;
+}
+
+fn parse_path(&parser p) -> ast::path {
+    auto lo = p.get_lo_pos();
+    auto hi = lo;
+    let vec[ast::ident] ids = [];
+    while (true) {
+        alt (p.peek()) {
+            case (token::IDENT(?i, _)) {
+                hi = p.get_hi_pos();
+                ids += [p.get_str(i)];
+                p.bump();
+                if (p.peek() == token::MOD_SEP) { p.bump(); } else { break; }
+            }
+            case (_) { break; }
+        }
+    }
+    hi = p.get_hi_pos();
+    ret spanned(lo, hi, rec(idents=ids, types=[]));
+}
+
+fn parse_path_and_ty_param_substs(&parser p) -> ast::path {
+    auto lo = p.get_lo_pos();
+    auto path = parse_path(p);
+    if (p.peek() == token::LBRACKET) {
+        auto seq = parse_seq(token::LBRACKET, token::RBRACKET,
+                             some(token::COMMA), parse_ty, p);
+        auto hi = p.get_hi_pos();
+        path = spanned(lo, hi, rec(idents=path.node.idents, types=seq.node));
+    }
+    ret path;
+}
+
+fn parse_mutability(&parser p) -> ast::mutability {
+    if (eat_word(p, "mutable")) {
+        if (p.peek() == token::QUES) { p.bump(); ret ast::maybe_mut; }
+        ret ast::mut;
+    }
+    ret ast::imm;
+}
+
+fn parse_field(&parser p) -> ast::field {
+    auto lo = p.get_lo_pos();
+    auto m = parse_mutability(p);
+    auto i = parse_ident(p);
+    expect(p, token::EQ);
+    auto e = parse_expr(p);
+    ret spanned(lo, e.span.hi, rec(mut=m, ident=i, expr=e));
+}
+
+fn mk_expr(&parser p, uint lo, uint hi, &ast::expr_ node) -> @ast::expr {
+    ret @rec(id=p.get_id(),
+             node=node,
+             span=rec(lo=lo, hi=hi));
+}
+
+fn parse_bottom_expr(&parser p) -> @ast::expr {
+    auto lo = p.get_lo_pos();
+    auto hi = p.get_hi_pos();
+    // FIXME: can only remove this sort of thing when both typestate and
+    // alt-exhaustive-match checking are co-operating.
+
+    auto lit = @spanned(lo, hi, ast::lit_nil);
+    let ast::expr_ ex = ast::expr_lit(lit);
+    if (p.peek() == token::LPAREN) {
+        p.bump();
+        alt (p.peek()) {
+            case (token::RPAREN) {
+                hi = p.get_hi_pos();
+                p.bump();
+                auto lit = @spanned(lo, hi, ast::lit_nil);
+                ret mk_expr(p, lo, hi, ast::expr_lit(lit));
+            }
+            case (_) {/* fall through */ }
+        }
+        auto e = parse_expr(p);
+        hi = p.get_hi_pos();
+        expect(p, token::RPAREN);
+        ret mk_expr(p, lo, hi, e.node);
+    } else if (p.peek() == token::LBRACE) {
+        auto blk = parse_block(p);
+        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
+    } else if (eat_word(p, "if")) {
+        ret parse_if_expr(p);
+    } else if (eat_word(p, "for")) {
+        ret parse_for_expr(p);
+    } else if (eat_word(p, "while")) {
+        ret parse_while_expr(p);
+    } else if (eat_word(p, "do")) {
+        ret parse_do_while_expr(p);
+    } else if (eat_word(p, "alt")) {
+        ret parse_alt_expr(p);
+    } else if (eat_word(p, "spawn")) {
+        ret parse_spawn_expr(p);
+    } else if (eat_word(p, "fn")) {
+        ret parse_fn_expr(p);
+    } else if (eat_word(p, "tup")) {
+        fn parse_elt(&parser p) -> ast::elt {
+            auto m = parse_mutability(p);
+            auto e = parse_expr(p);
+            ret rec(mut=m, expr=e);
+        }
+        auto es =
+            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
+                      parse_elt, p);
+        hi = es.span.hi;
+        ex = ast::expr_tup(es.node);
+    } else if (p.peek() == token::LBRACKET) {
+        p.bump();
+        auto mut = parse_mutability(p);
+        auto es =
+            parse_seq_to_end(token::RBRACKET, some(token::COMMA), parse_expr,
+                             p);
+        ex = ast::expr_vec(es, mut, ast::sk_rc);
+    } else if (p.peek() == token::TILDE) {
+        p.bump();
+        alt (p.peek()) {
+            case (token::LBRACKET) { // unique array (temporary)
+
+                p.bump();
+                auto mut = parse_mutability(p);
+                auto es =
+                    parse_seq_to_end(token::RBRACKET, some(token::COMMA),
+                                     parse_expr, p);
+                ex = ast::expr_vec(es, mut, ast::sk_unique);
+            }
+            case (token::LIT_STR(?s)) {
+                p.bump();
+                auto lit =
+                    @rec(node=ast::lit_str(p.get_str(s), ast::sk_unique),
+                         span=p.get_span());
+                ex = ast::expr_lit(lit);
+            }
+            case (_) {
+                p.fatal("unimplemented: unique pointer creation");
+            }
+        }
+    } else if (eat_word(p, "obj")) {
+        // Anonymous object
+
+        // FIXME: Can anonymous objects have ty params?
+        auto ty_params = parse_ty_params(p);
+
+        // Only make people type () if they're actually adding new fields
+        let option::t[vec[ast::anon_obj_field]] fields = none;
+        if (p.peek() == token::LPAREN) {
+            p.bump();
+            fields =
+                some(parse_seq_to_end(token::RPAREN, some(token::COMMA),
+                                      parse_anon_obj_field, p));
+        }
+        let vec[@ast::method] meths = [];
+        let option::t[@ast::expr] with_obj = none;
+        expect(p, token::LBRACE);
+        while (p.peek() != token::RBRACE) {
+            if (eat_word(p, "with")) {
+                with_obj = some(parse_expr(p));
+            } else { vec::push(meths, parse_method(p)); }
+        }
+        hi = p.get_hi_pos();
+        expect(p, token::RBRACE);
+        // fields and methods may be *additional* or *overriding* fields
+        // and methods if there's a with_obj, or they may be the *only*
+        // fields and methods if there's no with_obj.
+
+        // We don't need to pull ".node" out of fields because it's not a
+        // "spanned".
+        let ast::anon_obj ob =
+            rec(fields=fields, methods=meths, with_obj=with_obj);
+        auto odid = rec(ty=p.get_id(), ctor=p.get_id());
+        ex = ast::expr_anon_obj(ob, ty_params, odid);
+    } else if (eat_word(p, "rec")) {
+        expect(p, token::LPAREN);
+        auto fields = [parse_field(p)];
+        auto more = true;
+        auto base = none;
+        while (more) {
+            if (p.peek() == token::RPAREN) {
+                hi = p.get_hi_pos();
+                p.bump();
+                more = false;
+            } else if (eat_word(p, "with")) {
+                base = some(parse_expr(p));
+                hi = p.get_hi_pos();
+                expect(p, token::RPAREN);
+                more = false;
+            } else if (p.peek() == token::COMMA) {
+                p.bump();
+                fields += [parse_field(p)];
+            } else { unexpected(p, p.peek()); }
+        }
+        ex = ast::expr_rec(fields, base);
+    } else if (eat_word(p, "bind")) {
+        auto e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
+        fn parse_expr_opt(&parser p) -> option::t[@ast::expr] {
+            alt (p.peek()) {
+                case (token::UNDERSCORE) { p.bump(); ret none; }
+                case (_) { ret some(parse_expr(p)); }
+            }
+        }
+        auto es =
+            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
+                      parse_expr_opt, p);
+        hi = es.span.hi;
+        ex = ast::expr_bind(e, es.node);
+    } else if (p.peek() == token::POUND) {
+        auto ex_ext = parse_syntax_ext(p);
+        lo = ex_ext.span.lo;
+        ex = ex_ext.node;
+    } else if (eat_word(p, "fail")) {
+        if (can_begin_expr(p.peek())) {
+            auto e = parse_expr(p);
+            hi = e.span.hi;
+            ex = ast::expr_fail(some(e));
+        }
+        else {
+            ex = ast::expr_fail(none);
+        }
+    } else if (eat_word(p, "log")) {
+        auto e = parse_expr(p);
+        ex = ast::expr_log(1, e);
+    } else if (eat_word(p, "log_err")) {
+        auto e = parse_expr(p);
+        ex = ast::expr_log(0, e);
+    } else if (eat_word(p, "assert")) {
+        auto e = parse_expr(p);
+        ex = ast::expr_assert(e);
+    } else if (eat_word(p, "check")) {
+        /* Should be a predicate (pure boolean function) applied to 
+           arguments that are all either slot variables or literals.
+           but the typechecker enforces that. */
+
+        auto e = parse_expr(p);
+        ex = ast::expr_check(ast::checked, e);
+    } else if (eat_word(p, "claim")) {
+        /* Same rules as check, except that if check-claims
+         is enabled (a command-line flag), then the parser turns
+        claims into check */
+        
+        auto e = parse_expr(p);
+        ex = ast::expr_check(ast::unchecked, e);
+    } else if (eat_word(p, "ret")) {
+        alt (p.peek()) {
+            case (token::SEMI) { ex = ast::expr_ret(none); }
+            // Handle ret as the block result expression
+            case (token::RBRACE) { ex = ast::expr_ret(none); }
+            case (_) {
+                auto e = parse_expr(p);
+                hi = e.span.hi;
+                ex = ast::expr_ret(some(e));
+            }
+        }
+    } else if (eat_word(p, "break")) {
+        ex = ast::expr_break;
+    } else if (eat_word(p, "cont")) {
+        ex = ast::expr_cont;
+    } else if (eat_word(p, "put")) {
+        alt (p.peek()) {
+            case (token::SEMI) { ex = ast::expr_put(none); }
+            case (_) {
+                auto e = parse_expr(p);
+                hi = e.span.hi;
+                ex = ast::expr_put(some(e));
+            }
+        }
+    } else if (eat_word(p, "be")) {
+        auto e = parse_expr(p);
+
+        // FIXME: Is this the right place for this check?
+        if (/*check*/ast::is_call_expr(e)) {
+            hi = e.span.hi;
+            ex = ast::expr_be(e);
+        } else { p.fatal("Non-call expression in tail call"); }
+    } else if (eat_word(p, "port")) {
+        auto ty = none;
+        if(token::LBRACKET == p.peek()) {
+            expect(p, token::LBRACKET);
+            ty = some(parse_ty(p));
+            expect(p, token::RBRACKET);
+        }
+        expect(p, token::LPAREN);
+        expect(p, token::RPAREN);
+        hi = p.get_hi_pos();
+        ex = ast::expr_port(ty);
+    } else if (eat_word(p, "chan")) {
+        expect(p, token::LPAREN);
+        auto e = parse_expr(p);
+        hi = e.span.hi;
+        expect(p, token::RPAREN);
+        ex = ast::expr_chan(e);
+    } else if (eat_word(p, "self")) {
+        log "parsing a self-call...";
+        expect(p, token::DOT);
+        // The rest is a call expression.
+
+        let @ast::expr f = parse_self_method(p);
+        auto es =
+            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
+                      parse_expr, p);
+        hi = es.span.hi;
+        ex = ast::expr_call(f, es.node);
+    } else if (is_ident(p.peek()) && !is_word(p, "true") &&
+               !is_word(p, "false")) {
+        check_bad_word(p);
+        auto pth = parse_path_and_ty_param_substs(p);
+        hi = pth.span.hi;
+        ex = ast::expr_path(pth);
+    } else {
+        auto lit = parse_lit(p);
+        hi = lit.span.hi;
+        ex = ast::expr_lit(@lit);
+    }
+    ret mk_expr(p, lo, hi, ex);
+}
+
+fn parse_syntax_ext(&parser p) -> @ast::expr {
+    auto lo = p.get_lo_pos();
+    expect(p, token::POUND);
+    ret parse_syntax_ext_naked(p, lo);
+}
+
+fn parse_syntax_ext_naked(&parser p, uint lo) -> @ast::expr {
+    auto pth = parse_path(p);
+    if (vec::len(pth.node.idents) == 0u) {
+        p.fatal("expected a syntax expander name");
+    }
+    auto es = parse_seq(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,
+                     vec[@ast::expr] args, option::t[str] body) ->
+   ast::expr_ {
+    assert (vec::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(vec::empty[ast::elt]());
+        }
+    }
+}
+
+fn parse_self_method(&parser p) -> @ast::expr {
+    auto sp = p.get_span();
+    let ast::ident f_name = parse_ident(p);
+    ret mk_expr(p, sp.lo, sp.hi, ast::expr_self_method(f_name));
+}
+
+fn parse_dot_or_call_expr(&parser p) -> @ast::expr {
+    ret parse_dot_or_call_expr_with(p, parse_bottom_expr(p));
+}
+
+fn parse_dot_or_call_expr_with(&parser p, @ast::expr e) -> @ast::expr {
+    auto lo = e.span.lo;
+    auto hi = e.span.hi;
+    while (true) {
+        alt (p.peek()) {
+            case (token::LPAREN) {
+                if (p.get_restriction() == RESTRICT_NO_CALL_EXPRS) {
+                    ret e;
+                } else {
+                    // Call expr.
+
+                    auto es =
+                        parse_seq(token::LPAREN, token::RPAREN,
+                                  some(token::COMMA), parse_expr, p);
+                    hi = es.span.hi;
+                    e = mk_expr(p, lo, hi, ast::expr_call(e, es.node));
+                }
+            }
+            case (token::DOT) {
+                p.bump();
+                alt (p.peek()) {
+                    case (token::IDENT(?i, _)) {
+                        hi = p.get_hi_pos();
+                        p.bump();
+                        e = mk_expr(p, lo, hi,
+                                    ast::expr_field(e, p.get_str(i)));
+                    }
+                    case (token::LPAREN) {
+                        p.bump();
+                        auto ix = parse_expr(p);
+                        hi = ix.span.hi;
+                        expect(p, token::RPAREN);
+                        e = mk_expr(p, lo, hi, ast::expr_index(e, ix));
+                    }
+                    case (?t) { unexpected(p, t); }
+                }
+            }
+            case (_) { ret e; }
+        }
+    }
+    ret e;
+}
+
+fn parse_prefix_expr(&parser p) -> @ast::expr {
+    if (eat_word(p, "mutable")) {
+        p.warn("ignoring deprecated 'mutable' prefix operator");
+    }
+    auto lo = p.get_lo_pos();
+    auto hi = p.get_hi_pos();
+    // FIXME: can only remove this sort of thing when both typestate and
+    // alt-exhaustive-match checking are co-operating.
+
+    auto lit = @spanned(lo, lo, ast::lit_nil);
+    let ast::expr_ ex = ast::expr_lit(lit);
+    alt (p.peek()) {
+        case (token::NOT) {
+            p.bump();
+            auto e = parse_prefix_expr(p);
+            hi = e.span.hi;
+            ex = ast::expr_unary(ast::not, e);
+        }
+        case (token::BINOP(?b)) {
+            alt (b) {
+                case (token::MINUS) {
+                    p.bump();
+                    auto e = parse_prefix_expr(p);
+                    hi = e.span.hi;
+                    ex = ast::expr_unary(ast::neg, e);
+                }
+                case (token::STAR) {
+                    p.bump();
+                    auto e = parse_prefix_expr(p);
+                    hi = e.span.hi;
+                    ex = ast::expr_unary(ast::deref, e);
+                }
+                case (_) { ret parse_dot_or_call_expr(p); }
+            }
+        }
+        case (token::AT) {
+            p.bump();
+            auto m = parse_mutability(p);
+            auto e = parse_prefix_expr(p);
+            hi = e.span.hi;
+            ex = ast::expr_unary(ast::box(m), e);
+        }
+        case (_) { ret parse_dot_or_call_expr(p); }
+    }
+    ret mk_expr(p, lo, hi, ex);
+}
+
+fn parse_ternary(&parser p) -> @ast::expr {
+    auto cond_expr = parse_binops(p);
+    if (p.peek() == token::QUES) {
+        p.bump();
+        auto then_expr = parse_expr(p);
+        expect(p, token::COLON);
+        auto else_expr = parse_expr(p);
+        ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
+                    ast::expr_ternary(cond_expr, then_expr, else_expr));
+    } else {
+        ret cond_expr;
+    }
+}
+
+type op_spec = rec(token::token tok, ast::binop op, int prec);
+
+
+// FIXME make this a const, don't store it in parser state
+fn prec_table() -> vec[op_spec] {
+    ret [rec(tok=token::BINOP(token::STAR), op=ast::mul, prec=11),
+         rec(tok=token::BINOP(token::SLASH), op=ast::div, prec=11),
+         rec(tok=token::BINOP(token::PERCENT), op=ast::rem, prec=11),
+         rec(tok=token::BINOP(token::PLUS), op=ast::add, prec=10),
+         rec(tok=token::BINOP(token::MINUS), op=ast::sub, prec=10),
+         rec(tok=token::BINOP(token::LSL), op=ast::lsl, prec=9),
+         rec(tok=token::BINOP(token::LSR), op=ast::lsr, prec=9),
+         rec(tok=token::BINOP(token::ASR), op=ast::asr, prec=9),
+         rec(tok=token::BINOP(token::AND), op=ast::bitand, prec=8),
+         rec(tok=token::BINOP(token::CARET), op=ast::bitxor, prec=6),
+         rec(tok=token::BINOP(token::OR), op=ast::bitor, prec=6),
+         // 'as' sits between here with 5
+         rec(tok=token::LT, op=ast::lt, prec=4),
+         rec(tok=token::LE, op=ast::le, prec=4),
+         rec(tok=token::GE, op=ast::ge, prec=4),
+         rec(tok=token::GT, op=ast::gt, prec=4),
+         rec(tok=token::EQEQ, op=ast::eq, prec=3),
+         rec(tok=token::NE, op=ast::ne, prec=3),
+         rec(tok=token::ANDAND, op=ast::and, prec=2),
+         rec(tok=token::OROR, op=ast::or, prec=1)];
+}
+
+fn parse_binops(&parser p) -> @ast::expr {
+    ret parse_more_binops(p, parse_prefix_expr(p), 0);
+}
+
+const int unop_prec = 100;
+
+const int as_prec = 5;
+const int ternary_prec = 0;
+
+fn parse_more_binops(&parser p, @ast::expr lhs, int min_prec) -> @ast::expr {
+    auto peeked = p.peek();
+    for (op_spec cur in p.get_prec_table()) {
+        if (cur.prec > min_prec && cur.tok == peeked) {
+            p.bump();
+            auto rhs = parse_more_binops(p, parse_prefix_expr(p), cur.prec);
+            auto bin = mk_expr(p, lhs.span.lo, rhs.span.hi,
+                               ast::expr_binary(cur.op, lhs, rhs));
+            ret parse_more_binops(p, bin, min_prec);
+        }
+    }
+    if (as_prec > min_prec && eat_word(p, "as")) {
+        auto rhs = parse_ty(p);
+        auto _as = mk_expr(p, lhs.span.lo, rhs.span.hi,
+                           ast::expr_cast(lhs, rhs));
+        ret parse_more_binops(p, _as, min_prec);
+    }
+    ret lhs;
+}
+
+fn parse_assign_expr(&parser p) -> @ast::expr {
+    auto lo = p.get_lo_pos();
+    auto lhs = parse_ternary(p);
+    alt (p.peek()) {
+        case (token::EQ) {
+            p.bump();
+            auto rhs = parse_expr(p);
+            ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign(lhs, rhs));
+        }
+        case (token::BINOPEQ(?op)) {
+            p.bump();
+            auto rhs = parse_expr(p);
+            auto aop = ast::add;
+            alt (op) {
+                case (token::PLUS) { aop = ast::add; }
+                case (token::MINUS) { aop = ast::sub; }
+                case (token::STAR) { aop = ast::mul; }
+                case (token::SLASH) { aop = ast::div; }
+                case (token::PERCENT) { aop = ast::rem; }
+                case (token::CARET) { aop = ast::bitxor; }
+                case (token::AND) { aop = ast::bitand; }
+                case (token::OR) { aop = ast::bitor; }
+                case (token::LSL) { aop = ast::lsl; }
+                case (token::LSR) { aop = ast::lsr; }
+                case (token::ASR) { aop = ast::asr; }
+            }
+            ret mk_expr(p, lo, rhs.span.hi,
+                        ast::expr_assign_op(aop, lhs, rhs));
+        }
+        case (token::LARROW) {
+            p.bump();
+            auto rhs = parse_expr(p);
+            ret mk_expr(p, lo, rhs.span.hi, ast::expr_move(lhs, rhs));
+        }
+        case (token::SEND) {
+            p.bump();
+            auto rhs = parse_expr(p);
+            ret mk_expr(p, lo, rhs.span.hi, ast::expr_send(lhs, rhs));
+        }
+        case (token::RECV) {
+            p.bump();
+            auto rhs = parse_expr(p);
+            ret mk_expr(p, lo, rhs.span.hi, ast::expr_recv(lhs, rhs));
+        }
+        case (token::DARROW) {
+            p.bump();
+            auto rhs = parse_expr(p);
+            ret mk_expr(p, lo, rhs.span.hi, ast::expr_swap(lhs, rhs));
+        }
+        case (_) {/* fall through */ }
+    }
+    ret lhs;
+}
+
+fn parse_if_expr_1(&parser p) -> tup(@ast::expr,
+                                     ast::block, option::t[@ast::expr],
+                                     uint, uint) {
+    auto lo = p.get_last_lo_pos();
+    expect(p, token::LPAREN);
+    auto cond = parse_expr(p);
+    expect(p, token::RPAREN);
+    auto thn = parse_block(p);
+    let option::t[@ast::expr] els = none;
+    auto hi = thn.span.hi;
+    if (eat_word(p, "else")) {
+        auto elexpr = parse_else_expr(p);
+        els = some(elexpr);
+        hi = elexpr.span.hi;
+    }
+    ret tup(cond, thn, els, lo, hi);
+}
+
+fn parse_if_expr(&parser p) -> @ast::expr {
+    if (eat_word(p, "check")) {
+            auto q = parse_if_expr_1(p);
+            ret mk_expr(p, q._3, q._4, ast::expr_if_check(q._0, q._1, q._2));
+    }
+    else {
+        auto q = parse_if_expr_1(p);
+        ret mk_expr(p, q._3, q._4, ast::expr_if(q._0, q._1, q._2));
+    }
+}
+
+fn parse_fn_expr(&parser p) -> @ast::expr {
+    auto lo = p.get_last_lo_pos();
+    auto decl = parse_fn_decl(p, ast::impure_fn);
+    auto body = parse_block(p);
+    auto _fn = rec(decl=decl, proto=ast::proto_fn, body=body);
+    ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
+}
+
+fn parse_else_expr(&parser p) -> @ast::expr {
+    if (eat_word(p, "if")) {
+        ret parse_if_expr(p);
+    } else {
+        auto blk = parse_block(p);
+        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
+    }
+}
+
+fn parse_head_local(&parser p) -> @ast::local {
+    if (is_word(p, "auto")) {
+        ret parse_auto_local(p);
+    } else { 
+        ret parse_typed_local(p);
+    }
+}
+
+fn parse_for_expr(&parser p) -> @ast::expr {
+    auto lo = p.get_last_lo_pos();
+    auto is_each = eat_word(p, "each");
+    expect(p, token::LPAREN);
+    auto decl = parse_head_local(p);
+    expect_word(p, "in");
+    auto seq = parse_expr(p);
+    expect(p, token::RPAREN);
+    auto body = parse_block(p);
+    auto hi = body.span.hi;
+    if (is_each) {
+        ret mk_expr(p, lo, hi, ast::expr_for_each(decl, seq, body));
+    } else {
+        ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
+    }
+}
+
+fn parse_while_expr(&parser p) -> @ast::expr {
+    auto lo = p.get_last_lo_pos();
+    expect(p, token::LPAREN);
+    auto cond = parse_expr(p);
+    expect(p, token::RPAREN);
+    auto body = parse_block(p);
+    auto hi = body.span.hi;
+    ret mk_expr(p, lo, hi, ast::expr_while(cond, body));
+}
+
+fn parse_do_while_expr(&parser p) -> @ast::expr {
+    auto lo = p.get_last_lo_pos();
+    auto body = parse_block(p);
+    expect_word(p, "while");
+    expect(p, token::LPAREN);
+    auto cond = parse_expr(p);
+    expect(p, token::RPAREN);
+    auto hi = cond.span.hi;
+    ret mk_expr(p, lo, hi, ast::expr_do_while(body, cond));
+}
+
+fn parse_alt_expr(&parser p) -> @ast::expr {
+    auto lo = p.get_last_lo_pos();
+    expect(p, token::LPAREN);
+    auto discriminant = parse_expr(p);
+    expect(p, token::RPAREN);
+    expect(p, token::LBRACE);
+    let vec[ast::arm] arms = [];
+    while (p.peek() != token::RBRACE) {
+        if (eat_word(p, "case")) {
+            expect(p, token::LPAREN);
+            auto pat = parse_pat(p);
+            expect(p, token::RPAREN);
+            auto block = parse_block(p);
+            arms += [rec(pat=pat, block=block)];
+        } else if (p.peek() == token::RBRACE) {
+            /* empty */
+
+        } else {
+            p.fatal("expected 'case' or '}' when parsing 'alt' statement " +
+                      "but found " + token::to_str(p.get_reader(), p.peek()));
+        }
+    }
+    auto hi = p.get_hi_pos();
+    p.bump();
+    ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms));
+}
+
+fn parse_spawn_expr(&parser p) -> @ast::expr {
+    auto lo = p.get_last_lo_pos();
+    // FIXME: Parse domain and name
+    // FIXME: why no full expr?
+
+    auto fn_expr = parse_bottom_expr(p);
+    auto es =
+        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
+                  parse_expr, p);
+    auto hi = es.span.hi;
+    ret mk_expr(p, lo, hi, ast::expr_spawn
+                (ast::dom_implicit, option::none, fn_expr, es.node));
+}
+
+fn parse_expr(&parser p) -> @ast::expr {
+    ret parse_expr_res(p, UNRESTRICTED);
+}
+
+fn parse_expr_res(&parser p, restriction r) -> @ast::expr {
+    auto old = p.get_restriction();
+    p.restrict(r);
+    auto e = parse_assign_expr(p);
+    p.restrict(old);
+    ret e;
+}
+
+fn parse_initializer(&parser p) -> option::t[ast::initializer] {
+    alt (p.peek()) {
+        case (token::EQ) {
+            p.bump();
+            ret some(rec(op=ast::init_assign, expr=parse_expr(p)));
+        }
+        case (token::LARROW) {
+            p.bump();
+            ret some(rec(op=ast::init_move, expr=parse_expr(p)));
+        }
+        case (
+             // Now that the the channel is the first argument to receive,
+             // combining it with an initializer doesn't really make sense.
+             // case (token::RECV) {
+             //     p.bump();
+             //     ret some(rec(op = ast::init_recv,
+             //                  expr = parse_expr(p)));
+             // }
+             _) {
+            ret none;
+        }
+    }
+}
+
+fn parse_pat(&parser p) -> @ast::pat {
+    auto lo = p.get_lo_pos();
+    auto hi = p.get_hi_pos();
+    auto pat;
+    alt (p.peek()) {
+        case (token::UNDERSCORE) {
+            p.bump();
+            pat = ast::pat_wild;
+        }
+        case (token::QUES) {
+            p.bump();
+            alt (p.peek()) {
+                case (token::IDENT(?id, _)) {
+                    hi = p.get_hi_pos();
+                    p.bump();
+                    pat = ast::pat_bind(p.get_str(id));
+                }
+                case (?tok) {
+                    p.fatal("expected identifier after '?' in pattern but " +
+                              "found " + token::to_str(p.get_reader(), tok));
+                    fail;
+                }
+            }
+        }
+        case (?tok) {
+            if (!is_ident(tok) || is_word(p, "true") || is_word(p, "false")) {
+                auto lit = parse_lit(p);
+                hi = lit.span.hi;
+                pat = ast::pat_lit(@lit);
+            } else {
+                auto tag_path = parse_path_and_ty_param_substs(p);
+                hi = tag_path.span.hi;
+                let vec[@ast::pat] args;
+                alt (p.peek()) {
+                    case (token::LPAREN) {
+                        auto f = parse_pat;
+                        auto a =
+                            parse_seq(token::LPAREN, token::RPAREN,
+                                      some(token::COMMA), f, p);
+                        args = a.node;
+                        hi = a.span.hi;
+                    }
+                    case (_) { args = []; }
+                }
+                pat = ast::pat_tag(tag_path, args);
+            }
+        }
+    }
+    ret @rec(id=p.get_id(), node=pat, span=rec(lo=lo, hi=hi));
+}
+
+fn parse_local_full(&option::t[@ast::ty] tyopt, &parser p)
+    -> @ast::local {
+    auto lo = p.get_lo_pos();
+    auto ident = parse_value_ident(p);
+    auto init = parse_initializer(p);
+    ret @spanned(lo, p.get_hi_pos(),
+                 rec(ty=tyopt,
+                     infer=false,
+                     ident=ident,
+                     init=init,
+                     id=p.get_id()));
+}
+
+fn parse_typed_local(&parser p) -> @ast::local {
+    auto ty = parse_ty(p);
+    ret parse_local_full(some(ty), p);
+}
+
+fn parse_auto_local(&parser p) -> @ast::local {
+    ret parse_local_full(none, p);
+}
+
+fn parse_let(&parser p) -> @ast::decl {
+    auto lo = p.get_last_lo_pos();
+    auto local = parse_typed_local(p);
+    ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local));
+}
+
+fn parse_auto(&parser p) -> @ast::decl {
+    auto lo = p.get_last_lo_pos();
+    auto local = parse_auto_local(p);
+    ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local));
+}
+
+fn parse_stmt(&parser p) -> @ast::stmt {
+    if (p.get_file_type() == SOURCE_FILE) {
+        ret parse_source_stmt(p);
+    } else { ret parse_crate_stmt(p); }
+}
+
+fn parse_crate_stmt(&parser p) -> @ast::stmt {
+    auto cdir = parse_crate_directive(p, []);
+    ret @spanned(cdir.span.lo, cdir.span.hi,
+                 ast::stmt_crate_directive(@cdir));
+}
+
+fn parse_source_stmt(&parser p) -> @ast::stmt {
+    auto lo = p.get_lo_pos();
+    if (eat_word(p, "let")) {
+        auto decl = parse_let(p);
+        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
+    } else if (eat_word(p, "auto")) {
+        auto decl = parse_auto(p);
+        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
+    } else {
+
+        auto item_attrs;
+        alt (parse_outer_attrs_or_ext(p)) {
+            case (none) {
+                item_attrs = [];
+            }
+            case (some(left(?attrs))) {
+                item_attrs = attrs;
+            }
+            case (some(right(?ext))) {
+                ret @spanned(lo, ext.span.hi,
+                             ast::stmt_expr(ext, p.get_id()));
+            }
+        }
+
+        auto maybe_item = parse_item(p, item_attrs);
+
+        // If we have attributes then we should have an item
+        if (vec::len(item_attrs) > 0u) {
+            alt (maybe_item) {
+                case (got_item(_)) { /* fallthrough */ }
+                case (_) {
+                    ret p.fatal("expected item");
+                }
+            }
+        }
+
+        alt (maybe_item) {
+            case (got_item(?i)) {
+                auto hi = i.span.hi;
+                auto decl = @spanned(lo, hi, ast::decl_item(i));
+                ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_id()));
+            }
+            case (fn_no_item) { // parse_item will have already skipped "fn"
+
+                auto e = parse_fn_expr(p);
+                e = parse_dot_or_call_expr_with(p, e);
+                ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
+            }
+            case (no_item) {
+                // Remainder are line-expr stmts.
+
+                auto e = parse_expr(p);
+                ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
+            }
+        }
+    }
+    p.fatal("expected statement");
+    fail;
+}
+
+fn stmt_to_expr(@ast::stmt stmt) -> option::t[@ast::expr] {
+    ret alt (stmt.node) {
+            case (ast::stmt_expr(?e, _)) { some(e) }
+            case (_) { none }
+        };
+}
+
+fn stmt_ends_with_semi(&ast::stmt stmt) -> bool {
+    alt (stmt.node) {
+        case (ast::stmt_decl(?d, _)) {
+            ret alt (d.node) {
+                case (ast::decl_local(_)) { true }
+                case (ast::decl_item(_)) { false }
+            }
+        }
+        case (ast::stmt_expr(?e, _)) {
+            ret alt (e.node) {
+                case (ast::expr_vec(_, _, _)) { true }
+                case (ast::expr_tup(_)) { true }
+                case (ast::expr_rec(_, _)) { true }
+                case (ast::expr_call(_, _)) { true }
+                case (ast::expr_self_method(_)) { false }
+                case (ast::expr_bind(_, _)) { true }
+                case (ast::expr_spawn(_, _, _, _)) { true }
+                case (ast::expr_binary(_, _, _)) { true }
+                case (ast::expr_unary(_, _)) { true }
+                case (ast::expr_lit(_)) { true }
+                case (ast::expr_cast(_, _)) { true }
+                case (ast::expr_if(_, _, _)) { false }
+                case (ast::expr_ternary(_, _, _)) { true }
+                case (ast::expr_for(_, _, _)) { false }
+                case (ast::expr_for_each(_, _, _)) { false }
+                case (ast::expr_while(_, _)) { false }
+                case (ast::expr_do_while(_, _)) { false }
+                case (ast::expr_alt(_, _)) { false }
+                case (ast::expr_fn(_)) { false }
+                case (ast::expr_block(_)) { false }
+                case (ast::expr_move(_, _)) { true }
+                case (ast::expr_assign(_, _)) { true }
+                case (ast::expr_swap(_, _)) { true }
+                case (ast::expr_assign_op(_, _, _)) { true }
+                case (ast::expr_send(_, _)) { true }
+                case (ast::expr_recv(_, _)) { true }
+                case (ast::expr_field(_, _)) { true }
+                case (ast::expr_index(_, _)) { true }
+                case (ast::expr_path(_)) { true }
+                case (ast::expr_ext(_, _, _, _)) { true }
+                case (ast::expr_fail(_)) { true }
+                case (ast::expr_break) { true }
+                case (ast::expr_cont) { true }
+                case (ast::expr_ret(_)) { true }
+                case (ast::expr_put(_)) { true }
+                case (ast::expr_be(_)) { true }
+                case (ast::expr_log(_, _)) { true }
+                case (ast::expr_check(_, _)) { true }
+                case (ast::expr_if_check(_, _, _)) { false }
+                case (ast::expr_port(_)) { true }
+                case (ast::expr_chan(_)) { true }
+                case (ast::expr_anon_obj(_,_,_)) { false }
+                case (ast::expr_assert(_)) { true }
+            }
+        }
+        // We should not be calling this on a cdir.
+        case (ast::stmt_crate_directive(?cdir)) {
+            fail;
+        }
+    }
+}
+
+fn parse_block(&parser p) -> ast::block {
+    auto lo = p.get_lo_pos();
+    let vec[@ast::stmt] stmts = [];
+    let option::t[@ast::expr] expr = none;
+    expect(p, token::LBRACE);
+    while (p.peek() != token::RBRACE) {
+        alt (p.peek()) {
+            case (token::SEMI) {
+                p.bump(); // empty
+            }
+            case (_) {
+                auto stmt = parse_stmt(p);
+                alt (stmt_to_expr(stmt)) {
+                    case (some(?e)) {
+                        alt (p.peek()) {
+                            case (token::SEMI) { p.bump(); stmts += [stmt]; }
+                            case (token::RBRACE) { expr = some(e); }
+                            case (?t) {
+                                if (stmt_ends_with_semi(*stmt)) {
+                                    p.fatal("expected ';' or '}' after " +
+                                              "expression but found " +
+                                              token::to_str(p.get_reader(),
+                                                            t));
+                                    fail;
+                                }
+                                stmts += [stmt];
+                            }
+                        }
+                    }
+                    case (none) {
+                        // Not an expression statement.
+                        stmts += [stmt];
+
+                        if (p.get_file_type() == SOURCE_FILE
+                            && stmt_ends_with_semi(*stmt)) {
+                            expect(p, token::SEMI);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    auto hi = p.get_hi_pos();
+    p.bump();
+    auto bloc = rec(stmts=stmts, expr=expr, id=p.get_id());
+    ret spanned(lo, hi, bloc);
+}
+
+fn parse_ty_param(&parser p) -> ast::ty_param { ret parse_ident(p); }
+
+fn parse_ty_params(&parser p) -> vec[ast::ty_param] {
+    let vec[ast::ty_param] ty_params = [];
+    if (p.peek() == token::LBRACKET) {
+        ty_params =
+            parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA),
+                      parse_ty_param, p).node;
+    }
+    ret ty_params;
+}
+
+fn parse_fn_decl(&parser p, ast::purity purity) -> ast::fn_decl {
+    let ast::spanned[vec[ast::arg]] inputs =
+        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_arg,
+                  p);
+    let ty_or_bang rslt;
+    auto constrs = parse_constrs(inputs.node, p).node;
+    if (p.peek() == token::RARROW) {
+        p.bump();
+        rslt = parse_ty_or_bang(p);
+    } else {
+        rslt = a_ty(@spanned(inputs.span.lo, inputs.span.hi, ast::ty_nil));
+    }
+    alt (rslt) {
+        case (a_ty(?t)) {
+            ret rec(inputs=inputs.node,
+                    output=t,
+                    purity=purity,
+                    cf=ast::return,
+                    constraints=constrs);
+        }
+        case (a_bang) {
+            ret rec(inputs=inputs.node,
+                    output=@spanned(p.get_lo_pos(), p.get_hi_pos(),
+                                    ast::ty_bot),
+                    purity=purity,
+                    cf=ast::noreturn,
+                    constraints=constrs);
+        }
+    }
+}
+
+fn parse_fn(&parser p, ast::proto proto, ast::purity purity) -> ast::_fn {
+    auto decl = parse_fn_decl(p, purity);
+    auto body = parse_block(p);
+    ret rec(decl=decl, proto=proto, body=body);
+}
+
+fn parse_fn_header(&parser p) -> tup(ast::ident, vec[ast::ty_param]) {
+    auto id = parse_value_ident(p);
+    auto ty_params = parse_ty_params(p);
+    ret tup(id, ty_params);
+}
+
+fn mk_item(&parser p, uint lo, uint hi, &ast::ident ident, &ast::item_ node,
+           &vec[ast::attribute] attrs) -> @ast::item {
+    ret @rec(ident=ident,
+             attrs=attrs,
+             id=p.get_id(),
+             node=node,
+             span=rec(lo=lo, hi=hi));
+}
+
+fn parse_item_fn_or_iter(&parser p, ast::purity purity, ast::proto proto,
+                         vec[ast::attribute] attrs) -> @ast::item {
+    auto lo = p.get_last_lo_pos();
+    auto t = parse_fn_header(p);
+    auto f = parse_fn(p, proto, purity);
+    ret mk_item(p, lo, f.body.span.hi, t._0, ast::item_fn(f, t._1), attrs);
+}
+
+fn parse_obj_field(&parser p) -> ast::obj_field {
+    auto mut = parse_mutability(p);
+    auto ty = parse_ty(p);
+    auto ident = parse_value_ident(p);
+    ret rec(mut=mut, ty=ty, ident=ident, id=p.get_id());
+}
+
+fn parse_anon_obj_field(&parser p) -> ast::anon_obj_field {
+    auto mut = parse_mutability(p);
+    auto ty = parse_ty(p);
+    auto ident = parse_value_ident(p);
+    expect(p, token::EQ);
+    auto expr = parse_expr(p);
+    ret rec(mut=mut, ty=ty, expr=expr, ident=ident, id=p.get_id());
+}
+
+fn parse_method(&parser p) -> @ast::method {
+    auto lo = p.get_lo_pos();
+    auto proto = parse_proto(p);
+    auto ident = parse_value_ident(p);
+    auto f = parse_fn(p, proto, ast::impure_fn);
+    auto meth = rec(ident=ident, meth=f, id=p.get_id());
+    ret @spanned(lo, f.body.span.hi, meth);
+}
+
+fn parse_dtor(&parser p) -> @ast::method {
+    auto lo = p.get_last_lo_pos();
+    let ast::block b = parse_block(p);
+    let vec[ast::arg] inputs = [];
+    let @ast::ty output = @spanned(lo, lo, ast::ty_nil);
+    let ast::fn_decl d =
+        rec(inputs=inputs,
+            output=output,
+            purity=ast::impure_fn,
+            cf=ast::return,
+
+            // I guess dtors can't have constraints? 
+            constraints=[]);
+    let ast::_fn f = rec(decl=d, proto=ast::proto_fn, body=b);
+    let ast::method_ m =
+        rec(ident="drop", meth=f, id=p.get_id());
+    ret @spanned(lo, f.body.span.hi, m);
+}
+
+fn parse_item_obj(&parser p, ast::layer lyr, vec[ast::attribute] attrs) ->
+   @ast::item {
+    auto lo = p.get_last_lo_pos();
+    auto ident = parse_value_ident(p);
+    auto ty_params = parse_ty_params(p);
+    let ast::spanned[vec[ast::obj_field]] fields =
+        parse_seq[ast::obj_field](token::LPAREN, token::RPAREN,
+                                  some(token::COMMA), parse_obj_field, p);
+    let vec[@ast::method] meths = [];
+    let option::t[@ast::method] dtor = none;
+    expect(p, token::LBRACE);
+    while (p.peek() != token::RBRACE) {
+        if (eat_word(p, "drop")) {
+            dtor = some(parse_dtor(p));
+        } else { vec::push(meths, parse_method(p)); }
+    }
+    auto hi = p.get_hi_pos();
+    expect(p, token::RBRACE);
+    let ast::_obj ob = rec(fields=fields.node, methods=meths, dtor=dtor);
+    ret mk_item(p, lo, hi, ident, ast::item_obj(ob, ty_params,
+                                                p.get_id()), attrs);
+}
+
+fn parse_item_res(&parser p, ast::layer lyr, vec[ast::attribute] attrs) ->
+   @ast::item {
+    auto lo = p.get_last_lo_pos();
+    auto ident = parse_value_ident(p);
+    auto ty_params = parse_ty_params(p);
+    expect(p, token::LPAREN);
+    auto t = parse_ty(p);
+    auto arg_ident = parse_value_ident(p);
+    expect(p, token::RPAREN);
+    auto dtor = parse_block(p);
+    auto decl = rec(inputs=[rec(mode=ast::alias(false), ty=t, ident=arg_ident,
+                                id=p.get_id())],
+                    output=@spanned(lo, lo, ast::ty_nil),
+                    purity=ast::impure_fn,
+                    cf=ast::return,
+                    constraints=[]);
+    auto f = rec(decl=decl, proto=ast::proto_fn, body=dtor);
+    ret mk_item(p, lo, dtor.span.hi, ident,
+                ast::item_res(f, p.get_id(), ty_params, p.get_id()), attrs);
+}
+
+fn parse_mod_items(&parser p, token::token term,
+                   vec[ast::attribute] first_item_attrs) -> ast::_mod {
+    auto view_items = if (vec::len(first_item_attrs) == 0u) {
+        parse_view(p)
+    } else {
+        // Shouldn't be any view items since we've already parsed an item attr
+        []
+    };
+    let vec[@ast::item] items = [];
+    auto initial_attrs = first_item_attrs;
+    while (p.peek() != term) {
+        auto attrs = initial_attrs + parse_outer_attributes(p);
+        initial_attrs = [];
+        alt (parse_item(p, attrs)) {
+            case (got_item(?i)) { vec::push(items, i); }
+            case (_) {
+                p.fatal("expected item but found " +
+                          token::to_str(p.get_reader(), p.peek()));
+            }
+        }
+    }
+    ret rec(view_items=view_items, items=items);
+}
+
+fn parse_item_const(&parser p, vec[ast::attribute] attrs) -> @ast::item {
+    auto lo = p.get_last_lo_pos();
+    auto ty = parse_ty(p);
+    auto id = parse_value_ident(p);
+    expect(p, token::EQ);
+    auto e = parse_expr(p);
+    auto hi = p.get_hi_pos();
+    expect(p, token::SEMI);
+    ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
+}
+
+fn parse_item_mod(&parser p, vec[ast::attribute] attrs) -> @ast::item {
+    auto lo = p.get_last_lo_pos();
+    auto id = parse_ident(p);
+    expect(p, token::LBRACE);
+    auto inner_attrs = parse_inner_attrs_and_next(p);
+    auto first_item_outer_attrs = inner_attrs._1;
+    auto m = parse_mod_items(p, token::RBRACE,
+                             first_item_outer_attrs);
+    auto hi = p.get_hi_pos();
+    expect(p, token::RBRACE);
+    ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs._0);
+}
+
+fn parse_item_native_type(&parser p) -> @ast::native_item {
+    auto t = parse_type_decl(p);
+    auto hi = p.get_hi_pos();
+    expect(p, token::SEMI);
+    ret @rec(ident=t._1,
+             node=ast::native_item_ty,
+             id=p.get_id(),
+             span=rec(lo=t._0, hi=hi));
+}
+
+fn parse_item_native_fn(&parser p) -> @ast::native_item {
+    auto lo = p.get_last_lo_pos();
+    auto t = parse_fn_header(p);
+    auto decl = parse_fn_decl(p, ast::impure_fn);
+    auto link_name = none;
+    if (p.peek() == token::EQ) {
+        p.bump();
+        link_name = some(parse_str(p));
+    }
+    auto hi = p.get_hi_pos();
+    expect(p, token::SEMI);
+    ret @rec(ident=t._0,
+             node=ast::native_item_fn(link_name, decl, t._1),
+             id=p.get_id(),
+             span=rec(lo=lo, hi=hi));
+}
+
+fn parse_native_item(&parser p) -> @ast::native_item {
+    parse_layer(p);
+    if (eat_word(p, "type")) {
+        ret parse_item_native_type(p);
+    } else if (eat_word(p, "fn")) {
+        ret parse_item_native_fn(p);
+    } else { unexpected(p, p.peek()); fail; }
+}
+
+fn parse_native_mod_items(&parser p, &str native_name, ast::native_abi abi) ->
+   ast::native_mod {
+    let vec[@ast::native_item] items = [];
+    auto view_items = parse_native_view(p);
+    while (p.peek() != token::RBRACE) { items += [parse_native_item(p)]; }
+    ret rec(native_name=native_name,
+            abi=abi,
+            view_items=view_items,
+            items=items);
+}
+
+fn parse_item_native_mod(&parser p, vec[ast::attribute] attrs) -> @ast::item {
+    auto lo = p.get_last_lo_pos();
+    auto abi = ast::native_abi_cdecl;
+    if (!is_word(p, "mod")) {
+        auto t = parse_str(p);
+        if (str::eq(t, "cdecl")) {
+        } else if (str::eq(t, "rust")) {
+            abi = ast::native_abi_rust;
+        } else if (str::eq(t, "llvm")) {
+            abi = ast::native_abi_llvm;
+        } else if (str::eq(t, "rust-intrinsic")) {
+            abi = ast::native_abi_rust_intrinsic;
+        } else { p.fatal("unsupported abi: " + t); fail; }
+    }
+    expect_word(p, "mod");
+    auto id = parse_ident(p);
+    auto native_name;
+    if (p.peek() == token::EQ) {
+        expect(p, token::EQ);
+        native_name = parse_str(p);
+    } else {
+        native_name = id;
+    }
+    expect(p, token::LBRACE);
+    auto m = parse_native_mod_items(p, native_name, abi);
+    auto hi = p.get_hi_pos();
+    expect(p, token::RBRACE);
+    ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs);
+}
+
+fn parse_type_decl(&parser p) -> tup(uint, ast::ident) {
+    auto lo = p.get_last_lo_pos();
+    auto id = parse_ident(p);
+    ret tup(lo, id);
+}
+
+fn parse_item_type(&parser p, vec[ast::attribute] attrs) -> @ast::item {
+    auto t = parse_type_decl(p);
+    auto tps = parse_ty_params(p);
+    expect(p, token::EQ);
+    auto ty = parse_ty(p);
+    auto hi = p.get_hi_pos();
+    expect(p, token::SEMI);
+    ret mk_item(p, t._0, hi, t._1, ast::item_ty(ty, tps), attrs);
+}
+
+fn parse_item_tag(&parser p, vec[ast::attribute] attrs) -> @ast::item {
+    auto lo = p.get_last_lo_pos();
+    auto id = parse_ident(p);
+    auto ty_params = parse_ty_params(p);
+    let vec[ast::variant] variants = [];
+    // Newtype syntax
+    if (p.peek() == token::EQ) {
+        if (p.get_bad_expr_words().contains_key(id)) {
+            p.fatal("found " + id + " in tag constructor position");
+        }
+        p.bump();
+        auto ty = parse_ty(p);
+        expect(p, token::SEMI);
+        auto variant = spanned(ty.span.lo, ty.span.hi,
+                               rec(name=id,
+                                   args=[rec(ty=ty, id=p.get_id())],
+                                   id=p.get_id()));
+        ret mk_item(p, lo, ty.span.hi, id,
+                    ast::item_tag([variant], ty_params), attrs);
+    }
+    expect(p, token::LBRACE);
+    while (p.peek() != token::RBRACE) {
+        auto tok = p.peek();
+        alt (tok) {
+            case (token::IDENT(?name, _)) {
+                check_bad_word(p);
+                auto vlo = p.get_lo_pos();
+                p.bump();
+                let vec[ast::variant_arg] args = [];
+                alt (p.peek()) {
+                    case (token::LPAREN) {
+                        auto arg_tys =
+                            parse_seq(token::LPAREN, token::RPAREN,
+                                      some(token::COMMA), parse_ty, p);
+                        for (@ast::ty ty in arg_tys.node) {
+                            args += [rec(ty=ty, id=p.get_id())];
+                        }
+                    }
+                    case (_) {/* empty */ }
+                }
+                auto vhi = p.get_hi_pos();
+                expect(p, token::SEMI);
+                p.get_id();
+                auto vr =
+                    rec(name=p.get_str(name),
+                        args=args,
+                        id=p.get_id());
+                variants += [spanned(vlo, vhi, vr)];
+            }
+            case (token::RBRACE) {/* empty */ }
+            case (_) {
+                p.fatal("expected name of variant or '}' but found " +
+                          token::to_str(p.get_reader(), tok));
+            }
+        }
+    }
+    auto hi = p.get_hi_pos();
+    p.bump();
+    ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs);
+}
+
+fn parse_layer(&parser p) -> ast::layer {
+    if (eat_word(p, "state")) {
+        ret ast::layer_state;
+    } else if (eat_word(p, "gc")) {
+        ret ast::layer_gc;
+    } else { ret ast::layer_value; }
+    fail;
+}
+
+fn parse_auth(&parser p) -> ast::_auth {
+    if (eat_word(p, "unsafe")) {
+        ret ast::auth_unsafe;
+    } else { unexpected(p, p.peek()); }
+    fail;
+}
+
+tag parsed_item { got_item(@ast::item); no_item; fn_no_item; }
+
+fn parse_item(&parser p, vec[ast::attribute] attrs) -> parsed_item {
+    if (eat_word(p, "const")) {
+        ret got_item(parse_item_const(p, attrs));
+    } else if (eat_word(p, "fn")) {
+        // This is an anonymous function
+
+        if (p.peek() == token::LPAREN) { ret fn_no_item; }
+        ret got_item(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_fn,
+                                           attrs));
+    } else if (eat_word(p, "pred")) {
+        ret got_item(parse_item_fn_or_iter(p, ast::pure_fn, ast::proto_fn,
+                                           attrs));
+    } else if (eat_word(p, "iter")) {
+        ret got_item(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_iter,
+                                           attrs));
+    } else if (eat_word(p, "mod")) {
+        ret got_item(parse_item_mod(p, attrs));
+    } else if (eat_word(p, "native")) {
+        ret got_item(parse_item_native_mod(p, attrs));
+    }
+    auto lyr = parse_layer(p);
+    if (eat_word(p, "type")) {
+        ret got_item(parse_item_type(p, attrs));
+    } else if (eat_word(p, "tag")) {
+        ret got_item(parse_item_tag(p, attrs));
+    } else if (eat_word(p, "obj")) {
+        ret got_item(parse_item_obj(p, lyr, attrs));
+    } else if (eat_word(p, "resource")) {
+        ret got_item(parse_item_res(p, lyr, attrs));
+    } else { ret no_item; }
+}
+
+// A type to distingush between the parsing of item attributes or syntax
+// extensions, which both begin with token.POUND
+type attr_or_ext = option::t[either::t[vec[ast::attribute],
+                                       @ast::expr]];
+
+fn parse_outer_attrs_or_ext(&parser p) -> attr_or_ext {
+    if (p.peek() == token::POUND) {
+        auto lo = p.get_lo_pos();
+        p.bump();
+        if (p.peek() == token::LBRACKET) {
+            auto first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
+            ret some(left([first_attr] + parse_outer_attributes(p)));
+        } else {
+            ret some(right(parse_syntax_ext_naked(p, lo)));
+        }
+    } else {
+        ret none;
+    }
+}
+
+// Parse attributes that appear before an item
+fn parse_outer_attributes(&parser p) -> vec[ast::attribute] {
+    let vec[ast::attribute] attrs = [];
+    while (p.peek() == token::POUND) {
+        attrs += [parse_attribute(p, ast::attr_outer)];
+    }
+    ret attrs;
+}
+
+fn parse_attribute(&parser p, ast::attr_style style) -> ast::attribute {
+    auto lo = p.get_lo_pos();
+    expect(p, token::POUND);
+    ret parse_attribute_naked(p, style, lo);
+}
+
+fn parse_attribute_naked(&parser p, ast::attr_style style,
+                         uint lo) -> ast::attribute {
+    expect(p, token::LBRACKET);
+    auto meta_item = parse_meta_item(p);
+    expect(p, token::RBRACKET);
+    auto hi = p.get_hi_pos();
+    ret spanned(lo, hi, rec(style=style, value=*meta_item));
+}
+
+// Parse attributes that appear after the opening of an item, each terminated
+// by a semicolon. In addition to a vector of inner attributes, this function
+// also returns a vector that may contain the first outer attribute of the
+// next item (since we can't know whether the attribute is an inner attribute
+// of the containing item or an outer attribute of the first contained item
+// until we see the semi).
+fn parse_inner_attrs_and_next(&parser p) -> tup(vec[ast::attribute],
+                                                vec[ast::attribute]) {
+    let vec[ast::attribute] inner_attrs = [];
+    let vec[ast::attribute] next_outer_attrs = [];
+    while (p.peek() == token::POUND) {
+        auto attr = parse_attribute(p, ast::attr_inner);
+        if (p.peek() == token::SEMI) {
+            p.bump();
+            inner_attrs += [attr];
+        } else {
+            // It's not really an inner attribute
+            auto outer_attr = spanned(attr.span.lo,
+                                      attr.span.hi,
+                                      rec(style=ast::attr_outer,
+                                          value=attr.node.value));
+            next_outer_attrs += [outer_attr];
+            break;
+        }
+    }
+    ret tup(inner_attrs, next_outer_attrs);
+}
+
+fn parse_meta_item(&parser p) -> @ast::meta_item {
+    auto lo = p.get_lo_pos();
+    auto ident = parse_ident(p);
+    alt (p.peek()) {
+        case (token::EQ) {
+            p.bump();
+            alt (p.peek()) {
+                case (token::LIT_STR(?s)) {
+                    p.bump();
+                    auto value = p.get_str(s);
+                    auto hi = p.get_hi_pos();
+                    ret @spanned(lo, hi, ast::meta_name_value(ident, value));
+                }
+                case (_) {
+                    p.fatal("Metadata items must be string literals");
+                }
+            }
+        }
+        case (token::LPAREN) {
+            auto inner_items = parse_meta_seq(p);
+            auto hi = p.get_hi_pos();
+            ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
+        }
+        case (_) {
+            auto hi = p.get_hi_pos();
+            ret @spanned(lo, hi, ast::meta_word(ident));
+        }
+    }
+}
+
+fn parse_meta_seq(&parser p) -> vec[@ast::meta_item] {
+    ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
+                  parse_meta_item, p).node;
+}
+
+fn parse_optional_meta(&parser p) -> vec[@ast::meta_item] {
+    alt (p.peek()) {
+        case (token::LPAREN) { ret parse_meta_seq(p); }
+        case (_) { let vec[@ast::meta_item] v = []; ret v; }
+    }
+}
+
+fn parse_use(&parser p) -> @ast::view_item {
+    auto lo = p.get_last_lo_pos();
+    auto ident = parse_ident(p);
+    auto metadata = parse_optional_meta(p);
+    auto hi = p.get_hi_pos();
+    expect(p, token::SEMI);
+    auto use_decl =
+        ast::view_item_use(ident, metadata, p.get_id());
+    ret @spanned(lo, hi, use_decl);
+}
+
+fn parse_rest_import_name(&parser p, ast::ident first,
+                          option::t[ast::ident] def_ident) ->
+   @ast::view_item {
+    auto lo = p.get_lo_pos();
+    let vec[ast::ident] identifiers = [first];
+    let bool glob = false;
+    while (true) {
+        alt (p.peek()) {
+            case (token::SEMI) { p.bump(); break; }
+            case (token::MOD_SEP) {
+                if (glob) { p.fatal("cannot path into a glob"); }
+                p.bump();
+            }
+            case (_) { p.fatal("expecting '::' or ';'"); }
+        }
+        alt (p.peek()) {
+            case (token::IDENT(_, _)) { identifiers += [parse_ident(p)]; }
+            case (
+                 //the lexer can't tell the different kinds of stars apart ) :
+                 token::BINOP(token::STAR)) {
+                glob = true;
+                p.bump();
+            }
+            case (_) { p.fatal("expecting an identifier, or '*'"); }
+        }
+    }
+    auto hi = p.get_hi_pos();
+    auto import_decl;
+    alt (def_ident) {
+        case (some(?i)) {
+            if (glob) { p.fatal("globbed imports can't be renamed"); }
+            import_decl =
+                ast::view_item_import(i, identifiers, p.get_id());
+        }
+        case (_) {
+            if (glob) {
+                import_decl =
+                    ast::view_item_import_glob(identifiers, p.get_id());
+            } else {
+                auto len = vec::len(identifiers);
+                import_decl =
+                    ast::view_item_import(identifiers.(len - 1u), identifiers,
+                                          p.get_id());
+            }
+        }
+    }
+    ret @spanned(lo, hi, import_decl);
+}
+
+fn parse_full_import_name(&parser p, ast::ident def_ident) ->
+   @ast::view_item {
+    alt (p.peek()) {
+        case (token::IDENT(?i, _)) {
+            p.bump();
+            ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
+        }
+        case (_) { p.fatal("expecting an identifier"); }
+    }
+    fail;
+}
+
+fn parse_import(&parser p) -> @ast::view_item {
+    alt (p.peek()) {
+        case (token::IDENT(?i, _)) {
+            p.bump();
+            alt (p.peek()) {
+                case (token::EQ) {
+                    p.bump();
+                    ret parse_full_import_name(p, p.get_str(i));
+                }
+                case (_) {
+                    ret parse_rest_import_name(p, p.get_str(i), none);
+                }
+            }
+        }
+        case (_) { p.fatal("expecting an identifier"); }
+    }
+    fail;
+}
+
+fn parse_export(&parser p) -> @ast::view_item {
+    auto lo = p.get_last_lo_pos();
+    auto id = parse_ident(p);
+    auto hi = p.get_hi_pos();
+    expect(p, token::SEMI);
+    ret @spanned(lo, hi, ast::view_item_export(id, p.get_id()));
+}
+
+fn parse_view_item(&parser p) -> @ast::view_item {
+    if (eat_word(p, "use")) {
+        ret parse_use(p);
+    } else if (eat_word(p, "import")) {
+        ret parse_import(p);
+    } else if (eat_word(p, "export")) { ret parse_export(p); } else { fail; }
+}
+
+fn is_view_item(&parser p) -> bool {
+    alt (p.peek()) {
+        case (token::IDENT(?sid, false)) {
+            auto st = p.get_str(sid);
+            ret str::eq(st, "use") || str::eq(st, "import") ||
+                    str::eq(st, "export");
+        }
+        case (_) { ret false; }
+    }
+    ret false;
+}
+
+fn parse_view(&parser p) -> vec[@ast::view_item] {
+    let vec[@ast::view_item] items = [];
+    while (is_view_item(p)) { items += [parse_view_item(p)]; }
+    ret items;
+}
+
+fn parse_native_view(&parser p) -> vec[@ast::view_item] {
+    let vec[@ast::view_item] items = [];
+    while (is_view_item(p)) { items += [parse_view_item(p)]; }
+    ret items;
+}
+
+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);
+    auto p = new_parser(sess, cfg, input, 0u);
+    auto lo = p.get_lo_pos();
+    auto crate_attrs = parse_inner_attrs_and_next(p);
+    auto first_item_outer_attrs = crate_attrs._1;
+    auto m = parse_mod_items(p, token::EOF,
+                             first_item_outer_attrs);
+    let vec[@ast::crate_directive] cdirs = [];
+    ret @spanned(lo, p.get_lo_pos(), rec(directives=cdirs,
+                                         module=m,
+                                         attrs=crate_attrs._0,
+                                         config=p.get_cfg()));
+}
+
+fn parse_str(&parser p) -> ast::ident {
+    alt (p.peek()) {
+        case (token::LIT_STR(?s)) {
+            p.bump();
+            ret p.get_str(s);
+        }
+        case (_) { fail; }
+    }
+}
+
+// Logic for parsing crate files (.rc)
+//
+// Each crate file is a sequence of directives.
+//
+// Each directive imperatively extends its environment with 0 or more items.
+fn parse_crate_directive(&parser p, vec[ast::attribute] first_outer_attr)
+    -> ast::crate_directive {
+
+    // Collect the next attributes
+    auto outer_attrs = first_outer_attr
+        + parse_outer_attributes(p);
+    // In a crate file outer attributes are only going to apply to mods
+    auto expect_mod = vec::len(outer_attrs) > 0u;
+
+    auto lo = p.get_lo_pos();
+    if (expect_mod || is_word(p, "mod")) {
+        expect_word(p, "mod");
+        auto id = parse_ident(p);
+        auto file_opt =
+            alt (p.peek()) {
+                case (token::EQ) {
+                    p.bump();
+                    some(parse_str(p))
+                }
+                case (_) { none }
+            };
+        alt (p.peek()) {
+            case (
+                 // mod x = "foo.rs";
+                 token::SEMI) {
+                auto hi = p.get_hi_pos();
+                p.bump();
+                ret spanned(lo, hi, ast::cdir_src_mod(id, file_opt,
+                                                      outer_attrs));
+            }
+            case (
+                 // mod x = "foo_dir" { ...directives... }
+                 token::LBRACE) {
+                p.bump();
+                auto inner_attrs = parse_inner_attrs_and_next(p);
+                auto mod_attrs = outer_attrs + inner_attrs._0;
+                auto next_outer_attr = inner_attrs._1;
+                auto cdirs = parse_crate_directives(p, token::RBRACE,
+                                                    next_outer_attr);
+                auto hi = p.get_hi_pos();
+                expect(p, token::RBRACE);
+                ret spanned(lo, hi, ast::cdir_dir_mod(id, file_opt, cdirs,
+                                                      mod_attrs));
+            }
+            case (?t) { unexpected(p, t); }
+        }
+    } else if (eat_word(p, "auth")) {
+        auto n = parse_path(p);
+        expect(p, token::EQ);
+        auto a = parse_auth(p);
+        auto hi = p.get_hi_pos();
+        expect(p, token::SEMI);
+        ret spanned(lo, hi, ast::cdir_auth(n, a));
+    } else if (is_view_item(p)) {
+        auto vi = parse_view_item(p);
+        ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
+    } else {
+        ret p.fatal("expected crate directive");
+    }
+}
+
+fn parse_crate_directives(&parser p, token::token term,
+                          vec[ast::attribute] first_outer_attr) ->
+   vec[@ast::crate_directive] {
+
+    // This is pretty ugly. If we have an outer attribute then we can't accept
+    // seeing the terminator next, so if we do see it then fail the same way
+    // parse_crate_directive would
+    if (vec::len(first_outer_attr) > 0u && p.peek() == term) {
+        expect_word(p, "mod");
+    }
+
+    let vec[@ast::crate_directive] cdirs = [];
+    while (p.peek() != term) {
+        auto cdir = @parse_crate_directive(p, first_outer_attr);
+        vec::push(cdirs, cdir);
+    }
+    ret cdirs;
+}
+
+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);
+    auto p = new_parser(sess, cfg, input, 0u);
+    auto lo = p.get_lo_pos();
+    auto prefix = std::fs::dirname(p.get_filemap().name);
+    auto leading_attrs = parse_inner_attrs_and_next(p);
+    auto crate_attrs = leading_attrs._0;
+    auto first_cdir_attr = leading_attrs._1;
+    auto cdirs = parse_crate_directives(p, token::EOF, first_cdir_attr);
+    let vec[str] deps = [];
+    auto cx = @rec(p=p,
+                   mode=eval::mode_parse,
+                   mutable deps=deps,
+                   sess=sess,
+                   mutable chpos=p.get_chpos(),
+                   cfg = p.get_cfg());
+    auto m =
+        eval::eval_crate_directives_to_mod(cx, cdirs, prefix);
+    auto hi = p.get_hi_pos();
+    expect(p, token::EOF);
+    ret @spanned(lo, hi, rec(directives=cdirs,
+                             module=m,
+                             attrs=crate_attrs,
+                             config=p.get_cfg()));
+}
+//
+// 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/parse/token.rs b/src/comp/syntax/parse/token.rs
new file mode 100644 (file)
index 0000000..b8ea07d
--- /dev/null
@@ -0,0 +1,202 @@
+
+import ast::ty_mach;
+import ast::ty_mach_to_str;
+import _std::new_str_hash;
+import util::interner;
+import std::int;
+import std::uint;
+import std::str;
+
+type str_num = uint;
+
+tag binop {
+    PLUS;
+    MINUS;
+    STAR;
+    SLASH;
+    PERCENT;
+    CARET;
+    AND;
+    OR;
+    LSL;
+    LSR;
+    ASR;
+}
+
+tag token {
+
+    /* Expression-operator symbols. */
+    EQ;
+    LT;
+    LE;
+    EQEQ;
+    NE;
+    GE;
+    GT;
+    ANDAND;
+    OROR;
+    NOT;
+    TILDE;
+    BINOP(binop);
+    BINOPEQ(binop);
+
+    /* Structural symbols */
+    AT;
+    DOT;
+    COMMA;
+    SEMI;
+    COLON;
+    MOD_SEP;
+    QUES;
+    RARROW;
+    SEND;
+    RECV;
+    LARROW;
+    DARROW;
+    LPAREN;
+    RPAREN;
+    LBRACKET;
+    RBRACKET;
+    LBRACE;
+    RBRACE;
+    POUND;
+
+    /* Literals */
+    LIT_INT(int);
+    LIT_UINT(uint);
+    LIT_MACH_INT(ty_mach, int);
+    LIT_FLOAT(str_num);
+    LIT_MACH_FLOAT(ty_mach, str_num);
+    LIT_STR(str_num);
+    LIT_CHAR(char);
+    LIT_BOOL(bool);
+
+    /* Name components */
+    IDENT(str_num, bool);
+    IDX(int);
+    UNDERSCORE;
+    BRACEQUOTE(str_num);
+    EOF;
+}
+
+fn binop_to_str(binop o) -> str {
+    alt (o) {
+        case (PLUS) { ret "+"; }
+        case (MINUS) { ret "-"; }
+        case (STAR) { ret "*"; }
+        case (SLASH) { ret "/"; }
+        case (PERCENT) { ret "%"; }
+        case (CARET) { ret "^"; }
+        case (AND) { ret "&"; }
+        case (OR) { ret "|"; }
+        case (LSL) { ret "<<"; }
+        case (LSR) { ret ">>"; }
+        case (ASR) { ret ">>>"; }
+    }
+}
+
+fn to_str(lexer::reader r, token t) -> str {
+    alt (t) {
+        case (EQ) { ret "="; }
+        case (LT) { ret "<"; }
+        case (LE) { ret "<="; }
+        case (EQEQ) { ret "=="; }
+        case (NE) { ret "!="; }
+        case (GE) { ret ">="; }
+        case (GT) { ret ">"; }
+        case (NOT) { ret "!"; }
+        case (TILDE) { ret "~"; }
+        case (OROR) { ret "||"; }
+        case (ANDAND) { ret "&&"; }
+        case (BINOP(?op)) { ret binop_to_str(op); }
+        case (BINOPEQ(?op)) { ret binop_to_str(op) + "="; }
+        case (
+             /* Structural symbols */
+             AT) {
+            ret "@";
+        }
+        case (DOT) { ret "."; }
+        case (COMMA) { ret ","; }
+        case (SEMI) { ret ";"; }
+        case (COLON) { ret ":"; }
+        case (MOD_SEP) { ret "::"; }
+        case (QUES) { ret "?"; }
+        case (RARROW) { ret "->"; }
+        case (SEND) { ret "<|"; }
+        case (RECV) { ret "|>"; }
+        case (LARROW) { ret "<-"; }
+        case (DARROW) { ret "<->"; }
+        case (LPAREN) { ret "("; }
+        case (RPAREN) { ret ")"; }
+        case (LBRACKET) { ret "["; }
+        case (RBRACKET) { ret "]"; }
+        case (LBRACE) { ret "{"; }
+        case (RBRACE) { ret "}"; }
+        case (POUND) { ret "#"; }
+        case (
+             /* Literals */
+             LIT_INT(?i)) {
+            ret int::to_str(i, 10u);
+        }
+        case (LIT_UINT(?u)) { ret uint::to_str(u, 10u); }
+        case (LIT_MACH_INT(?tm, ?i)) {
+            ret int::to_str(i, 10u) + "_" + ty_mach_to_str(tm);
+        }
+        case (LIT_MACH_FLOAT(?tm, ?s)) {
+            ret interner::get[str](*r.get_interner(), s) + "_" +
+                    ty_mach_to_str(tm);
+        }
+        case (LIT_FLOAT(?s)) { ret interner::get[str](*r.get_interner(), s); }
+        case (LIT_STR(?s)) {
+            // FIXME: escape.
+
+            ret "\"" + interner::get[str](*r.get_interner(), s) + "\"";
+        }
+        case (LIT_CHAR(?c)) {
+            // FIXME: escape.
+
+            auto tmp = "'";
+            str::push_char(tmp, c);
+            str::push_byte(tmp, '\'' as u8);
+            ret tmp;
+        }
+        case (LIT_BOOL(?b)) { if (b) { ret "true"; } else { ret "false"; } }
+        case (
+             /* Name components */
+             IDENT(?s, _)) {
+            ret interner::get[str](*r.get_interner(), s);
+        }
+        case (IDX(?i)) { ret "_" + int::to_str(i, 10u); }
+        case (UNDERSCORE) { ret "_"; }
+        case (BRACEQUOTE(_)) { ret "<bracequote>"; }
+        case (EOF) { ret "<eof>"; }
+    }
+}
+
+
+pred can_begin_expr(token t) -> bool {
+    alt (t) {
+        case (LPAREN) { true }
+        case (LBRACE) { true }
+        case (IDENT(_,_)) { true }
+        case (UNDERSCORE) { true }
+        case (TILDE) { true }
+        case (LIT_INT(_)) { true }
+        case (LIT_UINT(_)) { true }
+        case (LIT_MACH_INT(_,_)) { true }
+        case (LIT_FLOAT(_)) { true }
+        case (LIT_MACH_FLOAT(_,_)) { true }
+        case (LIT_STR(_)) { true }
+        case (LIT_CHAR(_)) { true }
+        case (POUND) { true }
+        case (AT) { true }
+        case (_) { false }
+    }
+}
+// Local Variables:
+// 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/print/pp.rs b/src/comp/syntax/print/pp.rs
new file mode 100644 (file)
index 0000000..ef3a875
--- /dev/null
@@ -0,0 +1,532 @@
+
+import std::io;
+import std::vec;
+import std::str;
+
+
+/*
+ * This pretty-printer is a direct reimplementation of Philip Karlton's
+ * Mesa pretty-printer, as described in appendix A of
+ *
+ *     STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen.
+ *     Stanford Department of Computer Science, 1979.
+ *
+ * The algorithm's aim is to break a stream into as few lines as possible
+ * while respecting the indentation-consistency requirements of the enclosing
+ * block, and avoiding breaking at silly places on block boundaries, for
+ * example, between "x" and ")" in "x)".
+ *
+ * I am implementing this algorithm because it comes with 20 pages of
+ * documentation explaining its theory, and because it addresses the set of
+ * concerns I've seen other pretty-printers fall down on. Weirdly. Even though
+ * it's 32 years old and not written in Haskell. What can I say?
+ *
+ * Despite some redundancies and quirks in the way it's implemented in that
+ * paper, I've opted to keep the implementation here as similar as I can,
+ * changing only what was blatantly wrong, a typo, or sufficiently
+ * non-idiomatic rust that it really stuck out.
+ *
+ * In particular you'll see a certain amount of churn related to INTEGER vs.
+ * CARDINAL in the Mesa implementation. Mesa apparently interconverts the two
+ * somewhat readily? In any case, I've used uint for indices-in-buffers and
+ * ints for character-sizes-and-indentation-offsets. This respects the need
+ * for ints to "go negative" while carrying a pending-calculation balance, and
+ * helps differentiate all the numbers flying around internally (slightly).
+ *
+ * I also inverted the indentation arithmetic used in the print stack, since
+ * the Mesa implementation (somewhat randomly) stores the offset on the print
+ * stack in terms of margin-col rather than col itself. I store col.
+ *
+ * I also implemented a small change in the STRING token, in that I store an
+ * explicit length for the string. For most tokens this is just the length of
+ * the accompanying string. But it's necessary to permit it to differ, for
+ * encoding things that are supposed to "go on their own line" -- certain
+ * classes of comment and blank-line -- where relying on adjacent
+ * hardbreak-like BREAK tokens with long blankness indication doesn't actually
+ * work. To see why, consider when there is a "thing that should be on its own
+ * line" between two long blocks, say functions. If you put a hardbreak after
+ * each function (or before each) and the breaking algorithm decides to break
+ * there anyways (because the functions themselves are long) you wind up with
+ * extra blank lines. If you don't put hardbreaks you can wind up with the
+ * "thing which should be on its own line" not getting its own line in the
+ * rare case of "really small functions" or such. This re-occurs with comments
+ * and explicit blank lines. So in those cases we use a string with a payload
+ * we want isolated to a line and an explicit length that's huge, surrounded
+ * by two zero-length breaks. The algorithm will try its best to fit it on a
+ * line (which it can't) and so naturally place the content on its own line to
+ * avoid combining it with other lines and making matters even worse.
+ */
+tag breaks { consistent; inconsistent; }
+
+type break_t = rec(int offset, int blank_space);
+
+type begin_t = rec(int offset, breaks breaks);
+
+tag token { STRING(str, int); BREAK(break_t); BEGIN(begin_t); END; EOF; }
+
+fn tok_str(token t) -> str {
+    alt (t) {
+        case (STRING(?s, ?len)) { ret #fmt("STR(%s,%d)", s, len); }
+        case (BREAK(_)) { ret "BREAK"; }
+        case (BEGIN(_)) { ret "BEGIN"; }
+        case (END) { ret "END"; }
+        case (EOF) { ret "EOF"; }
+    }
+}
+
+fn buf_str(vec[mutable token] toks, vec[mutable int] szs, uint left,
+           uint right, uint lim) -> str {
+    auto n = vec::len(toks);
+    assert (n == vec::len(szs));
+    auto i = left;
+    auto L = lim;
+    auto s = "[";
+    while (i != right && L != 0u) {
+        L -= 1u;
+        if (i != left) { s += ", "; }
+        s += #fmt("%d=%s", szs.(i), tok_str(toks.(i)));
+        i += 1u;
+        i %= n;
+    }
+    s += "]";
+    ret s;
+}
+
+tag print_stack_break { fits; broken(breaks); }
+
+type print_stack_elt = rec(int offset, print_stack_break pbreak);
+
+const int size_infinity = 0xffff;
+
+fn mk_printer(io::writer out, uint linewidth) -> printer {
+    // Yes 3, it makes the ring buffers big enough to never
+    // fall behind.
+
+    let uint n = 3u * linewidth;
+    log #fmt("mk_printer %u", linewidth);
+    let vec[mutable token] token = vec::init_elt_mut(EOF, n);
+    let vec[mutable int] size = vec::init_elt_mut(0, n);
+    let vec[mutable uint] scan_stack = vec::init_elt_mut(0u, n);
+    let vec[print_stack_elt] print_stack = [];
+    ret printer(out, n, linewidth as int, // margin
+                 linewidth as int, // space
+                 0u, // left
+                 0u, // right
+                 token, size, 0, // left_total
+                 0, // right_total
+                 scan_stack, true, // scan_stack_empty
+                 0u, // top
+                 0u, // bottom
+                 print_stack, 0);
+}
+
+
+/*
+ * In case you do not have the paper, here is an explanation of what's going
+ * on.
+ *
+ * There is a stream of input tokens flowing through this printer.
+ *
+ * The printer buffers up to 3N tokens inside itself, where N is linewidth.
+ * Yes, linewidth is chars and tokens are multi-char, but in the worst
+ * case every token worth buffering is 1 char long, so it's ok.
+ *
+ * Tokens are STRING, BREAK, and BEGIN/END to delimit blocks.
+ *
+ * BEGIN tokens can carry an offset, saying "how far to indent when you break
+ * inside here", as well as a flag indicating "consistent" or "inconsistent"
+ * breaking. Consistent breaking means that after the first break, no attempt
+ * will be made to flow subsequent breaks together onto lines. Inconsistent
+ * is the opposite. Inconsistent breaking example would be, say:
+ *
+ *  foo(hello, there, good, friends)
+ *
+ * breaking inconsistently to become
+ *
+ *  foo(hello, there
+ *      good, friends);
+ *
+ * whereas a consistent breaking would yield:
+ *
+ *  foo(hello,
+ *      there
+ *      good,
+ *      friends);
+ *
+ * That is, in the consistent-break blocks we value vertical alignment
+ * more than the ability to cram stuff onto a line. But in all cases if it
+ * can make a block a one-liner, it'll do so.
+ *
+ * Carrying on with high-level logic:
+ *
+ * The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and
+ * 'right' indices denote the active portion of the ring buffer as well as
+ * describing hypothetical points-in-the-infinite-stream at most 3N tokens
+ * apart (i.e. "not wrapped to ring-buffer boundaries"). The paper will switch
+ * between using 'left' and 'right' terms to denote the wrapepd-to-ring-buffer
+ * and point-in-infinite-stream senses freely.
+ *
+ * There is a parallel ring buffer, 'size', that holds the calculated size of
+ * each token. Why calculated? Because for BEGIN/END pairs, the "size"
+ * includes everything betwen the pair. That is, the "size" of BEGIN is
+ * actually the sum of the sizes of everything between BEGIN and the paired
+ * END that follows. Since that is arbitrarily far in the future, 'size' is
+ * being rewritten regularly while the printer runs; in fact most of the
+ * machinery is here to work out 'size' entries on the fly (and give up when
+ * they're so obviously over-long that "infinity" is a good enough
+ * approximation for purposes of line breaking).
+ *
+ * The "input side" of the printer is managed as an abstract process called
+ * SCAN, which uses 'scan_stack', 'scan_stack_empty', 'top' and 'bottom', to
+ * manage calculating 'size'. SCAN is, in other words, the process of
+ * calculating 'size' entries.
+ *
+ * The "output side" of the printer is managed by an abstract process called
+ * PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to
+ * do with each token/size pair it consumes as it goes. It's trying to consume
+ * the entire buffered window, but can't output anything until the size is >=
+ * 0 (sizes are set to negative while they're pending calculation).
+ *
+ * So SCAN takeks input and buffers tokens and pending calculations, while
+ * PRINT gobbles up completed calculations and tokens from the buffer. The
+ * theory is that the two can never get more than 3N tokens apart, because
+ * once there's "obviously" too much data to fit on a line, in a size
+ * calculation, SCAN will write "infinity" to the size and let PRINT consume
+ * it.
+ *
+ * In this implementation (following the paper, again) the SCAN process is
+ * the method called 'pretty_print', and the 'PRINT' process is the method
+ * called 'print'.
+ */
+obj printer(io::writer out,
+            uint buf_len,
+            mutable int margin, // width of lines we're constrained to
+
+            mutable int space, // number of spaces left on line
+
+            mutable uint left, // index of left side of input stream
+
+            mutable uint right, // index of right side of input stream
+
+            mutable vec[mutable token] token,
+             // ring-buffr stream goes through
+            mutable vec[mutable int] size, // ring-buffer of calculated sizes
+
+            mutable int left_total, // running size of stream "...left"
+
+            mutable int right_total, // running size of stream "...right"
+
+             // pseudo-stack, really a ring too. Holds the
+             // primary-ring-buffers index of the BEGIN that started the
+             // current block, possibly with the most recent BREAK after that
+             // BEGIN (if there is any) on top of it. Stuff is flushed off the
+             // bottom as it becomes irrelevant due to the primary ring-buffer
+             // advancing.
+             mutable vec[mutable uint] scan_stack,
+            mutable bool scan_stack_empty, // top==bottom disambiguator
+
+            mutable uint top, // index of top of scan_stack
+
+            mutable uint bottom, // index of bottom of scan_stack
+
+             // stack of blocks-in-progress being flushed by print
+            mutable vec[print_stack_elt] print_stack,
+
+            // buffered indentation to avoid writing trailing whitespace
+            mutable int pending_indentation) {
+
+    fn last_token() -> token {
+        ret token.(right);
+    }
+
+    fn pretty_print(token t) {
+        log #fmt("pp [%u,%u]", left, right);
+        alt (t) {
+            case (EOF) {
+                if (!scan_stack_empty) {
+                    self.check_stack(0);
+                    self.advance_left(token.(left), size.(left));
+                }
+                self.indent(0);
+            }
+            case (BEGIN(?b)) {
+                if (scan_stack_empty) {
+                    left_total = 1;
+                    right_total = 1;
+                    left = 0u;
+                    right = 0u;
+                } else { self.advance_right(); }
+                log #fmt("pp BEGIN/buffer [%u,%u]", left, right);
+                token.(right) = t;
+                size.(right) = -right_total;
+                self.scan_push(right);
+            }
+            case (END) {
+                if (scan_stack_empty) {
+                    log #fmt("pp END/print [%u,%u]", left, right);
+                    self.print(t, 0);
+                } else {
+                    log #fmt("pp END/buffer [%u,%u]", left, right);
+                    self.advance_right();
+                    token.(right) = t;
+                    size.(right) = -1;
+                    self.scan_push(right);
+                }
+            }
+            case (BREAK(?b)) {
+                if (scan_stack_empty) {
+                    left_total = 1;
+                    right_total = 1;
+                    left = 0u;
+                    right = 0u;
+                } else { self.advance_right(); }
+                log #fmt("pp BREAK/buffer [%u,%u]", left, right);
+                self.check_stack(0);
+                self.scan_push(right);
+                token.(right) = t;
+                size.(right) = -right_total;
+                right_total += b.blank_space;
+            }
+            case (STRING(?s, ?len)) {
+                if (scan_stack_empty) {
+                    log #fmt("pp STRING/print [%u,%u]", left, right);
+                    self.print(t, len);
+                } else {
+                    log #fmt("pp STRING/buffer [%u,%u]", left, right);
+                    self.advance_right();
+                    token.(right) = t;
+                    size.(right) = len;
+                    right_total += len;
+                    self.check_stream();
+                }
+            }
+        }
+    }
+    fn check_stream() {
+        log #fmt("check_stream [%u, %u] with left_total=%d, right_total=%d",
+                 left, right, left_total, right_total);
+        if (right_total - left_total > space) {
+            log #fmt("scan window is %d, longer than space on line (%d)",
+                     right_total - left_total, space);
+            if (!scan_stack_empty) {
+                if (left == scan_stack.(bottom)) {
+                    log #fmt("setting %u to infinity and popping", left);
+                    size.(self.scan_pop_bottom()) = size_infinity;
+                }
+            }
+            self.advance_left(token.(left), size.(left));
+            if (left != right) { self.check_stream(); }
+        }
+    }
+    fn scan_push(uint x) {
+        log #fmt("scan_push %u", x);
+        if (scan_stack_empty) {
+            scan_stack_empty = false;
+        } else { top += 1u; top %= buf_len; assert (top != bottom); }
+        scan_stack.(top) = x;
+    }
+    fn scan_pop() -> uint {
+        assert (!scan_stack_empty);
+        auto x = scan_stack.(top);
+        if (top == bottom) {
+            scan_stack_empty = true;
+        } else { top += buf_len - 1u; top %= buf_len; }
+        ret x;
+    }
+    fn scan_top() -> uint {
+        assert (!scan_stack_empty);
+        ret scan_stack.(top);
+    }
+    fn scan_pop_bottom() -> uint {
+        assert (!scan_stack_empty);
+        auto x = scan_stack.(bottom);
+        if (top == bottom) {
+            scan_stack_empty = true;
+        } else { bottom += 1u; bottom %= buf_len; }
+        ret x;
+    }
+    fn advance_right() {
+        right += 1u;
+        right %= buf_len;
+        assert (right != left);
+    }
+    fn advance_left(token x, int L) {
+        log #fmt("advnce_left [%u,%u], sizeof(%u)=%d", left, right, left, L);
+        if (L >= 0) {
+            self.print(x, L);
+            alt (x) {
+                case (BREAK(?b)) { left_total += b.blank_space; }
+                case (STRING(_, ?len)) {
+                    assert (len == L);
+                    left_total += len;
+                }
+                case (_) { }
+            }
+            if (left != right) {
+                left += 1u;
+                left %= buf_len;
+                self.advance_left(token.(left), size.(left));
+            }
+        }
+    }
+    fn check_stack(int k) {
+        if (!scan_stack_empty) {
+            auto x = self.scan_top();
+            alt (token.(x)) {
+                case (BEGIN(?b)) {
+                    if (k > 0) {
+                        size.(self.scan_pop()) = size.(x) + right_total;
+                        self.check_stack(k - 1);
+                    }
+                }
+                case (END) {
+                    // paper says + not =, but that makes no sense.
+
+                    size.(self.scan_pop()) = 1;
+                    self.check_stack(k + 1);
+                }
+                case (_) {
+                    size.(self.scan_pop()) = size.(x) + right_total;
+                    if (k > 0) { self.check_stack(k); }
+                }
+            }
+        }
+    }
+    fn print_newline(int amount) {
+        log #fmt("NEWLINE %d", amount);
+        out.write_str("\n");
+        pending_indentation = 0;
+        self.indent(amount);
+    }
+    fn indent(int amount) {
+        log #fmt("INDENT %d", amount);
+        pending_indentation += amount;
+    }
+    fn top() -> print_stack_elt {
+        auto n = vec::len(print_stack);
+        let print_stack_elt top = rec(offset=0, pbreak=broken(inconsistent));
+        if (n != 0u) { top = print_stack.(n - 1u); }
+        ret top;
+    }
+    fn write_str(str s) {
+        while (pending_indentation > 0) {
+            out.write_str(" ");
+            pending_indentation -= 1;
+        }
+        out.write_str(s);
+    }
+    fn print(token x, int L) {
+        log #fmt("print %s %d (remaining line space=%d)", tok_str(x), L,
+                 space);
+        log buf_str(token, size, left, right, 6u);
+        alt (x) {
+            case (BEGIN(?b)) {
+                if (L > space) {
+                    auto col = margin - space + b.offset;
+                    log #fmt("print BEGIN -> push broken block at col %d",
+                             col);
+                    vec::push(print_stack,
+                              rec(offset=col, pbreak=broken(b.breaks)));
+                } else {
+                    log "print BEGIN -> push fitting block";
+                    vec::push(print_stack, rec(offset=0, pbreak=fits));
+                }
+            }
+            case (END) {
+                log "print END -> pop END";
+                assert (vec::len(print_stack) != 0u);
+                vec::pop(print_stack);
+            }
+            case (BREAK(?b)) {
+                auto top = self.top();
+                alt (top.pbreak) {
+                    case (fits) {
+                        log "print BREAK in fitting block";
+                        space -= b.blank_space;
+                        self.indent(b.blank_space);
+                    }
+                    case (broken(consistent)) {
+                        log "print BREAK in consistent block";
+                        self.print_newline(top.offset + b.offset);
+                        space = margin - (top.offset + b.offset);
+                    }
+                    case (broken(inconsistent)) {
+                        if (L > space) {
+                            log "print BREAK w/ newline in inconsistent";
+                            self.print_newline(top.offset + b.offset);
+                            space = margin - (top.offset + b.offset);
+                        } else {
+                            log "print BREAK w/o newline in inconsistent";
+                            self.indent(b.blank_space);
+                            space -= b.blank_space;
+                        }
+                    }
+                }
+            }
+            case (STRING(?s, ?len)) {
+                log "print STRING";
+                assert (L == len);
+                // assert L <= space;
+
+                space -= len;
+                self.write_str(s);
+            }
+            case (EOF) {
+                // EOF should never get here.
+
+                fail;
+            }
+        }
+    }
+}
+
+
+// Convenience functions to talk to the printer.
+fn box(printer p, uint indent, breaks b) {
+    p.pretty_print(BEGIN(rec(offset=indent as int, breaks=b)));
+}
+
+fn ibox(printer p, uint indent) { box(p, indent, inconsistent); }
+
+fn cbox(printer p, uint indent) { box(p, indent, consistent); }
+
+fn break_offset(printer p, uint n, int off) {
+    p.pretty_print(BREAK(rec(offset=off, blank_space=n as int)));
+}
+
+fn end(printer p) { p.pretty_print(END); }
+
+fn eof(printer p) { p.pretty_print(EOF); }
+
+fn word(printer p, str wrd) {
+    p.pretty_print(STRING(wrd, str::char_len(wrd) as int));
+}
+
+fn huge_word(printer p, str wrd) {
+    p.pretty_print(STRING(wrd, size_infinity));
+}
+
+fn zero_word(printer p, str wrd) { p.pretty_print(STRING(wrd, 0)); }
+
+fn spaces(printer p, uint n) { break_offset(p, n, 0); }
+
+fn zerobreak(printer p) { spaces(p, 0u); }
+
+fn space(printer p) { spaces(p, 1u); }
+
+fn hardbreak(printer p) { spaces(p, size_infinity as uint); }
+
+fn hardbreak_tok() -> token {
+    ret BREAK(rec(offset=0, blank_space=size_infinity));
+}
+
+//
+// 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/print/pprust.rs b/src/comp/syntax/print/pprust.rs
new file mode 100644 (file)
index 0000000..b146d70
--- /dev/null
@@ -0,0 +1,1473 @@
+
+import std::uint;
+import std::int;
+import std::vec;
+import std::str;
+import std::io;
+import std::option;
+import parse::lexer;
+import syntax::codemap::codemap;
+import ast;
+import _std::istr;
+import _std::uistr;
+import option::some;
+import option::none;
+import pp::printer;
+import pp::break_offset;
+import pp::word;
+import pp::huge_word;
+import pp::zero_word;
+import pp::space;
+import pp::zerobreak;
+import pp::hardbreak;
+import pp::breaks;
+import pp::consistent;
+import pp::inconsistent;
+import pp::eof;
+
+// The ps is stored here to prevent recursive type.
+// FIXME use a nominal tag instead
+tag ann_node {
+    node_block(ps, ast::block);
+    node_item(ps, @ast::item);
+    node_expr(ps, @ast::expr);
+    node_pat(ps, @ast::pat);
+}
+type pp_ann = rec(fn(&ann_node node) pre,
+                  fn(&ann_node node) post);
+
+fn no_ann() -> pp_ann {
+    fn ignore(&ann_node node) {}
+    ret rec(pre=ignore, post=ignore);
+}
+
+type ps =
+    @rec(pp::printer s,
+         option::t[codemap] cm,
+         option::t[vec[lexer::cmnt]] comments,
+         option::t[vec[lexer::lit]] literals,
+         mutable uint cur_cmnt,
+         mutable uint cur_lit,
+         mutable vec[pp::breaks] boxes,
+         pp_ann ann);
+
+fn ibox(&ps s, uint u) {
+    vec::push(s.boxes, pp::inconsistent);
+    pp::ibox(s.s, u);
+}
+
+fn end(&ps s) { vec::pop(s.boxes); pp::end(s.s); }
+
+fn rust_printer(io::writer writer) -> ps {
+    let vec[pp::breaks] boxes = [];
+    ret @rec(s=pp::mk_printer(writer, default_columns),
+             cm=none[codemap],
+             comments=none[vec[lexer::cmnt]],
+             literals=none[vec[lexer::lit]],
+             mutable cur_cmnt=0u,
+             mutable cur_lit=0u,
+             mutable boxes=boxes,
+             ann=no_ann());
+}
+
+const uint indent_unit = 4u;
+
+const uint default_columns = 78u;
+
+fn print_crate(&codemap cm, @ast::crate crate, str filename,
+               io::writer out, &pp_ann ann) {
+    let vec[pp::breaks] boxes = [];
+    auto r = lexer::gather_comments_and_literals(cm, filename);
+    auto s =
+        @rec(s=pp::mk_printer(out, default_columns),
+             cm=some(cm),
+             comments=some(r.cmnts),
+             literals=some(r.lits),
+             mutable cur_cmnt=0u,
+             mutable cur_lit=0u,
+             mutable boxes=boxes,
+             ann=ann);
+    print_mod(s, crate.node.module, crate.node.attrs);
+    eof(s.s);
+}
+
+fn ty_to_str(&ast::ty ty) -> str { be to_str(ty, print_type); }
+
+fn pat_to_str(&@ast::pat pat) -> str { be to_str(pat, print_pat); }
+
+fn expr_to_str(&@ast::expr e) -> str { be to_str(e, print_expr); }
+
+fn stmt_to_str(&ast::stmt s) -> str { be to_str(s, print_stmt); }
+
+fn item_to_str(&@ast::item i) -> str { be to_str(i, print_item); }
+
+fn path_to_str(&ast::path p) -> str { be to_str(p, print_path); }
+
+fn fun_to_str(&ast::_fn f, str name, vec[ast::ty_param] params) -> str {
+    auto writer = io::string_writer();
+    auto s = rust_printer(writer.get_writer());
+    print_fn(s, f.decl, f.proto, name, params);
+    eof(s.s);
+    ret writer.get_str();
+}
+
+fn block_to_str(&ast::block blk) -> str {
+    auto writer = io::string_writer();
+    auto s = rust_printer(writer.get_writer());
+    // containing cbox, will be closed by print-block at }
+
+    cbox(s, indent_unit);
+    // head-ibox, will be closed by print-block after {
+
+    ibox(s, 0u);
+    print_block(s, blk);
+    eof(s.s);
+    ret writer.get_str();
+}
+
+fn meta_item_to_str(&ast::meta_item mi) -> str {
+    ret to_str(@mi, print_meta_item);
+}
+
+fn attribute_to_str(&ast::attribute attr) -> str {
+    be to_str(attr, print_attribute);
+}
+
+fn cbox(&ps s, uint u) {
+    vec::push(s.boxes, pp::consistent);
+    pp::cbox(s.s, u);
+}
+
+fn box(&ps s, uint u, pp::breaks b) {
+    vec::push(s.boxes, b);
+    pp::box(s.s, u, b);
+}
+
+fn word_nbsp(&ps s, str w) { word(s.s, w); word(s.s, " "); }
+
+fn word_space(&ps s, str w) { word(s.s, w); space(s.s); }
+
+fn popen(&ps s) { word(s.s, "("); }
+
+fn pclose(&ps s) { word(s.s, ")"); }
+
+fn head(&ps s, str w) {
+    // outer-box is consistent
+    cbox(s, indent_unit);
+    // head-box is inconsistent
+    ibox(s, str::char_len(w) + 1u);
+    // keyword that starts the head
+    word_nbsp(s, w);
+}
+
+fn bopen(&ps s) {
+    word(s.s, "{");
+    end(s); // close the head-box
+
+}
+
+fn bclose(&ps s, codemap::span span) {
+    maybe_print_comment(s, span.hi);
+    break_offset(s.s, 1u, -(indent_unit as int));
+    word(s.s, "}");
+    end(s); // close the outer-box
+
+}
+
+fn hardbreak_if_not_bol(&ps s) {
+    if (s.s.last_token() != pp::EOF &&
+        s.s.last_token() != pp::hardbreak_tok()) {
+        hardbreak(s.s);
+    }
+}
+
+fn space_if_not_hardbreak(&ps s) {
+    if (s.s.last_token() != pp::hardbreak_tok()) {
+        space(s.s);
+    }
+}
+
+// Synthesizes a comment that was not textually present in the original source
+// file.
+fn synth_comment(&ps s, str text) {
+    word(s.s, "/*");
+    space(s.s);
+    word(s.s, text);
+    space(s.s);
+    word(s.s, "*/");
+}
+
+fn commasep[IN](&ps s, breaks b, vec[IN] elts, fn(&ps, &IN)  op) {
+    box(s, 0u, b);
+    auto first = true;
+    for (IN elt in elts) {
+        if (first) { first = false; } else { word_space(s, ","); }
+        op(s, elt);
+    }
+    end(s);
+}
+
+fn commasep_cmnt[IN](&ps s, breaks b, vec[IN] elts, fn(&ps, &IN)  op,
+                     fn(&IN) -> codemap::span  get_span) {
+    box(s, 0u, b);
+    auto len = vec::len[IN](elts);
+    auto i = 0u;
+    for (IN elt in elts) {
+        maybe_print_comment(s, get_span(elt).hi);
+        op(s, elt);
+        i += 1u;
+        if (i < len) {
+            word(s.s, ",");
+            maybe_print_trailing_comment(s, get_span(elt),
+                                         some(get_span(elts.(i)).hi));
+            space_if_not_hardbreak(s);
+        }
+    }
+    end(s);
+}
+
+fn commasep_exprs(&ps s, breaks b, vec[@ast::expr] exprs) {
+    fn expr_span(&@ast::expr expr) -> codemap::span { ret expr.span; }
+    commasep_cmnt(s, b, exprs, print_expr, expr_span);
+}
+
+fn print_mod(&ps s, ast::_mod _mod, &vec[ast::attribute] attrs) {
+    print_inner_attributes(s, attrs);
+    for (@ast::view_item vitem in _mod.view_items) {
+        print_view_item(s, vitem);
+    }
+    for (@ast::item item in _mod.items) {
+        hardbreak_if_not_bol(s);
+        print_item(s, item);
+    }
+    print_remaining_comments(s);
+}
+
+fn print_boxed_type(&ps s, &@ast::ty ty) { print_type(s, *ty); }
+
+fn print_type(&ps s, &ast::ty ty) {
+    maybe_print_comment(s, ty.span.lo);
+    ibox(s, 0u);
+    alt (ty.node) {
+        case (ast::ty_nil) { word(s.s, "()"); }
+        case (ast::ty_bool) { word(s.s, "bool"); }
+        case (ast::ty_bot) { word(s.s, "!"); }
+        case (ast::ty_int) { word(s.s, "int"); }
+        case (ast::ty_uint) { word(s.s, "uint"); }
+        case (ast::ty_float) { word(s.s, "float"); }
+        case (ast::ty_machine(?tm)) { word(s.s, ast::ty_mach_to_str(tm)); }
+        case (ast::ty_char) { word(s.s, "char"); }
+        case (ast::ty_str) { word(s.s, "str"); }
+        case (ast::ty_istr) { word(s.s, "istr"); }
+        case (ast::ty_box(?mt)) { word(s.s, "@"); print_mt(s, mt); }
+        case (ast::ty_vec(?mt)) {
+            word(s.s, "vec[");
+            print_mt(s, mt);
+            word(s.s, "]");
+        }
+        case (ast::ty_ivec(?mt)) {
+            print_type(s, *mt.ty);
+            word(s.s, "[");
+            print_mutability(s, mt.mut);
+            word(s.s, "]");
+        }
+        case (ast::ty_ptr(?mt)) {
+            word(s.s, "*");
+            print_mt(s, mt);
+        }
+        case (ast::ty_task) {
+            word(s.s, "task");
+        }
+        case (ast::ty_port(?t)) {
+            word(s.s, "port[");
+            print_type(s, *t);
+            word(s.s, "]");
+        }
+        case (ast::ty_chan(?t)) {
+            word(s.s, "chan[");
+            print_type(s, *t);
+            word(s.s, "]");
+        }
+        case (ast::ty_tup(?elts)) {
+            word(s.s, "tup");
+            popen(s);
+            commasep(s, inconsistent, elts, print_mt);
+            pclose(s);
+        }
+        case (ast::ty_rec(?fields)) {
+            word(s.s, "rec");
+            popen(s);
+            fn print_field(&ps s, &ast::ty_field f) {
+                cbox(s, indent_unit);
+                print_mt(s, f.node.mt);
+                space(s.s);
+                word(s.s, f.node.ident);
+                end(s);
+            }
+            fn get_span(&ast::ty_field f) -> codemap::span { ret f.span; }
+            commasep_cmnt(s, consistent, fields, print_field, get_span);
+            pclose(s);
+        }
+        case (ast::ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
+            print_ty_fn(s, proto, none[str], inputs, output, cf, constrs);
+        }
+        case (ast::ty_obj(?methods)) {
+            head(s, "obj");
+            bopen(s);
+            for (ast::ty_method m in methods) {
+                hardbreak_if_not_bol(s);
+                cbox(s, indent_unit);
+                maybe_print_comment(s, m.span.lo);
+                print_ty_fn(s, m.node.proto, some(m.node.ident),
+                            m.node.inputs, m.node.output, m.node.cf,
+                            m.node.constrs);
+                word(s.s, ";");
+                end(s);
+            }
+            bclose(s, ty.span);
+        }
+        case (ast::ty_path(?path, _)) { print_path(s, path); }
+        case (ast::ty_type) { word(s.s, "type"); }
+        case (ast::ty_constr(?t, ?cs)) {
+            print_type(s, *t);
+            space(s.s);
+            word(s.s, ":");
+            space(s.s);
+            word(s.s, ast_constrs_str(cs));
+        }
+    }
+    end(s);
+}
+
+fn print_item(&ps s, &@ast::item item) {
+    hardbreak_if_not_bol(s);
+    maybe_print_comment(s, item.span.lo);
+    print_outer_attributes(s, item.attrs);
+    auto ann_node = node_item(s, item);
+    s.ann.pre(ann_node);
+    alt (item.node) {
+        case (ast::item_const(?ty, ?expr)) {
+            head(s, "const");
+            print_type(s, *ty);
+            space(s.s);
+            word_space(s, item.ident);
+            end(s); // end the head-ibox
+
+            word_space(s, "=");
+            print_expr(s, expr);
+            word(s.s, ";");
+            end(s); // end the outer cbox
+
+        }
+        case (ast::item_fn(?_fn, ?typarams)) {
+            print_fn(s, _fn.decl, _fn.proto, item.ident, typarams);
+            word(s.s, " ");
+            print_block(s, _fn.body);
+        }
+        case (ast::item_mod(?_mod)) {
+            head(s, "mod");
+            word_nbsp(s, item.ident);
+            bopen(s);
+            print_mod(s, _mod, item.attrs);
+            bclose(s, item.span);
+        }
+        case (ast::item_native_mod(?nmod)) {
+            head(s, "native");
+            alt (nmod.abi) {
+                case (ast::native_abi_rust) { word_nbsp(s, "\"rust\""); }
+                case (ast::native_abi_cdecl) { word_nbsp(s, "\"cdecl\""); }
+                case (ast::native_abi_rust_intrinsic) {
+                    word_nbsp(s, "\"rust-intrinsic\"");
+                }
+            }
+            word_nbsp(s, "mod");
+            word_nbsp(s, item.ident);
+            bopen(s);
+            for (@ast::native_item item in nmod.items) {
+                hardbreak_if_not_bol(s);
+                ibox(s, indent_unit);
+                maybe_print_comment(s, item.span.lo);
+                alt (item.node) {
+                    case (ast::native_item_ty) {
+                        word_nbsp(s, "type");
+                        word(s.s, item.ident);
+                    }
+                    case (ast::native_item_fn(?lname, ?decl, ?typarams)) {
+                        print_fn(s, decl, ast::proto_fn, item.ident,
+                                 typarams);
+                        alt (lname) {
+                            case (none) { }
+                            case (some(?ss)) {
+                                space(s.s);
+                                word_space(s, "=");
+                                print_string(s, ss);
+                            }
+                        }
+                        end(s); // end head-ibox
+
+                        end(s); // end the outer fn box
+
+                    }
+                }
+                word(s.s, ";");
+                end(s);
+            }
+            bclose(s, item.span);
+        }
+        case (ast::item_ty(?ty, ?params)) {
+            ibox(s, indent_unit);
+            ibox(s, 0u);
+            word_nbsp(s, "type");
+            word(s.s, item.ident);
+            print_type_params(s, params);
+            end(s); // end the inner ibox
+
+            space(s.s);
+            word_space(s, "=");
+            print_type(s, *ty);
+            word(s.s, ";");
+            end(s); // end the outer ibox
+
+            break_offset(s.s, 0u, 0);
+        }
+        case (ast::item_tag(?variants, ?params)) {
+            auto newtype = vec::len(variants) == 1u &&
+                str::eq(item.ident, variants.(0).node.name) &&
+                vec::len(variants.(0).node.args) == 1u;
+            if (newtype) {
+                ibox(s, indent_unit);
+                word_space(s, "tag");
+            } else {
+                head(s, "tag");
+            }
+            word(s.s, item.ident);
+            print_type_params(s, params);
+            space(s.s);
+            if (newtype) {
+                word_space(s, "=");
+                print_type(s, *variants.(0).node.args.(0).ty);
+                word(s.s, ";");
+                end(s);
+            } else {
+                bopen(s);
+                for (ast::variant v in variants) {
+                    space(s.s);
+                    maybe_print_comment(s, v.span.lo);
+                    word(s.s, v.node.name);
+                    if (vec::len(v.node.args) > 0u) {
+                        popen(s);
+                        fn print_variant_arg(&ps s, &ast::variant_arg arg) {
+                            print_type(s, *arg.ty);
+                        }
+                        commasep(s, consistent, v.node.args,
+                                 print_variant_arg);
+                        pclose(s);
+                    }
+                    word(s.s, ";");
+                    maybe_print_trailing_comment(s, v.span, none[uint]);
+                }
+                bclose(s, item.span);
+            }
+        }
+        case (ast::item_obj(?_obj, ?params, _)) {
+            head(s, "obj");
+            word(s.s, item.ident);
+            print_type_params(s, params);
+            popen(s);
+            fn print_field(&ps s, &ast::obj_field field) {
+                ibox(s, indent_unit);
+                print_mutability(s, field.mut);
+                print_type(s, *field.ty);
+                space(s.s);
+                word(s.s, field.ident);
+                end(s);
+            }
+            fn get_span(&ast::obj_field f) -> codemap::span { ret f.ty.span; }
+            commasep_cmnt(s, consistent, _obj.fields, print_field, get_span);
+            pclose(s);
+            space(s.s);
+            bopen(s);
+            for (@ast::method meth in _obj.methods) {
+                let vec[ast::ty_param] typarams = [];
+                hardbreak_if_not_bol(s);
+                maybe_print_comment(s, meth.span.lo);
+                print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
+                         meth.node.ident, typarams);
+                word(s.s, " ");
+                print_block(s, meth.node.meth.body);
+            }
+            alt (_obj.dtor) {
+                case (some(?dtor)) {
+                    head(s, "drop");
+                    print_block(s, dtor.node.meth.body);
+                }
+                case (_) { }
+            }
+            bclose(s, item.span);
+        }
+        case (ast::item_res(?dt, ?dt_id, ?tps, ?ct_id)) {
+            head(s, "resource");
+            word(s.s, item.ident);
+            print_type_params(s, tps);
+            popen(s);
+            print_type(s, *dt.decl.inputs.(0).ty);
+            space(s.s);
+            word(s.s, dt.decl.inputs.(0).ident);
+            pclose(s);
+            space(s.s);
+            print_block(s, dt.body);
+        }
+    }
+    s.ann.post(ann_node);
+}
+
+fn print_outer_attributes(&ps s, vec[ast::attribute] attrs) {
+    auto count = 0;
+    for (ast::attribute attr in attrs) {
+        alt (attr.node.style) {
+            case (ast::attr_outer) { print_attribute(s, attr); count += 1; }
+            case (_) {/* fallthrough */ }
+        }
+    }
+    if (count > 0) { hardbreak_if_not_bol(s); }
+}
+
+fn print_inner_attributes(&ps s, vec[ast::attribute] attrs) {
+    auto count = 0;
+    for (ast::attribute attr in attrs) {
+        alt (attr.node.style) {
+            case (ast::attr_inner) {
+                print_attribute(s, attr);
+                word(s.s, ";");
+                count += 1;
+            }
+            case (_) { /* fallthrough */ }
+        }
+    }
+    if (count > 0) { hardbreak_if_not_bol(s); }
+}
+
+fn print_attribute(&ps s, &ast::attribute attr) {
+    hardbreak_if_not_bol(s);
+    maybe_print_comment(s, attr.span.lo);
+    word(s.s, "#[");
+    print_meta_item(s, @attr.node.value);
+    word(s.s, "]");
+}
+
+fn print_stmt(&ps s, &ast::stmt st) {
+    maybe_print_comment(s, st.span.lo);
+    alt (st.node) {
+        case (ast::stmt_decl(?decl, _)) { print_decl(s, decl); }
+        case (ast::stmt_expr(?expr, _)) {
+            space_if_not_hardbreak(s);
+            print_expr(s, expr);
+        }
+    }
+    if (parse::parser::stmt_ends_with_semi(st)) { word(s.s, ";"); }
+    maybe_print_trailing_comment(s, st.span, none[uint]);
+}
+
+fn print_block(&ps s, ast::block blk) {
+    maybe_print_comment(s, blk.span.lo);
+    auto ann_node = node_block(s, blk);
+    s.ann.pre(ann_node);
+    bopen(s);
+    for (@ast::stmt st in blk.node.stmts) { print_stmt(s, *st) }
+    alt (blk.node.expr) {
+        case (some(?expr)) {
+            space_if_not_hardbreak(s);
+            print_expr(s, expr);
+            maybe_print_trailing_comment(s, expr.span, some(blk.span.hi));
+        }
+        case (_) { }
+    }
+    bclose(s, blk.span);
+    s.ann.post(ann_node);
+}
+
+fn print_if(&ps s, &@ast::expr test, &ast::block block,
+            &option::t[@ast::expr] elseopt, bool chk) {
+    head(s, "if");
+    if (chk) {
+        word_nbsp(s, "check");
+    }
+    popen(s);
+    print_expr(s, test);
+    pclose(s);
+    space(s.s);
+    print_block(s, block);
+    fn do_else(&ps s, option::t[@ast::expr] els) {
+        alt (els) {
+            case (some(?_else)) {
+                alt (_else.node) {
+                    // "another else-if"
+                    case (ast::expr_if(?i, ?t, ?e)) {
+                        cbox(s, indent_unit - 1u);
+                        ibox(s, 0u);
+                        word(s.s, " else if ");
+                        popen(s);
+                        print_expr(s, i);
+                        pclose(s);
+                        space(s.s);
+                        print_block(s, t);
+                        do_else(s, e);
+                    }
+                    // "final else"
+                    case (ast::expr_block(?b)) {
+                        cbox(s, indent_unit - 1u);
+                        ibox(s, 0u);
+                        word(s.s, " else ");
+                        print_block(s, b);
+                    }
+                }
+            }
+            case (_) {/* fall through */ }
+        }
+    }
+    do_else(s, elseopt);
+}
+
+fn print_expr(&ps s, &@ast::expr expr) {
+    maybe_print_comment(s, expr.span.lo);
+    ibox(s, indent_unit);
+    auto ann_node = node_expr(s, expr);
+    s.ann.pre(ann_node);
+    alt (expr.node) {
+        case (ast::expr_vec(?exprs, ?mut, ?kind)) {
+            ibox(s, indent_unit);
+            alt (kind) {
+                case (ast::sk_rc) { word(s.s, "["); }
+                case (ast::sk_unique) { word(s.s, "~["); }
+            }
+            if (mut == ast::mut) { word_nbsp(s, "mutable"); }
+            commasep_exprs(s, inconsistent, exprs);
+            word(s.s, "]");
+            end(s);
+        }
+        case (ast::expr_tup(?exprs)) {
+            fn printElt(&ps s, &ast::elt elt) {
+                ibox(s, indent_unit);
+                if (elt.mut == ast::mut) { word_nbsp(s, "mutable"); }
+                print_expr(s, elt.expr);
+                end(s);
+            }
+            fn get_span(&ast::elt elt) -> codemap::span { ret elt.expr.span; }
+            word(s.s, "tup");
+            popen(s);
+            commasep_cmnt(s, inconsistent, exprs, printElt, get_span);
+            pclose(s);
+        }
+        case (ast::expr_rec(?fields, ?wth)) {
+            fn print_field(&ps s, &ast::field field) {
+                ibox(s, indent_unit);
+                if (field.node.mut == ast::mut) { word_nbsp(s, "mutable"); }
+                word(s.s, field.node.ident);
+                word(s.s, "=");
+                print_expr(s, field.node.expr);
+                end(s);
+            }
+            fn get_span(&ast::field field) -> codemap::span {
+                ret field.span;
+            }
+            word(s.s, "rec");
+            popen(s);
+            commasep_cmnt(s, consistent, fields, print_field, get_span);
+            alt (wth) {
+                case (some(?expr)) {
+                    if (vec::len(fields) > 0u) { space(s.s); }
+                    ibox(s, indent_unit);
+                    word_space(s, "with");
+                    print_expr(s, expr);
+                    end(s);
+                }
+                case (_) { }
+            }
+            pclose(s);
+        }
+        case (ast::expr_call(?func, ?args)) {
+            print_expr(s, func);
+            popen(s);
+            commasep_exprs(s, inconsistent, args);
+            pclose(s);
+        }
+        case (ast::expr_self_method(?ident)) {
+            word(s.s, "self.");
+            print_ident(s, ident);
+        }
+        case (ast::expr_bind(?func, ?args)) {
+            fn print_opt(&ps s, &option::t[@ast::expr] expr) {
+                alt (expr) {
+                    case (some(?expr)) { print_expr(s, expr); }
+                    case (_) { word(s.s, "_"); }
+                }
+            }
+            word_nbsp(s, "bind");
+            print_expr(s, func);
+            popen(s);
+            commasep(s, inconsistent, args, print_opt);
+            pclose(s);
+        }
+        case (ast::expr_spawn(_, _, ?e, ?es)) {
+            word_nbsp(s, "spawn");
+            print_expr(s, e);
+            popen(s);
+            commasep_exprs(s, inconsistent, es);
+            pclose(s);
+        }
+        case (ast::expr_binary(?op, ?lhs, ?rhs)) {
+            auto prec = operator_prec(op);
+            print_maybe_parens(s, lhs, prec);
+            space(s.s);
+            word_space(s, ast::binop_to_str(op));
+            print_maybe_parens(s, rhs, prec + 1);
+        }
+        case (ast::expr_unary(?op, ?expr)) {
+            word(s.s, ast::unop_to_str(op));
+            print_maybe_parens(s, expr, parse::parser::unop_prec);
+        }
+        case (ast::expr_lit(?lit)) { print_literal(s, lit); }
+        case (ast::expr_cast(?expr, ?ty)) {
+            print_maybe_parens(s, expr, parse::parser::as_prec);
+            space(s.s);
+            word_space(s, "as");
+            print_type(s, *ty);
+        }
+        case (ast::expr_if(?test, ?block, ?elseopt)) {
+            print_if(s, test, block, elseopt, false);
+        }
+        case (ast::expr_if_check(?test, ?block, ?elseopt)) {
+            print_if(s, test, block, elseopt, true);
+        }
+        case (ast::expr_ternary(?test, ?then, ?els)) {
+            print_expr(s, test);
+            space(s.s);
+            word_space(s, "?");
+            print_expr(s, then);
+            space(s.s);
+            word_space(s, ":");
+            print_expr(s, els);
+        }
+        case (ast::expr_while(?test, ?block)) {
+            head(s, "while");
+            popen(s);
+            print_expr(s, test);
+            pclose(s);
+            space(s.s);
+            print_block(s, block);
+        }
+        case (ast::expr_for(?decl, ?expr, ?block)) {
+            head(s, "for");
+            popen(s);
+            print_for_decl(s, decl);
+            space(s.s);
+            word_space(s, "in");
+            print_expr(s, expr);
+            pclose(s);
+            space(s.s);
+            print_block(s, block);
+        }
+        case (ast::expr_for_each(?decl, ?expr, ?block)) {
+            head(s, "for each");
+            popen(s);
+            print_for_decl(s, decl);
+            space(s.s);
+            word_space(s, "in");
+            print_expr(s, expr);
+            pclose(s);
+            space(s.s);
+            print_block(s, block);
+        }
+        case (ast::expr_do_while(?block, ?expr)) {
+            head(s, "do");
+            space(s.s);
+            print_block(s, block);
+            space(s.s);
+            word_space(s, "while");
+            popen(s);
+            print_expr(s, expr);
+            pclose(s);
+        }
+        case (ast::expr_alt(?expr, ?arms)) {
+            head(s, "alt");
+            popen(s);
+            print_expr(s, expr);
+            pclose(s);
+            space(s.s);
+            bopen(s);
+            for (ast::arm arm in arms) {
+                space(s.s);
+                head(s, "case");
+                popen(s);
+                print_pat(s, arm.pat);
+                pclose(s);
+                space(s.s);
+                print_block(s, arm.block);
+            }
+            bclose(s, expr.span);
+        }
+        case (ast::expr_fn(?f)) {
+            head(s, "fn");
+            print_fn_args_and_ret(s, f.decl);
+            space(s.s);
+            print_block(s, f.body);
+        }
+        case (ast::expr_block(?block)) {
+            // containing cbox, will be closed by print-block at }
+
+            cbox(s, indent_unit);
+            // head-box, will be closed by print-block after {
+
+            ibox(s, 0u);
+            print_block(s, block);
+        }
+        case (ast::expr_move(?lhs, ?rhs)) {
+            print_expr(s, lhs);
+            space(s.s);
+            word_space(s, "<-");
+            print_expr(s, rhs);
+        }
+        case (ast::expr_assign(?lhs, ?rhs)) {
+            print_expr(s, lhs);
+            space(s.s);
+            word_space(s, "=");
+            print_expr(s, rhs);
+        }
+        case (ast::expr_swap(?lhs, ?rhs)) {
+            print_expr(s, lhs);
+            space(s.s);
+            word_space(s, "<->");
+            print_expr(s, rhs);
+        }
+        case (ast::expr_assign_op(?op, ?lhs, ?rhs)) {
+            print_expr(s, lhs);
+            space(s.s);
+            word(s.s, ast::binop_to_str(op));
+            word_space(s, "=");
+            print_expr(s, rhs);
+        }
+        case (ast::expr_send(?lhs, ?rhs)) {
+            print_expr(s, lhs);
+            space(s.s);
+            word_space(s, "<|");
+            print_expr(s, rhs);
+        }
+        case (ast::expr_recv(?lhs, ?rhs)) {
+            print_expr(s, lhs);
+            space(s.s);
+            word_space(s, "|>");
+            print_expr(s, rhs);
+        }
+        case (ast::expr_field(?expr, ?id)) {
+            print_expr(s, expr);
+            word(s.s, ".");
+            word(s.s, id);
+        }
+        case (ast::expr_index(?expr, ?index)) {
+            print_expr(s, expr);
+            word(s.s, ".");
+            popen(s);
+            print_expr(s, index);
+            pclose(s);
+        }
+        case (ast::expr_path(?path)) { print_path(s, path); }
+        case (ast::expr_fail(?maybe_fail_val)) {
+            word(s.s, "fail");
+            alt (maybe_fail_val) {
+                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
+                case (_) { }
+            }
+        }
+        case (ast::expr_break) { word(s.s, "break"); }
+        case (ast::expr_cont) { word(s.s, "cont"); }
+        case (ast::expr_ret(?result)) {
+            word(s.s, "ret");
+            alt (result) {
+                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
+                case (_) { }
+            }
+        }
+        case (ast::expr_put(?result)) {
+            word(s.s, "put");
+            alt (result) {
+                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
+                case (_) { }
+            }
+        }
+        case (ast::expr_be(?result)) {
+            word_nbsp(s, "be");
+            print_expr(s, result);
+        }
+        case (ast::expr_log(?lvl, ?expr)) {
+            alt (lvl) {
+                case (1) { word_nbsp(s, "log"); }
+                case (0) { word_nbsp(s, "log_err"); }
+            }
+            print_expr(s, expr);
+        }
+        case (ast::expr_check(?m, ?expr)) {
+            alt (m) {
+                case (ast::unchecked) {
+                    word_nbsp(s, "claim");
+                }
+                case (ast::checked) {
+                    word_nbsp(s, "check");
+                }
+            }
+            popen(s);
+            print_expr(s, expr);
+            pclose(s);
+        }
+        case (ast::expr_assert(?expr)) {
+            word_nbsp(s, "assert");
+            popen(s);
+            print_expr(s, expr);
+            pclose(s);
+        }
+        case (ast::expr_ext(?path, ?args, ?body, _)) {
+            word(s.s, "#");
+            print_path(s, path);
+            if (vec::len(args) > 0u) {
+                popen(s);
+                commasep_exprs(s, inconsistent, args);
+                pclose(s);
+            }
+            // FIXME: extension 'body'
+
+        }
+        case (ast::expr_port(?ot)) {
+            word(s.s, "port");
+            alt(ot) {
+                case(some(?t)) {
+                    word(s.s, "[");
+                    print_type(s, *t);
+                    word(s.s, "]");
+                }
+                case(none) {}
+            }
+            popen(s); pclose(s);
+        }
+        case (ast::expr_chan(?expr)) {
+            word(s.s, "chan");
+            popen(s);
+            print_expr(s, expr);
+            pclose(s);
+        }
+        case (ast::expr_anon_obj(_, _, _)) {
+            word(s.s, "anon obj");
+            // FIXME (issue #499): nicer pretty-printing of anon objs
+
+        }
+    }
+    s.ann.post(ann_node);
+    end(s);
+}
+
+fn print_decl(&ps s, &@ast::decl decl) {
+    maybe_print_comment(s, decl.span.lo);
+    alt (decl.node) {
+        case (ast::decl_local(?loc)) {
+            space_if_not_hardbreak(s);
+            ibox(s, indent_unit);
+            alt (loc.node.ty) {
+                case (some(?ty)) {
+                    word_nbsp(s, "let");
+                    print_type(s, *ty);
+                    space(s.s);
+                }
+                case (_) {
+                    word_nbsp(s, "auto");
+                }
+            }
+            word(s.s, loc.node.ident);
+            alt (loc.node.init) {
+                case (some(?init)) {
+                    space(s.s);
+                    alt (init.op) {
+                        case (ast::init_assign) { word_space(s, "="); }
+                        case (ast::init_move) { word_space(s, "<-"); }
+                        case (ast::init_recv) { word_space(s, "|>"); }
+                    }
+                    print_expr(s, init.expr);
+                }
+                case (_) { }
+            }
+            end(s);
+        }
+        case (ast::decl_item(?item)) { print_item(s, item); }
+    }
+}
+
+fn print_ident(&ps s, &ast::ident ident) { word(s.s, ident); }
+
+fn print_for_decl(&ps s, @ast::local loc) {
+    print_type(s, *option::get(loc.node.ty));
+    space(s.s);
+    word(s.s, loc.node.ident);
+}
+
+fn print_path(&ps s, &ast::path path) {
+    maybe_print_comment(s, path.span.lo);
+    auto first = true;
+    for (str id in path.node.idents) {
+        if (first) { first = false; } else { word(s.s, "::"); }
+        word(s.s, id);
+    }
+    if (vec::len(path.node.types) > 0u) {
+        word(s.s, "[");
+        commasep(s, inconsistent, path.node.types, print_boxed_type);
+        word(s.s, "]");
+    }
+}
+
+fn print_pat(&ps s, &@ast::pat pat) {
+    maybe_print_comment(s, pat.span.lo);
+    auto ann_node = node_pat(s, pat);
+    s.ann.pre(ann_node);
+    alt (pat.node) {
+        case (ast::pat_wild) { word(s.s, "_"); }
+        case (ast::pat_bind(?id)) { word(s.s, "?" + id); }
+        case (ast::pat_lit(?lit)) { print_literal(s, lit); }
+        case (ast::pat_tag(?path, ?args)) {
+            print_path(s, path);
+            if (vec::len(args) > 0u) {
+                popen(s);
+                commasep(s, inconsistent, args, print_pat);
+                pclose(s);
+            }
+        }
+    }
+    s.ann.post(ann_node);
+}
+
+fn print_fn(&ps s, ast::fn_decl decl, ast::proto proto, str name,
+            vec[ast::ty_param] typarams) {
+    alt (decl.purity) {
+        case (ast::impure_fn) {
+            if (proto == ast::proto_iter) {
+                head(s, "iter");
+            } else { head(s, "fn"); }
+        }
+        case (_) { head(s, "pred"); }
+    }
+    word(s.s, name);
+    print_type_params(s, typarams);
+    print_fn_args_and_ret(s, decl);
+}
+
+fn print_fn_args_and_ret(&ps s, &ast::fn_decl decl) {
+    popen(s);
+    fn print_arg(&ps s, &ast::arg x) {
+        ibox(s, indent_unit);
+        print_alias(s, x.mode);
+        print_type(s, *x.ty);
+        space(s.s);
+        word(s.s, x.ident);
+        end(s);
+    }
+    commasep(s, inconsistent, decl.inputs, print_arg);
+    pclose(s);
+    maybe_print_comment(s, decl.output.span.lo);
+    if (decl.output.node != ast::ty_nil) {
+        space_if_not_hardbreak(s);
+        word_space(s, "->");
+        print_type(s, *decl.output);
+    }
+}
+
+fn print_alias(&ps s, ast::mode m) {
+    alt (m) {
+        case (ast::alias(true)) { word_space(s, "&mutable"); }
+        case (ast::alias(false)) { word(s.s, "&"); }
+        case (ast::val) { }
+    }
+}
+
+fn print_type_params(&ps s, &vec[ast::ty_param] params) {
+    if (vec::len(params) > 0u) {
+        word(s.s, "[");
+        fn printParam(&ps s, &ast::ty_param param) { word(s.s, param); }
+        commasep(s, inconsistent, params, printParam);
+        word(s.s, "]");
+    }
+}
+
+fn print_meta_item(&ps s, &@ast::meta_item item) {
+    ibox(s, indent_unit);
+    alt (item.node) {
+        case (ast::meta_word(?name)) {
+            word(s.s, name);
+        }
+        case (ast::meta_name_value(?name, ?value)) {
+            word_space(s, name);
+            word_space(s, "=");
+            print_string(s, value);
+        }
+        case (ast::meta_list(?name, ?items)) {
+            word(s.s, name);
+            popen(s);
+            commasep(s, consistent, items, print_meta_item);
+            pclose(s);
+        }
+    }
+    end(s);
+}
+
+fn print_view_item(&ps s, &@ast::view_item item) {
+    hardbreak_if_not_bol(s);
+    maybe_print_comment(s, item.span.lo);
+    alt (item.node) {
+        case (ast::view_item_use(?id, ?mta, _)) {
+            head(s, "use");
+            word(s.s, id);
+            if (vec::len(mta) > 0u) {
+                popen(s);
+                commasep(s, consistent, mta, print_meta_item);
+                pclose(s);
+            }
+        }
+        case (ast::view_item_import(?id, ?ids, _)) {
+            head(s, "import");
+            if (!str::eq(id, ids.(vec::len(ids) - 1u))) {
+                word_space(s, id);
+                word_space(s, "=");
+            }
+            auto first = true;
+            for (str elt in ids) {
+                if (first) { first = false; } else { word(s.s, "::"); }
+                word(s.s, elt);
+            }
+        }
+        case (ast::view_item_import_glob(?ids, _)) {
+            head(s, "import");
+            auto first = true;
+            for (str elt in ids) {
+                if (first) { first = false; } else { word(s.s, "::"); }
+                word(s.s, elt);
+            }
+            word(s.s, "::*");
+        }
+        case (ast::view_item_export(?id, _)) {
+            head(s, "export");
+            word(s.s, id);
+        }
+    }
+    word(s.s, ";");
+    end(s); // end inner head-block
+
+    end(s); // end outer head-block
+
+}
+
+
+// FIXME: The fact that this builds up the table anew for every call is
+// not good. Eventually, table should be a const.
+fn operator_prec(ast::binop op) -> int {
+    for (parse::parser::op_spec spec in parse::parser::prec_table()) {
+        if (spec.op == op) { ret spec.prec; }
+    }
+    fail;
+}
+
+fn print_maybe_parens(&ps s, &@ast::expr expr, int outer_prec) {
+    auto add_them;
+    alt (expr.node) {
+        case (ast::expr_binary(?op, _, _)) {
+            add_them = operator_prec(op) < outer_prec;
+        }
+        case (ast::expr_cast(_, _)) {
+            add_them = parse::parser::as_prec < outer_prec;
+        }
+        case (ast::expr_ternary(_, _, _)) {
+            add_them = parse::parser::ternary_prec < outer_prec;
+        }
+        case (_) { add_them = false; }
+    }
+    if (add_them) { popen(s); }
+    print_expr(s, expr);
+    if (add_them) { pclose(s); }
+}
+
+fn print_mutability(&ps s, &ast::mutability mut) {
+    alt (mut) {
+        case (ast::mut) { word_nbsp(s, "mutable"); }
+        case (ast::maybe_mut) { word_nbsp(s, "mutable?"); }
+        case (ast::imm) {/* nothing */ }
+    }
+}
+
+fn print_mt(&ps s, &ast::mt mt) {
+    print_mutability(s, mt.mut);
+    print_type(s, *mt.ty);
+}
+
+fn print_ty_fn(&ps s, &ast::proto proto, &option::t[str] id,
+               &vec[ast::ty_arg] inputs, &@ast::ty output,
+               &ast::controlflow cf, &vec[@ast::constr] constrs) {
+    ibox(s, indent_unit);
+    if (proto == ast::proto_fn) {
+        word(s.s, "fn");
+    } else { word(s.s, "iter"); }
+    alt (id) {
+        case (some(?id)) { word(s.s, " "); word(s.s, id); }
+        case (_) { }
+    }
+    zerobreak(s.s);
+    popen(s);
+    fn print_arg(&ps s, &ast::ty_arg input) {
+        print_alias(s, input.node.mode);
+        print_type(s, *input.node.ty);
+    }
+    commasep(s, inconsistent, inputs, print_arg);
+    pclose(s);
+    maybe_print_comment(s, output.span.lo);
+    if (output.node != ast::ty_nil) {
+        space_if_not_hardbreak(s);
+        ibox(s, indent_unit);
+        word_space(s, "->");
+        alt (cf) {
+            case (ast::return) { print_type(s, *output); }
+            case (ast::noreturn) { word_nbsp(s, "!"); }
+        }
+        end(s);
+    }
+    word_space(s, ast_constrs_str(constrs));
+    end(s);
+}
+
+fn maybe_print_trailing_comment(&ps s, codemap::span span,
+                                option::t[uint] next_pos) {
+    auto cm;
+    alt (s.cm) { case (some(?ccm)) { cm = ccm; } case (_) { ret; } }
+    alt (next_comment(s)) {
+        case (some(?cmnt)) {
+            if (cmnt.style != lexer::trailing) { ret; }
+            auto span_line = codemap::lookup_pos(cm, span.hi);
+            auto comment_line = codemap::lookup_pos(cm, cmnt.pos);
+            auto next = cmnt.pos + 1u;
+            alt (next_pos) { case (none) { } case (some(?p)) { next = p; } }
+            if (span.hi < cmnt.pos && cmnt.pos < next &&
+                span_line.line == comment_line.line) {
+                print_comment(s, cmnt);
+                s.cur_cmnt += 1u;
+            }
+        }
+        case (_) { }
+    }
+}
+
+fn print_remaining_comments(&ps s) {
+    while (true) {
+        alt (next_comment(s)) {
+            case (some(?cmnt)) { print_comment(s, cmnt); s.cur_cmnt += 1u; }
+            case (_) { break; }
+        }
+    }
+}
+
+fn in_cbox(&ps s) -> bool {
+    auto len = vec::len(s.boxes);
+    if (len == 0u) { ret false; }
+    ret s.boxes.(len - 1u) == pp::consistent;
+}
+
+fn print_literal(&ps s, &@ast::lit lit) {
+    maybe_print_comment(s, lit.span.lo);
+    alt (next_lit(s)) {
+        case (some(?lt)) {
+            if (lt.pos == lit.span.lo) {
+                word(s.s, lt.lit);
+                s.cur_lit += 1u;
+                ret;
+            }
+        }
+        case (_) { }
+    }
+    alt (lit.node) {
+        case (ast::lit_str(?st, ?kind)) {
+            if (kind == ast::sk_unique) { word(s.s, "~"); }
+            print_string(s, st);
+        }
+        case (ast::lit_char(?ch)) {
+            word(s.s,
+                 "'" + escape_str(str::from_bytes([ch as u8]), '\'') + "'");
+        }
+        case (ast::lit_int(?val)) { word(s.s, istr(val)); }
+        case (ast::lit_uint(?val)) { word(s.s, uistr(val) + "u"); }
+        case (ast::lit_float(?fstr)) { word(s.s, fstr); }
+        case (ast::lit_mach_int(?mach, ?val)) {
+            word(s.s, istr(val as int));
+            word(s.s, ast::ty_mach_to_str(mach));
+        }
+        case (ast::lit_mach_float(?mach, ?val)) {
+            // val is already a str
+            word(s.s, val);
+            word(s.s, ast::ty_mach_to_str(mach));
+        }
+        case (ast::lit_nil) { word(s.s, "()"); }
+        case (ast::lit_bool(?val)) {
+            if (val) { word(s.s, "true"); } else { word(s.s, "false"); }
+        }
+    }
+}
+
+fn lit_to_str(&@ast::lit l) -> str { be to_str(l, print_literal); }
+
+fn next_lit(&ps s) -> option::t[lexer::lit] {
+    alt (s.literals) {
+        case (some(?lits)) {
+            if (s.cur_lit < vec::len(lits)) {
+                ret some(lits.(s.cur_lit));
+            } else { ret none[lexer::lit]; }
+        }
+        case (_) { ret none[lexer::lit]; }
+    }
+}
+
+fn maybe_print_comment(&ps s, uint pos) {
+    while (true) {
+        alt (next_comment(s)) {
+            case (some(?cmnt)) {
+                if (cmnt.pos < pos) {
+                    print_comment(s, cmnt);
+                    s.cur_cmnt += 1u;
+                } else { break; }
+            }
+            case (_) { break; }
+        }
+    }
+}
+
+fn print_comment(&ps s, lexer::cmnt cmnt) {
+    alt (cmnt.style) {
+        case (lexer::mixed) {
+            assert (vec::len(cmnt.lines) == 1u);
+            zerobreak(s.s);
+            word(s.s, cmnt.lines.(0));
+            zerobreak(s.s);
+        }
+        case (lexer::isolated) {
+            pprust::hardbreak_if_not_bol(s);
+            for (str line in cmnt.lines) { word(s.s, line); hardbreak(s.s); }
+        }
+        case (lexer::trailing) {
+            word(s.s, " ");
+            if (vec::len(cmnt.lines) == 1u) {
+                word(s.s, cmnt.lines.(0));
+                hardbreak(s.s);
+            } else {
+                ibox(s, 0u);
+                for (str line in cmnt.lines) {
+                    word(s.s, line);
+                    hardbreak(s.s);
+                }
+                end(s);
+            }
+        }
+        case (lexer::blank_line) {
+            // We need to do at least one, possibly two hardbreaks.
+            pprust::hardbreak_if_not_bol(s);
+            hardbreak(s.s);
+        }
+    }
+}
+
+fn print_string(&ps s, &str st) {
+    word(s.s, "\"");
+    word(s.s, escape_str(st, '"'));
+    word(s.s, "\"");
+}
+
+fn escape_str(str st, char to_escape) -> str {
+    let str out = "";
+    auto len = str::byte_len(st);
+    auto i = 0u;
+    while (i < len) {
+        alt (st.(i) as char) {
+            case ('\n') { out += "\\n"; }
+            case ('\t') { out += "\\t"; }
+            case ('\r') { out += "\\r"; }
+            case ('\\') { out += "\\\\"; }
+            case (?cur) {
+                if (cur == to_escape) { out += "\\"; }
+                // FIXME some (or all?) non-ascii things should be escaped
+
+                str::push_char(out, cur);
+            }
+        }
+        i += 1u;
+    }
+    ret out;
+}
+
+fn to_str[T](&T t, fn(&ps, &T)  f) -> str {
+    auto writer = io::string_writer();
+    auto s = rust_printer(writer.get_writer());
+    f(s, t);
+    eof(s.s);
+    ret writer.get_str();
+}
+
+fn next_comment(&ps s) -> option::t[lexer::cmnt] {
+    alt (s.comments) {
+        case (some(?cmnts)) {
+            if (s.cur_cmnt < vec::len(cmnts)) {
+                ret some(cmnts.(s.cur_cmnt));
+            } else { ret none[lexer::cmnt]; }
+        }
+        case (_) { ret none[lexer::cmnt]; }
+    }
+}
+
+
+fn constr_args_to_str[T](fn(&T) -> str  f,
+                         &vec[@ast::constr_arg_general[T]] args) -> str {
+    auto comma = false;
+    auto s = "(";
+    for (@ast::constr_arg_general[T] a in args) {
+        if (comma) { s += ", "; } else { comma = true; }
+        s += constr_arg_to_str[T](f, a.node);
+    }
+    s += ")";
+    ret s;
+}
+
+fn constr_arg_to_str[T](fn(&T) -> str  f, &ast::constr_arg_general_[T] c) ->
+   str {
+    alt (c) {
+        case (ast::carg_base) { ret "*"; }
+        case (ast::carg_ident(?i)) { ret f(i); }
+        case (ast::carg_lit(?l)) { ret lit_to_str(l); }
+    }
+}
+
+// needed b/c constr_args_to_str needs
+// something that takes an alias
+// (argh)
+fn uint_to_str(&uint i) -> str { ret uistr(i); }
+
+fn ast_constr_to_str(&@ast::constr c) -> str {
+    ret ast::path_to_str(c.node.path) +
+            constr_args_to_str(uint_to_str, c.node.args);
+}
+
+fn ast_constrs_str(&vec[@ast::constr] constrs) -> str {
+    auto s = "";
+    auto colon = true;
+    for (@ast::constr c in constrs) {
+        if (colon) { s += " : "; colon = false; } else { s += ", "; }
+        s += ast_constr_to_str(c);
+    }
+    ret s;
+}
+
+//
+// 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/util/interner.rs b/src/comp/syntax/util/interner.rs
new file mode 100644 (file)
index 0000000..e096b95
--- /dev/null
@@ -0,0 +1,35 @@
+// An "interner" is a data structure that associates values with uint tags and
+// allows bidirectional lookup; i.e. given a value, one can easily find the
+// type, and vice versa.
+import std::vec;
+import std::map;
+import std::map::hashmap;
+import std::map::hashfn;
+import std::map::eqfn;
+import std::option;
+import std::option::none;
+import std::option::some;
+
+type interner[T] =
+    rec(hashmap[T, uint] map,
+        mutable vec[T] vect,
+        hashfn[T] hasher,
+        eqfn[T] eqer);
+
+fn mk[T](hashfn[T] hasher, eqfn[T] eqer) -> interner[T] {
+    auto m = map::mk_hashmap[T, uint](hasher, eqer);
+    let vec[T] vect = [];
+    ret rec(map=m, mutable vect=vect, hasher=hasher, eqer=eqer);
+}
+fn intern[T](&interner[T] itr, &T val) -> uint {
+    alt (itr.map.find(val)) {
+        case (some(?idx)) { ret idx; }
+        case (none) {
+            auto new_idx = vec::len[T](itr.vect);
+            itr.map.insert(val, new_idx);
+            itr.vect += [val];
+            ret new_idx;
+        }
+    }
+}
+fn get[T](&interner[T] itr, uint idx) -> T { ret itr.vect.(idx); }
diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs
new file mode 100644 (file)
index 0000000..a709814
--- /dev/null
@@ -0,0 +1,407 @@
+
+import ast::*;
+import std::option;
+import std::option::some;
+import std::option::none;
+import codemap::span;
+
+
+// Context-passing AST walker. Each overridden visit method has full control
+// over what happens with its node, it can do its own traversal of the node's
+// children (potentially passing in different contexts to each), call
+// visit::visit_* to apply the default traversal algorithm (again, it can
+// override the context), or prevent deeper traversal by doing nothing.
+
+// Lots of redundant indirection and refcounting. Our typesystem doesn't do
+// circular types, so the visitor record can not hold functions that take
+// visitors. A vt tag is used to break the cycle.
+tag vt[E] { vtor(visitor[E]); }
+
+fn vt[E](&vt[E] x) -> visitor[E] { alt (x) { case (vtor(?v)) { ret v; } } }
+
+type visitor[E] =
+    @rec(fn(&_mod, &span, &E, &vt[E])  visit_mod,
+         fn(&@view_item, &E, &vt[E])  visit_view_item,
+         fn(&@native_item, &E, &vt[E])  visit_native_item,
+         fn(&@item, &E, &vt[E])  visit_item,
+         fn(&@local, &E, &vt[E])  visit_local,
+         fn(&block, &E, &vt[E])  visit_block,
+         fn(&@stmt, &E, &vt[E])  visit_stmt,
+         fn(&arm, &E, &vt[E])  visit_arm,
+         fn(&@pat, &E, &vt[E])  visit_pat,
+         fn(&@decl, &E, &vt[E])  visit_decl,
+         fn(&@expr, &E, &vt[E])  visit_expr,
+         fn(&@ty, &E, &vt[E])  visit_ty,
+         fn(&@constr, &E, &vt[E])  visit_constr,
+         fn(&_fn, &vec[ty_param], &span, &fn_ident, node_id, &E, &vt[E])
+             visit_fn);
+
+fn default_visitor[E]() -> visitor[E] {
+    ret @rec(visit_mod=bind visit_mod[E](_, _, _, _),
+             visit_view_item=bind visit_view_item[E](_, _, _),
+             visit_native_item=bind visit_native_item[E](_, _, _),
+             visit_item=bind visit_item[E](_, _, _),
+             visit_local=bind visit_local[E](_, _, _),
+             visit_block=bind visit_block[E](_, _, _),
+             visit_stmt=bind visit_stmt[E](_, _, _),
+             visit_arm=bind visit_arm[E](_, _, _),
+             visit_pat=bind visit_pat[E](_, _, _),
+             visit_decl=bind visit_decl[E](_, _, _),
+             visit_expr=bind visit_expr[E](_, _, _),
+             visit_ty=bind visit_ty[E](_, _, _),
+             visit_constr=bind visit_constr[E](_, _, _),
+             visit_fn=bind visit_fn[E](_, _, _, _, _, _, _));
+}
+
+fn visit_crate[E](&crate c, &E e, &vt[E] v) {
+    vt(v).visit_mod(c.node.module, c.span, e, v);
+}
+
+fn visit_crate_directive[E](&@crate_directive cd, &E e, &vt[E] v) {
+    alt (cd.node) {
+        case (cdir_src_mod(_, _, _)) { }
+        case (cdir_dir_mod(_, _, ?cdirs, _)) {
+            for (@crate_directive cdir in cdirs) {
+                visit_crate_directive(cdir, e, v);
+            }
+        }
+        case (cdir_view_item(?vi)) { vt(v).visit_view_item(vi, e, v); }
+        case (cdir_syntax(_)) { }
+        case (cdir_auth(_, _)) { }
+    }
+}
+
+fn visit_mod[E](&_mod m, &span sp, &E e, &vt[E] v) {
+    for (@view_item vi in m.view_items) { vt(v).visit_view_item(vi, e, v); }
+    for (@item i in m.items) { vt(v).visit_item(i, e, v); }
+}
+
+fn visit_view_item[E](&@view_item vi, &E e, &vt[E] v) { }
+
+fn visit_local[E](&@local loc, &E e, &vt[E] v) {
+    alt (loc.node.ty) {
+        case (none) { }
+        case (some(?t)) { vt(v).visit_ty(t, e, v); }
+    }
+    alt (loc.node.init) {
+        case (none) { }
+        case (some(?i)) { vt(v).visit_expr(i.expr, e, v); }
+    }
+}
+
+fn visit_item[E](&@item i, &E e, &vt[E] v) {
+    alt (i.node) {
+        case (item_const(?t, ?ex)) {
+            vt(v).visit_ty(t, e, v);
+            vt(v).visit_expr(ex, e, v);
+        }
+        case (item_fn(?f, ?tp)) {
+            vt(v).visit_fn(f, tp, i.span, some(i.ident), i.id, e, v);
+        }
+        case (item_mod(?m)) { vt(v).visit_mod(m, i.span, e, v); }
+        case (item_native_mod(?nm)) {
+            for (@view_item vi in nm.view_items) {
+                vt(v).visit_view_item(vi, e, v);
+            }
+            for (@native_item ni in nm.items) {
+                vt(v).visit_native_item(ni, e, v);
+            }
+        }
+        case (item_ty(?t, _)) { vt(v).visit_ty(t, e, v); }
+        case (item_res(?f, ?dtor_id, ?tps, _)) {
+            vt(v).visit_fn(f, tps, i.span, some(i.ident), dtor_id, e, v);
+        }
+        case (item_tag(?variants, _)) {
+            for (variant vr in variants) {
+                for (variant_arg va in vr.node.args) {
+                    vt(v).visit_ty(va.ty, e, v);
+                }
+            }
+        }
+        case (item_obj(?ob, _, _)) {
+            for (obj_field f in ob.fields) { vt(v).visit_ty(f.ty, e, v); }
+            for (@method m in ob.methods) {
+                vt(v).visit_fn(m.node.meth, [], m.span, some(m.node.ident),
+                               m.node.id, e, v);
+            }
+            alt (ob.dtor) {
+                case (none) { }
+                case (some(?m)) {
+                    vt(v).visit_fn(m.node.meth, [], m.span,
+                                   some(m.node.ident),
+                                   m.node.id, e, v);
+                }
+            }
+        }
+    }
+}
+
+fn visit_ty[E](&@ty t, &E e, &vt[E] v) {
+    alt (t.node) {
+        case (ty_nil)           { /* no-op */ }
+        case (ty_bot)           { /* no-op */ }
+        case (ty_bool)          { /* no-op */ }
+        case (ty_int)           { /* no-op */ }
+        case (ty_float)         { /* no-op */ }
+        case (ty_uint)          { /* no-op */ }
+        case (ty_machine(_))    { /* no-op */ }
+        case (ty_char)          { /* no-op */ }
+        case (ty_str)           { /* no-op */ }
+        case (ty_istr)          { /* no-op */ }
+        case (ty_box(?mt))      { vt(v).visit_ty(mt.ty, e, v); }
+        case (ty_vec(?mt))      { vt(v).visit_ty(mt.ty, e, v); }
+        case (ty_ivec(?mt))     { vt(v).visit_ty(mt.ty, e, v); }
+        case (ty_ptr(?mt))      { vt(v).visit_ty(mt.ty, e, v); }
+        case (ty_port(?t))      { vt(v).visit_ty(t, e, v); }
+        case (ty_chan(?t))      { vt(v).visit_ty(t, e, v); }
+        case (ty_task)          { /* no-op */ }
+        case (ty_tup(?mts)) {
+            for (mt mt in mts) { vt(v).visit_ty(mt.ty, e, v); }
+        }
+        case (ty_rec(?flds)) {
+            for (ty_field f in flds) { vt(v).visit_ty(f.node.mt.ty, e, v); }
+        }
+        case (ty_fn(_, ?args, ?out, _, ?constrs)) {
+            for (ty_arg a in args) { vt(v).visit_ty(a.node.ty, e, v); }
+            for (@constr c in constrs) { vt(v).visit_constr(c, e, v); }
+            vt(v).visit_ty(out, e, v);
+        }
+        case (ty_obj(?tmeths)) {
+            for (ty_method m in tmeths) {
+                for (ty_arg a in m.node.inputs) {
+                    vt(v).visit_ty(a.node.ty, e, v);
+                }
+                vt(v).visit_ty(m.node.output, e, v);
+            }
+        }
+        case (ty_path(?p, _)) {
+            for (@ty tp in p.node.types) { vt(v).visit_ty(tp, e, v); }
+        }
+        case (ty_type)          { /* no-op */ }
+        case (ty_constr(?t, _)) { vt(v).visit_ty(t, e, v); }
+    }
+}
+
+fn visit_constr[E](&@constr c, &E e, &vt[E] v) {
+    // default
+
+}
+
+fn visit_pat[E](&@pat p, &E e, &vt[E] v) {
+    alt (p.node) {
+        case (pat_tag(?path, ?children)) {
+            for (@ty tp in path.node.types) { vt(v).visit_ty(tp, e, v); }
+            for (@pat child in children) { vt(v).visit_pat(child, e, v); }
+        }
+        case (_) { }
+    }
+}
+
+fn visit_native_item[E](&@native_item ni, &E e, &vt[E] v) {
+    alt (ni.node) {
+        case (native_item_fn(_, ?fd, _)) { visit_fn_decl(fd, e, v); }
+        case (native_item_ty) { }
+    }
+}
+
+fn visit_fn_decl[E](&fn_decl fd, &E e, &vt[E] v) {
+    for (arg a in fd.inputs) { vt(v).visit_ty(a.ty, e, v); }
+    for (@constr c in fd.constraints) { vt(v).visit_constr(c, e, v); }
+    vt(v).visit_ty(fd.output, e, v);
+}
+
+fn visit_fn[E](&_fn f, &vec[ty_param] tp, &span sp, &fn_ident i,
+               node_id id, &E e, &vt[E] v) {
+    visit_fn_decl(f.decl, e, v);
+    vt(v).visit_block(f.body, e, v);
+}
+
+fn visit_block[E](&block b, &E e, &vt[E] v) {
+    for (@stmt s in b.node.stmts) { vt(v).visit_stmt(s, e, v); }
+    visit_expr_opt(b.node.expr, e, v);
+}
+
+fn visit_stmt[E](&@stmt s, &E e, &vt[E] v) {
+    alt (s.node) {
+        case (stmt_decl(?d, _)) { vt(v).visit_decl(d, e, v); }
+        case (stmt_expr(?ex, _)) { vt(v).visit_expr(ex, e, v); }
+        case (stmt_crate_directive(?cd)) { visit_crate_directive(cd, e, v); }
+    }
+}
+
+fn visit_decl[E](&@decl d, &E e, &vt[E] v) {
+    alt (d.node) {
+        case (decl_local(?loc)) {
+            vt(v).visit_local(loc, e, v);
+        }
+        case (decl_item(?it)) { vt(v).visit_item(it, e, v); }
+    }
+}
+
+fn visit_expr_opt[E](option::t[@expr] eo, &E e, &vt[E] v) {
+    alt (eo) {
+        case (none) { }
+        case (some(?ex)) { vt(v).visit_expr(ex, e, v); }
+    }
+}
+
+fn visit_exprs[E](vec[@expr] exprs, &E e, &vt[E] v) {
+    for (@expr ex in exprs) { vt(v).visit_expr(ex, e, v); }
+}
+
+fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
+    alt (ex.node) {
+        case (expr_vec(?es, _, _)) { visit_exprs(es, e, v); }
+        case (expr_tup(?elts)) {
+            for (elt el in elts) { vt(v).visit_expr(el.expr, e, v); }
+        }
+        case (expr_rec(?flds, ?base)) {
+            for (field f in flds) { vt(v).visit_expr(f.node.expr, e, v); }
+            visit_expr_opt(base, e, v);
+        }
+        case (expr_call(?callee, ?args)) {
+            vt(v).visit_expr(callee, e, v);
+            visit_exprs(args, e, v);
+        }
+        case (expr_self_method(_)) { }
+        case (expr_bind(?callee, ?args)) {
+            vt(v).visit_expr(callee, e, v);
+            for (option::t[@expr] eo in args) { visit_expr_opt(eo, e, v); }
+        }
+        case (expr_spawn(_, _, ?callee, ?args)) {
+            vt(v).visit_expr(callee, e, v);
+            visit_exprs(args, e, v);
+        }
+        case (expr_binary(_, ?a, ?b)) {
+            vt(v).visit_expr(a, e, v);
+            vt(v).visit_expr(b, e, v);
+        }
+        case (expr_unary(_, ?a)) { vt(v).visit_expr(a, e, v); }
+        case (expr_lit(_)) { }
+        case (expr_cast(?x, ?t)) {
+            vt(v).visit_expr(x, e, v);
+            vt(v).visit_ty(t, e, v);
+        }
+        case (expr_if(?x, ?b, ?eo)) {
+            vt(v).visit_expr(x, e, v);
+            vt(v).visit_block(b, e, v);
+            visit_expr_opt(eo, e, v);
+        }
+        case (expr_if_check(?x, ?b, ?eo)) {
+            vt(v).visit_expr(x, e, v);
+            vt(v).visit_block(b, e, v);
+            visit_expr_opt(eo, e, v);
+        }
+        case (expr_ternary(?c, ?t, ?el)) {
+            vt(v).visit_expr(c, e, v);
+            vt(v).visit_expr(t, e, v);
+            vt(v).visit_expr(el, e, v);
+        }
+        case (expr_while(?x, ?b)) {
+            vt(v).visit_expr(x, e, v);
+            vt(v).visit_block(b, e, v);
+        }
+        case (expr_for(?dcl, ?x, ?b)) {
+            vt(v).visit_local(dcl, e, v);
+            vt(v).visit_expr(x, e, v);
+            vt(v).visit_block(b, e, v);
+        }
+        case (expr_for_each(?dcl, ?x, ?b)) {
+            vt(v).visit_local(dcl, e, v);
+            vt(v).visit_expr(x, e, v);
+            vt(v).visit_block(b, e, v);
+        }
+        case (expr_do_while(?b, ?x)) {
+            vt(v).visit_block(b, e, v);
+            vt(v).visit_expr(x, e, v);
+        }
+        case (expr_alt(?x, ?arms)) {
+            vt(v).visit_expr(x, e, v);
+            for (arm a in arms) { vt(v).visit_arm(a, e, v); }
+        }
+        case (expr_fn(?f)) {
+            vt(v).visit_fn(f, [], ex.span, none, ex.id, e, v);
+        }
+        case (expr_block(?b)) { vt(v).visit_block(b, e, v); }
+        case (expr_assign(?a, ?b)) {
+            vt(v).visit_expr(b, e, v);
+            vt(v).visit_expr(a, e, v);
+        }
+        case (expr_move(?a, ?b)) {
+            vt(v).visit_expr(b, e, v);
+            vt(v).visit_expr(a, e, v);
+        }
+        case (expr_swap(?a, ?b)) {
+            vt(v).visit_expr(a, e, v);
+            vt(v).visit_expr(b, e, v);
+        }
+        case (expr_assign_op(_, ?a, ?b)) {
+            vt(v).visit_expr(b, e, v);
+            vt(v).visit_expr(a, e, v);
+        }
+        case (expr_send(?a, ?b)) {
+            vt(v).visit_expr(a, e, v);
+            vt(v).visit_expr(b, e, v);
+        }
+        case (expr_recv(?a, ?b)) {
+            vt(v).visit_expr(a, e, v);
+            vt(v).visit_expr(b, e, v);
+        }
+        case (expr_field(?x, _)) { vt(v).visit_expr(x, e, v); }
+        case (expr_index(?a, ?b)) {
+            vt(v).visit_expr(a, e, v);
+            vt(v).visit_expr(b, e, v);
+        }
+        case (expr_path(?p)) {
+            for (@ty tp in p.node.types) { vt(v).visit_ty(tp, e, v); }
+        }
+        case (expr_ext(_, _, _, ?expansion)) {
+            vt(v).visit_expr(expansion, e, v);
+        }
+        case (expr_fail(?eo)) {
+            visit_expr_opt(eo, e, v);
+        }
+        case (expr_break) { }
+        case (expr_cont) { }
+        case (expr_ret(?eo)) { visit_expr_opt(eo, e, v); }
+        case (expr_put(?eo)) { visit_expr_opt(eo, e, v); }
+        case (expr_be(?x)) { vt(v).visit_expr(x, e, v); }
+        case (expr_log(_, ?x)) { vt(v).visit_expr(x, e, v); }
+        case (expr_check(_, ?x)) { vt(v).visit_expr(x, e, v); }
+        case (expr_assert(?x)) { vt(v).visit_expr(x, e, v); }
+        case (expr_port(_)) { }
+        case (expr_chan(?x)) { vt(v).visit_expr(x, e, v); }
+        case (expr_anon_obj(?anon_obj, _, _)) {
+            alt (anon_obj.fields) {
+                case (none) { }
+                case (some(?fields)) {
+                    for (anon_obj_field f in fields) {
+                        vt(v).visit_ty(f.ty, e, v);
+                        vt(v).visit_expr(f.expr, e, v);
+                    }
+                }
+            }
+            alt (anon_obj.with_obj) {
+                case (none) { }
+                case (some(?ex)) { vt(v).visit_expr(ex, e, v); }
+            }
+            for (@method m in anon_obj.methods) {
+                vt(v).visit_fn(m.node.meth, [], m.span, some(m.node.ident),
+                               m.node.id, e, v);
+            }
+        }
+    }
+}
+
+fn visit_arm[E](&arm a, &E e, &vt[E] v) {
+    vt(v).visit_pat(a.pat, e, v);
+    vt(v).visit_block(a.block, e, v);
+}
+// 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/walk.rs b/src/comp/syntax/walk.rs
new file mode 100644 (file)
index 0000000..79e8ca6
--- /dev/null
@@ -0,0 +1,495 @@
+
+import ast;
+import ast::ty_param;
+import ast::respan;
+import std::option;
+import std::option::some;
+import std::option::none;
+import codemap::span;
+
+type ast_visitor =
+    rec(fn() -> bool  keep_going,
+        fn() -> bool  want_crate_directives,
+        fn(&ast::crate)  visit_crate_pre,
+        fn(&ast::crate)  visit_crate_post,
+        fn(&@ast::crate_directive)  visit_crate_directive_pre,
+        fn(&@ast::crate_directive)  visit_crate_directive_post,
+        fn(&@ast::view_item)  visit_view_item_pre,
+        fn(&@ast::view_item)  visit_view_item_post,
+        fn(&@ast::native_item)  visit_native_item_pre,
+        fn(&@ast::native_item)  visit_native_item_post,
+        fn(&@ast::item)  visit_item_pre,
+        fn(&@ast::item)  visit_item_post,
+        fn(&@ast::method)  visit_method_pre,
+        fn(&@ast::method)  visit_method_post,
+        fn(&ast::block)  visit_block_pre,
+        fn(&ast::block)  visit_block_post,
+        fn(&@ast::stmt)  visit_stmt_pre,
+        fn(&@ast::stmt)  visit_stmt_post,
+        fn(&ast::arm)  visit_arm_pre,
+        fn(&ast::arm)  visit_arm_post,
+        fn(&@ast::pat)  visit_pat_pre,
+        fn(&@ast::pat)  visit_pat_post,
+        fn(&@ast::decl)  visit_decl_pre,
+        fn(&@ast::decl)  visit_decl_post,
+        fn(&@ast::local)  visit_local_pre,
+        fn(&@ast::local)  visit_local_post,
+        fn(&@ast::expr)  visit_expr_pre,
+        fn(&@ast::expr)  visit_expr_post,
+        fn(&@ast::ty)  visit_ty_pre,
+        fn(&@ast::ty)  visit_ty_post,
+        fn(&@ast::constr)  visit_constr,
+        fn(&ast::_fn, &vec[ast::ty_param], &span, &ast::fn_ident,
+           ast::node_id) visit_fn_pre,
+        fn(&ast::_fn, &vec[ast::ty_param], &span, &ast::fn_ident,
+           ast::node_id) visit_fn_post);
+
+fn walk_crate(&ast_visitor v, &ast::crate c) {
+    if (!v.keep_going()) { ret; }
+    v.visit_crate_pre(c);
+    walk_mod(v, c.node.module);
+    v.visit_crate_post(c);
+}
+
+fn walk_crate_directive(&ast_visitor v, @ast::crate_directive cd) {
+    if (!v.keep_going()) { ret; }
+    if (!v.want_crate_directives()) { ret; }
+    v.visit_crate_directive_pre(cd);
+    alt (cd.node) {
+        case (ast::cdir_src_mod(_, _, _)) { }
+        case (ast::cdir_dir_mod(_, _, ?cdirs, _)) {
+            for (@ast::crate_directive cdir in cdirs) {
+                walk_crate_directive(v, cdir);
+            }
+        }
+        case (ast::cdir_view_item(?vi)) { walk_view_item(v, vi); }
+        case (ast::cdir_syntax(_)) { }
+        case (ast::cdir_auth(_, _)) { }
+    }
+    v.visit_crate_directive_post(cd);
+}
+
+fn walk_mod(&ast_visitor v, &ast::_mod m) {
+    if (!v.keep_going()) { ret; }
+    for (@ast::view_item vi in m.view_items) { walk_view_item(v, vi); }
+    for (@ast::item i in m.items) { walk_item(v, i); }
+}
+
+fn walk_view_item(&ast_visitor v, @ast::view_item vi) {
+    if (!v.keep_going()) { ret; }
+    v.visit_view_item_pre(vi);
+    v.visit_view_item_post(vi);
+}
+
+fn walk_local(&ast_visitor v, @ast::local loc) {
+    v.visit_local_pre(loc);
+    alt (loc.node.ty) { case (none) { } case (some(?t)) { walk_ty(v, t); } }
+    alt (loc.node.init) {
+        case (none) { }
+        case (some(?i)) { walk_expr(v, i.expr); }
+    }
+    v.visit_local_post(loc);
+}
+
+fn walk_item(&ast_visitor v, @ast::item i) {
+    if (!v.keep_going()) { ret; }
+    v.visit_item_pre(i);
+    alt (i.node) {
+        case (ast::item_const(?t, ?e)) { walk_ty(v, t); walk_expr(v, e); }
+        case (ast::item_fn(?f, ?tps)) {
+            walk_fn(v, f, tps, i.span, some(i.ident), i.id);
+        }
+        case (ast::item_mod(?m)) { walk_mod(v, m); }
+        case (ast::item_native_mod(?nm)) { walk_native_mod(v, nm); }
+        case (ast::item_ty(?t, _)) { walk_ty(v, t); }
+        case (ast::item_res(?f, ?dtor_id, ?tps, _)) {
+            walk_fn(v, f, tps, i.span, some(i.ident), dtor_id);
+        }
+        case (ast::item_tag(?variants, _)) {
+            for (ast::variant vr in variants) {
+                for (ast::variant_arg va in vr.node.args) {
+                    walk_ty(v, va.ty);
+                }
+            }
+        }
+        case (ast::item_obj(?ob, _, _)) {
+            for (ast::obj_field f in ob.fields) { walk_ty(v, f.ty); }
+            for (@ast::method m in ob.methods) {
+                v.visit_method_pre(m);
+                // Methods don't have ty params?
+                walk_fn(v, m.node.meth, [], m.span,
+                        some(m.node.ident), m.node.id);
+                v.visit_method_post(m);
+            }
+            alt (ob.dtor) {
+                case (none) { }
+                case (some(?m)) {
+                    walk_fn(v, m.node.meth, [], m.span,
+                            some(m.node.ident), m.node.id);
+                }
+            }
+        }
+    }
+    v.visit_item_post(i);
+}
+
+fn walk_ty(&ast_visitor v, @ast::ty t) {
+    if (!v.keep_going()) { ret; }
+    v.visit_ty_pre(t);
+    alt (t.node) {
+        case (ast::ty_nil) { }
+        case (ast::ty_bot) { }
+        case (ast::ty_bool) { }
+        case (ast::ty_int) { }
+        case (ast::ty_uint) { }
+        case (ast::ty_float) { }
+        case (ast::ty_machine(_)) { }
+        case (ast::ty_char) { }
+        case (ast::ty_str) { }
+        case (ast::ty_istr) { }
+        case (ast::ty_box(?mt)) { walk_ty(v, mt.ty); }
+        case (ast::ty_vec(?mt)) { walk_ty(v, mt.ty); }
+        case (ast::ty_ivec(?mt)) { walk_ty(v, mt.ty); }
+        case (ast::ty_ptr(?mt)) { walk_ty(v, mt.ty); }
+        case (ast::ty_task) { }
+        case (ast::ty_port(?t)) { walk_ty(v, t); }
+        case (ast::ty_chan(?t)) { walk_ty(v, t); }
+        case (ast::ty_tup(?mts)) {
+            for (ast::mt mt in mts) { walk_ty(v, mt.ty); }
+        }
+        case (ast::ty_rec(?flds)) {
+            for (ast::ty_field f in flds) { walk_ty(v, f.node.mt.ty); }
+        }
+        case (ast::ty_fn(_, ?args, ?out, _, ?constrs)) {
+            for (ast::ty_arg a in args) { walk_ty(v, a.node.ty); }
+            for (@ast::constr c in constrs) { v.visit_constr(c); }
+            walk_ty(v, out);
+        }
+        case (ast::ty_obj(?tmeths)) {
+            for (ast::ty_method m in tmeths) {
+                for (ast::ty_arg a in m.node.inputs) {
+                    walk_ty(v, a.node.ty);
+                }
+                walk_ty(v, m.node.output);
+            }
+        }
+        case (ast::ty_path(?p, _)) {
+            for (@ast::ty tp in p.node.types) { walk_ty(v, tp); }
+        }
+        case (ast::ty_type) { }
+        case (ast::ty_constr(?t, _)) { walk_ty(v, t); }
+    }
+    v.visit_ty_post(t);
+}
+
+fn walk_pat(&ast_visitor v, &@ast::pat p) {
+    v.visit_pat_pre(p);
+    alt (p.node) {
+        case (ast::pat_tag(?path, ?children)) {
+            for (@ast::ty tp in path.node.types) { walk_ty(v, tp); }
+            for (@ast::pat child in children) { walk_pat(v, child); }
+        }
+        case (_) { }
+    }
+    v.visit_pat_post(p);
+}
+
+fn walk_native_mod(&ast_visitor v, &ast::native_mod nm) {
+    if (!v.keep_going()) { ret; }
+    for (@ast::view_item vi in nm.view_items) { walk_view_item(v, vi); }
+    for (@ast::native_item ni in nm.items) { walk_native_item(v, ni); }
+}
+
+fn walk_native_item(&ast_visitor v, @ast::native_item ni) {
+    if (!v.keep_going()) { ret; }
+    v.visit_native_item_pre(ni);
+    alt (ni.node) {
+        case (ast::native_item_fn(_, ?fd, _)) {
+            walk_fn_decl(v, fd);
+        }
+        case (ast::native_item_ty) { }
+    }
+    v.visit_native_item_post(ni);
+}
+
+fn walk_fn_decl(&ast_visitor v, &ast::fn_decl fd) {
+    for (ast::arg a in fd.inputs) { walk_ty(v, a.ty); }
+    for (@ast::constr c in fd.constraints) { v.visit_constr(c); }
+    walk_ty(v, fd.output);
+}
+
+fn walk_fn(&ast_visitor v, &ast::_fn f, &vec[ast::ty_param] tps,
+           &span sp, &ast::fn_ident i, ast::node_id d) {
+    if (!v.keep_going()) { ret; }
+    v.visit_fn_pre(f, tps, sp, i, d);
+    walk_fn_decl(v, f.decl);
+    walk_block(v, f.body);
+    v.visit_fn_post(f, tps, sp, i, d);
+}
+
+fn walk_block(&ast_visitor v, &ast::block b) {
+    if (!v.keep_going()) { ret; }
+    v.visit_block_pre(b);
+    for (@ast::stmt s in b.node.stmts) { walk_stmt(v, s); }
+    walk_expr_opt(v, b.node.expr);
+    v.visit_block_post(b);
+}
+
+fn walk_stmt(&ast_visitor v, @ast::stmt s) {
+    if (!v.keep_going()) { ret; }
+    v.visit_stmt_pre(s);
+    alt (s.node) {
+        case (ast::stmt_decl(?d, _)) { walk_decl(v, d); }
+        case (ast::stmt_expr(?e, _)) { walk_expr(v, e); }
+        case (ast::stmt_crate_directive(?cdir)) {
+            walk_crate_directive(v, cdir);
+        }
+    }
+    v.visit_stmt_post(s);
+}
+
+fn walk_decl(&ast_visitor v, @ast::decl d) {
+    if (!v.keep_going()) { ret; }
+    v.visit_decl_pre(d);
+    alt (d.node) {
+        case (ast::decl_local(?loc)) { walk_local(v, loc); }
+        case (ast::decl_item(?it)) { walk_item(v, it); }
+    }
+    v.visit_decl_post(d);
+}
+
+fn walk_expr_opt(&ast_visitor v, option::t[@ast::expr] eo) {
+    alt (eo) { case (none) { } case (some(?e)) { walk_expr(v, e); } }
+}
+
+fn walk_exprs(&ast_visitor v, vec[@ast::expr] exprs) {
+    for (@ast::expr e in exprs) { walk_expr(v, e); }
+}
+
+fn walk_expr(&ast_visitor v, @ast::expr e) {
+    if (!v.keep_going()) { ret; }
+    v.visit_expr_pre(e);
+    alt (e.node) {
+        case (ast::expr_vec(?es, _, _)) { walk_exprs(v, es); }
+        case (ast::expr_tup(?elts)) {
+            for (ast::elt e in elts) { walk_expr(v, e.expr); }
+        }
+        case (ast::expr_rec(?flds, ?base)) {
+            for (ast::field f in flds) { walk_expr(v, f.node.expr); }
+            walk_expr_opt(v, base);
+        }
+        case (ast::expr_call(?callee, ?args)) {
+            walk_expr(v, callee);
+            walk_exprs(v, args);
+        }
+        case (ast::expr_self_method(_)) { }
+        case (ast::expr_bind(?callee, ?args)) {
+            walk_expr(v, callee);
+            for (option::t[@ast::expr] eo in args) { walk_expr_opt(v, eo); }
+        }
+        case (ast::expr_spawn(_, _, ?callee, ?args)) {
+            walk_expr(v, callee);
+            walk_exprs(v, args);
+        }
+        case (ast::expr_binary(_, ?a, ?b)) {
+            walk_expr(v, a);
+            walk_expr(v, b);
+        }
+        case (ast::expr_unary(_, ?a)) { walk_expr(v, a); }
+        case (ast::expr_lit(_)) { }
+        case (ast::expr_cast(?x, ?t)) { walk_expr(v, x); walk_ty(v, t); }
+        case (ast::expr_if(?x, ?b, ?eo)) {
+            walk_expr(v, x);
+            walk_block(v, b);
+            walk_expr_opt(v, eo);
+        }
+        case (ast::expr_if_check(?x, ?b, ?eo)) {
+            walk_expr(v, x);
+            walk_block(v, b);
+            walk_expr_opt(v, eo);
+        }
+        case (ast::expr_ternary(?c, ?t, ?e)) {
+            walk_expr(v, c);
+            walk_expr(v, t);
+            walk_expr(v, e);
+        }
+        case (ast::expr_while(?x, ?b)) {
+            walk_expr(v, x);
+            walk_block(v, b);
+        }
+        case (ast::expr_for(?dcl, ?x, ?b)) {
+            walk_local(v, dcl);
+            walk_expr(v, x);
+            walk_block(v, b);
+        }
+        case (ast::expr_for_each(?dcl, ?x, ?b)) {
+            walk_local(v, dcl);
+            walk_expr(v, x);
+            walk_block(v, b);
+        }
+        case (ast::expr_do_while(?b, ?x)) {
+            walk_block(v, b);
+            walk_expr(v, x);
+        }
+        case (ast::expr_alt(?x, ?arms)) {
+            walk_expr(v, x);
+            for (ast::arm a in arms) {
+                walk_pat(v, a.pat);
+                v.visit_arm_pre(a);
+                walk_block(v, a.block);
+                v.visit_arm_post(a);
+            }
+        }
+        case (ast::expr_fn(?f)) {
+            walk_fn(v, f, [], e.span, none, e.id);
+        }
+        case (ast::expr_block(?b)) { walk_block(v, b); }
+        case (ast::expr_assign(?a, ?b)) {
+            walk_expr(v, a);
+            walk_expr(v, b);
+        }
+        case (ast::expr_move(?a, ?b)) { walk_expr(v, a); walk_expr(v, b); }
+        case (ast::expr_swap(?a, ?b)) { walk_expr(v, a); walk_expr(v, b); }
+        case (ast::expr_assign_op(_, ?a, ?b)) {
+            walk_expr(v, a);
+            walk_expr(v, b);
+        }
+        case (ast::expr_send(?a, ?b)) { walk_expr(v, a); walk_expr(v, b); }
+        case (ast::expr_recv(?a, ?b)) { walk_expr(v, a); walk_expr(v, b); }
+        case (ast::expr_field(?x, _)) { walk_expr(v, x); }
+        case (ast::expr_index(?a, ?b)) {
+            walk_expr(v, a);
+            walk_expr(v, b);
+        }
+        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_fail(?eo)) { walk_expr_opt(v, eo); }
+        case (ast::expr_break) { }
+        case (ast::expr_cont) { }
+        case (ast::expr_ret(?eo)) { walk_expr_opt(v, eo); }
+        case (ast::expr_put(?eo)) { walk_expr_opt(v, eo); }
+        case (ast::expr_be(?x)) { walk_expr(v, x); }
+        case (ast::expr_log(_, ?x)) { walk_expr(v, x); }
+        case (ast::expr_check(_, ?x)) { walk_expr(v, x); }
+        case (ast::expr_assert(?x)) { walk_expr(v, x); }
+        case (ast::expr_port(_)) { }
+        case (ast::expr_chan(?x)) { walk_expr(v, x); }
+        case (ast::expr_anon_obj(?anon_obj, _, _)) {
+            // Fields
+
+            alt (anon_obj.fields) {
+                case (none) { }
+                case (some(?fields)) {
+                    for (ast::anon_obj_field f in fields) { 
+                        walk_ty(v, f.ty);
+                        walk_expr(v, f.expr);
+                    }
+                }
+            }
+            // with_obj
+
+            alt (anon_obj.with_obj) {
+                case (none) { }
+                case (some(?e)) { walk_expr(v, e); }
+            }
+
+            // Methods
+            for (@ast::method m in anon_obj.methods) {
+                v.visit_method_pre(m);
+                walk_fn(v, m.node.meth, [], m.span, some(m.node.ident),
+                        m.node.id);
+                v.visit_method_post(m);
+            }
+        }
+    }
+    v.visit_expr_post(e);
+}
+
+fn def_keep_going() -> bool { ret true; }
+
+fn def_want_crate_directives() -> bool { ret false; }
+
+fn def_visit_crate(&ast::crate c) { }
+
+fn def_visit_crate_directive(&@ast::crate_directive c) { }
+
+fn def_visit_view_item(&@ast::view_item vi) { }
+
+fn def_visit_native_item(&@ast::native_item ni) { }
+
+fn def_visit_item(&@ast::item i) { }
+
+fn def_visit_method(&@ast::method m) { }
+
+fn def_visit_block(&ast::block b) { }
+
+fn def_visit_stmt(&@ast::stmt s) { }
+
+fn def_visit_arm(&ast::arm a) { }
+
+fn def_visit_pat(&@ast::pat p) { }
+
+fn def_visit_decl(&@ast::decl d) { }
+
+fn def_visit_local(&@ast::local l) { }
+
+fn def_visit_expr(&@ast::expr e) { }
+
+fn def_visit_ty(&@ast::ty t) { }
+
+fn def_visit_constr(&@ast::constr c) { }
+
+fn def_visit_fn(&ast::_fn f, &vec[ast::ty_param] tps,
+  &span sp, &ast::fn_ident i, ast::node_id d) { }
+
+fn default_visitor() -> ast_visitor {
+    ret rec(keep_going=def_keep_going,
+            want_crate_directives=def_want_crate_directives,
+            visit_crate_pre=def_visit_crate,
+            visit_crate_post=def_visit_crate,
+            visit_crate_directive_pre=def_visit_crate_directive,
+            visit_crate_directive_post=def_visit_crate_directive,
+            visit_view_item_pre=def_visit_view_item,
+            visit_view_item_post=def_visit_view_item,
+            visit_native_item_pre=def_visit_native_item,
+            visit_native_item_post=def_visit_native_item,
+            visit_item_pre=def_visit_item,
+            visit_item_post=def_visit_item,
+            visit_method_pre=def_visit_method,
+            visit_method_post=def_visit_method,
+            visit_block_pre=def_visit_block,
+            visit_block_post=def_visit_block,
+            visit_stmt_pre=def_visit_stmt,
+            visit_stmt_post=def_visit_stmt,
+            visit_arm_pre=def_visit_arm,
+            visit_arm_post=def_visit_arm,
+            visit_pat_pre=def_visit_pat,
+            visit_pat_post=def_visit_pat,
+            visit_decl_pre=def_visit_decl,
+            visit_decl_post=def_visit_decl,
+            visit_local_pre=def_visit_local,
+            visit_local_post=def_visit_local,
+            visit_expr_pre=def_visit_expr,
+            visit_expr_post=def_visit_expr,
+            visit_ty_pre=def_visit_ty,
+            visit_ty_post=def_visit_ty,
+            visit_constr=def_visit_constr,
+            visit_fn_pre=def_visit_fn,
+            visit_fn_post=def_visit_fn);
+}
+//
+// 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:
+//
index 9eca5c1f9b52820a50e5cbf0ef185c880e76509a..cf50c2fbc7333d738b697874d878ce55b7cdce15 100644 (file)
@@ -7,70 +7,30 @@
 import std::option;
 import std::option::none;
 import std::option::some;
-import front::ast;
-import front::ast::ty;
-import front::ast::pat;
-import front::codemap::codemap;
-import front::ast::lit;
-import front::ast::path;
-import middle::walk;
+import syntax::ast;
+import ast::ty;
+import ast::pat;
+import syntax::codemap::codemap;
+import syntax::codemap::span;
+import ast::lit;
+import ast::path;
+import syntax::walk;
 import std::io::stdout;
 import std::io::str_writer;
 import std::io::string_writer;
-import pretty::pprust::print_block;
-import pretty::pprust::print_item;
-import pretty::pprust::print_expr;
-import pretty::pprust::print_path;
-import pretty::pprust::print_decl;
-import pretty::pprust::print_fn;
-import pretty::pprust::print_type;
-import pretty::ppaux::print_literal;
-import pretty::pp::mk_printer;
-
-type filename = str;
-
-type span = rec(uint lo, uint hi);
-
-type spanned[T] = rec(T node, span span);
+import syntax::print;
+import print::pprust::print_block;
+import print::pprust::print_item;
+import print::pprust::print_expr;
+import print::pprust::print_path;
+import print::pprust::print_decl;
+import print::pprust::print_fn;
+import print::pprust::print_type;
+import print::pprust::print_literal;
+import print::pp::mk_printer;
 
 type flag = hashmap[str, ()];
 
-tag ty_mach {
-    ty_i8;
-    ty_i16;
-    ty_i32;
-    ty_i64;
-    ty_u8;
-    ty_u16;
-    ty_u32;
-    ty_u64;
-    ty_f32;
-    ty_f64;
-}
-
-tag ty_or_bang[T] { a_ty(T); a_bang; }
-
-fn ty_mach_to_str(ty_mach tm) -> str {
-    alt (tm) {
-        case (ty_u8) { ret "u8"; }
-        case (ty_u16) { ret "u16"; }
-        case (ty_u32) { ret "u32"; }
-        case (ty_u64) { ret "u64"; }
-        case (ty_i8) { ret "i8"; }
-        case (ty_i16) { ret "i16"; }
-        case (ty_i32) { ret "i32"; }
-        case (ty_i64) { ret "i64"; }
-        case (ty_f32) { ret "f32"; }
-        case (ty_f64) { ret "f64"; }
-    }
-}
-
-fn new_str_hash[V]() -> std::map::hashmap[str, V] {
-    let std::map::hashfn[str] hasher = std::str::hash;
-    let std::map::eqfn[str] eqer = std::str::eq;
-    ret std::map::mk_hashmap[str, V](hasher, eqer);
-}
-
 fn def_eq(&ast::def_id a, &ast::def_id b) -> bool {
     ret a._0 == b._0 && a._1 == b._1;
 }
@@ -88,26 +48,6 @@ fn new_def_hash[V]() -> std::map::hashmap[ast::def_id, V] {
     ret std::map::mk_hashmap[ast::def_id, V](hasher, eqer);
 }
 
-fn new_int_hash[V]() -> std::map::hashmap[int, V] {
-    fn hash_int(&int x) -> uint { ret x as uint; }
-    fn eq_int(&int a, &int b) -> bool { ret a == b; }
-    auto hasher = hash_int;
-    auto eqer = eq_int;
-    ret std::map::mk_hashmap[int, V](hasher, eqer);
-}
-
-fn new_uint_hash[V]() -> std::map::hashmap[uint, V] {
-    fn hash_uint(&uint x) -> uint { ret x; }
-    fn eq_uint(&uint a, &uint b) -> bool { ret a == b; }
-    auto hasher = hash_uint;
-    auto eqer = eq_uint;
-    ret std::map::mk_hashmap[uint, V](hasher, eqer);
-}
-
-fn istr(int i) -> str { ret int::to_str(i, 10u); }
-
-fn uistr(uint i) -> str { ret uint::to_str(i, 10u); }
-
 fn elt_expr(&ast::elt e) -> @ast::expr { ret e.expr; }
 
 fn elt_exprs(&vec[ast::elt] elts) -> vec[@ast::expr] {
@@ -122,31 +62,31 @@ fn field_exprs(vec[ast::field] fields) -> vec[@ast::expr] {
     ret vec::map[ast::field, @ast::expr](f, fields);
 }
 
-fn log_expr(&ast::expr e) { log pretty::pprust::expr_to_str(@e); }
+fn log_expr(&ast::expr e) { log print::pprust::expr_to_str(@e); }
 
-fn log_expr_err(&ast::expr e) { log_err pretty::pprust::expr_to_str(@e); }
+fn log_expr_err(&ast::expr e) { log_err print::pprust::expr_to_str(@e); }
 
-fn log_ty_err(&ty t) { log_err pretty::pprust::ty_to_str(t); }
+fn log_ty_err(&ty t) { log_err print::pprust::ty_to_str(t); }
 
-fn log_pat_err(&@pat p) { log_err pretty::pprust::pat_to_str(p); }
+fn log_pat_err(&@pat p) { log_err print::pprust::pat_to_str(p); }
 
-fn log_block(&ast::block b) { log pretty::pprust::block_to_str(b); }
+fn log_block(&ast::block b) { log print::pprust::block_to_str(b); }
 
-fn log_block_err(&ast::block b) { log_err pretty::pprust::block_to_str(b); }
+fn log_block_err(&ast::block b) { log_err print::pprust::block_to_str(b); }
 
-fn log_item_err(&@ast::item i) { log_err pretty::pprust::item_to_str(i); }
+fn log_item_err(&@ast::item i) { log_err print::pprust::item_to_str(i); }
 
 fn log_fn(&ast::_fn f, str name, vec[ast::ty_param] params) {
-    log pretty::pprust::fun_to_str(f, name, params);
+    log print::pprust::fun_to_str(f, name, params);
 }
 
 fn log_fn_err(&ast::_fn f, str name, vec[ast::ty_param] params) {
-    log_err pretty::pprust::fun_to_str(f, name, params);
+    log_err print::pprust::fun_to_str(f, name, params);
 }
 
-fn log_stmt(&ast::stmt st) { log pretty::pprust::stmt_to_str(st); }
+fn log_stmt(&ast::stmt st) { log print::pprust::stmt_to_str(st); }
 
-fn log_stmt_err(&ast::stmt st) { log_err pretty::pprust::stmt_to_str(st); }
+fn log_stmt_err(&ast::stmt st) { log_err print::pprust::stmt_to_str(st); }
 
 fn has_nonlocal_exits(&ast::block b) -> bool {
     auto has_exits = @mutable false;
@@ -232,27 +172,6 @@ fn lit_eq(&@ast::lit l, &@ast::lit m) -> bool {
     }
 }
 
-fn respan[T](&span sp, &T t) -> spanned[T] { ret rec(node=t, span=sp); }
-
-fn may_begin_ident(char c) -> bool { ret is_alpha(c) || c == '_'; }
-
-fn in_range(char c, char lo, char hi) -> bool { ret lo <= c && c <= hi; }
-
-fn is_alpha(char c) -> bool {
-    ret in_range(c, 'a', 'z') || in_range(c, 'A', 'Z');
-}
-
-fn is_dec_digit(char c) -> bool { ret in_range(c, '0', '9'); }
-
-fn is_alnum(char c) -> bool { ret is_alpha(c) || is_dec_digit(c); }
-
-fn is_hex_digit(char c) -> bool {
-    ret in_range(c, '0', '9') || in_range(c, 'a', 'f') ||
-            in_range(c, 'A', 'F');
-}
-
-fn is_bin_digit(char c) -> bool { ret c == '0' || c == '1'; }
-
 // FIXME move to vec
 fn any[T](&fn(&T) -> bool f, &vec[T] v) -> bool {
     for (T t in v) {
diff --git a/src/comp/util/data.rs b/src/comp/util/data.rs
deleted file mode 100644 (file)
index 5ff3cf6..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-// An "interner" is a data structure that associates values with uint tags and
-// allows bidirectional lookup; i.e. given a value, one can easily find the
-// type, and vice versa.
-import std::vec;
-import std::map;
-import std::map::hashmap;
-import std::map::hashfn;
-import std::map::eqfn;
-import std::option;
-import std::option::none;
-import std::option::some;
-
-mod interner {
-    type interner[T] =
-        rec(hashmap[T, uint] map,
-            mutable vec[T] vect,
-            hashfn[T] hasher,
-            eqfn[T] eqer);
-
-    fn mk[T](hashfn[T] hasher, eqfn[T] eqer) -> interner[T] {
-        auto m = map::mk_hashmap[T, uint](hasher, eqer);
-        let vec[T] vect = [];
-        ret rec(map=m, mutable vect=vect, hasher=hasher, eqer=eqer);
-    }
-    fn intern[T](&interner[T] itr, &T val) -> uint {
-        alt (itr.map.find(val)) {
-            case (some(?idx)) { ret idx; }
-            case (none) {
-                auto new_idx = vec::len[T](itr.vect);
-                itr.map.insert(val, new_idx);
-                itr.vect += [val];
-                ret new_idx;
-            }
-        }
-    }
-    fn get[T](&interner[T] itr, uint idx) -> T { ret itr.vect.(idx); }
-}
diff --git a/src/comp/util/ppaux.rs b/src/comp/util/ppaux.rs
new file mode 100644 (file)
index 0000000..4adc6c4
--- /dev/null
@@ -0,0 +1,182 @@
+import std::io;
+import std::vec;
+import std::str;
+import std::option;
+import std::option::none;
+import std::option::some;
+import middle::ty;
+import middle::ty::*;
+import syntax::print::pp;
+import syntax::print::pprust;
+import pp::word;
+import pp::eof;
+import pp::zerobreak;
+import pp::hardbreak;
+import syntax::_std::istr;
+import syntax::_std::uistr;
+import ast::ty_mach_to_str;
+import syntax::ast;
+
+fn mode_str(&ty::mode m) -> str {
+    alt (m) {
+        case (mo_val) { "" }
+        case (mo_alias(false)) { "&" }
+        case (mo_alias(true)) { "&mutable " }
+    }
+}
+
+fn mode_str_1(&ty::mode m) -> str {
+    alt (m) {
+        case (mo_val) { "val" }
+        case (_)      { mode_str(m) }
+    }
+}
+
+fn fn_ident_to_string(ast::node_id id, &ast::fn_ident i) -> str {
+    ret alt (i) {
+        case (none) { "anon" + istr(id) }
+        case (some(?s)) { s }
+    };
+}
+
+fn ty_to_str(&ctxt cx, &t typ) -> str {
+    fn fn_input_to_str(&ctxt cx, &rec(middle::ty::mode mode, t ty) input) ->
+       str {
+        auto s = mode_str(input.mode);
+        ret s + ty_to_str(cx, input.ty);
+    }
+    fn fn_to_str(&ctxt cx, ast::proto proto, option::t[ast::ident] ident,
+                 &arg[] inputs, t output, ast::controlflow cf,
+                 &vec[@constr_def] constrs) -> str {
+        auto s;
+        alt (proto) {
+            case (ast::proto_iter) { s = "iter"; }
+            case (ast::proto_fn) { s = "fn"; }
+        }
+        alt (ident) { case (some(?i)) { s += " "; s += i; } case (_) { } }
+        s += "(";
+        auto strs = [];
+        for (arg a in inputs) { strs += [fn_input_to_str(cx, a)]; }
+        s += str::connect(strs, ", ");
+        s += ")";
+        if (struct(cx, output) != ty_nil) {
+            alt (cf) {
+                case (ast::noreturn) { s += " -> !"; }
+                case (ast::return) { s += " -> " + ty_to_str(cx, output); }
+            }
+        }
+        s += constrs_str(constrs);
+        ret s;
+    }
+    fn method_to_str(&ctxt cx, &method m) -> str {
+        ret fn_to_str(cx, m.proto, some[ast::ident](m.ident), m.inputs,
+                      m.output, m.cf, m.constrs) + ";";
+    }
+    fn field_to_str(&ctxt cx, &field f) -> str {
+        ret mt_to_str(cx, f.mt) + " " + f.ident;
+    }
+    fn mt_to_str(&ctxt cx, &mt m) -> str {
+        auto mstr;
+        alt (m.mut) {
+            case (ast::mut) { mstr = "mutable "; }
+            case (ast::imm) { mstr = ""; }
+            case (ast::maybe_mut) { mstr = "mutable? "; }
+        }
+        ret mstr + ty_to_str(cx, m.ty);
+    }
+    alt (cname(cx, typ)) { case (some(?cs)) { ret cs; } case (_) { } }
+    auto s = "";
+    alt (struct(cx, typ)) {
+        case (ty_native(_)) { s += "native"; }
+        case (ty_nil) { s += "()"; }
+        case (ty_bot) { s += "_|_"; }
+        case (ty_bool) { s += "bool"; }
+        case (ty_int) { s += "int"; }
+        case (ty_float) { s += "float"; }
+        case (ty_uint) { s += "uint"; }
+        case (ty_machine(?tm)) { s += ty_mach_to_str(tm); }
+        case (ty_char) { s += "char"; }
+        case (ty_str) { s += "str"; }
+        case (ty_istr) { s += "istr"; }
+        case (ty_box(?tm)) { s += "@" + mt_to_str(cx, tm); }
+        case (ty_vec(?tm)) { s += "vec[" + mt_to_str(cx, tm) + "]"; }
+        case (ty_ivec(?tm)) { s += "ivec[" + mt_to_str(cx, tm) + "]"; }
+        case (ty_port(?t)) { s += "port[" + ty_to_str(cx, t) + "]"; }
+        case (ty_chan(?t)) { s += "chan[" + ty_to_str(cx, t) + "]"; }
+        case (ty_type) { s += "type"; }
+        case (ty_task) { s += "task"; }
+        case (ty_tup(?elems)) {
+            let vec[str] strs = [];
+            for (mt tm in elems) { strs += [mt_to_str(cx, tm)]; }
+            s += "tup(" + str::connect(strs, ",") + ")";
+        }
+        case (ty_rec(?elems)) {
+            let vec[str] strs = [];
+            for (field fld in elems) { strs += [field_to_str(cx, fld)]; }
+            s += "rec(" + str::connect(strs, ",") + ")";
+        }
+        case (ty_tag(?id, ?tps)) {
+            // The user should never see this if the cname is set properly!
+
+            s += "<tag#" + istr(id._0) + ":" + istr(id._1) + ">";
+            if (vec::len[t](tps) > 0u) {
+                auto f = bind ty_to_str(cx, _);
+                auto strs = vec::map[t, str](f, tps);
+                s += "[" + str::connect(strs, ",") + "]";
+            }
+        }
+        case (ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
+            s += fn_to_str(cx, proto, none, inputs, output, cf, constrs);
+        }
+        case (ty_native_fn(_, ?inputs, ?output)) {
+            s += fn_to_str(cx, ast::proto_fn, none, inputs, output,
+                           ast::return, []);
+        }
+        case (ty_obj(?meths)) {
+            auto f = bind method_to_str(cx, _);
+            auto m = vec::map[method, str](f, meths);
+            s += "obj {\n\t" + str::connect(m, "\n\t") + "\n}";
+        }
+        case (ty_res(?id, _, _)) {
+            s += "<resource#" + istr(id._0) + ":" + istr(id._1) + ">";
+        }
+        case (ty_var(?v)) { s += "<T" + istr(v) + ">"; }
+        case (ty_param(?id)) {
+            s += "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)]);
+        }
+        case (_) { s += ty_to_short_str(cx, typ); }
+    }
+    ret s;
+}
+
+fn ty_to_short_str(&ctxt cx, t typ) -> str {
+    auto f = def_to_str;
+    auto ecx = @rec(ds=f, tcx=cx, abbrevs=metadata::tyencode::ac_no_abbrevs);
+    auto s = metadata::tyencode::ty_str(ecx, typ);
+    if (str::byte_len(s) >= 32u) { s = str::substr(s, 0u, 32u); }
+    ret s;
+}
+
+fn constr_to_str(&@constr_def c) -> str {
+    ret ast::path_to_str(c.node.path) +
+        pprust::constr_args_to_str(pprust::uint_to_str, c.node.args);
+}
+
+fn constrs_str(&vec[@constr_def] constrs) -> str {
+    auto s = "";
+    auto colon = true;
+    for (@constr_def c in constrs) {
+        if (colon) { s += " : "; colon = false; } else { s += ", "; }
+        s += constr_to_str(c);
+    }
+    ret s;
+}
+
+// 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:
index 2387d258723901a4389d301f7b33ef656fa5876a..af2403cd4b01d6eed5341b1b45bf10ca7b842723 100644 (file)
@@ -47,6 +47,7 @@ fn to_str(int n, uint radix) -> str {
             "-" + uint::to_str(-n as uint, radix)
         } else { uint::to_str(n as uint, radix) };
 }
+fn str(int i) -> str { ret to_str(i, 10u); }
 
 fn pow(int base, uint exponent) -> int {
     ret if (exponent == 0u) {
index 90b2693bdcfd4757ee56fbda3de6b8c80507a0ab..95214bcbf26256848b51b8c7d6d7be38a6911b08 100644 (file)
@@ -1,6 +1,3 @@
-
-
-
 /**
  * At the moment, this is a partial hashmap implementation, not yet fit for
  * use, but useful as a stress test for rustboot.
@@ -196,6 +193,31 @@ fn rehash() {
     let vec[mutable bucket[K, V]] bkts = make_buckets[K, V](initial_capacity);
     ret hashmap[K, V](hasher, eqer, bkts, initial_capacity, 0u, load_factor);
 }
+
+// Hash map constructors for basic types
+
+fn new_str_hash[V]() -> hashmap[str, V] {
+    let hashfn[str] hasher = str::hash;
+    let eqfn[str] eqer = str::eq;
+    ret mk_hashmap[str, V](hasher, eqer);
+}
+
+fn new_int_hash[V]() -> hashmap[int, V] {
+    fn hash_int(&int x) -> uint { ret x as uint; }
+    fn eq_int(&int a, &int b) -> bool { ret a == b; }
+    auto hasher = hash_int;
+    auto eqer = eq_int;
+    ret mk_hashmap[int, V](hasher, eqer);
+}
+
+fn new_uint_hash[V]() -> hashmap[uint, V] {
+    fn hash_uint(&uint x) -> uint { ret x; }
+    fn eq_uint(&uint a, &uint b) -> bool { ret a == b; }
+    auto hasher = hash_uint;
+    auto eqer = eq_uint;
+    ret mk_hashmap[uint, V](hasher, eqer);
+}
+
 // Local Variables:
 // mode: rust;
 // fill-column: 78;
index ca632914a4592202eba20e843de02331faeffd45..6908aa6342a6261d16553a4d2179653f1bf3dcaf 100644 (file)
@@ -92,6 +92,8 @@ fn digit(uint n) -> char {
     while (len != 0u) { len -= 1u; s1 += str::unsafe_from_byte(s.(len)); }
     ret s1;
 }
+fn str(uint i) -> str { ret to_str(i, 10u); }
+
 // Local Variables:
 // mode: rust;
 // fill-column: 78;
index cf7be9167229635e108f4a184ab49f6a1f978ad3..2a0754779376e93c917812bd72c4e8c5261353dd 100644 (file)
@@ -301,6 +301,19 @@ fn or(&vec[bool] v) -> bool {
     ret vec::foldl[bool, bool](f, false, v);
 }
 
+fn any[T](&fn(&T) -> bool f, &vec[T] v) -> bool {
+    for (T t in v) {
+        if (f(t)) { ret true; } 
+    }
+    ret false;
+}
+fn all[T](&fn(&T) -> bool f, &vec[T] v) -> bool {
+    for (T t in v) {
+        if (!f(t)) { ret false; } 
+    }
+    ret true;
+}
+
 fn clone[T](&vec[T] v) -> vec[T] { ret slice[T](v, 0u, len[T](v)); }
 
 fn plus_option[T](&mutable vec[T] v, &option::t[T] o) {