add #mod[], which expands to the current module path
This commit is contained in:
parent
88f4d06941
commit
07e775404f
4 changed files with 44 additions and 5 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(), "::")));
|
||||
}
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue