1
Fork 0

add #mod[], which expands to the current module path

This commit is contained in:
Paul Stansifer 2012-05-18 10:00:49 -07:00
parent 88f4d06941
commit 07e775404f
4 changed files with 44 additions and 5 deletions

View file

@ -53,6 +53,8 @@ fn syntax_expander_table() -> hashmap<str, syntax_extension> {
builtin(ext::source_util::expand_stringify)); builtin(ext::source_util::expand_stringify));
syntax_expanders.insert("include", syntax_expanders.insert("include",
builtin(ext::source_util::expand_include)); builtin(ext::source_util::expand_include));
syntax_expanders.insert("mod",
builtin(ext::source_util::expand_mod));
ret syntax_expanders; ret syntax_expanders;
} }
@ -62,6 +64,9 @@ iface ext_ctxt {
fn cfg() -> ast::crate_cfg; fn cfg() -> ast::crate_cfg;
fn print_backtrace(); fn print_backtrace();
fn backtrace() -> expn_info; 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_push(ei: codemap::expn_info_);
fn bt_pop(); fn bt_pop();
fn span_fatal(sp: span, msg: str) -> !; 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 { cfg: ast::crate_cfg) -> ext_ctxt {
type ctxt_repr = {parse_sess: parse::parse_sess, type ctxt_repr = {parse_sess: parse::parse_sess,
cfg: ast::crate_cfg, cfg: ast::crate_cfg,
mut backtrace: expn_info}; mut backtrace: expn_info,
mut mod_path: [ast::ident]};
impl of ext_ctxt for ctxt_repr { impl of ext_ctxt for ctxt_repr {
fn codemap() -> codemap { self.parse_sess.cm } fn codemap() -> codemap { self.parse_sess.cm }
fn parse_sess() -> parse::parse_sess { self.parse_sess } fn parse_sess() -> parse::parse_sess { self.parse_sess }
fn cfg() -> ast::crate_cfg { self.cfg } fn cfg() -> ast::crate_cfg { self.cfg }
fn print_backtrace() { } fn print_backtrace() { }
fn backtrace() -> expn_info { self.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_) { fn bt_push(ei: codemap::expn_info_) {
alt ei { alt ei {
expanded_from({call_site: cs, callie: callie}) { expanded_from({call_site: cs, callie: callie}) {
@ -129,7 +138,8 @@ fn mk_ctxt(parse_sess: parse::parse_sess,
let imp : ctxt_repr = { let imp : ctxt_repr = {
parse_sess: parse_sess, parse_sess: parse_sess,
cfg: cfg, cfg: cfg,
mut backtrace: none mut backtrace: none,
mut mod_path: []
}; };
ret imp as ext_ctxt ret imp as ext_ctxt
} }

View file

@ -89,6 +89,21 @@ fn expand_mod_items(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
ret {items: new_items with module}; 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 { fn new_span(cx: ext_ctxt, sp: span) -> span {
/* this discards information in the case of macro-defining macros */ /* this discards information in the case of macro-defining macros */
ret {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()}; 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 = let f_pre =
{fold_expr: bind expand_expr(exts, cx, _, _, _, afp.fold_expr), {fold_expr: bind expand_expr(exts, cx, _, _, _, afp.fold_expr),
fold_mod: bind expand_mod_items(exts, cx, _, _, afp.fold_mod), 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, _) new_span: bind new_span(cx, _)
with *afp}; with *afp};
let f = make_fold(f_pre); let f = make_fold(f_pre);

View file

@ -3,7 +3,6 @@ import ast;
import codemap::span; import codemap::span;
import print::pprust; import print::pprust;
/* #line(): expands to the current line number */ /* #line(): expands to the current line number */
fn expand_line(cx: ext_ctxt, sp: span, arg: ast::mac_arg, fn expand_line(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
_body: ast::mac_body) -> @ast::expr { _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); parse::parser::SOURCE_FILE);
ret parse::parser::parse_expr(p) 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(), "::")));
}

View file

@ -1,11 +1,19 @@
// This test is brittle! // This test is brittle!
// xfail-pretty - the pretty tests lose path information, breaking #include // xfail-pretty - the pretty tests lose path information, breaking #include
mod m1 {
mod m2 {
fn where_am_i() -> str { #mod[] }
}
}
fn main() { fn main() {
assert(#line[] == 5u); assert(#line[] == 11u);
assert(#col[] == 12u); assert(#col[] == 12u);
assert(#file[].ends_with("syntax-extension-source-utils.rs")); assert(#file[].ends_with("syntax-extension-source-utils.rs"));
assert(#stringify[(2*3) + 5] == "2 * 3 + 5"); assert(#stringify[(2*3) + 5] == "2 * 3 + 5");
assert(#include["syntax-extension-source-utils-files/includeme.fragment"] 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"));
} }