about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2012-07-18 16:18:02 -0700
committerPaul Stansifer <paul.stansifer@gmail.com>2012-08-22 14:59:25 -0700
commit1153b5dcc86c3567b0a86e441938f05d4f2e295b (patch)
treefdcbcea39abecb4ad1ea5145e62e8c013b05e930 /src/libsyntax/ext
parent7317bf8792ebb3f27768109b7d574ee0806cc5e5 (diff)
intern identifiers
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/auto_serialize.rs73
-rw-r--r--src/libsyntax/ext/base.rs34
-rw-r--r--src/libsyntax/ext/concat_idents.rs8
-rw-r--r--src/libsyntax/ext/expand.rs16
-rw-r--r--src/libsyntax/ext/fmt.rs26
-rw-r--r--src/libsyntax/ext/ident_to_str.rs4
-rw-r--r--src/libsyntax/ext/log_syntax.rs3
-rw-r--r--src/libsyntax/ext/pipes.rs2
-rw-r--r--src/libsyntax/ext/pipes/ast_builder.rs15
-rw-r--r--src/libsyntax/ext/pipes/check.rs10
-rw-r--r--src/libsyntax/ext/pipes/liveness.rs6
-rw-r--r--src/libsyntax/ext/pipes/parse_proto.rs15
-rw-r--r--src/libsyntax/ext/pipes/pipec.rs142
-rw-r--r--src/libsyntax/ext/pipes/proto.rs41
-rw-r--r--src/libsyntax/ext/qquote.rs57
-rw-r--r--src/libsyntax/ext/simplext.rs33
-rw-r--r--src/libsyntax/ext/source_util.rs5
-rw-r--r--src/libsyntax/ext/trace_macros.rs6
-rw-r--r--src/libsyntax/ext/tt/earley_parser.rs13
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs19
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs14
21 files changed, 298 insertions, 244 deletions
diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs
index 1fc77bae8bf..e5b65b41fc8 100644
--- a/src/libsyntax/ext/auto_serialize.rs
+++ b/src/libsyntax/ext/auto_serialize.rs
@@ -84,15 +84,15 @@ mod syntax {
     export parse;
 }
 
