Skip to content

Quote misc #4129

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 8 commits into from
2 changes: 1 addition & 1 deletion RELEASES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Version 0.5 (December 2012)
* Removed `<-` move operator
* Completed the transition from the `#fmt` extension syntax to `fmt!`
* Removed old fixed length vector syntax - `[T]/N`
* New token-based quasi-quoter, `quote!`
* New token-based quasi-quoters, `quote_tokens!`, `quote_expr!`, etc.
* Macros may now expand to items and statements
* `a.b()` is always parsed as a method call, never as a field projection
* `Eq` and `IterBytes` implementations can be automatically generated
Expand Down
11 changes: 9 additions & 2 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
~"quote_tokens", builtin_normal_tt(ext::quote::expand_quote_tokens));
syntax_expanders.insert(~"quote_expr",
builtin_normal_tt(ext::quote::expand_quote_expr));
syntax_expanders.insert(~"quote_type",
builtin_normal_tt(ext::quote::expand_quote_type));
syntax_expanders.insert(~"quote_ty",
builtin_normal_tt(ext::quote::expand_quote_ty));
syntax_expanders.insert(~"quote_item",
builtin_normal_tt(ext::quote::expand_quote_item));
syntax_expanders.insert(~"quote_pat",
Expand Down Expand Up @@ -163,6 +163,7 @@ trait ext_ctxt {
fn codemap() -> @CodeMap;
fn parse_sess() -> parse::parse_sess;
fn cfg() -> ast::crate_cfg;
fn call_site() -> span;
fn print_backtrace();
fn backtrace() -> Option<@ExpnInfo>;
fn mod_push(mod_name: ast::ident);
Expand Down Expand Up @@ -195,6 +196,12 @@ fn mk_ctxt(parse_sess: parse::parse_sess,
fn codemap() -> @CodeMap { self.parse_sess.cm }
fn parse_sess() -> parse::parse_sess { self.parse_sess }
fn cfg() -> ast::crate_cfg { self.cfg }
fn call_site() -> span {
match self.backtrace {
Some(@ExpandedFrom({call_site: cs, _})) => cs,
None => self.bug(~"missing top span")
}
}
fn print_backtrace() { }
fn backtrace() -> Option<@ExpnInfo> { self.backtrace }
fn mod_push(i: ast::ident) { self.mod_path.push(i); }
Expand Down
18 changes: 18 additions & 0 deletions src/libsyntax/ext/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,24 @@ fn mk_glob_use(cx: ext_ctxt, sp: span,
vis: ast::private,
span: sp}
}
fn mk_local(cx: ext_ctxt, sp: span, mutbl: bool,
ident: ast::ident, ex: @ast::expr) -> @ast::stmt {

let pat : @ast::pat = @{id: cx.next_id(),
node: ast::pat_ident(ast::bind_by_value,
mk_raw_path(sp, ~[ident]),
None),
span: sp};
let ty : @ast::Ty = @{ id: cx.next_id(), node: ast::ty_infer, span: sp };
let local : @ast::local = @{node: {is_mutbl: mutbl,
ty: ty,
pat: pat,
init: Some(ex),
id: cx.next_id()},
span: sp};
let decl = {node: ast::decl_local(~[local]), span: sp};
@{ node: ast::stmt_decl(@decl, cx.next_id()), span: sp }
}
fn mk_block(cx: ext_ctxt, sp: span,
view_items: ~[@ast::view_item],
stmts: ~[@ast::stmt],
Expand Down
37 changes: 22 additions & 15 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
fmt!("%s can only be used as a decorator", *extname));
}
Some(normal({expander: exp, span: exp_sp})) => {
let expanded = exp(cx, (*mac).span, args, body);

cx.bt_push(ExpandedFrom({call_site: s,
callie: {name: *extname, span: exp_sp}}));
let expanded = exp(cx, (*mac).span, args, body);

//keep going, outside-in
let fully_expanded = fld.fold_expr(expanded).node;
cx.bt_pop();
Expand Down Expand Up @@ -90,6 +91,9 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
fmt!("macro undefined: '%s'", *extname))
}
Some(normal_tt({expander: exp, span: exp_sp})) => {
cx.bt_push(ExpandedFrom({call_site: s,
callie: {name: *extname, span: exp_sp}}));

let expanded = match exp(cx, (*mac).span, (*tts)) {
mr_expr(e) => e,
mr_any(expr_maker,_,_) => expr_maker(),
Expand All @@ -98,22 +102,21 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
*extname))
};

cx.bt_push(ExpandedFrom({call_site: s,
callie: {name: *extname, span: exp_sp}}));
//keep going, outside-in
let fully_expanded = fld.fold_expr(expanded).node;
cx.bt_pop();

