about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorJohn Clements <clements@racket-lang.org>2013-05-08 15:27:29 -0700
committerJohn Clements <clements@racket-lang.org>2013-06-05 12:01:36 -0700
commitd7638f9dba5cef5c4db7b9008196ede4450d8521 (patch)
treeca96d50b78c7defd451ef9807a7f7554acc3436f /src/libsyntax
parent77c2c0900f975e1fa9179c3e7492d62656734295 (diff)
downloadrust-d7638f9dba5cef5c4db7b9008196ede4450d8521.tar.gz
rust-d7638f9dba5cef5c4db7b9008196ede4450d8521.zip
change to newer macro escape mechanism, using uints in more places
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/base.rs125
-rw-r--r--src/libsyntax/ext/expand.rs128
-rw-r--r--src/libsyntax/parse/mod.rs28
-rw-r--r--src/libsyntax/parse/parser.rs7
-rw-r--r--src/libsyntax/parse/token.rs6
5 files changed, 166 insertions, 128 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 5fae6ff3c18..48cfe61309c 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -11,6 +11,7 @@
 use core::prelude::*;
 
 use ast;
+use ast::Name;
 use codemap;
 use codemap::{CodeMap, span, ExpnInfo, ExpandedFrom};
 use codemap::CallInfo;
@@ -18,6 +19,7 @@ use diagnostic::span_handler;
 use ext;
 use parse;
 use parse::token;
+use parse::token::{intern};
 
 use core::hashmap::HashMap;
 use core::vec;
@@ -91,29 +93,33 @@ pub enum SyntaxExtension {
     IdentTT(SyntaxExpanderTTItem),
 }
 
+// The SyntaxEnv is the environment that's threaded through the expansion
+// of macros. It contains bindings for macros, and also a special binding
+// for " block" (not a legal identifier) that maps to a BlockInfo
 pub type SyntaxEnv = @mut MapChain<Name, Transformer>;
 
-// Name : the domain of SyntaxEnvs
-// want to change these to uints....
-// note that we use certain strings that are not legal as identifiers
-// to indicate, for instance, how blocks are supposed to behave.
-type Name = @~str;
-
 // Transformer : the codomain of SyntaxEnvs
 
-// NB: it may seem crazy to lump both of these into one environment;
-// what would it mean to bind "foo" to BlockLimit(true)? The idea
-// is that this follows the lead of MTWT, and accommodates growth
-// toward a more uniform syntax syntax (sorry) where blocks are just
-// another kind of transformer.
-
 pub enum Transformer {
     // this identifier maps to a syntax extension or macro
     SE(SyntaxExtension),
-    // should blocks occurring here limit macro scopes?
-    ScopeMacros(bool)
+    // blockinfo : this is ... well, it's simpler than threading
+    // another whole data stack-structured data structure through
+    // expansion. Basically, there's an invariant that every
+    // map must contain a binding for " block".
+    BlockInfo(BlockInfo)
+}
+
+pub struct BlockInfo {
+    // should macros escape from this scope?
+    macros_escape : bool,
+    // what are the pending renames?
+    pending_renames : @mut RenameList
 }
 
