about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorKevin Atkinson <kevina@cs.utah.edu>2012-02-01 16:19:45 -0700
committerKevin Atkinson <kevina@cs.utah.edu>2012-02-03 20:41:49 -0700
commita2dde9a69218ab350b442caec00d2b991ba2262c (patch)
treec66979892a5229502d56c586f2327ef97f872e4c /src/comp
parentf7fab77102057b55202992c7e73d62d7123f6356 (diff)
downloadrust-a2dde9a69218ab350b442caec00d2b991ba2262c.tar.gz
rust-a2dde9a69218ab350b442caec00d2b991ba2262c.zip
Allow anti-quotes to also be ast::ty rather than just ast::expr.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/syntax/ast.rs2
-rw-r--r--src/comp/syntax/ext/qquote.rs79
-rw-r--r--src/comp/syntax/parse/parser.rs7
3 files changed, 74 insertions, 14 deletions
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs
index 576e0ab865a..d8044ae3807 100644
--- a/src/comp/syntax/ast.rs
+++ b/src/comp/syntax/ast.rs
@@ -285,7 +285,7 @@ enum mac_ {
     // the span is used by the quoter/anti-quoter ...
     mac_qq(span /* span of expr */, @expr), // quasi-quote
     mac_aq(span /* span of quote */, @expr), // anti-quote
-    mac_var(uint),
+    mac_var(uint)
 }
 
 type lit = spanned<lit_>;
diff --git a/src/comp/syntax/ext/qquote.rs b/src/comp/syntax/ext/qquote.rs
index 174c58d807c..23e6eba2775 100644
--- a/src/comp/syntax/ext/qquote.rs
+++ b/src/comp/syntax/ext/qquote.rs
@@ -2,7 +2,7 @@ import driver::session;
 
 import option::{none, some};
 
-import syntax::ast::{crate, expr_, expr_mac, mac_invoc,
+import syntax::ast::{crate, expr_, mac_invoc,
                      mac_qq, mac_aq, mac_var};
 import syntax::fold::*;
 import syntax::visit::*;
@@ -17,16 +17,28 @@ import std::io::*;
 import codemap::span;
 
 type aq_ctxt = @{lo: uint,
-                 mutable gather: [{lo: uint, hi: uint, e: @ast::expr}]};
+                 mutable gather: [{lo: uint, hi: uint,
+                                   e: @ast::expr, constr: str}]};
+enum fragment {
+    from_expr(@ast::expr),
+    from_ty(@ast::ty)
+}
 
 iface qq_helper {
     fn span() -> span;
     fn visit(aq_ctxt, vt<aq_ctxt>);
+    fn extract_mac() -> option<ast::mac_>;
     fn mk_parse_fn(ext_ctxt,span) -> @ast::expr;
 }
 impl of qq_helper for @ast::expr {
     fn span() -> span {self.span}
     fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_expr(self, cx, v);}
+    fn extract_mac() -> option<ast::mac_> {
+        alt (self.node) {
+          ast::expr_mac({node: mac, _}) {some(mac)}
+          _ {none}
+        }
+    }
     fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
         mk_path(cx, sp, ["syntax", "parse", "parser", "parse_expr"])
     }
@@ -34,6 +46,12 @@ impl of qq_helper for @ast::expr {
 impl of qq_helper for @ast::ty {
     fn span() -> span {self.span}
     fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_ty(self, cx, v);}
+    fn extract_mac() -> option<ast::mac_> {
+        alt (self.node) {
+          ast::ty_mac({node: mac, _}) {some(mac)}
+          _ {none}
+        }
+    }
     fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
         mk_path(cx, sp, ["syntax", "ext", "qquote", "parse_ty"])
     }
@@ -41,6 +59,7 @@ impl of qq_helper for @ast::ty {
 impl of qq_helper for @ast::item {
     fn span() -> span {self.span}
     fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_item(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_item"])
     }
@@ -48,6 +67,7 @@ impl of qq_helper for @ast::item {
 impl of qq_helper for @ast::stmt {
     fn span() -> span {self.span}
     fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_stmt(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_stmt"])
     }
@@ -55,6 +75,7 @@ impl of qq_helper for @ast::stmt {
 impl of qq_helper for @ast::pat {
     fn span() -> span {self.span}
     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", "parse", "parser", "parse_pat"])
     }
@@ -62,23 +83,32 @@ impl of qq_helper for @ast::pat {
 
 fn gather_anti_quotes<N: qq_helper>(lo: uint, node: N) -> aq_ctxt
 {
-    let v = @{visit_expr: visit_expr_aq
+    let v = @{visit_expr: visit_aq_expr,
+              visit_ty: visit_aq_ty
               with *default_visitor()};
     let cx = @{lo:lo, mutable gather: []};
     node.visit(cx, mk_vt(v));
     ret cx;
 }
 
-fn visit_expr_aq(expr: @ast::expr, &&cx: aq_ctxt, v: vt<aq_ctxt>)
+fn visit_aq<T:qq_helper>(node: T, constr: str, &&cx: aq_ctxt, v: vt<aq_ctxt>)
 {
-    alt (expr.node) {
-      expr_mac({node: mac_aq(sp, e), _}) {
+    alt (node.extract_mac()) {
+      some(mac_aq(sp, e)) {
         cx.gather += [{lo: sp.lo - cx.lo, hi: sp.hi - cx.lo,
-                       e: e}];
+                       e: e, constr: constr}];
       }
-      _ {visit_expr(expr, cx, v);}
+      _ {node.visit(cx, v);}
     }
 }
+// FIXME: these are only here because I (kevina) couldn't figure out how to
+// get bind to work in gather_anti_quotes
+fn visit_aq_expr(node: @ast::expr, &&cx: aq_ctxt, v: vt<aq_ctxt>) {
+    visit_aq(node,"from_expr",cx,v);
+}
+fn visit_aq_ty(node: @ast::ty, &&cx: aq_ctxt, v: vt<aq_ctxt>) {
+    visit_aq(node,"from_ty",cx,v);
+}
 
 fn is_space(c: char) -> bool {
     syntax::parse::lexer::is_whitespace(c)
@@ -211,28 +241,51 @@ fn expand_qquote<N: qq_helper>
         rcall = mk_call(cx,sp,
                         ["syntax", "ext", "qquote", "replace"],
                         [pcall,
-                         mk_vec_e(cx,sp, vec::map(qcx.gather, {|g| g.e}))]);
+                         mk_vec_e(cx,sp, vec::map(qcx.gather) {|g|
+                             mk_call(cx,sp,
+                                     ["syntax", "ext", "qquote", g.constr],
+                                     [g.e])
+                         })]);
     }
 
     ret rcall;
 }
 
-fn replace(e: @ast::expr, repls: [@ast::expr]) -> @ast::expr {
+fn replace(e: @ast::expr, repls: [fragment]) -> @ast::expr {
     let aft = default_ast_fold();
     let f_pre = {fold_expr: bind replace_expr(repls, _, _, _,
-                                              aft.fold_expr)
+                                              aft.fold_expr),
+                 fold_ty: bind replace_ty(repls, _, _, _,
+                                          aft.fold_ty)
                  with *aft};
     let f = make_fold(f_pre);
     ret f.fold_expr(e);
 }
 
-fn replace_expr(repls: [@ast::expr],
+fn replace_expr(repls: [fragment],
                 e: ast::expr_, s: span, fld: ast_fold,
                 orig: fn@(ast::expr_, span, ast_fold)->(ast::expr_, span))
     -> (ast::expr_, span)
 {
     alt e {
-      expr_mac({node: mac_var(i), _}) {let r = repls[i]; (r.node, r.span)}
+      ast::expr_mac({node: mac_var(i), _}) {
+        alt (repls[i]) {
+          from_expr(r) {(r.node, r.span)}
+          _ {fail /* fixme error message */}}}
+      _ {orig(e,s,fld)}
+    }
+}
+
+fn replace_ty(repls: [fragment],
+                e: ast::ty_, s: span, fld: ast_fold,
+                orig: fn@(ast::ty_, span, ast_fold)->(ast::ty_, span))
+    -> (ast::ty_, span)
+{
+    alt e {
+      ast::ty_mac({node: mac_var(i), _}) {
+        alt (repls[i]) {
+          from_ty(r) {(r.node, r.span)}
+          _ {fail /* fixme error message */}}}
       _ {orig(e,s,fld)}
     }
 }
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index 2327350eb82..7253109d022 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -420,6 +420,13 @@ fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
 
 fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
     let lo = p.span.lo;
+
+    alt have_dollar(p) {
+      some(e) {ret @spanned(lo, p.span.hi,
+                            ast::ty_mac(spanned(lo, p.span.hi, e)))}
+      none {}
+    }
+
     let t: ast::ty_;
     // FIXME: do something with this