(fully_expanded, s)
}
Some(normal({expander: exp, span: exp_sp})) => {
cx.bt_push(ExpandedFrom({call_site: s,
callie: {name: *extname, span: exp_sp}}));

//convert the new-style invoc for the old-style macro
let arg = base::tt_args_to_original_flavor(cx, pth.span,
(*tts));
let expanded = exp(cx, (*mac).span, arg, None);

cx.bt_push(ExpandedFrom({call_site: s,
callie: {name: *extname, span: exp_sp}}));
//keep going, outside-in
let fully_expanded = fld.fold_expr(expanded).node;
cx.bt_pop();
Expand Down Expand Up @@ -234,7 +237,7 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
);

let extname = cx.parse_sess().interner.get(pth.idents[0]);
let (expanded, ex_span) = match exts.find(*extname) {
let expanded = match exts.find(*extname) {
None => cx.span_fatal(pth.span,
fmt!("macro undefined: '%s!'", *extname)),

Expand All @@ -245,22 +248,26 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
given '%s'", *extname,
*cx.parse_sess().interner.get(it.ident)));
}
(((*expand).expander)(cx, it.span, tts), (*expand).span)
cx.bt_push(ExpandedFrom({call_site: it.span,
callie: {name: *extname,
span: (*expand).span}}));
((*expand).expander)(cx, it.span, tts)
}
Some(item_tt(ref expand)) => {
if it.ident == parse::token::special_idents::invalid {
cx.span_fatal(pth.span,
fmt!("macro %s! expects an ident argument",
*extname));
}
(((*expand).expander)(cx, it.span, it.ident, tts), (*expand).span)
cx.bt_push(ExpandedFrom({call_site: it.span,
callie: {name: *extname,
span: (*expand).span}}));
((*expand).expander)(cx, it.span, it.ident, tts)
}
_ => cx.span_fatal(
it.span, fmt!("%s! is not legal in item position", *extname))
};

cx.bt_push(ExpandedFrom({call_site: it.span,
callie: {name: *extname, span: ex_span}}));
let maybe_it = match expanded {
mr_item(it) => fld.fold_item(it),
mr_expr(_) => cx.span_fatal(pth.span,
Expand Down Expand Up @@ -296,6 +303,8 @@ fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),

Some(normal_tt({expander: exp, span: exp_sp})) => {
cx.bt_push(ExpandedFrom(
{call_site: sp, callie: {name: *extname, span: exp_sp}}));
let expanded = match exp(cx, mac.span, tts) {
mr_expr(e) =>
@{node: stmt_expr(e, cx.next_id()), span: e.span},
Expand All @@ -305,8 +314,6 @@ fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
fmt!("non-stmt macro in stmt pos: %s", *extname))
};

cx.bt_push(ExpandedFrom(
{call_site: sp, callie: {name: *extname, span: exp_sp}}));
//keep going, outside-in
let fully_expanded = fld.fold_stmt(expanded).node;
cx.bt_pop();
Expand All @@ -315,15 +322,15 @@ fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
}

Some(normal({expander: exp, span: exp_sp})) => {
cx.bt_push(ExpandedFrom({call_site: sp,
callie: {name: *extname,
span: exp_sp}}));
//convert the new-style invoc for the old-style macro
let arg = base::tt_args_to_original_flavor(cx, pth.span, tts);
let exp_expr = exp(cx, mac.span, arg, None);
let expanded = @{node: stmt_expr(exp_expr, cx.next_id()),
span: exp_expr.span};

cx.bt_push(ExpandedFrom({call_site: sp,
callie: {name: *extname,
span: exp_sp}}));
//keep going, outside-in
let fully_expanded = fld.fold_stmt(expanded).node;
cx.bt_pop();
Expand Down
9 changes: 9 additions & 0 deletions src/libsyntax/ext/pipes/ast_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use ast::{ident, node_id};
use ast_util::{ident_to_path, respan, dummy_sp};
use codemap::span;
use ext::base::mk_ctxt;
use quote::rt::*;

// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
Expand Down Expand Up @@ -121,6 +122,7 @@ impl ext_ctxt: ext_ctxt_ast_builder {
span: dummy_sp()}
}

#[cfg(stage0)]
fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt {
// If the quasiquoter could interpolate idents, this is all
// we'd need.
Expand All @@ -142,6 +144,13 @@ impl ext_ctxt: ext_ctxt_ast_builder {
span: dummy_sp()}]),
span: dummy_sp()}, self.next_id()),
span: dummy_sp()}
}

#[cfg(stage1)]
#[cfg(stage2)]
fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt {
let ext_cx = self;
quote_stmt!( let $ident = $e; )
}

fn field_imm(name: ident, e: @ast::expr) -> ast::field {
Expand Down
Loading