about summary refs log tree commit diff
path: root/src/rustc/syntax
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-03-02 14:36:22 -0800
committerNiko Matsakis <niko@alum.mit.edu>2012-03-13 21:30:06 -0400
commitbdd0c9387bb10e0db01c00dcd47ea3e6bc343e45 (patch)
tree1dbc43e5cd08037aa6cd11de8e1528b2a118b7f3 /src/rustc/syntax
parentc3516f091bbf051f8f9d40ea0dda9ab8c4584e74 (diff)
downloadrust-bdd0c9387bb10e0db01c00dcd47ea3e6bc343e45.tar.gz
rust-bdd0c9387bb10e0db01c00dcd47ea3e6bc343e45.zip
get new decorator extensions working
Diffstat (limited to 'src/rustc/syntax')
-rw-r--r--src/rustc/syntax/ext/base.rs3
-rw-r--r--src/rustc/syntax/ext/expand.rs48
-rw-r--r--src/rustc/syntax/fold.rs1
3 files changed, 52 insertions, 0 deletions
diff --git a/src/rustc/syntax/ext/base.rs b/src/rustc/syntax/ext/base.rs
index d59591d849a..721f059ee35 100644
--- a/src/rustc/syntax/ext/base.rs
+++ b/src/rustc/syntax/ext/base.rs
@@ -11,10 +11,13 @@ type syntax_expander = {
 type macro_def = {ident: str, ext: syntax_extension};
 type macro_definer =
     fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> macro_def;
+type item_decorator =
+    fn@(ext_ctxt, span, ast::meta_item, [@ast::item]) -> [@ast::item];
 
 enum syntax_extension {
     normal(syntax_expander),
     macro_defining(macro_definer),
+    item_decorator(item_decorator),
 }
 
 // A temporary hard-coded map of methods for expanding syntax extension
diff --git a/src/rustc/syntax/ext/expand.rs b/src/rustc/syntax/ext/expand.rs
index 104f49aebac..8384f7a8873 100644
--- a/src/rustc/syntax/ext/expand.rs
+++ b/src/rustc/syntax/ext/expand.rs
@@ -1,13 +1,17 @@
 import driver::session;
+import driver::session::session;
 
 import std::map::hashmap;
 
+import front::attr;
+
 import syntax::ast::{crate, expr_, expr_mac, mac_invoc};
 import syntax::fold::*;
 import syntax::ext::base::*;
 import syntax::ext::qquote::{qq_helper};
 import syntax::parse::parser::parse_expr_from_source_str;
 
+
 import codemap::{span, expanded_from};
 
 fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
@@ -26,6 +30,11 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
                     cx.span_fatal(pth.span,
                                   #fmt["macro undefined: '%s'", extname])
                   }
+                  some(item_decorator(_)) {
+                    cx.span_fatal(
+                        pth.span,
+                        #fmt["%s can only be used as a decorator", extname]);
+                  }
                   some(normal({expander: exp, span: exp_sp})) {
                     let expanded = exp(cx, pth.span, args, body);
 
@@ -52,6 +61,44 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
         };
 }
 
+fn expand_mod_items(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
+                    module: ast::_mod, fld: ast_fold,
+                    orig: fn@(ast::_mod, ast_fold) -> ast::_mod)
+    -> ast::_mod
+{
+    // Fold the contents first:
+    let module = orig(module, fld);
+
+    // For each item, look through the attributes.  If any of them are
+    // decorated with "item decorators", then use that function to transform
+    // the item into a new set of items.
+    let new_items = vec::flat_map(module.items) {|item|
+        vec::foldr(item.attrs, [item]) {|attr, items|
+            let mname = alt attr.node.value.node {
+              ast::meta_word(n) { n }
+              ast::meta_name_value(n, _) { n }
+              ast::meta_list(n, _) { n }
+            };
+            alt exts.find(mname) {
+              none { items }
+
+              some(normal(_)) | some(macro_defining(_)) {
+                cx.span_err(
+                    attr.span,
+                    #fmt["%s cannot be used as a decorator", mname]);
+                items
+              }
+
+              some(item_decorator(dec_fn)) {
+                dec_fn(cx, attr.span, attr.node.value, items)
+              }
+            }
+        }
+    };
+
+    ret {items: new_items with module};
+}
+
 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()};
@@ -78,6 +125,7 @@ fn expand_crate(sess: session::session, c: @crate) -> @crate {
     let cx: ext_ctxt = mk_ctxt(sess);
     let f_pre =
         {fold_expr: bind expand_expr(exts, cx, _, _, _, afp.fold_expr),
+         fold_mod: bind expand_mod_items(exts, cx, _, _, afp.fold_mod),
          new_span: bind new_span(cx, _)
             with *afp};
     let f = make_fold(f_pre);
diff --git a/src/rustc/syntax/fold.rs b/src/rustc/syntax/fold.rs
index f24f339590d..9e6ee76db9b 100644
--- a/src/rustc/syntax/fold.rs
+++ b/src/rustc/syntax/fold.rs
@@ -13,6 +13,7 @@ export noop_fold_mod;
 export noop_fold_ty;
 export noop_fold_block;
 export wrap;
+export fold_ty_param;
 
 type ast_fold = @mutable a_f;