diff --git a/src/librustsyntax/ext/base.rs b/src/librustsyntax/ext/base.rs index 92b6acba5b0..8cc388c7b1b 100644 --- a/src/librustsyntax/ext/base.rs +++ b/src/librustsyntax/ext/base.rs @@ -43,6 +43,16 @@ fn syntax_expander_table() -> hashmap { builtin(ext::log_syntax::expand_syntax_ext)); syntax_expanders.insert("ast", builtin(ext::qquote::expand_ast)); + syntax_expanders.insert("line", + builtin(ext::source_util::expand_line)); + syntax_expanders.insert("col", + builtin(ext::source_util::expand_col)); + syntax_expanders.insert("file", + builtin(ext::source_util::expand_file)); + syntax_expanders.insert("stringify", + builtin(ext::source_util::expand_stringify)); + syntax_expanders.insert("include", + builtin(ext::source_util::expand_include)); ret syntax_expanders; } diff --git a/src/librustsyntax/ext/source_util.rs b/src/librustsyntax/ext/source_util.rs new file mode 100644 index 00000000000..7b3471d03b4 --- /dev/null +++ b/src/librustsyntax/ext/source_util.rs @@ -0,0 +1,48 @@ +import base::*; +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 { + get_mac_args(cx, sp, arg, 0u, option::some(0u), "line"); + let loc = codemap::lookup_char_pos(cx.codemap(), sp.lo); + ret make_new_lit(cx, sp, ast::lit_uint(loc.line as u64, ast::ty_u)); +} + +/* #col(): expands to the current column number */ +fn expand_col(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), "col"); + let loc = codemap::lookup_char_pos(cx.codemap(), sp.lo); + ret make_new_lit(cx, sp, ast::lit_uint(loc.col as u64, ast::ty_u)); +} + +/* #file(): expands to the current filename */ +/* The filemap (`loc.file`) contains a bunch more information we could spit + * out if we wanted. */ +fn expand_file(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"); + let loc = codemap::lookup_char_pos(cx.codemap(), sp.lo); + ret make_new_lit(cx, sp, ast::lit_str(loc.file.name)); +} + +fn expand_stringify(cx: ext_ctxt, sp: span, arg: ast::mac_arg, + _body: ast::mac_body) -> @ast::expr { + let args = get_mac_args(cx, sp, arg, 1u, option::some(1u), "stringify"); + ret make_new_lit(cx, sp, ast::lit_str(pprust::expr_to_str(args[0]))); +} + +fn expand_include(cx: ext_ctxt, sp: span, arg: ast::mac_arg, + _body: ast::mac_body) -> @ast::expr { + let args = get_mac_args(cx, sp, arg, 1u, option::some(1u), "include"); + let loc = codemap::lookup_char_pos(cx.codemap(), sp.lo); + let path = path::connect(path::dirname(loc.file.name), + expr_to_str(cx, args[0], "#include requires a string literal")); + let p = parse::new_parser_from_file(cx.parse_sess(), cx.cfg(), path, + parse::parser::SOURCE_FILE); + ret parse::parser::parse_expr(p) +} diff --git a/src/librustsyntax/rustsyntax.rc b/src/librustsyntax/rustsyntax.rc index 293238aac3c..91f1463fc19 100644 --- a/src/librustsyntax/rustsyntax.rc +++ b/src/librustsyntax/rustsyntax.rc @@ -66,4 +66,5 @@ mod ext { mod include; mod log_syntax; mod auto_serialize; + mod source_util; } diff --git a/src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment b/src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment new file mode 100644 index 00000000000..5db5b0f6ff5 --- /dev/null +++ b/src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment @@ -0,0 +1,7 @@ +/* this is for run-pass/syntax-extension-source-utils.rs */ + +{ + assert(#file[].ends_with("utils-files/includeme.fragment")); + assert(#line[] == 5u); + #fmt["victory robot %u", #line[]] +} \ No newline at end of file diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs new file mode 100644 index 00000000000..926228534cc --- /dev/null +++ b/src/test/run-pass/syntax-extension-source-utils.rs @@ -0,0 +1,11 @@ +// This test is brittle! +// xfail-pretty - the pretty tests lose path information, breaking #include + +fn main() { + assert(#line[] == 5u); + 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") +}