summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorEric Holk <eric.holk@gmail.com>2012-07-05 12:10:33 -0700
committerEric Holk <eric.holk@gmail.com>2012-07-06 10:42:40 -0700
commit05cdda3a2c147fdc8caef4e6c662f518ec325e0a (patch)
treefba957706d8588512bfd259d7873edd615854d36 /src/libsyntax/ext
parenta787f4001388a394d5219b74113a718d980e4c90 (diff)
downloadrust-05cdda3a2c147fdc8caef4e6c662f518ec325e0a.tar.gz
rust-05cdda3a2c147fdc8caef4e6c662f518ec325e0a.zip
Plumbing and parsing for item-position macros.
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/base.rs13
-rw-r--r--src/libsyntax/ext/expand.rs42
-rw-r--r--src/libsyntax/ext/pipes.rs10
3 files changed, 60 insertions, 5 deletions
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