-type ser_tps_map = map::hashmap<~str, fn@(@ast::expr) -> ~[@ast::stmt]>;
-type deser_tps_map = map::hashmap<~str, fn@() -> @ast::expr>;
+type ser_tps_map = map::hashmap<ast::ident, fn@(@ast::expr) -> ~[@ast::stmt]>;
+type deser_tps_map = map::hashmap<ast::ident, fn@() -> @ast::expr>;
 
 fn expand(cx: ext_ctxt,
           span: span,
           _mitem: ast::meta_item,
           in_items: ~[@ast::item]) -> ~[@ast::item] {
     fn not_auto_serialize(a: ast::attribute) -> bool {
-        attr::get_attr_name(a) != @~"auto_serialize"
+        attr::get_attr_name(a) != ~"auto_serialize"
     }
 
     fn filter_attrs(item: @ast::item) -> @ast::item {
@@ -156,7 +156,11 @@ impl ext_ctxt: ext_ctxt_helpers {
         let head = vec::init(base_path.idents);
         let tail = vec::last(base_path.idents);
         self.path(base_path.span,
-                  vec::append(head, ~[@(helper_name + ~"_" + *tail)]))
+                  vec::append(head,
+                              ~[self.parse_sess().interner.
+                                intern(@(helper_name + ~"_" +
+                                         *self.parse_sess().interner.get(
+                                             tail)))]))
     }
 
     fn path(span: span, strs: ~[ast::ident]) -> @ast::path {
@@ -181,7 +185,7 @@ impl ext_ctxt: ext_ctxt_helpers {
         let args = do vec::map(input_tys) |ty| {
             {mode: ast::expl(ast::by_ref),
              ty: ty,
-             ident: @~"",
+             ident: parse::token::special_idents::invalid,
              id: self.next_id()}
         };
 
@@ -352,7 +356,7 @@ fn ser_variant(cx: ext_ctxt,
                argfn: fn(-@ast::expr, uint, ast::blk) -> @ast::expr)
     -> ast::arm {
     let vnames = do vec::from_fn(vec::len(tys)) |i| {
-        @fmt!{"__v%u", i}
+        cx.parse_sess().interner.intern(@fmt!{"__v%u", i})
     };
     let pats = do vec::from_fn(vec::len(tys)) |i| {
         cx.binder_pat(tys[i].span, vnames[i])
@@ -384,7 +388,7 @@ fn is_vec_or_str(ty: @ast::ty) -> bool {
       // This may be wrong if the user has shadowed (!) str
       ast::ty_path(@{span: _, global: _, idents: ids,
                              rp: none, types: _}, _)
-      if ids == ~[@~"str"] => true,
+      if ids == ~[parse::token::special_idents::str] => true,
       _ => false
     }
 }
@@ -434,7 +438,8 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
                                              fld.node.ident,
                                              ~[]));
             let s = cx.clone(s);
-            let f = cx.lit_str(fld.span, fld.node.ident);
+            let f = cx.lit_str(fld.span, cx.parse_sess().interner.get(
+                fld.node.ident));
             let i = cx.lit_uint(fld.span, fidx);
             let l = ser_lambda(cx, tps, fld.node.mt.ty, cx.clone(s), vf);
             #ast[stmt]{$(s).emit_rec_field($(f), $(i), $(l));}
@@ -487,7 +492,7 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
             vec::is_empty(path.types) {
             let ident = path.idents[0];
 
-            match tps.find(*ident) {
+            match tps.find(ident) {
               some(f) => f(v),
               none => ser_path(cx, tps, path, s, v)
             }
@@ -545,7 +550,7 @@ fn mk_ser_fn(cx: ext_ctxt, span: span, name: ast::ident,
              ty: cx.ty_fn(span,
                           ~[cx.ty_path(span, ~[tp.ident], ~[])],
                           cx.ty_nil(span)),
-             ident: @(~"__s" + *tp.ident),
+             ident: cx.ident_of(~"__s" + cx.str_of(tp.ident)),
              id: cx.next_id()});
 
     debug!{"tp_inputs = %?", tp_inputs};
@@ -553,35 +558,36 @@ fn mk_ser_fn(cx: ext_ctxt, span: span, name: ast::ident,
 
     let ser_inputs: ~[ast::arg] =
         vec::append(~[{mode: ast::expl(ast::by_ref),
-                      ty: cx.ty_path(span, ~[@~"__S"], ~[]),
-                      ident: @~"__s",
+                      ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]),
+                      ident: cx.ident_of(~"__s"),
                       id: cx.next_id()},
                      {mode: ast::expl(ast::by_ref),
                       ty: v_ty,
-                      ident: @~"__v",
+                      ident: cx.ident_of(~"__v"),
                       id: cx.next_id()}],
                     tp_inputs);
 
-    let tps_map = map::str_hash();
+    let tps_map = map::uint_hash();
     do vec::iter2(tps, tp_inputs) |tp, arg| {
         let arg_ident = arg.ident;
         tps_map.insert(
-            *tp.ident,
+            tp.ident,
             fn@(v: @ast::expr) -> ~[@ast::stmt] {
                 let f = cx.var_ref(span, arg_ident);
-                debug!{"serializing type arg %s", *arg_ident};
+                debug!{"serializing type arg %s", cx.str_of(arg_ident)};
                 ~[#ast[stmt]{$(f)($(v));}]
             });
     }
 
     let ser_bnds = @~[
         ast::bound_trait(cx.ty_path(span,
-                                    ~[@~"std", @~"serialization",
-                                     @~"serializer"],
+                                    ~[cx.ident_of(~"std"),
+                                      cx.ident_of(~"serialization"),
+                                      cx.ident_of(~"serializer")],
                                     ~[]))];
 
     let ser_tps: ~[ast::ty_param] =
-        vec::append(~[{ident: @~"__S",
+        vec::append(~[{ident: cx.ident_of(~"__S"),
                       id: cx.next_id(),
                       bounds: ser_bnds}],
                     vec::map(tps, |tp| cx.clone_ty_param(tp)));
@@ -593,7 +599,7 @@ fn mk_ser_fn(cx: ext_ctxt, span: span, name: ast::ident,
     let ser_blk = cx.blk(span,
                          f(cx, tps_map, #ast{ __s }, #ast{ __v }));
 
-    @{ident: @(~"serialize_" + *name),
+    @{ident: cx.ident_of(~"serialize_" + cx.str_of(name)),
       attrs: ~[],
       id: cx.next_id(),
       node: ast::item_fn({inputs: ser_inputs,
@@ -670,7 +676,7 @@ fn deser_ty(cx: ext_ctxt, tps: deser_tps_map,
         let fields = do vec::from_fn(vec::len(flds)) |fidx| {
             let fld = flds[fidx];
             let d = cx.clone(d);
-            let f = cx.lit_str(fld.span, fld.node.ident);
+            let f = cx.lit_str(fld.span, @cx.str_of(fld.node.ident));
             let i = cx.lit_uint(fld.span, fidx);
             let l = deser_lambda(cx, tps, fld.node.mt.ty, cx.clone(d));
             {node: {mutbl: fld.node.mt.mutbl,
@@ -713,7 +719,7 @@ fn deser_ty(cx: ext_ctxt, tps: deser_tps_map,
             vec::is_empty(path.types) {
             let ident = path.idents[0];
 
-            match tps.find(*ident) {
+            match tps.find(ident) {
               some(f) => f(),
               none => deser_path(cx, tps, path, d)
             }
@@ -756,23 +762,23 @@ fn mk_deser_fn(cx: ext_ctxt, span: span,
              ty: cx.ty_fn(span,
                           ~[],
                           cx.ty_path(span, ~[tp.ident], ~[])),
-             ident: @(~"__d" + *tp.ident),
+             ident: cx.ident_of(~"__d" + cx.str_of(tp.ident)),
              id: cx.next_id()});
 
     debug!{"tp_inputs = %?", tp_inputs};
 
     let deser_inputs: ~[ast::arg] =
         vec::append(~[{mode: ast::expl(ast::by_ref),
-                      ty: cx.ty_path(span, ~[@~"__D"], ~[]),
-                      ident: @~"__d",
+                      ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]),
+                      ident: cx.ident_of(~"__d"),
                       id: cx.next_id()}],
                     tp_inputs);
 
-    let tps_map = map::str_hash();
+    let tps_map = map::uint_hash();
     do vec::iter2(tps, tp_inputs) |tp, arg| {
         let arg_ident = arg.ident;
         tps_map.insert(
-            *tp.ident,
+            tp.ident,
             fn@() -> @ast::expr {
                 let f = cx.var_ref(span, arg_ident);
                 #ast{ $(f)() }
@@ -782,11 +788,12 @@ fn mk_deser_fn(cx: ext_ctxt, span: span,
     let deser_bnds = @~[
         ast::bound_trait(cx.ty_path(
             span,
-            ~[@~"std", @~"serialization", @~"deserializer"],
+            ~[cx.ident_of(~"std"), cx.ident_of(~"serialization"),
+              cx.ident_of(~"deserializer")],
             ~[]))];
 
     let deser_tps: ~[ast::ty_param] =
-        vec::append(~[{ident: @~"__D",
+        vec::append(~[{ident: cx.ident_of(~"__D"),
                       id: cx.next_id(),
                       bounds: deser_bnds}],
                     vec::map(tps, |tp| {
@@ -798,7 +805,7 @@ fn mk_deser_fn(cx: ext_ctxt, span: span,
 
     let deser_blk = cx.expr_blk(f(cx, tps_map, #ast[expr]{__d}));
 
-    @{ident: @(~"deserialize_" + *name),
+    @{ident: cx.ident_of(~"deserialize_" + cx.str_of(name)),
       attrs: ~[],
       id: cx.next_id(),
       node: ast::item_fn({inputs: deser_inputs,
@@ -853,7 +860,7 @@ fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident,
                     // Generate body s.emit_enum_variant("foo", 0u,
                     //                                   3u, {|| blk })
                     |-s, blk| {
-                        let v_name = cx.lit_str(v_span, v_name);
+                        let v_name = cx.lit_str(v_span, @cx.str_of(v_name));
                         let v_id = cx.lit_uint(v_span, vidx);
                         let sz = cx.lit_uint(v_span, vec::len(variant_tys));
                         let body = cx.lambda(blk);
@@ -877,7 +884,7 @@ fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident,
         }
     };
     let lam = cx.lambda(cx.blk(e_span, ~[cx.alt_stmt(arms, e_span, v)]));
-    let e_name = cx.lit_str(e_span, e_name);
+    let e_name = cx.lit_str(e_span, @cx.str_of(e_name));
     ~[#ast[stmt]{ $(s).emit_enum($(e_name), $(lam)) }]
 }
 
@@ -935,7 +942,7 @@ fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: ast::ident,
     arms += ~[impossible_case];
 
     // Generate code like:
-    let e_name = cx.lit_str(e_span, e_name);
+    let e_name = cx.lit_str(e_span, @cx.str_of(e_name));
     let alt_expr = cx.expr(e_span,
                    ast::expr_match(#ast{__i}, arms, ast::alt_exhaustive));
     let var_lambda = #ast{ |__i| $(alt_expr) };
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index b8c036f5724..bb8a845d731 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -23,7 +23,7 @@ type syntax_expander_ =
 // second argument is the origin of the macro, if user-defined
 type syntax_expander = {expander: syntax_expander_, span: option<span>};
 
-type macro_def = {ident: ast::ident, ext: syntax_extension};
+type macro_def = {name: ~str, ext: syntax_extension};
 
 // macro_definer is obsolete, remove when #old_macros go away.
 type macro_definer =
@@ -141,6 +141,9 @@ trait ext_ctxt {
     fn next_id() -> ast::node_id;
     pure fn trace_macros() -> bool;
     fn set_trace_macros(x: bool);
+    /* for unhygienic identifier transformation */
+    fn str_of(id: ast::ident) -> ~str;
+    fn ident_of(st: ~str) -> ast::ident;
 }
 
 fn mk_ctxt(parse_sess: parse::parse_sess,
@@ -211,6 +214,13 @@ fn mk_ctxt(parse_sess: parse::parse_sess,
         fn set_trace_macros(x: bool) {
             self.trace_mac = x
         }
+
+        fn str_of(id: ast::ident) -> ~str {
+            *self.parse_sess.interner.get(id)
+        }
+        fn ident_of(st: ~str) -> ast::ident {
+            self.parse_sess.interner.intern(@st)
+        }
     }
     let imp : ctxt_repr = {
         parse_sess: parse_sess,
@@ -264,12 +274,12 @@ fn get_mac_args(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
                   cx.span_fatal(sp, fmt!{"#%s needs at least %u arguments.",
                                          name, min});
                 }
-                _ => return elts /* we're good */
+                _ => return elts /* we are good */
               }
           }
         _ => {
             cx.span_fatal(sp, fmt!{"#%s: malformed invocation", name})
-          }
+        }
       },
       none => cx.span_fatal(sp, fmt!{"#%s: missing arguments", name})
     }
@@ -298,22 +308,24 @@ fn tt_args_to_original_flavor(cx: ext_ctxt, sp: span, arg: ~[ast::token_tree])
     fn ms(m: matcher_) -> matcher {
         {node: m, span: {lo: 0u, hi: 0u, expn_info: none}}
     }
+    let arg_nm = cx.parse_sess().interner.gensym(@~"arg");
 
     let argument_gram = ~[ms(match_seq(~[
-        ms(match_nonterminal(@~"arg",@~"expr", 0u))
+        ms(match_nonterminal(arg_nm, parse::token::special_idents::expr, 0u))
     ], some(parse::token::COMMA), true, 0u, 1u))];
 
     let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic,
                                    cx.parse_sess().interner, none, arg);
     let args =
         match parse_or_else(cx.parse_sess(), cx.cfg(), arg_reader as reader,
-                          argument_gram).get(@~"arg") {
-          @matched_seq(s, _) => do s.map() |lf| {
-            match lf {
-              @matched_nonterminal(parse::token::nt_expr(arg)) => {
-                arg /* whew! list of exprs, here we come! */
-              }
-              _ => fail ~"badly-structured parse result"
+                          argument_gram).get(arg_nm) {
+          @matched_seq(s, _) => {
+            do s.map() |lf| {
+                match lf {
+                  @matched_nonterminal(parse::token::nt_expr(arg)) =>
+                    arg, /* whew! list of exprs, here we come! */
+                  _ => fail ~"badly-structured parse result"
+                }
             }
           },
           _ => fail ~"badly-structured parse result"
diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs
index f5d22e6754c..b53a0439e59 100644
--- a/src/libsyntax/ext/concat_idents.rs
+++ b/src/libsyntax/ext/concat_idents.rs
@@ -3,14 +3,16 @@ import base::*;
 fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
                      _body: ast::mac_body) -> @ast::expr {
     let args = get_mac_args_no_max(cx,sp,arg,1u,~"concat_idents");
-    let mut res = ~"";
+    let mut res_str = ~"";
     for args.each |e| {
-        res += *expr_to_ident(cx, e, ~"expected an ident");
+        res_str += *cx.parse_sess().interner.get(
+            expr_to_ident(cx, e, ~"expected an ident"));
     }
+    let res = cx.parse_sess().interner.intern(@res_str);
 
     return @{id: cx.next_id(),
           callee_id: cx.next_id(),
-          node: ast::expr_path(@{span: sp, global: false, idents: ~[@res],
+          node: ast::expr_path(@{span: sp, global: false, idents: ~[res],
                                  rp: none, types: ~[]}),
           span: sp};
 }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 9b50101683a..fb083744321 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -25,7 +25,9 @@ fn expand_expr(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt,
             match mac.node {
               mac_invoc(pth, args, body) => {
                 assert (vec::len(pth.idents) > 0u);
-                let extname = pth.idents[0];
+                /* using idents and token::special_idents would make the
+                the macro names be hygienic */
+                let extname = cx.parse_sess().interner.get(pth.idents[0]);
                 match exts.find(*extname) {
                   none => {
                     cx.span_fatal(pth.span,
@@ -49,7 +51,7 @@ fn expand_expr(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt,
                   }
                   some(macro_defining(ext)) => {
                     let named_extension = ext(cx, mac.span, args, body);
-                    exts.insert(*named_extension.ident, named_extension.ext);
+                    exts.insert(named_extension.name, named_extension.ext);
                     (ast::expr_rec(~[], none), s)
                   }
                   some(expr_tt(_)) => {
@@ -68,7 +70,9 @@ fn expand_expr(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt,
               // finished transitioning.
               mac_invoc_tt(pth, tts) => {
                 assert (vec::len(pth.idents) == 1u);
-                let extname = pth.idents[0];
+                /* using idents and token::special_idents would make the
+                the macro names be hygienic */
+                let extname = cx.parse_sess().interner.get(pth.idents[0]);
                 match exts.find(*extname) {
                   none => {
                     cx.span_fatal(pth.span,
@@ -146,7 +150,7 @@ fn expand_mod_items(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt,
               ast::meta_name_value(n, _) => n,
               ast::meta_list(n, _) => n
             };
-            match exts.find(*mname) {
+            match exts.find(mname) {
               none | some(normal(_)) | some(macro_defining(_))
               | some(expr_tt(_)) | some(item_tt(*)) => items,
               some(item_decorator(dec_fn)) => {
@@ -194,7 +198,7 @@ fn expand_item_mac(exts: hashmap<~str, syntax_extension>,
                    fld: ast_fold) -> option<@ast::item> {
     match it.node {
       item_mac({node: mac_invoc_tt(pth, tts), span}) => {
-        let extname = pth.idents[0];
+        let extname = cx.parse_sess().interner.get(pth.idents[0]);
         match exts.find(*extname) {
           none => {
             cx.span_fatal(pth.span,
@@ -211,7 +215,7 @@ fn expand_item_mac(exts: hashmap<~str, syntax_extension>,
                                          ~"expr macro in item position: " +
                                          *extname),
               mr_def(mdef) => {
-                exts.insert(*mdef.ident, mdef.ext);
+                exts.insert(mdef.name, mdef.ext);
                 none
               }
             };
diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs
index f8966196749..9392ea5ad3c 100644
--- a/src/libsyntax/ext/fmt.rs
+++ b/src/libsyntax/ext/fmt.rs
@@ -37,12 +37,13 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
 fn pieces_to_expr(cx: ext_ctxt, sp: span,
                   pieces: ~[piece], args: ~[@ast::expr])
    -> @ast::expr {
-    fn make_path_vec(_cx: ext_ctxt, ident: ast::ident) -> ~[ast::ident] {
-        return ~[@~"extfmt", @~"rt", ident];
+    fn make_path_vec(_cx: ext_ctxt, ident: @~str) -> ~[ast::ident] {
+        let intr = _cx.parse_sess().interner;
+        return ~[intr.intern(@~"extfmt"), intr.intern(@~"rt"),
+                 intr.intern(ident)];
     }
-    fn make_rt_path_expr(cx: ext_ctxt, sp: span,
-                         ident: ast::ident) -> @ast::expr {
-        let path = make_path_vec(cx, ident);
+    fn make_rt_path_expr(cx: ext_ctxt, sp: span, nm: @~str) -> @ast::expr {
+        let path = make_path_vec(cx, nm);
         return mk_path(cx, sp, path);
     }
     // Produces an AST expression that represents a RT::conv record,
@@ -94,11 +95,13 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span,
         fn make_conv_rec(cx: ext_ctxt, sp: span, flags_expr: @ast::expr,
                          width_expr: @ast::expr, precision_expr: @ast::expr,
                          ty_expr: @ast::expr) -> @ast::expr {
+            let intr = cx.parse_sess().interner;
             return mk_rec_e(cx, sp,
-                         ~[{ident: @~"flags", ex: flags_expr},
-                          {ident: @~"width", ex: width_expr},
-                          {ident: @~"precision", ex: precision_expr},
-                          {ident: @~"ty", ex: ty_expr}]);
+                         ~[{ident: intr.intern(@~"flags"), ex: flags_expr},
+                           {ident: intr.intern(@~"width"), ex: width_expr},
+                           {ident: intr.intern(@~"precision"),
+                            ex: precision_expr},
+                           {ident: intr.intern(@~"ty"), ex: ty_expr}]);
         }
         let rt_conv_flags = make_flags(cx, sp, cnv.flags);
         let rt_conv_width = make_count(cx, sp, cnv.width);
@@ -268,7 +271,10 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span,
     }
 
     let arg_vec = mk_fixed_vec_e(cx, fmt_sp, piece_exprs);
-    return mk_call(cx, fmt_sp, ~[@~"str", @~"concat"], ~[arg_vec]);
+    return mk_call(cx, fmt_sp,
+                   ~[cx.parse_sess().interner.intern(@~"str"),
+                     cx.parse_sess().interner.intern(@~"concat")],
+                   ~[arg_vec]);
 }
 //
 // Local Variables:
diff --git a/src/libsyntax/ext/ident_to_str.rs b/src/libsyntax/ext/ident_to_str.rs
index 06faff9ee1b..9daaf164562 100644
--- a/src/libsyntax/ext/ident_to_str.rs
+++ b/src/libsyntax/ext/ident_to_str.rs
@@ -6,6 +6,6 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
                      _body: ast::mac_body) -> @ast::expr {
     let args = get_mac_args(cx,sp,arg,1u,option::some(1u),~"ident_to_str");
 
-    return mk_uniq_str(cx, sp, *expr_to_ident(cx, args[0u],
-                                           ~"expected an ident"));
+    return mk_uniq_str(cx, sp, *cx.parse_sess().interner.get(
+        expr_to_ident(cx, args[0u], ~"expected an ident")));
 }
diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs
index 4ab3bb29045..61bb00fd6de 100644
--- a/src/libsyntax/ext/log_syntax.rs
+++ b/src/libsyntax/ext/log_syntax.rs
@@ -6,8 +6,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, tt: ~[ast::token_tree])
 
     cx.print_backtrace();
     io::stdout().write_line(
-        print::pprust::unexpanded_tt_to_str(ast::tt_delim(tt),
-                                            cx.parse_sess().interner));
+        print::pprust::tt_to_str(ast::tt_delim(tt),cx.parse_sess().interner));
 
     //trivial expression
     return mr_expr(@{id: cx.next_id(), callee_id: cx.next_id(),
diff --git a/src/libsyntax/ext/pipes.rs b/src/libsyntax/ext/pipes.rs
index b9ff13c9578..beda46a2c3b 100644
--- a/src/libsyntax/ext/pipes.rs
+++ b/src/libsyntax/ext/pipes.rs
@@ -54,7 +54,7 @@ fn expand_proto(cx: ext_ctxt, _sp: span, id: ast::ident,
     let rdr = tt_rdr as reader;
     let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE);
 
-    let proto = rust_parser.parse_proto(id);
+    let proto = rust_parser.parse_proto(cx.str_of(id));
 
     // check for errors
     visit(proto, cx);
diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs
index 39132fd0d59..45873f81dea 100644
--- a/src/libsyntax/ext/pipes/ast_builder.rs
+++ b/src/libsyntax/ext/pipes/ast_builder.rs
@@ -15,14 +15,10 @@ mod syntax {
     export parse;
 }
 
-fn ident(s: &str) -> ast::ident {
-    @(s.to_unique())
-}
-
-fn path(id: ident, span: span) -> @ast::path {
+fn path(ids: ~[ident], span: span) -> @ast::path {
     @{span: span,
       global: false,
-      idents: ~[id],
+      idents: ids,
       rp: none,
       types: ~[]}
 }
@@ -94,7 +90,8 @@ trait ext_ctxt_ast_builder {
 
 impl ext_ctxt: ext_ctxt_ast_builder {
     fn ty_option(ty: @ast::ty) -> @ast::ty {
-        self.ty_path_ast_builder(path(@~"option", self.empty_span())
+        self.ty_path_ast_builder(path(~[self.ident_of(~"option")],
+                                      self.empty_span())
                                  .add_ty(ty))
     }
 
@@ -126,7 +123,7 @@ impl ext_ctxt: ext_ctxt_ast_builder {
                      ty: self.ty_infer(),
                      pat: @{id: self.next_id(),
                             node: ast::pat_ident(ast::bind_by_implicit_ref,
-                                                 path(ident,
+                                                 path(~[ident],
                                                       self.empty_span()),
                                                  none),
                             span: self.empty_span()},
@@ -301,6 +298,6 @@ impl ext_ctxt: ext_ctxt_ast_builder {
 
     fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty] {
         ty_params.map(|p| self.ty_path_ast_builder(
-            path(p.ident, self.empty_span())))
+            path(~[p.ident], self.empty_span())))
     }
 }
diff --git a/src/libsyntax/ext/pipes/check.rs b/src/libsyntax/ext/pipes/check.rs
index e286b4f76be..b7ad5c21bd9 100644
--- a/src/libsyntax/ext/pipes/check.rs
+++ b/src/libsyntax/ext/pipes/check.rs
@@ -21,8 +21,6 @@ that.
 
 import ext::base::ext_ctxt;
 
-import ast::{ident};
-
 import proto::{state, protocol, next_state};
 import ast_builder::empty_span;
 
@@ -36,11 +34,11 @@ impl ext_ctxt: proto::visitor<(), (), ()>  {
                 state.span, // use a real span!
                 fmt!{"state %s contains no messages, \
                       consider stepping to a terminal state instead",
-                     *state.name})
+                      state.name})
         }
     }
 
-    fn visit_message(name: ident, _span: span, _tys: &[@ast::ty],
+    fn visit_message(name: ~str, _span: span, _tys: &[@ast::ty],
                      this: state, next: next_state) {
         match next {
           some({state: next, tys: next_tys}) => {
@@ -51,7 +49,7 @@ impl ext_ctxt: proto::visitor<(), (), ()>  {
                 self.span_err(
                     proto.get_state(next).span,
                     fmt!{"message %s steps to undefined state, %s",
-                         *name, *next});
+                         name, next});
             }
             else {
                 let next = proto.get_state(next);
@@ -61,7 +59,7 @@ impl ext_ctxt: proto::visitor<(), (), ()>  {
                         next.span, // use a real span
                         fmt!{"message %s target (%s) \
                               needs %u type parameters, but got %u",
-                             *name, *next.name,
+                             name, next.name,
                              next.ty_params.len(),
                              next_tys.len()});
                 }
diff --git a/src/libsyntax/ext/pipes/liveness.rs b/src/libsyntax/ext/pipes/liveness.rs
index 17e569552a7..2325e4ed27d 100644
--- a/src/libsyntax/ext/pipes/liveness.rs
+++ b/src/libsyntax/ext/pipes/liveness.rs
@@ -70,10 +70,10 @@ fn analyze(proto: protocol, _cx: ext_ctxt) {
     }
 
     if self_live.len() > 0 {
-        let states = str::connect(self_live.map(|s| *s.name), ~" ");
+        let states = str::connect(self_live.map(|s| s.name), ~" ");
 
         debug!{"protocol %s is unbounded due to loops involving: %s",
-               *proto.name, states};
+               proto.name, states};
 
         // Someday this will be configurable with a warning
         //cx.span_warn(empty_span(),
@@ -85,7 +85,7 @@ fn analyze(proto: protocol, _cx: ext_ctxt) {
         proto.bounded = some(false);
     }
     else {
-        debug!{"protocol %s is bounded. yay!", *proto.name};
+        debug!{"protocol %s is bounded. yay!", proto.name};
         proto.bounded = some(true);
     }
 }
\ No newline at end of file
diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs
index 84180ff3797..4dc61e54aa4 100644
--- a/src/libsyntax/ext/pipes/parse_proto.rs
+++ b/src/libsyntax/ext/pipes/parse_proto.rs
@@ -1,18 +1,17 @@
 // Parsing pipes protocols from token trees.
 
 import parse::parser;
-import ast::ident;
 import parse::token;
 
 import pipec::*;
 
 trait proto_parser {
-    fn parse_proto(id: ident) -> protocol;
+    fn parse_proto(id: ~str) -> protocol;
     fn parse_state(proto: protocol);
 }
 
 impl parser: proto_parser {
-    fn parse_proto(id: ident) -> protocol {
+    fn parse_proto(id: ~str) -> protocol {
         let proto = protocol(id, self.span);
 
         self.parse_seq_to_before_end(token::EOF,
@@ -24,9 +23,11 @@ impl parser: proto_parser {
 
     fn parse_state(proto: protocol) {
         let id = self.parse_ident();
+        let name = *self.interner.get(id);
+
         self.expect(token::COLON);
         let dir = match copy self.token {
-          token::IDENT(n, _) => self.get_str(n),
+          token::IDENT(n, _) => self.interner.get(n),
           _ => fail
         };
         self.bump();
@@ -41,7 +42,7 @@ impl parser: proto_parser {
         }
         else { ~[] };
 
-        let state = proto.add_state_poly(id, dir, typarms);
+        let state = proto.add_state_poly(name, id, dir, typarms);
 
         // parse the messages
         self.parse_unspanned_seq(
@@ -51,7 +52,7 @@ impl parser: proto_parser {
     }
 
     fn parse_message(state: state) {
-        let mname = self.parse_ident();
+        let mname = *self.interner.get(self.parse_ident());
 
         let args = if self.token == token::LPAREN {
             self.parse_unspanned_seq(token::LPAREN,
@@ -66,7 +67,7 @@ impl parser: proto_parser {
 
         let next = match copy self.token {
           token::IDENT(_, _) => {
-            let name = self.parse_ident();
+            let name = *self.interner.get(self.parse_ident());
             let ntys = if self.token == token::LT {
                 self.parse_unspanned_seq(token::LT,
                                          token::GT,
diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs
index f7f2981f066..b5a1ae588a7 100644
--- a/src/libsyntax/ext/pipes/pipec.rs
+++ b/src/libsyntax/ext/pipes/pipec.rs
@@ -13,8 +13,7 @@ import parse;
 import parse::*;
 import proto::*;
 
-import ast_builder::append_types;
-import ast_builder::path;
+import ast_builder::{append_types, path, empty_span};
 
 // Transitional reexports so qquote can find the paths it is looking for
 mod syntax {
@@ -47,17 +46,17 @@ impl message: gen_send {
             debug!("pipec: next state exists");
             let next = this.proto.get_state(next);
             assert next_tys.len() == next.ty_params.len();
-            let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
+            let arg_names = tys.mapi(|i, _ty| cx.ident_of(~"x_"+i.to_str()));
 
             let args_ast = (arg_names, tys).map(
                 |n, t| cx.arg_mode(n, t, ast::by_copy)
             );
 
             let pipe_ty = cx.ty_path_ast_builder(
-                path(this.data_name(), span)
+                path(~[this.data_name()], span)
                 .add_tys(cx.ty_vars(this.ty_params)));
             let args_ast = vec::append(
-                ~[cx.arg_mode(@~"pipe",
+                ~[cx.arg_mode(cx.ident_of(~"pipe"),
                               pipe_ty,
                               ast::by_copy)],
                 args_ast);
@@ -75,10 +74,10 @@ impl message: gen_send {
                 body += ~"let b = pipe.reuse_buffer();\n";
                 body += fmt!("let %s = pipes::send_packet_buffered(\
                               ptr::addr_of(b.buffer.data.%s));\n",
-                             sp, *next.name);
-                body += fmt!("let %s = pipes::recv_packet_buffered(\
+                             sp, next.name);
+                body += fmt!{"let %s = pipes::recv_packet_buffered(\
                               ptr::addr_of(b.buffer.data.%s));\n",
-                             rp, *next.name);
+                             rp, next.name};
             }
             else {
                 let pat = match (this.dir, next.dir) {
@@ -91,10 +90,10 @@ impl message: gen_send {
                 body += fmt!("let %s = pipes::entangle();\n", pat);
             }
             body += fmt!("let message = %s::%s(%s);\n",
-                         *this.proto.name,
-                         *self.name(),
-                         str::connect(vec::append_one(arg_names, @~"s")
-                                      .map(|x| *x),
+                         this.proto.name,
+                         self.name(),
+                         str::connect(vec::append_one(
+                             arg_names.map(|x| cx.str_of(x)), ~"s"),
                                       ~", "));
 
             if !try {
@@ -110,17 +109,15 @@ impl message: gen_send {
 
             let body = cx.parse_expr(body);
 
-            let mut rty = cx.ty_path_ast_builder(path(next.data_name(),
+            let mut rty = cx.ty_path_ast_builder(path(~[next.data_name()],
                                                       span)
                                                  .add_tys(next_tys));
             if try {
                 rty = cx.ty_option(rty);
             }
 
-            let name = if try {
-                @(~"try_" + *self.name())
-            }
-            else { self.name() };
+            let name = cx.ident_of(if try { ~"try_" + self.name()
+                                          } else { self.name() } );
 
             cx.item_fn_poly(name,
                             args_ast,
@@ -131,16 +128,16 @@ impl message: gen_send {
 
             message(id, span, tys, this, none) => {
                 debug!{"pipec: no next state"};
-                let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
+                let arg_names = tys.mapi(|i, _ty| (~"x_" + i.to_str()));
 
                 let args_ast = (arg_names, tys).map(
-                    |n, t| cx.arg_mode(n, t, ast::by_copy)
+                    |n, t| cx.arg_mode(cx.ident_of(n), t, ast::by_copy)
                 );
 
                 let args_ast = vec::append(
-                    ~[cx.arg_mode(@~"pipe",
+                    ~[cx.arg_mode(cx.ident_of(~"pipe"),
                                   cx.ty_path_ast_builder(
-                                      path(this.data_name(), span)
+                                      path(~[this.data_name()], span)
                                       .add_tys(cx.ty_vars(this.ty_params))),
                                   ast::by_copy)],
                     args_ast);
@@ -149,13 +146,13 @@ impl message: gen_send {
                     ~""
                 }
                 else {
-                    ~"(" + str::connect(arg_names.map(|x| *x), ~", ") + ~")"
+                    ~"(" + str::connect(arg_names, ~", ") + ~")"
                 };
 
                 let mut body = ~"{ ";
                 body += fmt!{"let message = %s::%s%s;\n",
-                             *this.proto.name,
-                             *self.name(),
+                             this.proto.name,
+                             self.name(),
                              message_args};
 
                 if !try {
@@ -170,11 +167,11 @@ impl message: gen_send {
                 let body = cx.parse_expr(body);
 
                 let name = if try {
-                    @(~"try_" + *self.name())
+                    ~"try_" + self.name()
                 }
                 else { self.name() };
 
-                cx.item_fn_poly(name,
+                cx.item_fn_poly(cx.ident_of(name),
                                 args_ast,
                                 if try {
                                     cx.ty_option(cx.ty_nil_ast_builder())
@@ -188,7 +185,7 @@ impl message: gen_send {
         }
 
     fn to_ty(cx: ext_ctxt) -> @ast::ty {
-        cx.ty_path_ast_builder(path(self.name(), self.span())
+        cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span())
           .add_tys(cx.ty_vars(self.get_params())))
     }
 }
@@ -212,21 +209,23 @@ impl state: to_type_decls {
             let tys = match next {
               some({state: next, tys: next_tys}) => {
                 let next = this.proto.get_state(next);
-                let next_name = next.data_name();
+                let next_name = cx.str_of(next.data_name());
 
                 let dir = match this.dir {
-                  send => @~"server",
-                  recv => @~"client"
+                  send => ~"server",
+                  recv => ~"client"
                 };
 
                 vec::append_one(tys,
-                                cx.ty_path_ast_builder((dir + next_name)
-                                           .add_tys(next_tys)))
+                                cx.ty_path_ast_builder(
+                                    path(~[cx.ident_of(dir),
+                                           cx.ident_of(next_name)], span)
+                                    .add_tys(next_tys)))
               }
               none => tys
             };
 
-            let v = cx.variant(name, span, tys);
+            let v = cx.variant(cx.ident_of(name), span, tys);
 
             vec::push(items_msg, v);
         }
@@ -258,9 +257,13 @@ impl state: to_type_decls {
                           self.data_name(),
                           self.span,
                           cx.ty_path_ast_builder(
-                              (@~"pipes" + @(dir.to_str() + ~"_packet"))
+                              path(~[cx.ident_of(~"pipes"),
+                                     cx.ident_of(dir.to_str() + ~"_packet")],
+                                   empty_span())
                               .add_ty(cx.ty_path_ast_builder(
-                                  (self.proto.name + self.data_name())
+                                  path(~[cx.ident_of(self.proto.name),
+                                         self.data_name()],
+                                       empty_span())
                                   .add_tys(cx.ty_vars(self.ty_params))))),
                           self.ty_params));
         }
@@ -270,10 +273,14 @@ impl state: to_type_decls {
                           self.data_name(),
                           self.span,
                           cx.ty_path_ast_builder(
-                              (@~"pipes" + @(dir.to_str()
-                                             + ~"_packet_buffered"))
+                              path(~[cx.ident_of(~"pipes"),
+                                     cx.ident_of(dir.to_str()
+                                                 + ~"_packet_buffered")],
+                                  empty_span())
                               .add_tys(~[cx.ty_path_ast_builder(
-                                  (self.proto.name + self.data_name())
+                                  path(~[cx.ident_of(self.proto.name),
+                                         self.data_name()],
+                                       empty_span())
                                   .add_tys(cx.ty_vars(self.ty_params))),
                                          self.proto.buffer_ty_path(cx)])),
                           self.ty_params));
@@ -315,16 +322,17 @@ impl protocol: gen_init {
 
         cx.parse_item(fmt!{"fn init%s() -> (client::%s, server::%s)\
                             { import pipes::has_buffer; %s }",
-                           start_state.ty_params.to_source(),
-                           start_state.to_ty(cx).to_source(),
-                           start_state.to_ty(cx).to_source(),
-                           body.to_source()})
+                           start_state.ty_params.to_source(cx),
+                           start_state.to_ty(cx).to_source(cx),
+                           start_state.to_ty(cx).to_source(cx),
+                           body.to_source(cx)})
     }
 
     fn gen_buffer_init(ext_cx: ext_ctxt) -> @ast::expr {
         ext_cx.rec(self.states.map_to_vec(|s| {
             let fty = s.to_ty(ext_cx);
-            ext_cx.field_imm(s.name, #ast { pipes::mk_packet::<$(fty)>() })
+            ext_cx.field_imm(ext_cx.ident_of(s.name),
+                             #ast { pipes::mk_packet::<$(fty)>() })
         }))
     }
 
@@ -341,9 +349,11 @@ impl protocol: gen_init {
             ext_cx.block(
                 self.states.map_to_vec(
                     |s| ext_cx.parse_stmt(
-                        fmt!{"data.%s.set_buffer(buffer)", *s.name})),
+                        fmt!{"data.%s.set_buffer(buffer)",
+                             s.name})),
                 ext_cx.parse_expr(
-                    fmt!{"ptr::addr_of(data.%s)", *self.states[0].name})));
+                    fmt!{"ptr::addr_of(data.%s)",
+                         self.states[0].name})));
 
         #ast {{
             let buffer = $(buffer);
@@ -357,14 +367,14 @@ impl protocol: gen_init {
         let mut params: ~[ast::ty_param] = ~[];
         for (copy self.states).each |s| {
             for s.ty_params.each |tp| {
-                match params.find(|tpp| *tp.ident == *tpp.ident) {
+                match params.find(|tpp| tp.ident == tpp.ident) {
                   none => vec::push(params, tp),
                   _ => ()
                 }
             }
         }
 
-        cx.ty_path_ast_builder(path(@~"__Buffer", self.span)
+        cx.ty_path_ast_builder(path(~[cx.ident_of(~"__Buffer")], self.span)
                                .add_tys(cx.ty_vars(params)))
     }
 
@@ -373,7 +383,7 @@ impl protocol: gen_init {
         let mut params: ~[ast::ty_param] = ~[];
         let fields = do (copy self.states).map_to_vec |s| {
             for s.ty_params.each |tp| {
-                match params.find(|tpp| *tp.ident == *tpp.ident) {
+                match params.find(|tpp| tp.ident == tpp.ident) {
                   none => vec::push(params, tp),
                   _ => ()
                 }
@@ -382,11 +392,11 @@ impl protocol: gen_init {
             let fty = #ast[ty] {
                 pipes::packet<$(ty)>
             };
-            cx.ty_field_imm(s.name, fty)
+            cx.ty_field_imm(cx.ident_of(s.name), fty)
         };
 
         cx.item_ty_poly(
-            @~"__Buffer",
+            cx.ident_of(~"__Buffer"),
             cx.empty_span(),
             cx.ty_rec(fields),
             params)
@@ -410,56 +420,56 @@ impl protocol: gen_init {
         }
 
         vec::push(items,
-                  cx.item_mod(@~"client",
+                  cx.item_mod(cx.ident_of(~"client"),
                               self.span,
                               client_states));
         vec::push(items,
-                  cx.item_mod(@~"server",
+                  cx.item_mod(cx.ident_of(~"server"),
                               self.span,
                               server_states));
 
-        cx.item_mod(self.name, self.span, items)
+        cx.item_mod(cx.ident_of(self.name), self.span, items)
     }
 }
 
 trait to_source {
     // Takes a thing and generates a string containing rust code for it.
-    fn to_source() -> ~str;
+    fn to_source(cx: ext_ctxt) -> ~str;
 }
 
 impl @ast::item: to_source {
-    fn to_source() -> ~str {
-        item_to_str(self)
+    fn to_source(cx: ext_ctxt) -> ~str {
+        item_to_str(self, cx.parse_sess().interner)
     }
 }
 
 impl ~[@ast::item]: to_source {
-    fn to_source() -> ~str {
-        str::connect(self.map(|i| i.to_source()), ~"\n\n")
+    fn to_source(cx: ext_ctxt) -> ~str {
+        str::connect(self.map(|i| i.to_source(cx)), ~"\n\n")
     }
 }
 
 impl @ast::ty: to_source {
-    fn to_source() -> ~str {
-        ty_to_str(self)
+    fn to_source(cx: ext_ctxt) -> ~str {
+        ty_to_str(self, cx.parse_sess().interner)
     }
 }
 
 impl ~[@ast::ty]: to_source {
-    fn to_source() -> ~str {
-        str::connect(self.map(|i| i.to_source()), ~", ")
+    fn to_source(cx: ext_ctxt) -> ~str {
+        str::connect(self.map(|i| i.to_source(cx)), ~", ")
     }
 }
 
 impl ~[ast::ty_param]: to_source {
-    fn to_source() -> ~str {
-        pprust::typarams_to_str(self)
+    fn to_source(cx: ext_ctxt) -> ~str {
+        pprust::typarams_to_str(self, cx.parse_sess().interner)
     }
 }
 
 impl @ast::expr: to_source {
-    fn to_source() -> ~str {
-        pprust::expr_to_str(self)
+    fn to_source(cx: ext_ctxt) -> ~str {
+        pprust::expr_to_str(self, cx.parse_sess().interner)
     }
 }
 
diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs
index 9e44ce7acda..62c5329525f 100644
--- a/src/libsyntax/ext/pipes/proto.rs
+++ b/src/libsyntax/ext/pipes/proto.rs
@@ -1,8 +1,6 @@
 import to_str::ToStr;
 import dvec::{DVec, dvec};
 
-import ast::{ident};
-
 import ast_builder::{path, append_types};
 
 enum direction {
@@ -27,15 +25,15 @@ impl direction {
     }
 }
 
-type next_state = option<{state: ident, tys: ~[@ast::ty]}>;
+type next_state = option<{state: ~str, tys: ~[@ast::ty]}>;
 
 enum message {
     // name, span, data, current state, next state
-    message(ident, span, ~[@ast::ty], state, next_state)
+    message(~str, span, ~[@ast::ty], state, next_state)
 }
 
 impl message {
-    fn name() -> ident {
+    fn name() -> ~str {
         match self {
           message(id, _, _, _, _) => id
         }
@@ -58,7 +56,8 @@ impl message {
 enum state {
     state_(@{
         id: uint,
-        name: ident,
+        name: ~str,
+        ident: ast::ident,
         span: span,
         dir: direction,
         ty_params: ~[ast::ty_param],
@@ -68,7 +67,7 @@ enum state {
 }
 
 impl state {
-    fn add_message(name: ident, span: span,
+    fn add_message(name: ~str, span: span,
                    +data: ~[@ast::ty], next: next_state) {
         self.messages.push(message(name, span, data, self,
                                    next));
@@ -78,14 +77,15 @@ impl state {
         (*self).proto.filename()
     }
 
-    fn data_name() -> ident {
-        self.name
+    fn data_name() -> ast::ident {
+        self.ident
     }
 
     /// Returns the type that is used for the messages.
     fn to_ty(cx: ext_ctxt) -> @ast::ty {
         cx.ty_path_ast_builder
-            (path(self.name, self.span).add_tys(cx.ty_vars(self.ty_params)))
+            (path(~[cx.ident_of(self.name)],self.span).add_tys(
+                cx.ty_vars(self.ty_params)))
     }
 
     /// Iterate over the states that can be reached in one message
@@ -105,18 +105,18 @@ impl state {
 
 type protocol = @protocol_;
 
-fn protocol(name: ident, +span: span) -> protocol {
+fn protocol(name: ~str, +span: span) -> protocol {
     @protocol_(name, span)
 }
 
 struct protocol_ {
-    let name: ident;
+    let name: ~str;
     let span: span;
     let states: DVec<state>;
 
     let mut bounded: option<bool>;
 
-    new(name: ident, span: span) {
+    new(name: ~str, span: span) {
         self.name = name;
         self.span = span;
         self.states = dvec();
@@ -124,18 +124,18 @@ struct protocol_ {
     }
 
     /// Get a state.
-    fn get_state(name: ident) -> state {
+    fn get_state(name: ~str) -> state {
         self.states.find(|i| i.name == name).get()
     }
 
     fn get_state_by_id(id: uint) -> state { self.states[id] }
 
-    fn has_state(name: ident) -> bool {
+    fn has_state(name: ~str) -> bool {
         self.states.find(|i| i.name == name) != none
     }
 
     fn filename() -> ~str {
-        ~"proto://" + *self.name
+        ~"proto://" + self.name
     }
 
     fn num_states() -> uint { self.states.len() }
@@ -162,17 +162,14 @@ struct protocol_ {
 }
 
 impl protocol {
-    fn add_state(name: ident, dir: direction) -> state {
-        self.add_state_poly(name, dir, ~[])
-    }
-
-    fn add_state_poly(name: ident, dir: direction,
+    fn add_state_poly(name: ~str, ident: ast::ident, dir: direction,
                       +ty_params: ~[ast::ty_param]) -> state {
         let messages = dvec();
 
         let state = state_(@{
             id: self.states.len(),
             name: name,
+            ident: ident,
             span: self.span,
             dir: dir,
             ty_params: ty_params,
@@ -188,7 +185,7 @@ impl protocol {
 trait visitor<Tproto, Tstate, Tmessage> {
     fn visit_proto(proto: protocol, st: &[Tstate]) -> Tproto;
     fn visit_state(state: state, m: &[Tmessage]) -> Tstate;
-    fn visit_message(name: ident, spane: span, tys: &[@ast::ty],
+    fn visit_message(name: ~str, spane: span, tys: &[@ast::ty],
                      this: state, next: next_state) -> Tmessage;
 }
 
diff --git a/src/libsyntax/ext/qquote.rs b/src/libsyntax/ext/qquote.rs
index 6b5dce312d6..8024f5f9542 100644
--- a/src/libsyntax/ext/qquote.rs
+++ b/src/libsyntax/ext/qquote.rs
@@ -3,6 +3,7 @@ import ast::{crate, expr_, mac_invoc,
 import parse::parser;
 import parse::parser::parse_from_source_str;
 import dvec::{DVec, dvec};
+import parse::token::ident_interner;
 
 import fold::*;
 import visit::*;
@@ -26,6 +27,14 @@ enum fragment {
     from_ty(@ast::ty)
 }
 
+fn ids_ext(cx: ext_ctxt, strs: ~[~str]) -> ~[ast::ident] {
+    strs.map(|str| cx.parse_sess().interner.intern(@str))
+}
+fn id_ext(cx: ext_ctxt, str: ~str) -> ast::ident {
+    cx.parse_sess().interner.intern(@str)
+}
+
+
 trait qq_helper {
     fn span() -> span;
     fn visit(aq_ctxt, vt<aq_ctxt>);
@@ -40,7 +49,7 @@ impl @ast::crate: qq_helper {
     fn extract_mac() -> option<ast::mac_> {fail}
     fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
         mk_path(cx, sp,
-                ~[@~"syntax", @~"ext", @~"qquote", @~"parse_crate"])
+                ids_ext(cx, ~[~"syntax", ~"ext", ~"qquote", ~"parse_crate"]))
     }
     fn get_fold_fn() -> ~str {~"fold_crate"}
 }
@@ -55,7 +64,7 @@ impl @ast::expr: qq_helper {
     }
     fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
         mk_path(cx, sp,
-                ~[@~"syntax", @~"ext", @~"qquote", @~"parse_expr"])
+                ids_ext(cx, ~[~"syntax", ~"ext", ~"qquote", ~"parse_expr"]))
     }
     fn get_fold_fn() -> ~str {~"fold_expr"}
 }
@@ -70,7 +79,7 @@ impl @ast::ty: qq_helper {
     }
     fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
         mk_path(cx, sp,
-                ~[@~"syntax", @~"ext", @~"qquote", @~"parse_ty"])
+                ids_ext(cx, ~[~"syntax", ~"ext", ~"qquote", ~"parse_ty"]))
     }
     fn get_fold_fn() -> ~str {~"fold_ty"}
 }
@@ -80,7 +89,7 @@ impl @ast::item: qq_helper {
     fn extract_mac() -> option<ast::mac_> {fail}
     fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
         mk_path(cx, sp,
-                ~[@~"syntax", @~"ext", @~"qquote", @~"parse_item"])
+                ids_ext(cx, ~[~"syntax", ~"ext", ~"qquote", ~"parse_item"]))
     }
     fn get_fold_fn() -> ~str {~"fold_item"}
 }
@@ -90,7 +99,7 @@ impl @ast::stmt: qq_helper {
     fn extract_mac() -> option<ast::mac_> {fail}
     fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
         mk_path(cx, sp,
-                ~[@~"syntax", @~"ext", @~"qquote", @~"parse_stmt"])
+                ids_ext(cx, ~[~"syntax", ~"ext", ~"qquote", ~"parse_stmt"]))
     }
     fn get_fold_fn() -> ~str {~"fold_stmt"}
 }
@@ -99,7 +108,8 @@ impl @ast::pat: qq_helper {
     fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_pat(self, cx, v);}
     fn extract_mac() -> option<ast::mac_> {fail}
     fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
-        mk_path(cx, sp, ~[@~"syntax", @~"ext", @~"qquote", @~"parse_pat"])
+        mk_path(cx, sp, ids_ext(cx, ~[~"syntax", ~"ext", ~"qquote",
+                                      ~"parse_pat"]))
     }
     fn get_fold_fn() -> ~str {~"fold_pat"}
 }
@@ -159,7 +169,7 @@ fn expand_ast(ecx: ext_ctxt, _sp: span,
         }
         match (args[0].node) {
           ast::expr_path(@{idents: id, _}) if vec::len(id) == 1u
-          => what = *id[0],
+            => what = *ecx.parse_sess().interner.get(id[0]),
           _ => ecx.span_fatal(args[0].span, ~"expected an identifier")
         }
     }
@@ -243,19 +253,21 @@ fn finish<T: qq_helper>
     let cx = ecx;
 
     let cfg_call = || mk_call_(
-        cx, sp, mk_access(cx, sp, ~[@~"ext_cx"], @~"cfg"), ~[]);
+        cx, sp, mk_access(cx, sp, ids_ext(cx, ~[~"ext_cx"]),
+                          id_ext(cx, ~"cfg")), ~[]);
 
     let parse_sess_call = || mk_call_(
-        cx, sp, mk_access(cx, sp, ~[@~"ext_cx"], @~"parse_sess"), ~[]);
+        cx, sp, mk_access(cx, sp, ids_ext(cx, ~[~"ext_cx"]),
+                          id_ext(cx, ~"parse_sess")), ~[]);
 
     let pcall = mk_call(cx,sp,
-                       ~[@~"syntax", @~"parse", @~"parser",
-                        @~"parse_from_source_str"],
+                       ids_ext(cx, ~[~"syntax", ~"parse", ~"parser",
+                        ~"parse_from_source_str"]),
                        ~[node.mk_parse_fn(cx,sp),
                         mk_uniq_str(cx,sp, fname),
                         mk_call(cx,sp,
-                                ~[@~"syntax",@~"ext",
-                                 @~"qquote", @~"mk_file_substr"],
+                                ids_ext(cx, ~[~"syntax",~"ext",
+                                 ~"qquote", ~"mk_file_substr"]),
                                 ~[mk_uniq_str(cx,sp, loc.file.name),
                                  mk_uint(cx,sp, loc.line),
                                  mk_uint(cx,sp, loc.col)]),
@@ -267,16 +279,17 @@ fn finish<T: qq_helper>
     let mut rcall = pcall;
     if (g_len > 0u) {
         rcall = mk_call(cx,sp,
-                        ~[@~"syntax", @~"ext", @~"qquote", @~"replace"],
+                        ids_ext(cx, ~[~"syntax", ~"ext", ~"qquote",
+                                      ~"replace"]),
                         ~[pcall,
                           mk_uniq_vec_e(cx,sp, qcx.gather.map_to_vec(|g| {
                              mk_call(cx,sp,
-                                     ~[@~"syntax", @~"ext",
-                                      @~"qquote", @g.constr],
+                                     ids_ext(cx, ~[~"syntax", ~"ext",
+                                                   ~"qquote", g.constr]),
                                      ~[g.e])})),
                          mk_path(cx,sp,
-                                 ~[@~"syntax", @~"ext", @~"qquote",
-                                  @node.get_fold_fn()])]);
+                                 ids_ext(cx, ~[~"syntax", ~"ext", ~"qquote",
+                                               node.get_fold_fn()]))]);
     }
     return rcall;
 }
@@ -331,14 +344,6 @@ fn replace_ty(repls: ~[fragment],
     }
 }
 
-fn print_expr(expr: @ast::expr) {
-    let stdout = io::stdout();
-    let pp = pprust::rust_printer(stdout);
-    pprust::print_expr(pp, expr);
-    pp::eof(pp.s);
-    stdout.write_str(~"\n");
-}
-
 fn mk_file_substr(fname: ~str, line: uint, col: uint) ->
     codemap::file_substr {
     codemap::fss_external({filename: fname, line: line, col: col})
diff --git a/src/libsyntax/ext/simplext.rs b/src/libsyntax/ext/simplext.rs
index e8899a2e541..5b9bac1948f 100644
--- a/src/libsyntax/ext/simplext.rs
+++ b/src/libsyntax/ext/simplext.rs
@@ -1,5 +1,5 @@
 import codemap::span;
-import std::map::{hashmap, str_hash, box_str_hash};
+import std::map::{hashmap, str_hash, uint_hash};
 import dvec::{DVec, dvec};
 
 import base::*;
@@ -135,7 +135,7 @@ fn acumm_bindings(_cx: ext_ctxt, _b_dest: bindings, _b_src: bindings) { }
 
 fn pattern_to_selectors(cx: ext_ctxt, e: @expr) -> binders {
     let res: binders =
-        {real_binders: box_str_hash::<selector>(),
+        {real_binders: uint_hash::<selector>(),
          literal_ast_matchers: dvec()};
     //this oughta return binders instead, but macro args are a sequence of
     //expressions, rather than a single expression
@@ -153,7 +153,7 @@ bindings. Most of the work is done in p_t_s, which generates the
 selectors. */
 
 fn use_selectors_to_bind(b: binders, e: @expr) -> option<bindings> {
-    let res = box_str_hash::<arb_depth<matchable>>();
+    let res = uint_hash::<arb_depth<matchable>>();
     //need to do this first, to check vec lengths.
     for b.literal_ast_matchers.each |sel| {
         match sel(match_expr(e)) { none => return none, _ => () }
@@ -237,7 +237,7 @@ fn follow_for_trans(cx: ext_ctxt, mmaybe: option<arb_depth<matchable>>,
 
 /* helper for transcribe_exprs: what vars from `b` occur in `e`? */
 fn free_vars(b: bindings, e: @expr, it: fn(ident)) {
-    let idents: hashmap<ident, ()> = box_str_hash::<()>();
+    let idents: hashmap<ident, ()> = uint_hash::<()>();
     fn mark_ident(&&i: ident, _fld: ast_fold, b: bindings,
                   idents: hashmap<ident, ()>) -> ident {
         if b.contains_key(i) { idents.insert(i, ()); }
@@ -253,6 +253,12 @@ fn free_vars(b: bindings, e: @expr, it: fn(ident)) {
     for idents.each_key |x| { it(x); };
 }
 
+fn wrong_occurs(cx: ext_ctxt, l: ident, l_c: uint, r: ident, r_c: uint)
+    -> ~str {
+    fmt!{"'%s' occurs %u times, but '%s' occurs %u times",
+         *cx.parse_sess().interner.get(l), l_c,
+         *cx.parse_sess().interner.get(r), r_c}
+}
 
 /* handle sequences (anywhere in the AST) of exprs, either real or ...ed */
 fn transcribe_exprs(cx: ext_ctxt, b: bindings, idx_path: @mut ~[uint],
@@ -279,10 +285,8 @@ fn transcribe_exprs(cx: ext_ctxt, b: bindings, idx_path: @mut ~[uint],
                       some({rep_count: old_len, name: old_name}) => {
                         let len = vec::len(*ms);
                         if old_len != len {
-                            let msg =
-                                fmt!{"'%s' occurs %u times, but ", *fv, len} +
-                                    fmt!{"'%s' occurs %u times", *old_name,
-                                         old_len};
+                            let msg = wrong_occurs(cx, fv, len,
+                                                   old_name, old_len);
                             cx.span_fatal(repeat_me.span, msg);
                         }
                       }
@@ -626,7 +630,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
                      _body: ast::mac_body) -> base::macro_def {
     let args = get_mac_args_no_max(cx, sp, arg, 0u, ~"macro");
 
-    let mut macro_name: option<@~str> = none;
+    let mut macro_name: option<~str> = none;
     let mut clauses: ~[@clause] = ~[];
     for args.each |arg| {
         match arg.node {
@@ -643,12 +647,15 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
                 match mac.node {
                   mac_invoc(pth, invoc_arg, body) => {
                     match path_to_ident(pth) {
-                      some(id) => match macro_name {
-                        none => macro_name = some(id),
-                        some(other_id) => if id != other_id {
+                      some(id) => {
+                        let id_str = cx.str_of(id);
+                        match macro_name {
+                          none => macro_name = some(id_str),
+                          some(other_id) => if id_str != other_id {
                             cx.span_fatal(pth.span,
                                           ~"macro name must be " +
                                           ~"consistent");
+                          }
                         }
                       },
                       none => cx.span_fatal(pth.span,
@@ -688,7 +695,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
 
     let ext = |a,b,c,d, move clauses| generic_extension(a,b,c,d,clauses);
 
-    return {ident:
+    return {name:
              match macro_name {
                some(id) => id,
                none => cx.span_fatal(sp, ~"macro definition must have " +
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index e05a713165b..c323f201b83 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -43,14 +43,15 @@ fn expand_file(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
 fn expand_stringify(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
                     _body: ast::mac_body) -> @ast::expr {
     let args = get_mac_args(cx, sp, arg, 1u, option::some(1u), ~"stringify");
-    return mk_uniq_str(cx, sp, pprust::expr_to_str(args[0]));
+    let s = pprust::expr_to_str(args[0], cx.parse_sess().interner);
+    return mk_uniq_str(cx, sp, s);
 }
 
 fn expand_mod(cx: ext_ctxt, sp: span, arg: ast::mac_arg, _body: ast::mac_body)
     -> @ast::expr {
     get_mac_args(cx, sp, arg, 0u, option::some(0u), ~"file");
     return mk_uniq_str(cx, sp,
-                    str::connect(cx.mod_path().map(|x|*x), ~"::"));
+                    str::connect(cx.mod_path().map(|x| cx.str_of(x)), ~"::"));
 }
 
 fn expand_include(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs
index d4f1493169f..22f0aeaa2c0 100644
--- a/src/libsyntax/ext/trace_macros.rs
+++ b/src/libsyntax/ext/trace_macros.rs
@@ -15,10 +15,10 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span,
     let rdr = tt_rdr as reader;
     let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE);
 
-    let arg = rust_parser.parse_ident();
+    let arg = cx.str_of(rust_parser.parse_ident());
     match arg {
-      @~"true"  => cx.set_trace_macros(true),
-      @~"false" => cx.set_trace_macros(false),
+      ~"true"  => cx.set_trace_macros(true),
+      ~"false" => cx.set_trace_macros(false),
       _ => cx.span_fatal(sp, ~"trace_macros! only accepts `true` or `false`")
     }
     let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE);
diff --git a/src/libsyntax/ext/tt/earley_parser.rs b/src/libsyntax/ext/tt/earley_parser.rs
index 77ba941015b..896b6f6e54f 100644
--- a/src/libsyntax/ext/tt/earley_parser.rs
+++ b/src/libsyntax/ext/tt/earley_parser.rs
@@ -10,7 +10,7 @@ import parse::parse_sess;
 import dvec::{DVec, dvec};
 import ast::{matcher, match_tok, match_seq, match_nonterminal, ident};
 import ast_util::mk_sp;
-import std::map::{hashmap, box_str_hash};
+import std::map::{hashmap, uint_hash};
 
 /* This is an Earley-like parser, without support for in-grammar nonterminals,
 onlyl calling out to the main rust parser for named nonterminals (which it
@@ -120,14 +120,14 @@ fn nameize(p_s: parse_sess, ms: ~[matcher], res: ~[@named_match])
           }
           {node: match_nonterminal(bind_name, _, idx), span: sp} => {
             if ret_val.contains_key(bind_name) {
-                p_s.span_diagnostic.span_fatal(sp, ~"Duplicated bind name: "
-                                               + *bind_name)
+                p_s.span_diagnostic.span_fatal(sp, ~"Duplicated bind name: "+
+                                               *p_s.interner.get(bind_name))
             }
             ret_val.insert(bind_name, res[idx]);
           }
         }
     }
-    let ret_val = box_str_hash::<@named_match>();
+    let ret_val = uint_hash::<@named_match>();
     for ms.each() |m| { n_rec(p_s, m, res, ret_val) }
     return ret_val;
 }
@@ -274,7 +274,8 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
                 let nts = str::connect(vec::map(bb_eis, |ei| {
                     match ei.elts[ei.idx].node {
                       match_nonterminal(bind,name,_) => {
-                        fmt!{"%s ('%s')", *name, *bind}
+                        fmt!{"%s ('%s')", *sess.interner.get(name),
+                             *sess.interner.get(bind)}
                       }
                       _ => fail
                     } }), ~" or ");
@@ -298,7 +299,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
                 match ei.elts[ei.idx].node {
                   match_nonterminal(_, name, idx) => {
                     ei.matches[idx].push(@matched_nonterminal(
-                        parse_nt(rust_parser, *name)));
+                        parse_nt(rust_parser, *sess.interner.get(name))));
                     ei.idx += 1u;
                   }
                   _ => fail
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 05db498a022..be7594ff843 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -8,6 +8,7 @@ import parse::parser::{parser, SOURCE_FILE};
 import earley_parser::{parse, parse_or_else, success, failure, named_match,
                        matched_seq, matched_nonterminal, error};
 import std::map::hashmap;
+import parse::token::special_idents;
 
 fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
                      arg: ~[ast::token_tree]) -> base::mac_result {
@@ -16,14 +17,17 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
         {node: m, span: {lo: 0u, hi: 0u, expn_info: none}}
     }
 
+    let lhs_nm =  cx.parse_sess().interner.gensym(@~"lhs");
+    let rhs_nm =  cx.parse_sess().interner.gensym(@~"rhs");
+
     // The grammar for macro_rules! is:
     // $( $lhs:mtcs => $rhs:tt );+
     // ...quasiquoting this would be nice.
     let argument_gram = ~[
         ms(match_seq(~[
-            ms(match_nonterminal(@~"lhs",@~"matchers", 0u)),
+            ms(match_nonterminal(lhs_nm, special_idents::matchers, 0u)),
             ms(match_tok(FAT_ARROW)),
-            ms(match_nonterminal(@~"rhs",@~"tt", 1u)),
+            ms(match_nonterminal(rhs_nm, special_idents::tt, 1u)),
         ], some(SEMI), false, 0u, 2u)),
         //to phase into semicolon-termination instead of
         //semicolon-separation
@@ -37,11 +41,11 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
                                      arg_reader as reader, argument_gram);
 
     // Extract the arguments:
-    let lhses:~[@named_match] = match argument_map.get(@~"lhs") {
+    let lhses:~[@named_match] = match argument_map.get(lhs_nm) {
       @matched_seq(s, sp) => s,
       _ => cx.span_bug(sp, ~"wrong-structured lhs")
     };
-    let rhses:~[@named_match] = match argument_map.get(@~"rhs") {
+    let rhses:~[@named_match] = match argument_map.get(rhs_nm) {
       @matched_seq(s, sp) => s,
       _ => cx.span_bug(sp, ~"wrong-structured rhs")
     };
@@ -53,8 +57,9 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
     -> mac_result {
 
         if cx.trace_macros() {
-            io::println(fmt!("%s! { %s }", *name,
-                             print::pprust::unexpanded_tt_to_str(
+            io::println(fmt!("%s! { %s }",
+                             cx.str_of(name),
+                             print::pprust::tt_to_str(
                                  ast::tt_delim(arg),
                                  cx.parse_sess().interner)));
         }
@@ -103,7 +108,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
                                               arg, lhses, rhses);
 
     return mr_def({
-        ident: name,
+        name: *cx.parse_sess().interner.get(name),
         ext: expr_tt({expander: exp, span: some(sp)})
     });
 }
\ No newline at end of file
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index a166957231e..1653c57bf2c 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -47,7 +47,7 @@ fn new_tt_reader(sp_diag: span_handler, itr: ident_interner,
               mut cur: @{readme: src, mut idx: 0u, dotdotdoted: false,
                          sep: none, up: tt_frame_up(option::none)},
               interpolations: match interp { /* just a convienience */
-                none => std::map::box_str_hash::<@named_match>(),
+                none => std::map::uint_hash::<@named_match>(),
                 some(x) => x
               },
               mut repeat_idx: ~[mut], mut repeat_len: ~[],
@@ -100,8 +100,8 @@ enum lis {
     lis_unconstrained, lis_constraint(uint, ident), lis_contradiction(~str)
 }
 
-fn lockstep_iter_size(&&t: token_tree, &&r: tt_reader) -> lis {
-    fn lis_merge(lhs: lis, rhs: lis) -> lis {
+fn lockstep_iter_size(t: token_tree, r: tt_reader) -> lis {
+    fn lis_merge(lhs: lis, rhs: lis, r: tt_reader) -> lis {
         match lhs {
           lis_unconstrained => rhs,
           lis_contradiction(_) => lhs,
@@ -110,9 +110,11 @@ fn lockstep_iter_size(&&t: token_tree, &&r: tt_reader) -> lis {
             lis_contradiction(_) => rhs,
             lis_constraint(r_len, _) if l_len == r_len => lhs,
             lis_constraint(r_len, r_id) => {
+                let l_n = *r.interner.get(l_id);
+                let r_n = *r.interner.get(r_id);
                 lis_contradiction(fmt!{"Inconsistent lockstep iteration: \
                                        '%s' has %u items, but '%s' has %u",
-                                        *l_id, l_len, *r_id, r_len})
+                                        l_n, l_len, r_n, r_len})
             }
           }
         }
@@ -120,7 +122,7 @@ fn lockstep_iter_size(&&t: token_tree, &&r: tt_reader) -> lis {
     match t {
       tt_delim(tts) | tt_seq(_, tts, _, _) => {
         vec::foldl(lis_unconstrained, tts, {|lis, tt|
-            lis_merge(lis, lockstep_iter_size(tt, r)) })
+            lis_merge(lis, lockstep_iter_size(tt, r), r) })
       }
       tt_tok(*) => lis_unconstrained,
       tt_nonterminal(_, name) => match *lookup_cur_matched(r, name) {
@@ -230,7 +232,7 @@ fn tt_next_token(&&r: tt_reader) -> {tok: token, sp: span} {
                 r.sp_diag.span_fatal(
                     copy r.cur_span, /* blame the macro writer */
                     fmt!{"variable '%s' is still repeating at this depth",
-                         *ident});
+                         *r.interner.get(ident)});
               }
             }
           }