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));
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
}

View file

@ -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);

View file

@ -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(), "::")));
}

View file

@ -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"));
}