+// a list of ident->name renamings
+type RenameList = ~[(ast::ident,Name)];
+
 // The base map of methods for expanding syntax extension
 // AST nodes into full ASTs
 pub fn syntax_expander_table() -> SyntaxEnv {
@@ -127,77 +133,80 @@ pub fn syntax_expander_table() -> SyntaxEnv {
     }
     let mut syntax_expanders = HashMap::new();
     // NB identifier starts with space, and can't conflict with legal idents
-    syntax_expanders.insert(@~" block",
-                            @ScopeMacros(true));
-    syntax_expanders.insert(@~"macro_rules",
+    syntax_expanders.insert(intern(&" block"),
+                            @BlockInfo(BlockInfo{
+                                macros_escape : false,
+                                pending_renames : @mut ~[]
+                            }));
+    syntax_expanders.insert(intern(&"macro_rules"),
                             builtin_item_tt(
                                 ext::tt::macro_rules::add_new_extension));
-    syntax_expanders.insert(@~"fmt",
+    syntax_expanders.insert(intern(&"fmt"),
                             builtin_normal_tt(ext::fmt::expand_syntax_ext));
     syntax_expanders.insert(
-        @~"auto_encode",
+        intern(&"auto_encode"),
         @SE(ItemDecorator(ext::auto_encode::expand_auto_encode)));
     syntax_expanders.insert(
-        @~"auto_decode",
+        intern(&"auto_decode"),
         @SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
-    syntax_expanders.insert(@~"env",
+    syntax_expanders.insert(intern(&"env"),
                             builtin_normal_tt(ext::env::expand_syntax_ext));
-    syntax_expanders.insert(@~"bytes",
+    syntax_expanders.insert(intern("bytes"),
                             builtin_normal_tt(ext::bytes::expand_syntax_ext));
-    syntax_expanders.insert(@~"concat_idents",
+    syntax_expanders.insert(intern("concat_idents"),
                             builtin_normal_tt(
                                 ext::concat_idents::expand_syntax_ext));
-    syntax_expanders.insert(@~"log_syntax",
+    syntax_expanders.insert(intern(&"log_syntax"),
                             builtin_normal_tt(
                                 ext::log_syntax::expand_syntax_ext));
-    syntax_expanders.insert(@~"deriving",
+    syntax_expanders.insert(intern(&"deriving"),
                             @SE(ItemDecorator(
                                 ext::deriving::expand_meta_deriving)));
 
     // Quasi-quoting expanders
-    syntax_expanders.insert(@~"quote_tokens",
+    syntax_expanders.insert(intern(&"quote_tokens"),
                        builtin_normal_tt(ext::quote::expand_quote_tokens));
-    syntax_expanders.insert(@~"quote_expr",
+    syntax_expanders.insert(intern(&"quote_expr"),
                        builtin_normal_tt(ext::quote::expand_quote_expr));
-    syntax_expanders.insert(@~"quote_ty",
+    syntax_expanders.insert(intern(&"quote_ty"),
                        builtin_normal_tt(ext::quote::expand_quote_ty));
-    syntax_expanders.insert(@~"quote_item",
+    syntax_expanders.insert(intern(&"quote_item"),
                        builtin_normal_tt(ext::quote::expand_quote_item));
-    syntax_expanders.insert(@~"quote_pat",
+    syntax_expanders.insert(intern(&"quote_pat"),
                        builtin_normal_tt(ext::quote::expand_quote_pat));
-    syntax_expanders.insert(@~"quote_stmt",
+    syntax_expanders.insert(intern(&"quote_stmt"),
                        builtin_normal_tt(ext::quote::expand_quote_stmt));
 
-    syntax_expanders.insert(@~"line",
+    syntax_expanders.insert(intern(&"line"),
                             builtin_normal_tt(
                                 ext::source_util::expand_line));
-    syntax_expanders.insert(@~"col",
+    syntax_expanders.insert(intern(&"col"),
                             builtin_normal_tt(
                                 ext::source_util::expand_col));
-    syntax_expanders.insert(@~"file",
+    syntax_expanders.insert(intern(&"file"),
                             builtin_normal_tt(
                                 ext::source_util::expand_file));
-    syntax_expanders.insert(@~"stringify",
+    syntax_expanders.insert(intern(&"stringify"),
                             builtin_normal_tt(
                                 ext::source_util::expand_stringify));
-    syntax_expanders.insert(@~"include",
+    syntax_expanders.insert(intern(&"include"),
                             builtin_normal_tt(
                                 ext::source_util::expand_include));
-    syntax_expanders.insert(@~"include_str",
+    syntax_expanders.insert(intern(&"include_str"),
                             builtin_normal_tt(
                                 ext::source_util::expand_include_str));
-    syntax_expanders.insert(@~"include_bin",
+    syntax_expanders.insert(intern(&"include_bin"),
                             builtin_normal_tt(
                                 ext::source_util::expand_include_bin));
-    syntax_expanders.insert(@~"module_path",
+    syntax_expanders.insert(intern(&"module_path"),
                             builtin_normal_tt(
                                 ext::source_util::expand_mod));
-    syntax_expanders.insert(@~"proto",
+    syntax_expanders.insert(intern(&"proto"),
                             builtin_item_tt(ext::pipes::expand_proto));
-    syntax_expanders.insert(@~"asm",
+    syntax_expanders.insert(intern(&"asm"),
                             builtin_normal_tt(ext::asm::expand_asm));
     syntax_expanders.insert(
-        @~"trace_macros",
+        intern(&"trace_macros"),
         builtin_normal_tt(ext::trace_macros::expand_trace_macros));
     MapChain::new(~syntax_expanders)
 }
@@ -478,7 +487,39 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
             ConsMapChain (~ref mut map,_) => map.insert(key,ext)
         }
     }
+    // insert the binding into the topmost frame for which the binding
+    // associated with 'n' exists and satisfies pred
+    // ... there are definitely some opportunities for abstraction
+    // here that I'm ignoring. (e.g., manufacturing a predicate on
+    // the maps in the chain, and using an abstract "find".
+    fn insert_into_frame(&mut self, key: K, ext: @V, n: K, pred: &fn(&@V)->bool) {
+        match *self {
+            BaseMapChain (~ref mut map) => {
+                if satisfies_pred(map,&n,pred) {
+                    map.insert(key,ext);
+                } else {
+                    fail!(~"expected map chain containing satisfying frame")
+                }
+            },
+            ConsMapChain (~ref mut map, rest) => {
+                if satisfies_pred(map,&n,pred) {
+                    map.insert(key,ext);
+                } else {
+                    rest.insert_into_frame(key,ext,n,pred)
+                }
+            }
+        }
+    }
+}
 
+fn satisfies_pred<K : Eq + Hash + IterBytes,V>(map : &mut HashMap<K,V>,
+                                               n: &K,
+                                               pred: &fn(&V)->bool)
+    -> bool {
+    match map.find(n) {
+        Some(ref v) => (pred(*v)),
+        None => false
+    }
 }
 
 #[cfg(test)]
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 6ea1160c267..c23e34e0f91 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -25,6 +25,7 @@ use ext::base::*;
 use fold::*;
 use parse;
 use parse::{parse_item_from_source_str};
+use parse::token::{get_ident_interner,intern};
 
 use core::vec;
 
@@ -48,15 +49,14 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                             fmt!("expected macro name without module \
                                   separators"));
                     }
-                    /* using idents and token::special_idents would make the
-                    the macro names be hygienic */
-                    let extname = cx.parse_sess().interner.get(pth.idents[0]);
+                    let extname = pth.idents[0];
+                    let extnamestr = get_ident_interner().get(extname);
                     // leaving explicit deref here to highlight unbox op:
-                    match (*extsbox).find(&extname) {
+                    match (*extsbox).find(&extname.repr) {
                         None => {
                             cx.span_fatal(
                                 pth.span,
-                                fmt!("macro undefined: '%s'", *extname))
+                                fmt!("macro undefined: '%s'", *extnamestr))
                         }
                         Some(@SE(NormalTT(SyntaxExpanderTT{
                             expander: exp,
@@ -65,7 +65,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                             cx.bt_push(ExpandedFrom(CallInfo {
                                 call_site: s,
                                 callee: NameAndSpan {
-                                    name: copy *extname,
+                                    name: copy *extnamestr,
                                     span: exp_sp,
                                 },
                             }));
@@ -78,7 +78,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                                         pth.span,
                                         fmt!(
                                             "non-expr macro in expr pos: %s",
-                                            *extname
+                                            *extnamestr
                                         )
                                     )
                                 }
@@ -94,7 +94,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                         _ => {
                             cx.span_fatal(
                                 pth.span,
-                                fmt!("'%s' is not a tt-style macro", *extname)
+                                fmt!("'%s' is not a tt-style macro", *extnamestr)
                             )
                         }
                     }
@@ -131,7 +131,7 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv,
         do vec::foldr(item.attrs, ~[*item]) |attr, items| {
             let mname = attr::get_attr_name(attr);
 
-            match (*extsbox).find(&mname) {
+            match (*extsbox).find(&intern(*mname)) {
               Some(@SE(ItemDecorator(dec_fn))) => {
                   cx.bt_push(ExpandedFrom(CallInfo {
                       call_site: attr.span,
@@ -155,16 +155,20 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv,
 
 // eval $e with a new exts frame:
 macro_rules! with_exts_frame (
-    ($extsboxexpr:expr,$e:expr) =>
+    ($extsboxexpr:expr,$macros_escape:expr,$e:expr) =>
     ({let extsbox = $extsboxexpr;
       let oldexts = *extsbox;
       *extsbox = oldexts.push_frame();
+      extsbox.insert(intern(special_block_name),
+                     @BlockInfo(BlockInfo{macros_escape:$macros_escape,pending_renames:@mut ~[]}));
       let result = $e;
       *extsbox = oldexts;
       result
      })
 )
 
+static special_block_name : &'static str = " block";
+
 // When we enter a module, record it, for the sake of `module!`
 pub fn expand_item(extsbox: @mut SyntaxEnv,
                    cx: @ExtCtxt,
@@ -182,14 +186,8 @@ pub fn expand_item(extsbox: @mut SyntaxEnv,
           match it.node {
               ast::item_mod(_) | ast::item_foreign_mod(_) => {
                   cx.mod_push(it.ident);
-                  let result =
-                      // don't push a macro scope for macro_escape:
-                      if contains_macro_escape(it.attrs) {
-                      orig(it,fld)
-                  } else {
-                      // otherwise, push a scope:
-                      with_exts_frame!(extsbox,orig(it,fld))
-                  };
+                  let macro_escape = contains_macro_escape(it.attrs);
+                  let result = with_exts_frame!(extsbox,macro_escape,orig(it,fld));
                   cx.mod_pop();
                   result
               }
@@ -205,31 +203,6 @@ pub fn contains_macro_escape (attrs: &[ast::attribute]) -> bool {
     attrs.any(|attr| "macro_escape" == *attr::get_attr_name(attr))
 }
 
-// this macro disables (one layer of) macro
-// scoping, to allow a block to add macro bindings
-// to its parent env
-macro_rules! without_macro_scoping(
-    ($extsexpr:expr,$exp:expr) =>
-    ({
-        // only evaluate this once:
-        let exts = $extsexpr;
-        // capture the existing binding:
-        let existingBlockBinding =
-            match exts.find(&@~" block"){
-                Some(binding) => binding,
-                None => cx.bug("expected to find \" block\" binding")
-            };
-        // this prevents the block from limiting the macros' scope:
-        exts.insert(@~" block",@ScopeMacros(false));
-        let result = $exp;
-        // reset the block binding. Note that since the original
-        // one may have been inherited, this procedure may wind
-        // up introducing a block binding where one didn't exist
-        // before.
-        exts.insert(@~" block",existingBlockBinding);
-        result
-    }))
-
 // Support for item-position macro invocations, exactly the same
 // logic as for expression-position macro invocations.
 pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
@@ -243,22 +216,24 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
         _ => cx.span_bug(it.span, "invalid item macro invocation")
     };
 
-    let extname = cx.parse_sess().interner.get(pth.idents[0]);
-    let expanded = match (*extsbox).find(&extname) {
+    let extname = pth.idents[0];
+    let interner = get_ident_interner();
+    let extnamestr = interner.get(extname);
+    let expanded = match (*extsbox).find(&extname.repr) {
         None => cx.span_fatal(pth.span,
-                              fmt!("macro undefined: '%s!'", *extname)),
+                              fmt!("macro undefined: '%s!'", *extnamestr)),
 
         Some(@SE(NormalTT(ref expand))) => {
             if it.ident != parse::token::special_idents::invalid {
                 cx.span_fatal(pth.span,
                               fmt!("macro %s! expects no ident argument, \
-                                    given '%s'", *extname,
-                                   *cx.parse_sess().interner.get(it.ident)));
+                                    given '%s'", *extnamestr,
+                                   *interner.get(it.ident)));
             }
             cx.bt_push(ExpandedFrom(CallInfo {
                 call_site: it.span,
                 callee: NameAndSpan {
-                    name: copy *extname,
+                    name: copy *extnamestr,
                     span: expand.span
                 }
             }));
@@ -268,29 +243,29 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
             if it.ident == parse::token::special_idents::invalid {
                 cx.span_fatal(pth.span,
                               fmt!("macro %s! expects an ident argument",
-                                   *extname));
+                                   *extnamestr));
             }
             cx.bt_push(ExpandedFrom(CallInfo {
                 call_site: it.span,
                 callee: NameAndSpan {
-                    name: copy *extname,
+                    name: copy *extnamestr,
                     span: expand.span
                 }
             }));
             ((*expand).expander)(cx, it.span, it.ident, tts)
         }
         _ => cx.span_fatal(
-            it.span, fmt!("%s! is not legal in item position", *extname))
+            it.span, fmt!("%s! is not legal in item position", *extnamestr))
     };
 
     let maybe_it = match expanded {
         MRItem(it) => fld.fold_item(it),
         MRExpr(_) => cx.span_fatal(pth.span,
                                     ~"expr macro in item position: "
-                                    + *extname),
+                                    + *extnamestr),
         MRAny(_, item_maker, _) => item_maker().chain(|i| {fld.fold_item(i)}),
         MRDef(ref mdef) => {
-            extsbox.insert(@/*bad*/ copy mdef.name, @SE((*mdef).ext));
+            insert_macro(*extsbox,intern(mdef.name), @SE((*mdef).ext));
             None
         }
     };
@@ -298,6 +273,23 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
     return maybe_it;
 }
 
+
+// insert a macro into the innermost frame that doesn't have the
+// macro_escape tag.
+fn insert_macro(exts: SyntaxEnv, name: ast::Name, transformer: @Transformer) {
+    let block_err_msg = "special identifier ' block' was bound to a non-BlockInfo";
+    let is_non_escaping_block =
+        |t : &@Transformer| -> bool{
+        match t {
+            &@BlockInfo(BlockInfo {macros_escape:false,_}) => true,
+            &@BlockInfo(BlockInfo {_}) => false,
+            _ => fail!(block_err_msg)
+        }
+    };
+    exts.insert_into_frame(name,transformer,intern(special_block_name),
+                           is_non_escaping_block)
+}
+
 // expand a stmt
 pub fn expand_stmt(extsbox: @mut SyntaxEnv,
                    cx: @ExtCtxt,
@@ -323,16 +315,17 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
             fmt!("expected macro name without module \
                   separators"));
     }
-    let extname = cx.parse_sess().interner.get(pth.idents[0]);
-    let (fully_expanded, sp) = match (*extsbox).find(&extname) {
+    let extname = pth.idents[0];
+    let extnamestr = get_ident_interner().get(extname);
+    let (fully_expanded, sp) = match (*extsbox).find(&extname.repr) {
         None =>
-            cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),
+            cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extnamestr)),
 
         Some(@SE(NormalTT(
             SyntaxExpanderTT{expander: exp, span: exp_sp}))) => {
             cx.bt_push(ExpandedFrom(CallInfo {
                 call_site: sp,
-                callee: NameAndSpan { name: copy *extname, span: exp_sp }
+                callee: NameAndSpan { name: copy *extnamestr, span: exp_sp }
             }));
             let expanded = match exp(cx, mac.span, tts) {
                 MRExpr(e) =>
@@ -341,7 +334,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
                 MRAny(_,_,stmt_mkr) => stmt_mkr(),
                 _ => cx.span_fatal(
                     pth.span,
-                    fmt!("non-stmt macro in stmt pos: %s", *extname))
+                    fmt!("non-stmt macro in stmt pos: %s", *extnamestr))
             };
 
             //keep going, outside-in
@@ -362,7 +355,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
 
         _ => {
             cx.span_fatal(pth.span,
-                          fmt!("'%s' is not a tt-style macro", *extname))
+                          fmt!("'%s' is not a tt-style macro", *extnamestr))
         }
     };
 
@@ -382,19 +375,8 @@ pub fn expand_block(extsbox: @mut SyntaxEnv,
                     fld: @ast_fold,
                     orig: @fn(&blk_, span, @ast_fold) -> (blk_, span))
                  -> (blk_, span) {
-    match (*extsbox).find(&@~" block") {
-        // no scope limit on macros in this block, no need
-        // to push an exts frame:
-        Some(@ScopeMacros(false)) => {
-            orig (blk,sp,fld)
-        },
-        // this block should limit the scope of its macros:
-        Some(@ScopeMacros(true)) => {
-            // see note below about treatment of exts table
-            with_exts_frame!(extsbox,orig(blk,sp,fld))
-        },
-        _ => cx.span_bug(sp, "expected ScopeMacros binding for \" block\"")
-    }
+    // see note below about treatment of exts table
+    with_exts_frame!(extsbox,false,orig(blk,sp,fld))
 }
 
 // given a mutable list of renames, return a tree-folder that applies those
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 9c716f5631f..8306b0ff1a9 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -351,6 +351,7 @@ mod test {
     use codemap::{span, BytePos, spanned};
     use opt_vec;
     use ast;
+    use ast_util::new_ident;
     use abi;
     use parse::parser::Parser;
     use parse::token::intern;
@@ -377,9 +378,14 @@ mod test {
         span{lo:BytePos(a),hi:BytePos(b),expn_info:None}
     }
 
+    // compose new_ident and intern:
+    fn intern_ident(str : &str) -> ast::ident {
+        new_ident(intern(str))
+    }
+
     // convert a vector of uints to a vector of ast::idents
     fn ints_to_idents(ids: ~[~str]) -> ~[ast::ident] {
-        ids.map(|u| intern(*u))
+        ids.map(|u| intern_ident(*u))
     }
 
     #[test] fn path_exprs_1 () {
@@ -387,7 +393,7 @@ mod test {
                    @ast::expr{id:1,
                               node:ast::expr_path(@ast::Path {span:sp(0,1),
                                                               global:false,
-                                                              idents:~[intern("a")],
+                                                              idents:~[intern_ident("a")],
                                                               rp:None,
                                                               types:~[]}),
                               span:sp(0,1)})
@@ -449,7 +455,7 @@ mod test {
                                                   node:ast::expr_path(
                                                       @ast::Path{span:sp(7,8),
                                                                  global:false,
-                                                                 idents:~[intern("d")],
+                                                                 idents:~[intern_ident("d")],
                                                                  rp:None,
                                                                  types:~[]
                                                                 }),
@@ -466,7 +472,7 @@ mod test {
                                @ast::Path{
                                    span:sp(0,1),
                                    global:false,
-                                   idents:~[intern("b")],
+                                   idents:~[intern_ident("b")],
                                    rp:None,
                                    types: ~[]}),
                            span: sp(0,1)},
@@ -487,7 +493,7 @@ mod test {
                                                   @ast::Path{
                                                       span:sp(0,1),
                                                       global:false,
-                                                      idents:~[intern("b")],
+                                                      idents:~[intern_ident("b")],
                                                       rp: None,
                                                       types: ~[]},
                                                   None // no idea
@@ -506,7 +512,7 @@ mod test {
                                         span:sp(4,4), // this is bizarre...
                                         // check this in the original parser?
                                         global:false,
-                                        idents:~[intern("int")],
+                                        idents:~[intern_ident("int")],
                                         rp: None,
                                         types: ~[]},
                                                        2),
@@ -516,7 +522,7 @@ mod test {
                                                            @ast::Path{
                                                                span:sp(0,1),
                                                                global:false,
-                                                               idents:~[intern("b")],
+                                                               idents:~[intern_ident("b")],
                                                                rp: None,
                                                                types: ~[]},
                                                            None // no idea
@@ -532,7 +538,7 @@ mod test {
         // assignment order of the node_ids.
         assert_eq!(string_to_item(@~"fn a (b : int) { b; }"),
                   Some(
-                      @ast::item{ident:intern("a"),
+                      @ast::item{ident:intern_ident("a"),
                             attrs:~[],
                             id: 9, // fixme
                             node: ast::item_fn(ast::fn_decl{
@@ -542,7 +548,7 @@ mod test {
                                                 node: ast::ty_path(@ast::Path{
                                         span:sp(10,13),
                                         global:false,
-                                        idents:~[intern("int")],
+                                        idents:~[intern_ident("int")],
                                         rp: None,
                                         types: ~[]},
                                                        2),
@@ -553,7 +559,7 @@ mod test {
                                                        @ast::Path{
                                                            span:sp(6,7),
                                                            global:false,
-                                                           idents:~[intern("b")],
+                                                           idents:~[intern_ident("b")],
                                                            rp: None,
                                                            types: ~[]},
                                                        None // no idea
@@ -583,7 +589,7 @@ mod test {
                                                         @ast::Path{
                                                             span:sp(17,18),
                                                             global:false,
-                                                            idents:~[intern("b")],
+                                                            idents:~[intern_ident("b")],
                                                             rp:None,
                                                             types: ~[]}),
                                                     span: sp(17,18)},
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 23e3f145398..4635db0e10f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2628,6 +2628,13 @@ impl Parser {
             // to the macro clause of parse_item_or_view_item. This
             // could use some cleanup, it appears to me.
 
+            // whoops! I now have a guess: I'm guessing the "parens-only"
+            // rule here is deliberate, to allow macro users to use parens
+            // for things that should be parsed as stmt_mac, and braces
+            // for things that should expand into items. Tricky, and
+            // somewhat awkward... and probably undocumented. Of course,
+            // I could just be wrong.
+
             check_expected_item(self, item_attrs);
 
             // Potential trouble: if we allow macros with paths instead of
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index b716384c6cc..cd274817a16 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -394,6 +394,8 @@ pub struct ident_interner {
 }
 
 impl ident_interner {
+    // I'm torn as to whether these should produce idents or
+    // just uints.
     pub fn intern(&self, val: &str) -> ast::ident {
         ast::ident { repr: self.interner.intern(val), ctxt: 0 }
     }
@@ -530,9 +532,9 @@ pub fn mk_fake_ident_interner() -> @ident_interner {
 }
 
 // maps a string to its interned representation
-pub fn intern(str : &str) -> ast::ident {
+pub fn intern(str : &str) -> uint {
     let interner = get_ident_interner();
-    interner.intern(str)
+    interner.intern(str).repr
 }
 
 /**