about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs1
-rw-r--r--src/libsyntax/ext/base.rs13
-rw-r--r--src/libsyntax/ext/expand.rs42
-rw-r--r--src/libsyntax/ext/pipes.rs10
-rw-r--r--src/libsyntax/fold.rs4
-rw-r--r--src/libsyntax/parse.rs6
-rw-r--r--src/libsyntax/parse/attr.rs1
-rw-r--r--src/libsyntax/parse/common.rs9
-rw-r--r--src/libsyntax/parse/parser.rs17
-rw-r--r--src/libsyntax/print/pprust.rs3
-rw-r--r--src/libsyntax/syntax.rc2
-rw-r--r--src/libsyntax/visit.rs1
12 files changed, 100 insertions, 9 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index a817faad069..4c0be731df4 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -704,6 +704,7 @@ enum item_ {
     item_trait(~[ty_param], region_param, ~[ty_method]),
     item_impl(~[ty_param], region_param, option<@trait_ref> /* trait */,
               @ty /* self */, ~[@method]),
+    item_mac(mac),
 }
 
 #[auto_serialize]
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 28e5c2c5f17..0e6cce27b2b 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -17,12 +17,18 @@ type item_decorator =
 type syntax_expander_tt = {expander: syntax_expander_tt_, span: option<span>};
 type syntax_expander_tt_ = fn@(ext_ctxt, span, ast::token_tree) -> @ast::expr;
 
+type syntax_expander_tt_item
+    = {expander: syntax_expander_tt_item_, span: option<span>};
+type syntax_expander_tt_item_
+    = fn@(ext_ctxt, span, ast::ident, ast::token_tree) -> @ast::item;
+
 enum syntax_extension {
     normal(syntax_expander),
     macro_defining(macro_definer),
     item_decorator(item_decorator),
 
-    normal_tt(syntax_expander_tt)
+    normal_tt(syntax_expander_tt),
+    item_tt(syntax_expander_tt_item),
 }
 
 // A temporary hard-coded map of methods for expanding syntax extension
@@ -30,6 +36,9 @@ enum syntax_extension {
 fn syntax_expander_table() -> hashmap<str, syntax_extension> {
     fn builtin(f: syntax_expander_) -> syntax_extension
         {normal({expander: f, span: none})}
+    fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension {
+        item_tt({expander: f, span: none})
+    }
     let syntax_expanders = str_hash::<syntax_extension>();
     syntax_expanders.insert("fmt", builtin(ext::fmt::expand_syntax_ext));
     syntax_expanders.insert("auto_serialize",
@@ -61,6 +70,8 @@ fn syntax_expander_table() -> hashmap<str, syntax_extension> {
                             builtin(ext::source_util::expand_include_bin));
     syntax_expanders.insert("mod",
                             builtin(ext::source_util::expand_mod));
+    syntax_expanders.insert("proto",
+                            builtin_item_tt(ext::pipes::expand_proto));
     ret syntax_expanders;
 }
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index a037d87166a..63b3c0881e1 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1,7 +1,7 @@
 import std::map::hashmap;
 
 import ast::{crate, expr_, expr_mac, mac_invoc, mac_invoc_tt,
-             tt_delim, tt_flat};
+             tt_delim, tt_flat, item_mac};
 import fold::*;
 import ext::base::*;
 import ext::qquote::{qq_helper};
@@ -52,6 +52,10 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
                                   #fmt["this tt-style macro should be \
                                         invoked '%s!{...}'", *extname])
                   }
