change to newer macro escape mechanism, using uints in more places
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use ast;
|
||||
use ast::Name;
|
||||
use codemap;
|
||||
use codemap::{CodeMap, span, ExpnInfo, ExpandedFrom};
|
||||
use codemap::CallInfo;
|
||||
@@ -18,6 +19,7 @@ use diagnostic::span_handler;
|
||||
use ext;
|
||||
use parse;
|
||||
use parse::token;
|
||||
use parse::token::{intern};
|
||||
|
||||
use core::hashmap::HashMap;
|
||||
use core::vec;
|
||||
@@ -91,29 +93,33 @@ pub enum SyntaxExtension {
|
||||
IdentTT(SyntaxExpanderTTItem),
|
||||
}
|
||||
|
||||
// The SyntaxEnv is the environment that's threaded through the expansion
|
||||
// of macros. It contains bindings for macros, and also a special binding
|
||||
// for " block" (not a legal identifier) that maps to a BlockInfo
|
||||
pub type SyntaxEnv = @mut MapChain<Name, Transformer>;
|
||||
|
||||
// Name : the domain of SyntaxEnvs
|
||||
// want to change these to uints....
|
||||
// note that we use certain strings that are not legal as identifiers
|
||||
// to indicate, for instance, how blocks are supposed to behave.
|
||||
type Name = @~str;
|
||||
|
||||
// Transformer : the codomain of SyntaxEnvs
|
||||
|
||||
// NB: it may seem crazy to lump both of these into one environment;
|
||||
// what would it mean to bind "foo" to BlockLimit(true)? The idea
|
||||
// is that this follows the lead of MTWT, and accommodates growth
|
||||
// toward a more uniform syntax syntax (sorry) where blocks are just
|
||||
// another kind of transformer.
|
||||
|
||||
pub enum Transformer {
|
||||
// this identifier maps to a syntax extension or macro
|
||||
SE(SyntaxExtension),
|
||||
// should blocks occurring here limit macro scopes?
|
||||
ScopeMacros(bool)
|
||||
// blockinfo : this is ... well, it's simpler than threading
|
||||
// another whole data stack-structured data structure through
|
||||
// expansion. Basically, there's an invariant that every
|
||||
// map must contain a binding for " block".
|
||||
BlockInfo(BlockInfo)
|
||||
}
|
||||
|
||||
pub struct BlockInfo {
|
||||
// should macros escape from this scope?
|
||||
macros_escape : bool,
|
||||
// what are the pending renames?
|
||||
pending_renames : @mut RenameList
|
||||
}
|
||||
|
||||
// a list of ident->name renamings
|
||||
type RenameList = ~[(ast::ident,Name)];
|
||||
|
||||
// The base map of methods for expanding syntax extension
|
||||
// AST nodes into full ASTs
|
||||
pub fn syntax_expander_table() -> SyntaxEnv {
|
||||
@@ -127,77 +133,80 @@ pub fn syntax_expander_table() -> SyntaxEnv {
|
||||
}
|
||||
let mut syntax_expanders = HashMap::new();
|
||||
// NB identifier starts with space, and can't conflict with legal idents
|
||||
syntax_expanders.insert(@~" block",
|
||||
@ScopeMacros(true));
|
||||
syntax_expanders.insert(@~"macro_rules",
|
||||
syntax_expanders.insert(intern(&" block"),
|
||||
@BlockInfo(BlockInfo{
|
||||
macros_escape : false,
|
||||
pending_renames : @mut ~[]
|
||||
}));
|
||||
syntax_expanders.insert(intern(&"macro_rules"),
|
||||
builtin_item_tt(
|
||||
ext::tt::macro_rules::add_new_extension));
|
||||
syntax_expanders.insert(@~"fmt",
|
||||
syntax_expanders.insert(intern(&"fmt"),
|
||||
builtin_normal_tt(ext::fmt::expand_syntax_ext));
|
||||
syntax_expanders.insert(
|
||||
@~"auto_encode",
|
||||
intern(&"auto_encode"),
|
||||
@SE(ItemDecorator(ext::auto_encode::expand_auto_encode)));
|
||||
syntax_expanders.insert(
|
||||
@~"auto_decode",
|
||||
intern(&"auto_decode"),
|
||||
@SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
|
||||
syntax_expanders.insert(@~"env",
|
||||
syntax_expanders.insert(intern(&"env"),
|
||||
builtin_normal_tt(ext::env::expand_syntax_ext));
|
||||
syntax_expanders.insert(@~"bytes",
|
||||
syntax_expanders.insert(intern("bytes"),
|
||||
builtin_normal_tt(ext::bytes::expand_syntax_ext));
|
||||
syntax_expanders.insert(@~"concat_idents",
|
||||
syntax_expanders.insert(intern("concat_idents"),
|
||||
builtin_normal_tt(
|
||||
ext::concat_idents::expand_syntax_ext));
|
||||
syntax_expanders.insert(@~"log_syntax",
|
||||
syntax_expanders.insert(intern(&"log_syntax"),
|
||||
builtin_normal_tt(
|
||||
ext::log_syntax::expand_syntax_ext));
|
||||
syntax_expanders.insert(@~"deriving",
|
||||
syntax_expanders.insert(intern(&"deriving"),
|
||||
@SE(ItemDecorator(
|
||||
ext::deriving::expand_meta_deriving)));
|
||||
|
||||
// Quasi-quoting expanders
|
||||
syntax_expanders.insert(@~"quote_tokens",
|
||||
syntax_expanders.insert(intern(&"quote_tokens"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_tokens));
|
||||
syntax_expanders.insert(@~"quote_expr",
|
||||
syntax_expanders.insert(intern(&"quote_expr"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_expr));
|
||||
syntax_expanders.insert(@~"quote_ty",
|
||||
syntax_expanders.insert(intern(&"quote_ty"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_ty));
|
||||
syntax_expanders.insert(@~"quote_item",
|
||||
syntax_expanders.insert(intern(&"quote_item"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_item));
|
||||
syntax_expanders.insert(@~"quote_pat",
|
||||
syntax_expanders.insert(intern(&"quote_pat"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_pat));
|
||||
syntax_expanders.insert(@~"quote_stmt",
|
||||
syntax_expanders.insert(intern(&"quote_stmt"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_stmt));
|
||||
|
||||
syntax_expanders.insert(@~"line",
|
||||
syntax_expanders.insert(intern(&"line"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_line));
|
||||
syntax_expanders.insert(@~"col",
|
||||
syntax_expanders.insert(intern(&"col"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_col));
|
||||
syntax_expanders.insert(@~"file",
|
||||
syntax_expanders.insert(intern(&"file"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_file));
|
||||
syntax_expanders.insert(@~"stringify",
|
||||
syntax_expanders.insert(intern(&"stringify"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_stringify));
|
||||
syntax_expanders.insert(@~"include",
|
||||
syntax_expanders.insert(intern(&"include"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_include));
|
||||
syntax_expanders.insert(@~"include_str",
|
||||
syntax_expanders.insert(intern(&"include_str"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_include_str));
|
||||
syntax_expanders.insert(@~"include_bin",
|
||||
syntax_expanders.insert(intern(&"include_bin"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_include_bin));
|
||||
syntax_expanders.insert(@~"module_path",
|
||||
syntax_expanders.insert(intern(&"module_path"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_mod));
|
||||
syntax_expanders.insert(@~"proto",
|
||||
syntax_expanders.insert(intern(&"proto"),
|
||||
builtin_item_tt(ext::pipes::expand_proto));
|
||||
syntax_expanders.insert(@~"asm",
|
||||
syntax_expanders.insert(intern(&"asm"),
|
||||
builtin_normal_tt(ext::asm::expand_asm));
|
||||
syntax_expanders.insert(
|
||||
@~"trace_macros",
|
||||
intern(&"trace_macros"),
|
||||
builtin_normal_tt(ext::trace_macros::expand_trace_macros));
|
||||
MapChain::new(~syntax_expanders)
|
||||
}
|
||||
@@ -478,7 +487,39 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
|
||||
ConsMapChain (~ref mut map,_) => map.insert(key,ext)
|
||||
}
|
||||
}
|
||||
// insert the binding into the topmost frame for which the binding
|
||||
// associated with 'n' exists and satisfies pred
|
||||
// ... there are definitely some opportunities for abstraction
|
||||
// here that I'm ignoring. (e.g., manufacturing a predicate on
|
||||
// the maps in the chain, and using an abstract "find".
|
||||
fn insert_into_frame(&mut self, key: K, ext: @V, n: K, pred: &fn(&@V)->bool) {
|
||||
match *self {
|
||||
BaseMapChain (~ref mut map) => {
|
||||
if satisfies_pred(map,&n,pred) {
|
||||
map.insert(key,ext);
|
||||
} else {
|
||||
fail!(~"expected map chain containing satisfying frame")
|
||||
}
|
||||
},
|
||||
ConsMapChain (~ref mut map, rest) => {
|
||||
if satisfies_pred(map,&n,pred) {
|
||||
map.insert(key,ext);
|
||||
} else {
|
||||
rest.insert_into_frame(key,ext,n,pred)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn satisfies_pred<K : Eq + Hash + IterBytes,V>(map : &mut HashMap<K,V>,
|
||||
n: &K,
|
||||
pred: &fn(&V)->bool)
|
||||
-> bool {
|
||||
match map.find(n) {
|
||||
Some(ref v) => (pred(*v)),
|
||||
None => false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user