Make it possible to make built-in tt syntax extensions
This commit is contained in:
parent
4f104954a6
commit
4df2654f82
3 changed files with 53 additions and 6 deletions
|
@ -6,19 +6,23 @@ import std::map::str_hash;
|
||||||
|
|
||||||
type syntax_expander_ =
|
type syntax_expander_ =
|
||||||
fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> @ast::expr;
|
fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> @ast::expr;
|
||||||
type syntax_expander = {
|
type syntax_expander = {expander: syntax_expander_, span: option<span>};
|
||||||
expander: syntax_expander_,
|
|
||||||
span: option<span>};
|
|
||||||
type macro_def = {ident: ast::ident, ext: syntax_extension};
|
type macro_def = {ident: ast::ident, ext: syntax_extension};
|
||||||
type macro_definer =
|
type macro_definer =
|
||||||
fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> macro_def;
|
fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> macro_def;
|
||||||
type item_decorator =
|
type item_decorator =
|
||||||
fn@(ext_ctxt, span, ast::meta_item, [@ast::item]) -> [@ast::item];
|
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 {
|
enum syntax_extension {
|
||||||
normal(syntax_expander),
|
normal(syntax_expander),
|
||||||
macro_defining(macro_definer),
|
macro_defining(macro_definer),
|
||||||
item_decorator(item_decorator),
|
item_decorator(item_decorator),
|
||||||
|
|
||||||
|
normal_tt(syntax_expander_tt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A temporary hard-coded map of methods for expanding syntax extension
|
// A temporary hard-coded map of methods for expanding syntax extension
|
||||||
|
|
|
@ -47,6 +47,39 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
|
||||||
exts.insert(*named_extension.ident, named_extension.ext);
|
exts.insert(*named_extension.ident, named_extension.ext);
|
||||||
(ast::expr_rec([], none), s)
|
(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") }
|
_ { cx.span_bug(mac.span, "naked syntactic bit") }
|
||||||
|
@ -75,7 +108,8 @@ fn expand_mod_items(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
|
||||||
ast::meta_list(n, _) { n }
|
ast::meta_list(n, _) { n }
|
||||||
};
|
};
|
||||||
alt exts.find(*mname) {
|
alt exts.find(*mname) {
|
||||||
none | some(normal(_)) | some(macro_defining(_)) {
|
none | some(normal(_)) | some(macro_defining(_))
|
||||||
|
| some(normal_tt(_)) {
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -883,8 +883,17 @@ class parser {
|
||||||
is_ident(self.token) && !self.is_keyword("true") &&
|
is_ident(self.token) && !self.is_keyword("true") &&
|
||||||
!self.is_keyword("false") {
|
!self.is_keyword("false") {
|
||||||
let pth = self.parse_path_with_tps(true);
|
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 {
|
} else {
|
||||||
let lit = self.parse_lit();
|
let lit = self.parse_lit();
|
||||||
hi = lit.span.hi;
|
hi = lit.span.hi;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue