about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2012-05-18 10:00:49 -0700
committerPaul Stansifer <paul.stansifer@gmail.com>2012-05-18 10:05:25 -0700
commit07e775404f21b2a3e66e4038461918f73807f9f9 (patch)
tree9ef5bd22d4eeb343d6ea163353f40289425373fd
parent88f4d0694187a451173d40e9c44db4499a6c04f4 (diff)
downloadrust-07e775404f21b2a3e66e4038461918f73807f9f9.tar.gz
rust-07e775404f21b2a3e66e4038461918f73807f9f9.zip
add #mod[], which expands to the current module path
-rw-r--r--src/librustsyntax/ext/base.rs14
-rw-r--r--src/librustsyntax/ext/expand.rs16
-rw-r--r--src/librustsyntax/ext/source_util.rs7
-rw-r--r--src/test/run-pass/syntax-extension-source-utils.rs12
4 files changed, 44 insertions, 5 deletions
diff --git a/src/librustsyntax/ext/base.rs b/src/librustsyntax/ext/base.rs
index 8cc388c7b1b..f669db3c470 100644
--- a/src/librustsyntax/ext/base.rs
+++ b/src/librustsyntax/ext/base.rs
@@ -53,6 +53,8 @@ fn syntax_expander_table() -> hashmap<str, syntax_extension> {
                             builtin(ext::source_util::expand_stringify));
     syntax_expanders.insert("include",
                             builtin(ext::source_util::expand_include));
+    syntax_expanders.insert("mod",
+                            builtin(ext::source_util::expand_mod));
     ret syntax_expanders;
 }
 
@@ -62,6 +64,9 @@ iface ext_ctxt {
     fn cfg() -> ast::crate_cfg;
     fn print_backtrace();
     fn backtrace() -> expn_info;
+    fn mod_push(mod_name: ast::ident);
+    fn mod_pop();
+    fn mod_path() -> [ast::ident];
     fn bt_push(ei: codemap::expn_info_);
     fn bt_pop();
     fn span_fatal(sp: span, msg: str) -> !;
@@ -76,13 +81,17 @@ fn mk_ctxt(parse_sess: parse::parse_sess,
            cfg: ast::crate_cfg) -> ext_ctxt {
     type ctxt_repr = {parse_sess: parse::parse_sess,
                       cfg: ast::crate_cfg,
-                      mut backtrace: expn_info};
+                      mut backtrace: expn_info,
+                      mut mod_path: [ast::ident]};
     impl of ext_ctxt for ctxt_repr {
         fn codemap() -> codemap { self.parse_sess.cm }
         fn parse_sess() -> parse::parse_sess { self.parse_sess }
         fn cfg() -> ast::crate_cfg { self.cfg }
         fn print_backtrace() { }
         fn backtrace() -> expn_info { self.backtrace }
+        fn mod_push(i: ast::ident) { vec::push(self.mod_path, i); }
+        fn mod_pop() { vec::pop(self.mod_path); }
+        fn mod_path() -> [ast::ident] { ret self.mod_path; }
         fn bt_push(ei: codemap::expn_info_) {
             alt ei {
               expanded_from({call_site: cs, callie: callie}) {
@@ -129,7 +138,8 @@ fn mk_ctxt(parse_sess: parse::parse_sess,
     let imp : ctxt_repr = {
         parse_sess: parse_sess,
         cfg: cfg,
-        mut backtrace: none
+        mut backtrace: none,
+        mut mod_path: []
     };
     ret imp as ext_ctxt
 }
diff --git a/src/librustsyntax/ext/expand.rs b/src/librustsyntax/ext/expand.rs
index f70a75bd96a..c9de4d84602 100644
--- a/src/librustsyntax/ext/expand.rs
+++ b/src/librustsyntax/ext/expand.rs
@@ -89,6 +89,21 @@ fn expand_mod_items(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
     ret {items: new_items with module};
 }
 
+/* record module we enter for `#mod` */
+fn expand_item(cx: ext_ctxt, &&it: @ast::item, fld: ast_fold,
+               orig: fn@(&&@ast::item, ast_fold) -> @ast::item)
+    -> @ast::item
+{
+    let is_mod = alt it.node {
+      ast::item_mod(_) | ast::item_native_mod(_) {true}
+      _ {false}
+    };
+    if is_mod { cx.mod_push(it.ident); }
+    let ret_val = orig(it, fld);
+    if is_mod { cx.mod_pop(); }
+    ret ret_val;
+}
+
 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()};
@@ -117,6 +132,7 @@ fn expand_crate(parse_sess: parse::parse_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),
+         fold_item: bind expand_item(cx, _, _, afp.fold_item),
          new_span: bind new_span(cx, _)
             with *afp};
     let f = make_fold(f_pre);
diff --git a/src/librustsyntax/ext/source_util.rs b/src/librustsyntax/ext/source_util.rs
index 7b3471d03b4..ba3ab3342c6 100644
--- a/src/librustsyntax/ext/source_util.rs
+++ b/src/librustsyntax/ext/source_util.rs
@@ -3,7 +3,6 @@ import ast;
 import codemap::span;
 import print::pprust;
 
-
 /* #line(): expands to the current line number */
 fn expand_line(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
                _body: ast::mac_body) -> @ast::expr {
@@ -46,3 +45,9 @@ fn expand_include(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
                                         parse::parser::SOURCE_FILE);
     ret parse::parser::parse_expr(p)
 }
+
+fn expand_mod(cx: ext_ctxt, sp: span, arg: ast::mac_arg, _body: ast::mac_body)
+    -> @ast::expr {
+    get_mac_args(cx, sp, arg, 0u, option::some(0u), "file");
+    ret make_new_lit(cx, sp, ast::lit_str(str::connect(cx.mod_path(), "::")));
+}
diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs
index 926228534cc..23943ece409 100644
--- a/src/test/run-pass/syntax-extension-source-utils.rs
+++ b/src/test/run-pass/syntax-extension-source-utils.rs
@@ -1,11 +1,19 @@
 // This test is brittle! 
 // xfail-pretty - the pretty tests lose path information, breaking #include
 
+mod m1 {
+    mod m2 {
+        fn where_am_i() -> str { #mod[] }
+    }
+}
+
 fn main() {
-    assert(#line[] == 5u);
+    assert(#line[] == 11u);
     assert(#col[] == 12u);
     assert(#file[].ends_with("syntax-extension-source-utils.rs"));
     assert(#stringify[(2*3) + 5] == "2 * 3 + 5");
     assert(#include["syntax-extension-source-utils-files/includeme.fragment"]
-           == "victory robot 6")
+           == "victory robot 6");
+    // The Windows tests are wrapped in an extra module for some reason
+    assert(m1::m2::where_am_i().ends_with("m1::m2"));
 }