+                  some(item_tt(*)) {
+                    cx.span_fatal(pth.span,
+                                  "cannot use item macros in this context");
+                  }
                 }
               }
               mac_invoc_tt(pth, tt) {
@@ -109,7 +113,7 @@ fn expand_mod_items(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
             };
             alt exts.find(*mname) {
               none | some(normal(_)) | some(macro_defining(_))
-              | some(normal_tt(_)) {
+              | some(normal_tt(_)) | some(item_tt(*)) {
                 items
               }
 
@@ -124,7 +128,8 @@ fn expand_mod_items(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
 }
 
 /* record module we enter for `#mod` */
-fn expand_item(cx: ext_ctxt, &&it: @ast::item, fld: ast_fold,
+fn expand_item(exts: hashmap<str, syntax_extension>,
+               cx: ext_ctxt, &&it: @ast::item, fld: ast_fold,
                orig: fn@(&&@ast::item, ast_fold) -> @ast::item)
     -> @ast::item
 {
@@ -132,12 +137,41 @@ fn expand_item(cx: ext_ctxt, &&it: @ast::item, fld: ast_fold,
       ast::item_mod(_) | ast::item_foreign_mod(_) {true}
       _ {false}
     };
+    let it = alt it.node {
+      ast::item_mac(*) {
+        expand_item_mac(exts, cx, it)
+      }
+      _ { it }
+    };
     if is_mod { cx.mod_push(it.ident); }
     let ret_val = orig(it, fld);
     if is_mod { cx.mod_pop(); }
     ret ret_val;
 }
 
+fn expand_item_mac(exts: hashmap<str, syntax_extension>,
+                   cx: ext_ctxt, &&it: @ast::item) -> @ast::item {
+    alt it.node {
+      item_mac({node: mac_invoc_tt(pth, tt), span}) {
+        let extname = pth.idents[0];
+        alt exts.find(*extname) {
+          none {
+            cx.span_fatal(pth.span,
+                          #fmt("macro undefined: '%s'", *extname))
+          }
+          some(item_tt(expand)) {
+            expand.expander(cx, it.span, it.ident, tt)
+          }
+          _ { cx.span_fatal(it.span,
+                            #fmt("%s is not a legal here", *extname)) }
+        }
+      }
+      _ {
+        cx.span_bug(it.span, "invalid item macro invocation");
+      }
+    }
+}
+
 fn new_span(cx: ext_ctxt, sp: span) -> span {
     /* this discards information in the case of macro-defining macros */
     ret {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
@@ -166,7 +200,7 @@ fn expand_crate(parse_sess: parse::parse_sess,
     let f_pre =
         @{fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr),
           fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod),
-          fold_item: |a,b| expand_item(cx, a, b, afp.fold_item),
+          fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item),
           new_span: |a|new_span(cx, a)
           with *afp};
     let f = make_fold(f_pre);
diff --git a/src/libsyntax/ext/pipes.rs b/src/libsyntax/ext/pipes.rs
new file mode 100644
index 00000000000..23bd95226c3
--- /dev/null
+++ b/src/libsyntax/ext/pipes.rs
@@ -0,0 +1,10 @@
+
+import codemap::span;
+import ext::base::ext_ctxt;
+
+fn expand_proto(cx: ext_ctxt, span: span, id: ast::ident, tt: ast::token_tree)
+    -> @ast::item
+{
+    cx.span_unimpl(span,
+                   "Protocol compiler")
+}
\ No newline at end of file
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index ad55c85496b..75977ba6169 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -283,6 +283,10 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
                        rp,
                        /* FIXME (#2543) */ copy methods)
           }
+      item_mac(m) {
+        // TODO: we might actually want to do something here.
+        item_mac(m)
+      }
         };
 }
 
diff --git a/src/libsyntax/parse.rs b/src/libsyntax/parse.rs
index 9c143257e9e..b2d06311e67 100644
--- a/src/libsyntax/parse.rs
+++ b/src/libsyntax/parse.rs
@@ -12,6 +12,9 @@ export parse_crate_from_source_str;
 export parse_expr_from_source_str, parse_item_from_source_str;
 export parse_from_source_str;
 
+// this used to be `import common::parser_common`, but it was causing
+// unresolved import errors. Maybe resolve3 will fix it.
+import common::*;
 import parser::parser;
 //import attr::parser_attr;
 import attr::*; //resolve bug?
@@ -20,8 +23,7 @@ import common::*; //resolve bug?
 import ast::node_id;
 import util::interner;
 // FIXME (#1935): resolve badness
-import lexer::{string_reader_as_reader, tt_reader_as_reader, reader,
-               string_reader, tt_reader};
+import lexer::*;
 import diagnostic::{span_handler, mk_span_handler, mk_handler, emitter};
 
 type parse_sess = @{
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index d7ae4995520..e62de46f5db 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -1,7 +1,6 @@
 import either::{either, left, right};
 import ast_util::spanned;
 import common::*; //resolve bug?
-//import common::{parser_common, seq_sep_trailing_disallowed};
 
 export attr_or_ext;
 export parser_attr;
diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs
index d4331ee766f..16059b473bb 100644
--- a/src/libsyntax/parse/common.rs
+++ b/src/libsyntax/parse/common.rs
@@ -92,6 +92,15 @@ impl parser_common for parser {
         self.token_is_keyword(word, self.token)
     }
 
+    fn is_any_keyword(tok: token::token) -> bool {
+        alt tok {
+          token::IDENT(sid, false) {
+            self.keywords.contains_key(*self.get_str(sid))
+          }
+          _ { false }
+        }
+    }
+
     fn eat_keyword(word: str) -> bool {
         self.require_keyword(word);
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 8bac3e0d751..2f4fe783b49 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -9,7 +9,7 @@ import lexer::reader;
 import prec::{as_prec, token_to_binop};
 import attr::parser_attr;
 import common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed,
-                seq_sep_none, token_to_str, parser_common};
+                seq_sep_none, token_to_str};
 import dvec::{dvec, extensions};
 import vec::{push};
 import ast::*;
@@ -2595,6 +2595,21 @@ class parser {
             self.parse_item_impl()
         } else if self.eat_keyword("class") {
             self.parse_item_class()
+        } else if !self.is_any_keyword(copy self.token)
+            && self.look_ahead(1) == token::NOT
+        {
+            // item macro.
+            let pth = self.parse_path_without_tps();
+            #error("parsing invocation of %s", *pth.idents[0]);
+            self.expect(token::NOT);
+            let id = self.parse_ident();
+            let tt = self.parse_token_tree();
+            let m = ast::mac_invoc_tt(pth, tt);
+            let m: ast::mac = {node: m,
+                               span: {lo: self.span.lo,
+                                      hi: self.span.hi,
+                                      expn_info: none}};
+            (id, item_mac(m), none)
         } else { ret none; };
         some(self.mk_item(lo, self.last_span.hi, ident, item_, vis,
                           alt extra_attrs {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 8e85de17613..5220ecdce93 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -589,6 +589,9 @@ fn print_item(s: ps, &&item: @ast::item) {
         for methods.each |meth| { print_ty_method(s, meth); }
         bclose(s, item.span);
       }
+      ast::item_mac(_m) {
+        fail "item macros unimplemented"
+      }
     }
     s.ann.post(ann_node);
 }
diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc
index 9cf5528e1a3..5a384f04cb3 100644
--- a/src/libsyntax/syntax.rc
+++ b/src/libsyntax/syntax.rc
@@ -78,4 +78,6 @@ mod ext {
     mod log_syntax;
     mod auto_serialize;
     mod source_util;
+
+    mod pipes;
 }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 25c61535fcf..ed54ad3308b 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -163,6 +163,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
             v.visit_ty(m.decl.output, e, v);
         }
       }
+      item_mac(_m) { fail "item macros unimplemented" }
     }
 }