From 88f4d0694187a451173d40e9c44db4499a6c04f4 Mon Sep 17 00:00:00 2001 From: Paul Stansifer Date: Mon, 14 May 2012 17:43:31 -0700 Subject: [PATCH] New syntax extensions: #line[], #col[], #file[], #stringify[], #include[] --- src/librustsyntax/ext/base.rs | 10 ++++ src/librustsyntax/ext/source_util.rs | 48 +++++++++++++++++++ src/librustsyntax/rustsyntax.rc | 1 + .../includeme.fragment | 7 +++ .../run-pass/syntax-extension-source-utils.rs | 11 +++++ 5 files changed, 77 insertions(+) create mode 100644 src/librustsyntax/ext/source_util.rs create mode 100644 src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment create mode 100644 src/test/run-pass/syntax-extension-source-utils.rs 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") +}