about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-01-13 09:32:05 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-01-13 11:51:17 +0100
commiteb07fa4d3ba6f98d26930c908cbe400f5ea7d6bb (patch)
tree55932215575f8a632742603ac5e606a1dbe861f7 /src
parent7f6294455963334fec69fc799442ae74ef65b35e (diff)
downloadrust-eb07fa4d3ba6f98d26930c908cbe400f5ea7d6bb.tar.gz
rust-eb07fa4d3ba6f98d26930c908cbe400f5ea7d6bb.zip
Remove all remaining uses of objs from the compiler
Diffstat (limited to 'src')
-rw-r--r--src/comp/back/link.rs4
-rw-r--r--src/comp/lib/llvm.rs42
-rw-r--r--src/comp/middle/debuginfo.rs6
-rw-r--r--src/comp/middle/trans.rs10
-rw-r--r--src/comp/middle/trans_closure.rs2
-rw-r--r--src/comp/middle/trans_common.rs43
-rw-r--r--src/comp/middle/trans_impl.rs2
-rw-r--r--src/comp/syntax/ext/base.rs96
-rw-r--r--src/comp/syntax/print/pp.rs311
-rw-r--r--src/comp/syntax/print/pprust.rs2
-rw-r--r--src/comp/util/filesearch.rs25
11 files changed, 271 insertions, 272 deletions
diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs
index 46984d1ad6f..e16223178e7 100644
--- a/src/comp/back/link.rs
+++ b/src/comp/back/link.rs
@@ -545,7 +545,7 @@ fn mangle_internal_name_by_type_only(ccx: @crate_ctxt, t: ty::t, name: str) ->
 
 fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt, path: [str],
                                         flav: str) -> str {
-    ret mangle(path + [ccx.names.next(flav)]);
+    ret mangle(path + [ccx.names(flav)]);
 }
 
 fn mangle_internal_name_by_path(_ccx: @crate_ctxt, path: [str]) -> str {
@@ -553,7 +553,7 @@ fn mangle_internal_name_by_path(_ccx: @crate_ctxt, path: [str]) -> str {
 }
 
 fn mangle_internal_name_by_seq(ccx: @crate_ctxt, flav: str) -> str {
-    ret ccx.names.next(flav);
+    ret ccx.names(flav);
 }
 
 // If the user wants an exe generated we need to invoke
diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs
index 927e9879657..e3d36e4ed5c 100644
--- a/src/comp/lib/llvm.rs
+++ b/src/comp/lib/llvm.rs
@@ -898,37 +898,27 @@ native mod llvm {
 
 /* Memory-managed object interface to type handles. */
 
-obj type_names(type_names: std::map::hashmap<TypeRef, str>,
-               named_types: std::map::hashmap<str, TypeRef>) {
-
-    fn associate(s: str, t: TypeRef) {
-        assert (!named_types.contains_key(s));
-        assert (!type_names.contains_key(t));
-        type_names.insert(t, s);
-        named_types.insert(s, t);
-    }
-
-    fn type_has_name(t: TypeRef) -> bool { ret type_names.contains_key(t); }
+type type_names = @{type_names: std::map::hashmap<TypeRef, str>,
+                    named_types: std::map::hashmap<str, TypeRef>};
 
-    fn get_name(t: TypeRef) -> str { ret type_names.get(t); }
+fn associate_type(tn: type_names, s: str, t: TypeRef) {
+    assert tn.type_names.insert(t, s);
+    assert tn.named_types.insert(s, t);
+}
 
-    fn name_has_type(s: str) -> bool { ret named_types.contains_key(s); }
+fn type_has_name(tn: type_names, t: TypeRef) -> option::t<str> {
+    ret tn.type_names.find(t);
+}
 
-    fn get_type(s: str) -> TypeRef { ret named_types.get(s); }
+fn name_has_type(tn: type_names, s: str) -> option::t<TypeRef> {
+    ret tn.named_types.find(s);
 }
 
 fn mk_type_names() -> type_names {
-    let nt = std::map::new_str_hash::<TypeRef>();
-
     fn hash(&&t: TypeRef) -> uint { ret t as uint; }
-
     fn eq(&&a: TypeRef, &&b: TypeRef) -> bool { ret a as uint == b as uint; }
-
-    let hasher: std::map::hashfn<TypeRef> = hash;
-    let eqer: std::map::eqfn<TypeRef> = eq;
-    let tn = std::map::mk_hashmap::<TypeRef, str>(hasher, eqer);
-
-    ret type_names(tn, nt);
+    @{type_names: std::map::mk_hashmap(hash, eq),
+      named_types: std::map::new_str_hash()}
 }
 
 fn type_to_str(names: type_names, ty: TypeRef) -> str {
@@ -937,8 +927,10 @@ fn type_to_str(names: type_names, ty: TypeRef) -> str {
 
 fn type_to_str_inner(names: type_names, outer0: [TypeRef], ty: TypeRef) ->
    str {
-
-    if names.type_has_name(ty) { ret names.get_name(ty); }
+    alt type_has_name(names, ty) {
+      option::some(n) { ret n; }
+      _ {}
+    }
 
     let outer = outer0 + [ty];
 
diff --git a/src/comp/middle/debuginfo.rs b/src/comp/middle/debuginfo.rs
index babe01963ef..fab7f625b0f 100644
--- a/src/comp/middle/debuginfo.rs
+++ b/src/comp/middle/debuginfo.rs
@@ -394,7 +394,7 @@ fn create_record(cx: @crate_ctxt, t: ty::t, fields: [ast::ty_field],
     let fname = filename_from_span(cx, span);
     let file_node = create_file(cx, fname);
     let scx = create_structure(file_node,
-                               option::get(cx.dbg_cx).names.next("rec"),
+                               option::get(cx.dbg_cx).names("rec"),
                                line_from_span(cx.sess.codemap,
                                               span) as int);
     for field in fields {
@@ -738,10 +738,10 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
       ast_map::node_expr(expr) {
         alt expr.node {
           ast::expr_fn(_, decl, _, _) {
-            (dbg_cx.names.next("fn"), decl.output, expr.id)
+            (dbg_cx.names("fn"), decl.output, expr.id)
           }
           ast::expr_fn_block(decl, _) {
-            (dbg_cx.names.next("fn"), decl.output, expr.id)
+            (dbg_cx.names("fn"), decl.output, expr.id)
           }
         }
       }
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index dd064a60800..38f9ec7813a 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -4119,7 +4119,7 @@ fn new_block_ctxt(cx: @fn_ctxt, parent: block_parent, kind: block_kind,
     let s = "";
     if cx.lcx.ccx.sess.opts.save_temps ||
            cx.lcx.ccx.sess.opts.debuginfo {
-        s = cx.lcx.ccx.names.next(name);
+        s = cx.lcx.ccx.names(name);
     }
     let llbb: BasicBlockRef =
         str::as_buf(s, {|buf| llvm::LLVMAppendBasicBlock(cx.llfn, buf) });
@@ -5665,13 +5665,13 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
     let float_type = T_float(targ_cfg);
     let task_type = T_task(targ_cfg);
     let taskptr_type = T_ptr(task_type);
-    tn.associate("taskptr", taskptr_type);
+    lib::llvm::associate_type(tn, "taskptr", taskptr_type);
     let tydesc_type = T_tydesc(targ_cfg);
-    tn.associate("tydesc", tydesc_type);
+    lib::llvm::associate_type(tn, "tydesc", tydesc_type);
     let crate_map = decl_crate_map(sess, link_meta.name, llmod);
     let dbg_cx = if sess.opts.debuginfo {
         option::some(@{llmetadata: map::new_int_hash(),
-                       names: namegen(0)})
+                       names: new_namegen()})
     } else {
         option::none
     };
@@ -5696,7 +5696,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           dicts: map::mk_hashmap(hash_dict_id, {|a, b| a == b}),
           module_data: new_str_hash::<ValueRef>(),
           lltypes: ty::new_ty_hash(),
-          names: namegen(0),
+          names: new_namegen(),
           sha: sha,
           type_sha1s: ty::new_ty_hash(),
           type_short_names: ty::new_ty_hash(),
diff --git a/src/comp/middle/trans_closure.rs b/src/comp/middle/trans_closure.rs
index 4bd82d8b803..d4221ea2d25 100644
--- a/src/comp/middle/trans_closure.rs
+++ b/src/comp/middle/trans_closure.rs
@@ -507,7 +507,7 @@ fn trans_expr_fn(bcx: @block_ctxt,
     let ccx = bcx_ccx(bcx), bcx = bcx;
     let fty = node_id_type(ccx, id);
     let llfnty = type_of_fn_from_ty(ccx, sp, fty, []);
-    let sub_cx = extend_path(bcx.fcx.lcx, ccx.names.next("anon"));
+    let sub_cx = extend_path(bcx.fcx.lcx, ccx.names("anon"));
     let s = mangle_internal_name_by_path(ccx, sub_cx.path);
     let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
     register_fn(ccx, sp, sub_cx.path, "anon fn", [], id);
diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs
index c0f110e65c3..1073234923a 100644
--- a/src/comp/middle/trans_common.rs
+++ b/src/comp/middle/trans_common.rs
@@ -14,7 +14,8 @@ import middle::{resolve, ty};
 import back::{link, abi, upcall};
 import util::common::*;
 import syntax::codemap::span;
-import lib::llvm::{llvm, target_data, type_names};
+import lib::llvm::{llvm, target_data, type_names, associate_type,
+                   name_has_type};
 import lib::llvm::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef};
 import lib::llvm::{True, False, Bool};
 import metadata::{csearch};
@@ -22,8 +23,10 @@ import metadata::{csearch};
 // FIXME: These should probably be pulled in here too.
 import trans::{type_of_fn, drop_ty};
 
-obj namegen(mutable i: int) {
-    fn next(prefix: str) -> str { i += 1; ret prefix + int::str(i); }
+type namegen = fn@(str) -> str;
+fn new_namegen() -> namegen {
+    let i = @mutable 0;
+    ret fn@(prefix: str) -> str { *i += 1; prefix + int::str(*i) };
 }
 
 type derived_tydesc_info = {lltydesc: ValueRef, escapes: bool};
@@ -616,17 +619,17 @@ fn T_tydesc_field(cx: @crate_ctxt, field: int) -> TypeRef unsafe {
 
 fn T_glue_fn(cx: @crate_ctxt) -> TypeRef {
     let s = "glue_fn";
-    if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
+    alt name_has_type(cx.tn, s) { some(t) { ret t; } _ {} }
     let t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
-    cx.tn.associate(s, t);
+    associate_type(cx.tn, s, t);
     ret t;
 }
 
 fn T_cmp_glue_fn(cx: @crate_ctxt) -> TypeRef {
     let s = "cmp_glue_fn";
-    if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
+    alt name_has_type(cx.tn, s) { some(t) { ret t; } _ {} }
     let t = T_tydesc_field(cx, abi::tydesc_field_cmp_glue);
-    cx.tn.associate(s, t);
+    associate_type(cx.tn, s, t);
     ret t;
 }
 
@@ -691,9 +694,9 @@ fn T_taskptr(cx: @crate_ctxt) -> TypeRef { ret T_ptr(cx.task_type); }
 // This type must never be used directly; it must always be cast away.
 fn T_typaram(tn: type_names) -> TypeRef {
     let s = "typaram";
-    if tn.name_has_type(s) { ret tn.get_type(s); }
+    alt name_has_type(tn, s) { some(t) { ret t; } _ {} }
     let t = T_i8();
-    tn.associate(s, t);
+    associate_type(tn, s, t);
     ret t;
 }
 
@@ -701,13 +704,13 @@ fn T_typaram_ptr(tn: type_names) -> TypeRef { ret T_ptr(T_typaram(tn)); }
 
 fn T_opaque_cbox_ptr(cx: @crate_ctxt) -> TypeRef {
     let s = "*cbox";
-    if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
+    alt name_has_type(cx.tn, s) { some(t) { ret t; } _ {} }
     let t = T_ptr(T_struct([cx.int_type,
                             T_ptr(cx.tydesc_type),
                             T_i8() /* represents closed over tydescs
                             and data go here; see trans_closure.rs*/
                            ]));
-    cx.tn.associate(s, t);
+    associate_type(cx.tn, s, t);
     ret t;
 }
 
@@ -717,20 +720,20 @@ fn T_tag_variant(cx: @crate_ctxt) -> TypeRef {
 
 fn T_tag(cx: @crate_ctxt, size: uint) -> TypeRef {
     let s = "tag_" + uint::to_str(size, 10u);
-    if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
+    alt name_has_type(cx.tn, s) { some(t) { ret t; } _ {} }
     let t =
         if size == 0u {
             T_struct([T_tag_variant(cx)])
         } else { T_struct([T_tag_variant(cx), T_array(T_i8(), size)]) };
-    cx.tn.associate(s, t);
+    associate_type(cx.tn, s, t);
     ret t;
 }
 
 fn T_opaque_tag(cx: @crate_ctxt) -> TypeRef {
     let s = "opaque_tag";
-    if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
+    alt name_has_type(cx.tn, s) { some(t) { ret t; } _ {} }
     let t = T_struct([T_tag_variant(cx), T_i8()]);
-    cx.tn.associate(s, t);
+    associate_type(cx.tn, s, t);
     ret t;
 }
 
@@ -818,7 +821,7 @@ fn C_cstr(cx: @crate_ctxt, s: str) -> ValueRef {
                         llvm::LLVMConstString(buf, str::byte_len(s), False)
                     });
     let g =
-        str::as_buf(cx.names.next("str"),
+        str::as_buf(cx.names("str"),
                     {|buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf) });
     llvm::LLVMSetInitializer(g, sc);
     llvm::LLVMSetGlobalConstant(g, True);
@@ -865,11 +868,9 @@ fn C_bytes(bytes: [u8]) -> ValueRef unsafe {
 
 fn C_shape(ccx: @crate_ctxt, bytes: [u8]) -> ValueRef {
     let llshape = C_bytes(bytes);
-    let llglobal =
-        str::as_buf(ccx.names.next("shape"),
-                    {|buf|
-                        llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
-                    });
+    let llglobal = str::as_buf(ccx.names("shape"), {|buf|
+        llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
+    });
     llvm::LLVMSetInitializer(llglobal, llshape);
     llvm::LLVMSetGlobalConstant(llglobal, True);
     llvm::LLVMSetLinkage(llglobal,
diff --git a/src/comp/middle/trans_impl.rs b/src/comp/middle/trans_impl.rs
index 0a883c193f8..55886df07d5 100644
--- a/src/comp/middle/trans_impl.rs
+++ b/src/comp/middle/trans_impl.rs
@@ -340,7 +340,7 @@ fn get_static_dict(bcx: @block_ctxt, origin: typeck::dict_origin)
       none. {}
     }
     let ptrs = C_struct(get_dict_ptrs(bcx, origin).ptrs);
-    let name = ccx.names.next("dict");
+    let name = ccx.names("dict");
     let gvar = str::as_buf(name, {|buf|
         llvm::LLVMAddGlobal(ccx.llmod, val_ty(ptrs), buf)
     });
diff --git a/src/comp/syntax/ext/base.rs b/src/comp/syntax/ext/base.rs
index 0ace58ff953..0dee29db0f9 100644
--- a/src/comp/syntax/ext/base.rs
+++ b/src/comp/syntax/ext/base.rs
@@ -33,54 +33,60 @@ fn syntax_expander_table() -> hashmap<str, syntax_extension> {
     ret syntax_expanders;
 }
 
-obj ext_ctxt(sess: session,
-             mutable backtrace: codemap::opt_span) {
-
-    fn session() -> session { ret sess; }
-
-    fn print_backtrace() { }
-
-    fn backtrace() -> codemap::opt_span { ret backtrace; }
-
-    fn bt_push(sp: span) {
-        backtrace =
-            codemap::os_some(@{lo: sp.lo,
-                               hi: sp.hi,
-                               expanded_from: backtrace});
-    }
-    fn bt_pop() {
-        alt backtrace {
-          codemap::os_some(@{expanded_from: pre, _}) {
-            let tmp = pre;
-            backtrace = tmp;
-          }
-          _ { self.bug("tried to pop without a push"); }
-        }
-    }
-
-    fn span_fatal(sp: span, msg: str) -> ! {
-        self.print_backtrace();
-        sess.span_fatal(sp, msg);
-    }
-    fn span_err(sp: span, msg: str) {
-        self.print_backtrace();
-        sess.span_err(sp, msg);
-    }
-    fn span_unimpl(sp: span, msg: str) -> ! {
-        self.print_backtrace();
-        sess.span_unimpl(sp, msg);
-    }
-    fn span_bug(sp: span, msg: str) -> ! {
-        self.print_backtrace();
-        sess.span_bug(sp, msg);
-    }
-    fn bug(msg: str) -> ! { self.print_backtrace(); sess.bug(msg); }
-    fn next_id() -> ast::node_id { ret sess.next_node_id(); }
-
+iface ext_ctxt {
+    fn session() -> session;
+    fn print_backtrace();
+    fn backtrace() -> codemap::opt_span;
+    fn bt_push(sp: span);
+    fn bt_pop();
+    fn span_fatal(sp: span, msg: str) -> !;
+    fn span_err(sp: span, msg: str);
+    fn span_unimpl(sp: span, msg: str) -> !;
+    fn span_bug(sp: span, msg: str) -> !;
+    fn bug(msg: str) -> !;
+    fn next_id() -> ast::node_id;
 }
 
 fn mk_ctxt(sess: session) -> ext_ctxt {
-    ret ext_ctxt(sess, codemap::os_none);
+    type ctxt_repr = {sess: session,
+                      mutable backtrace: codemap::opt_span};
+    impl of ext_ctxt for ctxt_repr {
+        fn session() -> session { self.sess }
+        fn print_backtrace() { }
+        fn backtrace() -> codemap::opt_span { self.backtrace }
+        fn bt_push(sp: span) {
+            self.backtrace = codemap::os_some(
+                @{lo: sp.lo, hi: sp.hi, expanded_from: self.backtrace});
+        }
+        fn bt_pop() {
+            alt self.backtrace {
+              codemap::os_some(@{expanded_from: pre, _}) {
+                let tmp = pre;
+                self.backtrace = tmp;
+              }
+              _ { self.bug("tried to pop without a push"); }
+            }
+        }
+        fn span_fatal(sp: span, msg: str) -> ! {
+            self.print_backtrace();
+            self.sess.span_fatal(sp, msg);
+        }
+        fn span_err(sp: span, msg: str) {
+            self.print_backtrace();
+            self.sess.span_err(sp, msg);
+        }
+        fn span_unimpl(sp: span, msg: str) -> ! {
+            self.print_backtrace();
+            self.sess.span_unimpl(sp, msg);
+        }
+        fn span_bug(sp: span, msg: str) -> ! {
+            self.print_backtrace();
+            self.sess.span_bug(sp, msg);
+        }
+        fn bug(msg: str) -> ! { self.print_backtrace(); self.sess.bug(msg); }
+        fn next_id() -> ast::node_id { ret self.sess.next_node_id(); }
+    }
+    {sess: sess, mutable backtrace: codemap::os_none} as ext_ctxt
 }
 
 fn expr_to_str(cx: ext_ctxt, expr: @ast::expr, error: str) -> str {
diff --git a/src/comp/syntax/print/pp.rs b/src/comp/syntax/print/pp.rs
index ac4d92c47b2..eea0bfbcfec 100644
--- a/src/comp/syntax/print/pp.rs
+++ b/src/comp/syntax/print/pp.rs
@@ -100,23 +100,28 @@ const size_infinity: int = 0xffff;
 fn mk_printer(out: io::writer, linewidth: uint) -> printer {
     // Yes 3, it makes the ring buffers big enough to never
     // fall behind.
-
     let n: uint = 3u * linewidth;
     #debug("mk_printer %u", linewidth);
     let token: [mutable token] = vec::init_elt_mut(EOF, n);
     let size: [mutable int] = vec::init_elt_mut(0, n);
     let scan_stack: [mutable uint] = vec::init_elt_mut(0u, n);
     let print_stack: [print_stack_elt] = [];
-    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);
+    @{out: out,
+      buf_len: n,
+      mutable margin: linewidth as int,
+      mutable space: linewidth as int,
+      mutable left: 0u,
+      mutable right: 0u,
+      mutable token: token,
+      mutable size: size,
+      mutable left_total: 0,
+      mutable right_total: 0,
+      mutable scan_stack: scan_stack,
+      mutable scan_stack_empty: true,
+      mutable top: 0u,
+      mutable bottom: 0u,
+      mutable print_stack: print_stack,
+      mutable pending_indentation: 0}
 }
 
 
@@ -197,108 +202,96 @@ fn mk_printer(out: io::writer, linewidth: uint) -> printer {
  * the method called 'pretty_print', and the 'PRINT' process is the method
  * called 'print'.
  */
-obj printer(out: io::writer,
-            buf_len: uint,
-            mutable margin: int, // width of lines we're constrained to
-
-            mutable space: int, // number of spaces left on line
-
-            mutable left: uint, // index of left side of input stream
-
-            mutable right: uint, // index of right side of input stream
-
-            mutable token: [mutable token],
-
-            // ring-buffr stream goes through
-            mutable size: [mutable int], // ring-buffer of calculated sizes
-
-            mutable left_total: int, // running size of stream "...left"
-
-            mutable right_total: int, // 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 scan_stack: [mutable uint],
-            mutable scan_stack_empty: bool, // top==bottom disambiguator
-
-            mutable top: uint, // index of top of scan_stack
-
-            mutable bottom: uint, // index of bottom of scan_stack
-
-             // stack of blocks-in-progress being flushed by print
-            mutable print_stack: [print_stack_elt],
-
-
-            // buffered indentation to avoid writing trailing whitespace
-            mutable pending_indentation: int) {
-
-    fn last_token() -> token { ret token[right]; }
-
+type printer = @{
+    out: io::writer,
+    buf_len: uint,
+    mutable margin: int, // width of lines we're constrained to
+    mutable space: int, // number of spaces left on line
+    mutable left: uint, // index of left side of input stream
+    mutable right: uint, // index of right side of input stream
+    mutable token: [mutable token], // ring-buffr stream goes through
+    mutable size: [mutable int], // ring-buffer of calculated sizes
+    mutable left_total: int, // running size of stream "...left"
+    mutable right_total: int, // 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 scan_stack: [mutable uint],
+    mutable scan_stack_empty: bool, // top==bottom disambiguator
+    mutable top: uint, // index of top of scan_stack
+    mutable bottom: uint, // index of bottom of scan_stack
+    // stack of blocks-in-progress being flushed by print
+    mutable print_stack: [print_stack_elt],
+    // buffered indentation to avoid writing trailing whitespace
+    mutable pending_indentation: int
+};
+
+impl printer for printer {
+    fn last_token() -> token { self.token[self.right] }
     // be very careful with this!
-    fn replace_last_token(t: token) { token[right] = t; }
-
+    fn replace_last_token(t: token) { self.token[self.right] = t; }
     fn pretty_print(t: token) {
-        #debug("pp [%u,%u]", left, right);
+        #debug("pp [%u,%u]", self.left, self.right);
         alt t {
           EOF. {
-            if !scan_stack_empty {
+            if !self.scan_stack_empty {
                 self.check_stack(0);
-                self.advance_left(token[left], size[left]);
+                self.advance_left(self.token[self.left],
+                                  self.size[self.left]);
             }
             self.indent(0);
           }
           BEGIN(b) {
-            if scan_stack_empty {
-                left_total = 1;
-                right_total = 1;
-                left = 0u;
-                right = 0u;
+            if self.scan_stack_empty {
+                self.left_total = 1;
+                self.right_total = 1;
+                self.left = 0u;
+                self.right = 0u;
             } else { self.advance_right(); }
-            #debug("pp BEGIN/buffer [%u,%u]", left, right);
-            token[right] = t;
-            size[right] = -right_total;
-            self.scan_push(right);
+            #debug("pp BEGIN/buffer [%u,%u]", self.left, self.right);
+            self.token[self.right] = t;
+            self.size[self.right] = -self.right_total;
+            self.scan_push(self.right);
           }
           END. {
-            if scan_stack_empty {
-                #debug("pp END/print [%u,%u]", left, right);
+            if self.scan_stack_empty {
+                #debug("pp END/print [%u,%u]", self.left, self.right);
                 self.print(t, 0);
             } else {
-                #debug("pp END/buffer [%u,%u]", left, right);
+                #debug("pp END/buffer [%u,%u]", self.left, self.right);
                 self.advance_right();
-                token[right] = t;
-                size[right] = -1;
-                self.scan_push(right);
+                self.token[self.right] = t;
+                self.size[self.right] = -1;
+                self.scan_push(self.right);
             }
           }
           BREAK(b) {
-            if scan_stack_empty {
-                left_total = 1;
-                right_total = 1;
-                left = 0u;
-                right = 0u;
+            if self.scan_stack_empty {
+                self.left_total = 1;
+                self.right_total = 1;
+                self.left = 0u;
+                self.right = 0u;
             } else { self.advance_right(); }
-            #debug("pp BREAK/buffer [%u,%u]", left, right);
+            #debug("pp BREAK/buffer [%u,%u]", self.left, self.right);
             self.check_stack(0);
-            self.scan_push(right);
-            token[right] = t;
-            size[right] = -right_total;
-            right_total += b.blank_space;
+            self.scan_push(self.right);
+            self.token[self.right] = t;
+            self.size[self.right] = -self.right_total;
+            self.right_total += b.blank_space;
           }
           STRING(s, len) {
-            if scan_stack_empty {
-                #debug("pp STRING/print [%u,%u]", left, right);
+            if self.scan_stack_empty {
+                #debug("pp STRING/print [%u,%u]", self.left, self.right);
                 self.print(t, len);
             } else {
-                #debug("pp STRING/buffer [%u,%u]", left, right);
+                #debug("pp STRING/buffer [%u,%u]", self.left, self.right);
                 self.advance_right();
-                token[right] = t;
-                size[right] = len;
-                right_total += len;
+                self.token[self.right] = t;
+                self.size[self.right] = len;
+                self.right_total += len;
                 self.check_stream();
             }
           }
@@ -306,83 +299,92 @@ obj printer(out: io::writer,
     }
     fn check_stream() {
         #debug("check_stream [%u, %u] with left_total=%d, right_total=%d",
-               left, right, left_total, right_total);
-        if right_total - left_total > space {
+               self.left, self.right, self.left_total, self.right_total);
+        if self.right_total - self.left_total > self.space {
             #debug("scan window is %d, longer than space on line (%d)",
-                   right_total - left_total, space);
-            if !scan_stack_empty {
-                if left == scan_stack[bottom] {
-                    #debug("setting %u to infinity and popping", left);
-                    size[self.scan_pop_bottom()] = size_infinity;
+                   self.right_total - self.left_total, self.space);
+            if !self.scan_stack_empty {
+                if self.left == self.scan_stack[self.bottom] {
+                    #debug("setting %u to infinity and popping", self.left);
+                    self.size[self.scan_pop_bottom()] = size_infinity;
                 }
             }
-            self.advance_left(token[left], size[left]);
-            if left != right { self.check_stream(); }
+            self.advance_left(self.token[self.left], self.size[self.left]);
+            if self.left != self.right { self.check_stream(); }
         }
     }
     fn scan_push(x: uint) {
         #debug("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;
+        if self.scan_stack_empty {
+            self.scan_stack_empty = false;
+        } else {
+            self.top += 1u;
+            self.top %= self.buf_len;
+            assert (self.top != self.bottom);
+        }
+        self.scan_stack[self.top] = x;
     }
     fn scan_pop() -> uint {
-        assert (!scan_stack_empty);
-        let x = scan_stack[top];
-        if top == bottom {
-            scan_stack_empty = true;
-        } else { top += buf_len - 1u; top %= buf_len; }
+        assert (!self.scan_stack_empty);
+        let x = self.scan_stack[self.top];
+        if self.top == self.bottom {
+            self.scan_stack_empty = true;
+        } else { self.top += self.buf_len - 1u; self.top %= self.buf_len; }
         ret x;
     }
-    fn scan_top() -> uint { assert (!scan_stack_empty); ret scan_stack[top]; }
+    fn scan_top() -> uint {
+        assert (!self.scan_stack_empty);
+        ret self.scan_stack[self.top];
+    }
     fn scan_pop_bottom() -> uint {
-        assert (!scan_stack_empty);
-        let x = scan_stack[bottom];
-        if top == bottom {
-            scan_stack_empty = true;
-        } else { bottom += 1u; bottom %= buf_len; }
+        assert (!self.scan_stack_empty);
+        let x = self.scan_stack[self.bottom];
+        if self.top == self.bottom {
+            self.scan_stack_empty = true;
+        } else { self.bottom += 1u; self.bottom %= self.buf_len; }
         ret x;
     }
     fn advance_right() {
-        right += 1u;
-        right %= buf_len;
-        assert (right != left);
+        self.right += 1u;
+        self.right %= self.buf_len;
+        assert (self.right != self.left);
     }
     fn advance_left(x: token, L: int) {
-        #debug("advnce_left [%u,%u], sizeof(%u)=%d", left, right, left, L);
+        #debug("advnce_left [%u,%u], sizeof(%u)=%d", self.left, self.right,
+               self.left, L);
         if L >= 0 {
             self.print(x, L);
             alt x {
-              BREAK(b) { left_total += b.blank_space; }
-              STRING(_, len) { assert (len == L); left_total += len; }
+              BREAK(b) { self.left_total += b.blank_space; }
+              STRING(_, len) { assert (len == L); self.left_total += len; }
               _ { }
             }
-            if left != right {
-                left += 1u;
-                left %= buf_len;
-                self.advance_left(token[left], size[left]);
+            if self.left != self.right {
+                self.left += 1u;
+                self.left %= self.buf_len;
+                self.advance_left(self.token[self.left],
+                                  self.size[self.left]);
             }
         }
     }
     fn check_stack(k: int) {
-        if !scan_stack_empty {
+        if !self.scan_stack_empty {
             let x = self.scan_top();
-            alt token[x] {
+            alt self.token[x] {
               BEGIN(b) {
                 if k > 0 {
-                    size[self.scan_pop()] = size[x] + right_total;
+                    self.size[self.scan_pop()] = self.size[x] +
+                        self.right_total;
                     self.check_stack(k - 1);
                 }
               }
               END. {
                 // paper says + not =, but that makes no sense.
-
-                size[self.scan_pop()] = 1;
+                self.size[self.scan_pop()] = 1;
                 self.check_stack(k + 1);
               }
               _ {
-                size[self.scan_pop()] = size[x] + right_total;
+                self.size[self.scan_pop()] = self.size[x] + self.right_total;
                 if k > 0 { self.check_stack(k); }
               }
             }
@@ -390,69 +392,69 @@ obj printer(out: io::writer,
     }
     fn print_newline(amount: int) {
         #debug("NEWLINE %d", amount);
-        out.write_str("\n");
-        pending_indentation = 0;
+        self.out.write_str("\n");
+        self.pending_indentation = 0;
         self.indent(amount);
     }
     fn indent(amount: int) {
         #debug("INDENT %d", amount);
-        pending_indentation += amount;
+        self.pending_indentation += amount;
     }
-    fn top() -> print_stack_elt {
-        let n = vec::len(print_stack);
+    fn get_top() -> print_stack_elt {
+        let n = vec::len(self.print_stack);
         let top: print_stack_elt = {offset: 0, pbreak: broken(inconsistent)};
-        if n != 0u { top = print_stack[n - 1u]; }
+        if n != 0u { top = self.print_stack[n - 1u]; }
         ret top;
     }
     fn write_str(s: str) {
-        while pending_indentation > 0 {
-            out.write_str(" ");
-            pending_indentation -= 1;
+        while self.pending_indentation > 0 {
+            self.out.write_str(" ");
+            self.pending_indentation -= 1;
         }
-        out.write_str(s);
+        self.out.write_str(s);
     }
     fn print(x: token, L: int) {
         #debug("print %s %d (remaining line space=%d)", tok_str(x), L,
-               space);
-        log(debug, buf_str(token, size, left, right, 6u));
+               self.space);
+        log(debug, buf_str(self.token, self.size, self.left, self.right, 6u));
         alt x {
           BEGIN(b) {
-            if L > space {
-                let col = margin - space + b.offset;
+            if L > self.space {
+                let col = self.margin - self.space + b.offset;
                 #debug("print BEGIN -> push broken block at col %d", col);
-                print_stack += [{offset: col, pbreak: broken(b.breaks)}];
+                self.print_stack += [{offset: col, pbreak: broken(b.breaks)}];
             } else {
                 #debug("print BEGIN -> push fitting block");
-                print_stack += [{offset: 0, pbreak: fits}];
+                self.print_stack += [{offset: 0, pbreak: fits}];
             }
           }
           END. {
             #debug("print END -> pop END");
-            assert (vec::len(print_stack) != 0u);
-            vec::pop(print_stack);
+            assert (vec::len(self.print_stack) != 0u);
+            vec::pop(self.print_stack);
           }
           BREAK(b) {
-            let top = self.top();
+            let top = self.get_top();
             alt top.pbreak {
               fits. {
                 #debug("print BREAK in fitting block");
-                space -= b.blank_space;
+                self.space -= b.blank_space;
                 self.indent(b.blank_space);
               }
               broken(consistent.) {
                 #debug("print BREAK in consistent block");
                 self.print_newline(top.offset + b.offset);
-                space = margin - (top.offset + b.offset);
+                self.space = self.margin - (top.offset + b.offset);
               }
               broken(inconsistent.) {
-                if L > space {
+                if L > self.space {
                     #debug("print BREAK w/ newline in inconsistent");
                     self.print_newline(top.offset + b.offset);
-                    space = margin - (top.offset + b.offset);
+                    self.space = self.margin - (top.offset + b.offset);
                 } else {
                     #debug("print BREAK w/o newline in inconsistent");
                     self.indent(b.blank_space);
-                    space -= b.blank_space;
+                    self.space -= b.blank_space;
                 }
               }
             }
@@ -461,20 +463,17 @@ obj printer(out: io::writer,
             #debug("print STRING");
             assert (L == len);
             // assert L <= space;
-
-            space -= len;
+            self.space -= len;
             self.write_str(s);
           }
           EOF. {
             // EOF should never get here.
-
             fail;
           }
         }
     }
 }
 
-
 // Convenience functions to talk to the printer.
 fn box(p: printer, indent: uint, b: breaks) {
     p.pretty_print(BEGIN({offset: indent as int, breaks: b}));
diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs
index 3e0f3503ef1..50fb51986fe 100644
--- a/src/comp/syntax/print/pprust.rs
+++ b/src/comp/syntax/print/pprust.rs
@@ -6,7 +6,7 @@ import syntax::codemap::codemap;
 import ast;
 import ast_util;
 import option::{some, none};
-import pp::{break_offset, word,
+import pp::{break_offset, word, printer,
             space, zerobreak, hardbreak, breaks, consistent,
             inconsistent, eof};
 
diff --git a/src/comp/util/filesearch.rs b/src/comp/util/filesearch.rs
index e030ddeed40..7aceaf1ef1a 100644
--- a/src/comp/util/filesearch.rs
+++ b/src/comp/util/filesearch.rs
@@ -24,33 +24,32 @@ fn pick_file(file: fs::path, path: fs::path) -> option::t<fs::path> {
     else { option::none }
 }
 
-type filesearch = obj {
+iface filesearch {
     fn sysroot() -> fs::path;
     fn lib_search_paths() -> [fs::path];
     fn get_target_lib_path() -> fs::path;
     fn get_target_lib_file_path(file: fs::path) -> fs::path;
-};
+}
 
 fn mk_filesearch(maybe_sysroot: option::t<fs::path>,
                  target_triple: str,
                  addl_lib_search_paths: [fs::path]) -> filesearch {
-    obj filesearch_impl(sysroot: fs::path,
-                        addl_lib_search_paths: [fs::path],
-                        target_triple: str) {
-        fn sysroot() -> fs::path { sysroot }
+    type filesearch_impl = {sysroot: fs::path,
+                            addl_lib_search_paths: [fs::path],
+                            target_triple: str};
+    impl of filesearch for filesearch_impl {
+        fn sysroot() -> fs::path { self.sysroot }
         fn lib_search_paths() -> [fs::path] {
-            addl_lib_search_paths
-                + [make_target_lib_path(sysroot, target_triple)]
+            self.addl_lib_search_paths
+                + [make_target_lib_path(self.sysroot, self.target_triple)]
                 + alt get_cargo_lib_path() {
                   result::ok(p) { [p] }
                   result::err(p) { [] }
                 }
         }
-
         fn get_target_lib_path() -> fs::path {
-            make_target_lib_path(sysroot, target_triple)
+            make_target_lib_path(self.sysroot, self.target_triple)
         }
-
         fn get_target_lib_file_path(file: fs::path) -> fs::path {
             fs::connect(self.get_target_lib_path(), file)
         }
@@ -58,7 +57,9 @@ fn mk_filesearch(maybe_sysroot: option::t<fs::path>,
 
     let sysroot = get_sysroot(maybe_sysroot);
     #debug("using sysroot = %s", sysroot);
-    ret filesearch_impl(sysroot, addl_lib_search_paths, target_triple);
+    {sysroot: sysroot,
+     addl_lib_search_paths: addl_lib_search_paths,
+     target_triple: target_triple} as filesearch
 }
 
 // FIXME #1001: This can't be an obj method