Skip to content

Commit

Permalink
Make it possible to make built-in tt syntax extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
paulstansifer committed Jun 26, 2012
1 parent 4f10495 commit 4df2654
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 6 deletions.
10 changes: 7 additions & 3 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@ import std::map::str_hash;

type syntax_expander_ =
fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> @ast::expr;
type syntax_expander = {
expander: syntax_expander_,
span: option<span>};
type syntax_expander = {expander: syntax_expander_, span: option<span>};

type macro_def = {ident: ast::ident, ext: syntax_extension};
type macro_definer =
fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> macro_def;
type item_decorator =
fn@(ext_ctxt, span, ast::meta_item, [@ast::item]) -> [@ast::item];

type syntax_expander_tt = {expander: syntax_expander_tt_, span: option<span>};
type syntax_expander_tt_ = fn@(ext_ctxt, span, ast::token_tree) -> @ast::expr;

enum syntax_extension {
normal(syntax_expander),
macro_defining(macro_definer),
item_decorator(item_decorator),

normal_tt(syntax_expander_tt)
}

// A temporary hard-coded map of methods for expanding syntax extension
Expand Down
36 changes: 35 additions & 1 deletion src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,39 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
exts.insert(*named_extension.ident, named_extension.ext);
(ast::expr_rec([], none), s)
}
some(normal_tt(_)) {
cx.span_fatal(pth.span,
#fmt["this tt-style macro should be \
invoked '%s!{...}'", *extname])
}
}
}
mac_invoc_tt(pth, tt) {
assert (vec::len(pth.idents) > 0u);
let extname = pth.idents[0];
alt exts.find(*extname) {
none {
cx.span_fatal(pth.span,
#fmt["macro undefined: '%s'", *extname])
}
some(normal_tt({expander: exp, span: exp_sp})) {
let expanded = exp(cx, pth.span, tt);

cx.bt_push(expanded_from({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)

}
_ {
cx.span_fatal(pth.span,
#fmt["'%s' is not a tt-style macro",
*extname])
}

}
}
_ { cx.span_bug(mac.span, "naked syntactic bit") }
Expand Down Expand Up @@ -75,7 +108,8 @@ fn expand_mod_items(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
ast::meta_list(n, _) { n }
};
alt exts.find(*mname) {
none | some(normal(_)) | some(macro_defining(_)) {
none | some(normal(_)) | some(macro_defining(_))
| some(normal_tt(_)) {
items
}

Expand Down
13 changes: 11 additions & 2 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -883,8 +883,17 @@ class parser {
is_ident(self.token) && !self.is_keyword("true") &&
!self.is_keyword("false") {
let pth = self.parse_path_with_tps(true);
hi = pth.span.hi;
ex = expr_path(pth);

/* `!`, as an operator, is prefix, so we know this isn't that */
if self.token == token::NOT {
self.bump();
let m_body = self.parse_token_tree();
let hi = self.span.hi;
ret pexpr(self.mk_mac_expr(lo, hi, mac_invoc_tt(pth,m_body)));
} else {
hi = pth.span.hi;
ex = expr_path(pth);
}
} else {
let lit = self.parse_lit();
hi = lit.span.hi;
Expand Down

0 comments on commit 4df2654

Please # to comment.