From 07e775404f21b2a3e66e4038461918f73807f9f9 Mon Sep 17 00:00:00 2001 From: Paul Stansifer Date: Fri, 18 May 2012 10:00:49 -0700 Subject: [PATCH] add #mod[], which expands to the current module path --- src/librustsyntax/ext/base.rs | 14 ++++++++++++-- src/librustsyntax/ext/expand.rs | 16 ++++++++++++++++ src/librustsyntax/ext/source_util.rs | 7 ++++++- .../run-pass/syntax-extension-source-utils.rs | 12 ++++++++++-- 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 { 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, 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")); }