From 1d9f01cb421eae8e7ace0fa6b4d7f5ddf3ce4f65 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 27 Jul 2012 17:42:32 -0700 Subject: Comments in the new macro system, reflecting conversation with pauls. --- src/libsyntax/ext/base.rs | 42 +++++++++++++++++++++++++++++++++++ src/libsyntax/ext/expand.rs | 20 ++++++++++++++++- src/libsyntax/ext/tt/earley_parser.rs | 19 +++++++++++++++- 3 files changed, 79 insertions(+), 2 deletions(-) (limited to 'src/libsyntax/ext') diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 544b1316354..5fca084b181 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -4,6 +4,31 @@ import diagnostic::span_handler; import codemap::{codemap, span, expn_info, expanded_from}; import std::map::str_hash; + +// Nomenclature / abbreviations in the ext modules: +// +// ms: matcher span, wraps a matcher with fake span +// mtc: matcher +// mtcs: matchers +// tt: token tree +// bt: backtrace +// cx: expansion context +// mr: macro result +// + +// obsolete old-style #macro code: +// +// syntax_expander, normal, macro_defining, macro_definer, +// builtin +// +// new-style macro! tt code: +// +// syntax_expander_tt, syntax_expander_tt_item, mac_result, +// expr_tt, item_tt +// +// also note that ast::mac has way too many cases and can probably +// be trimmed down substantially. + // second argument is the span to blame for general argument problems type syntax_expander_ = fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> @ast::expr; @@ -11,8 +36,11 @@ type syntax_expander_ = type syntax_expander = {expander: syntax_expander_, span: option}; type macro_def = {ident: ast::ident, ext: syntax_extension}; + +// macro_definer is obsolete, remove when #old_macros go away. 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]; @@ -32,10 +60,17 @@ enum mac_result { } enum syntax_extension { + + // normal() is obsolete, remove when #old_macros go away. normal(syntax_expander), + + // macro_defining() is obsolete, remove when #old_macros go away. macro_defining(macro_definer), + + // #[auto_serialize] and such. will probably survive death of #old_macros item_decorator(item_decorator), + // Token-tree expanders expr_tt(syntax_expander_tt), item_tt(syntax_expander_tt_item), } @@ -87,6 +122,10 @@ fn syntax_expander_table() -> hashmap<~str, syntax_extension> { ret syntax_expanders; } + +// One of these is made during expansion and incrementally updated as we go; +// when a macro expansion occurs, the resulting nodes have the backtrace() +// -> expn_info of their expansion context stored into their span. iface ext_ctxt { fn codemap() -> codemap; fn parse_sess() -> parse::parse_sess; @@ -244,6 +283,9 @@ fn get_mac_body(cx: ext_ctxt, sp: span, args: ast::mac_body) } } +// Massage syntactic form of new-style arguments to internal representation +// of old-style macro args, such that old-style macro can be run and invoked +// using new syntax. This will be obsolete when #old_macros go away. fn tt_args_to_original_flavor(cx: ext_ctxt, sp: span, arg: ~[ast::token_tree]) -> ast::mac_arg { import ast::{matcher, matcher_, mtc_tok, mtc_rep, mtc_bb}; diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index c470daaf022..e453a0f556f 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -16,7 +16,12 @@ fn expand_expr(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt, -> (expr_, span) { ret alt e { + // expr_mac should really be expr_ext or something; it's the + // entry-point for all syntax extensions. expr_mac(mac) { + + // Old-style macros, for compatibility, will erase this whole + // block once we've transitioned. alt mac.node { mac_invoc(pth, args, body) { assert (vec::len(pth.idents) > 0u); @@ -58,6 +63,9 @@ fn expand_expr(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt, } } } + + // Token-tree macros, these will be the only case when we're + // finished transitioning. mac_invoc_tt(pth, tts) { assert (vec::len(pth.idents) == 1u); let extname = pth.idents[0]; @@ -111,6 +119,15 @@ fn expand_expr(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt, }; } +// This is a secondary mechanism for invoking syntax extensions on items: +// "decorator" attributes, such as #[auto_serialize]. These are invoked by an +// attribute prefixing an item, and are interpreted by feeding the item +// through the named attribute _as a syntax extension_ and splicing in the +// resulting item vec into place in favour of the decorator. Note that +// these do _not_ work for macro extensions, just item_decorator ones. +// +// NB: there is some redundancy between this and expand_item, below, and +// they might benefit from some amount of semantic and language-UI merger. fn expand_mod_items(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt, module: ast::_mod, fld: ast_fold, orig: fn@(ast::_mod, ast_fold) -> ast::_mod) @@ -145,7 +162,8 @@ fn expand_mod_items(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt, ret {items: new_items with module}; } -/* record module we enter for `#mod` */ +// Support for item-position macro invocations, exactly the same +// logic as for expression-position macro invocations. fn expand_item(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt, &&it: @ast::item, fld: ast_fold, orig: fn@(&&@ast::item, ast_fold) -> option<@ast::item>) diff --git a/src/libsyntax/ext/tt/earley_parser.rs b/src/libsyntax/ext/tt/earley_parser.rs index 54e5a1b5867..be331a08fcf 100644 --- a/src/libsyntax/ext/tt/earley_parser.rs +++ b/src/libsyntax/ext/tt/earley_parser.rs @@ -77,7 +77,24 @@ fn initial_matcher_pos(ms: ~[matcher], sep: option, lo: uint) match_lo: 0u, match_hi: match_idx_hi, sp_lo: lo} } -/* logically, an arb_depth should contain only one kind of nonterminal */ +// arb_depth is a pattern-match result for a single black-box matcher +// (ast::mtc_bb): so it is associated with a single ident in a parse, and all +// leaves in the arb_depth have the same nonterminal type (expr, item, +// etc). All the leaves in a single arb_depth correspond to a single mtc_bb in +// the ast::matcher that produced it. +// +// It should probably be renamed, it has more or less exact correspondence to +// ast::match nodes, and the in-memory structure of a particular arb_depth +// represents the match that occurred when a particular subset of an +// ast::match -- those ast::matcher nodes leading to a single mtc_bb -- was +// applied to a particular token tree. +// +// The width of each seq in the arb_depth, and the identity of the leaf nodes, +// will depend on the token tree it was applied to: each seq corresponds to a +// single mtc_rep in the originating ast::matcher. The depth of the arb_depth +// structure will therefore depend only on the nesting depth of mtc_reps in +// the originating ast::matcher it was derived from. + enum arb_depth { leaf(whole_nt), seq(~[@arb_depth], codemap::span) } type earley_item = matcher_pos; -- cgit 1.4.1-3-g733a5