Skip to content

quote_*! macros take an ExtCtx #8556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions src/librustc/front/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ fn mk_std(cx: &TestCtxt) -> ast::view_item {
}
}

#[cfg(stage0)]
fn mk_test_module(cx: &TestCtxt) -> @ast::item {

// Link to extra
Expand Down Expand Up @@ -334,6 +335,48 @@ fn mk_test_module(cx: &TestCtxt) -> @ast::item {

return @item;
}
#[cfg(not(stage0))]
fn mk_test_module(cx: &TestCtxt) -> @ast::item {

// Link to extra
let view_items = ~[mk_std(cx)];

// A constant vector of test descriptors.
let tests = mk_tests(cx);

// The synthesized main function which will call the console test runner
// with our list of tests
let mainfn = (quote_item!(cx.ext_cx,
pub fn main() {
#[main];
extra::test::test_main_static(::std::os::args(), TESTS);
}
)).unwrap();

let testmod = ast::_mod {
view_items: view_items,
items: ~[mainfn, tests],
};
let item_ = ast::item_mod(testmod);

// This attribute tells resolve to let us call unexported functions
let resolve_unexported_attr =
attr::mk_attr(attr::mk_word_item(@"!resolve_unexported"));

let item = ast::item {
ident: cx.sess.ident_of("__test"),
attrs: ~[resolve_unexported_attr],
id: cx.sess.next_node_id(),
node: item_,
vis: ast::public,
span: dummy_sp(),
};

debug!("Synthetic test module:\n%s\n",
pprust::item_to_str(@item.clone(), cx.sess.intr()));

return @item;
}

fn nospan<T>(t: T) -> codemap::spanned<T> {
codemap::spanned { node: t, span: dummy_sp() }
Expand All @@ -355,6 +398,7 @@ fn path_node_global(ids: ~[ast::ident]) -> ast::Path {
types: ~[] }
}

#[cfg(stage0)]
fn mk_tests(cx: &TestCtxt) -> @ast::item {

let ext_cx = cx.ext_cx;
Expand All @@ -368,6 +412,17 @@ fn mk_tests(cx: &TestCtxt) -> @ast::item {
;
)).unwrap()
}
#[cfg(not(stage0))]
fn mk_tests(cx: &TestCtxt) -> @ast::item {
// The vector of test_descs for this crate
let test_descs = mk_test_descs(cx);

(quote_item!(cx.ext_cx,
pub static TESTS : &'static [self::extra::test::TestDescAndFn] =
$test_descs
;
)).unwrap()
}

fn is_extra(cx: &TestCtxt) -> bool {
let items = attr::find_linkage_metas(cx.crate.attrs);
Expand Down Expand Up @@ -398,6 +453,7 @@ fn mk_test_descs(cx: &TestCtxt) -> @ast::expr {
}
}

#[cfg(stage0)]
fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr {
let span = test.span;
let path = test.path.clone();
Expand Down Expand Up @@ -453,3 +509,57 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr {
);
e
}
#[cfg(not(stage0))]
fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr {
let span = test.span;
let path = test.path.clone();

debug!("encoding %s", ast_util::path_name_i(path));

let name_lit: ast::lit =
nospan(ast::lit_str(ast_util::path_name_i(path).to_managed()));

let name_expr = @ast::expr {
id: cx.sess.next_node_id(),
node: ast::expr_lit(@name_lit),
span: span
};

let fn_path = path_node_global(path);

let fn_expr = @ast::expr {
id: cx.sess.next_node_id(),
node: ast::expr_path(fn_path),
span: span,
};

let t_expr = if test.bench {
quote_expr!(cx.ext_cx, self::extra::test::StaticBenchFn($fn_expr) )
} else {
quote_expr!(cx.ext_cx, self::extra::test::StaticTestFn($fn_expr) )
};

let ignore_expr = if test.ignore {
quote_expr!(cx.ext_cx, true )
} else {
quote_expr!(cx.ext_cx, false )
};

let fail_expr = if test.should_fail {
quote_expr!(cx.ext_cx, true )
} else {
quote_expr!(cx.ext_cx, false )
};

let e = quote_expr!(cx.ext_cx,
self::extra::test::TestDescAndFn {
desc: self::extra::test::TestDesc {
name: self::extra::test::StaticTestName($name_expr),
ignore: $ignore_expr,
should_fail: $fail_expr
},
testfn: $t_expr,
}
);
e
}
18 changes: 9 additions & 9 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1288,24 +1288,24 @@ fn roundtrip(in_item: Option<@ast::item>) {

#[test]
fn test_basic() {
let ext_cx = mk_ctxt();
roundtrip(quote_item!(
let cx = mk_ctxt();
roundtrip(quote_item!(cx,
fn foo() {}
));
}

#[test]
fn test_smalltalk() {
let ext_cx = mk_ctxt();
roundtrip(quote_item!(
let cx = mk_ctxt();
roundtrip(quote_item!(cx,
fn foo() -> int { 3 + 4 } // first smalltalk program ever executed.
));
}

#[test]
fn test_more() {
let ext_cx = mk_ctxt();
roundtrip(quote_item!(
let cx = mk_ctxt();
roundtrip(quote_item!(cx,
fn foo(x: uint, y: uint) -> uint {
let z = x + y;
return z;
Expand All @@ -1315,15 +1315,15 @@ fn test_more() {

#[test]
fn test_simplification() {
let ext_cx = mk_ctxt();
let item_in = ast::ii_item(quote_item!(
let cx = mk_ctxt();
let item_in = ast::ii_item(quote_item!(cx,
fn new_int_alist<B>() -> alist<int, B> {
fn eq_int(a: int, b: int) -> bool { a == b }
return alist {eq_fn: eq_int, data: ~[]};
}
).unwrap());
let item_out = simplify_ast(&item_in);
let item_exp = ast::ii_item(quote_item!(
let item_exp = ast::ii_item(quote_item!(cx,
fn new_int_alist<B>() -> alist<int, B> {
return alist {eq_fn: eq_int, data: ~[]};
}
Expand Down
12 changes: 12 additions & 0 deletions src/libsyntax/ext/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,17 +605,29 @@ impl AstBuilder for @ExtCtxt {

self.expr(span, ast::expr_fn_block(fn_decl, blk))
}
#[cfg(stage0)]
fn lambda0(&self, _span: span, blk: ast::Block) -> @ast::expr {
let ext_cx = *self;
let blk_e = self.expr(blk.span, ast::expr_block(blk.clone()));
quote_expr!(|| $blk_e )
}
#[cfg(not(stage0))]
fn lambda0(&self, _span: span, blk: ast::Block) -> @ast::expr {
let blk_e = self.expr(blk.span, ast::expr_block(blk.clone()));
quote_expr!(*self, || $blk_e )
}

#[cfg(stage0)]
fn lambda1(&self, _span: span, blk: ast::Block, ident: ast::ident) -> @ast::expr {
let ext_cx = *self;
let blk_e = self.expr(blk.span, ast::expr_block(blk.clone()));
quote_expr!(|$ident| $blk_e )
}
#[cfg(not(stage0))]
fn lambda1(&self, _span: span, blk: ast::Block, ident: ast::ident) -> @ast::expr {
let blk_e = self.expr(blk.span, ast::expr_block(blk.clone()));
quote_expr!(*self, |$ident| $blk_e )
}

fn lambda_expr(&self, span: span, ids: ~[ast::ident], expr: @ast::expr) -> @ast::expr {
self.lambda(span, ids, self.block_expr(expr))
Expand Down
28 changes: 20 additions & 8 deletions src/libsyntax/ext/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use ext::build::AstBuilder;

use std::os;

#[cfg(stage0)]
pub fn expand_option_env(ext_cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
-> base::MacResult {
let var = get_single_str_from_tts(ext_cx, sp, tts, "option_env!");
Expand All @@ -32,25 +33,36 @@ pub fn expand_option_env(ext_cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
};
MRExpr(e)
}
#[cfg(not(stage0))]
pub fn expand_option_env(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
-> base::MacResult {
let var = get_single_str_from_tts(cx, sp, tts, "option_env!");

let e = match os::getenv(var) {
None => quote_expr!(cx, ::std::option::None::<&'static str>),
Some(s) => quote_expr!(cx, ::std::option::Some($s))
};
MRExpr(e)
}

pub fn expand_env(ext_cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
pub fn expand_env(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
-> base::MacResult {
let exprs = get_exprs_from_tts(ext_cx, sp, tts);
let exprs = get_exprs_from_tts(cx, sp, tts);

if exprs.len() == 0 {
ext_cx.span_fatal(sp, "env! takes 1 or 2 arguments");
cx.span_fatal(sp, "env! takes 1 or 2 arguments");
}

let var = expr_to_str(ext_cx, exprs[0], "expected string literal");
let var = expr_to_str(cx, exprs[0], "expected string literal");
let msg = match exprs.len() {
1 => fmt!("Environment variable %s not defined", var).to_managed(),
2 => expr_to_str(ext_cx, exprs[1], "expected string literal"),
_ => ext_cx.span_fatal(sp, "env! takes 1 or 2 arguments")
2 => expr_to_str(cx, exprs[1], "expected string literal"),
_ => cx.span_fatal(sp, "env! takes 1 or 2 arguments")
};

let e = match os::getenv(var) {
None => ext_cx.span_fatal(sp, msg),
Some(s) => ext_cx.expr_str(sp, s.to_managed())
None => cx.span_fatal(sp, msg),
Some(s) => cx.expr_str(sp, s.to_managed())
};
MRExpr(e)
}
Loading