11
11
use core:: prelude:: * ;
12
12
13
13
use ast;
14
+ use ast:: Name ;
14
15
use codemap;
15
16
use codemap:: { CodeMap , span, ExpnInfo , ExpandedFrom } ;
16
17
use codemap:: CallInfo ;
17
18
use diagnostic:: span_handler;
18
19
use ext;
19
20
use parse;
20
21
use parse:: token;
22
+ use parse:: token:: { intern} ;
21
23
22
24
use core:: hashmap:: HashMap ;
23
25
use core:: vec;
@@ -91,29 +93,33 @@ pub enum SyntaxExtension {
91
93
IdentTT ( SyntaxExpanderTTItem ) ,
92
94
}
93
95
96
+ // The SyntaxEnv is the environment that's threaded through the expansion
97
+ // of macros. It contains bindings for macros, and also a special binding
98
+ // for " block" (not a legal identifier) that maps to a BlockInfo
94
99
pub type SyntaxEnv = @mut MapChain < Name , Transformer > ;
95
100
96
- // Name : the domain of SyntaxEnvs
97
- // want to change these to uints....
98
- // note that we use certain strings that are not legal as identifiers
99
- // to indicate, for instance, how blocks are supposed to behave.
100
- type Name = @~str ;
101
-
102
101
// Transformer : the codomain of SyntaxEnvs
103
102
104
- // NB: it may seem crazy to lump both of these into one environment;
105
- // what would it mean to bind "foo" to BlockLimit(true)? The idea
106
- // is that this follows the lead of MTWT, and accommodates growth
107
- // toward a more uniform syntax syntax (sorry) where blocks are just
108
- // another kind of transformer.
109
-
110
103
pub enum Transformer {
111
104
// this identifier maps to a syntax extension or macro
112
105
SE ( SyntaxExtension ) ,
113
- // should blocks occurring here limit macro scopes?
114
- ScopeMacros ( bool )
106
+ // blockinfo : this is ... well, it's simpler than threading
107
+ // another whole data stack-structured data structure through
108
+ // expansion. Basically, there's an invariant that every
109
+ // map must contain a binding for " block".
110
+ BlockInfo ( BlockInfo )
111
+ }
112
+
113
+ pub struct BlockInfo {
114
+ // should macros escape from this scope?
115
+ macros_escape : bool ,
116
+ // what are the pending renames?
117
+ pending_renames : @mut RenameList
115
118
}
116
119
120
+ // a list of ident->name renamings
121
+ type RenameList = ~[ ( ast:: ident , Name ) ] ;
122
+
117
123
// The base map of methods for expanding syntax extension
118
124
// AST nodes into full ASTs
119
125
pub fn syntax_expander_table ( ) -> SyntaxEnv {
@@ -127,77 +133,80 @@ pub fn syntax_expander_table() -> SyntaxEnv {
127
133
}
128
134
let mut syntax_expanders = HashMap :: new ( ) ;
129
135
// NB identifier starts with space, and can't conflict with legal idents
130
- syntax_expanders. insert ( @~" block",
131
- @ScopeMacros ( true ) ) ;
132
- syntax_expanders. insert ( @~"macro_rules",
136
+ syntax_expanders. insert ( intern ( & " block" ) ,
137
+ @BlockInfo ( BlockInfo {
138
+ macros_escape : false ,
139
+ pending_renames : @mut ~[ ]
140
+ } ) ) ;
141
+ syntax_expanders. insert ( intern ( & "macro_rules" ) ,
133
142
builtin_item_tt (
134
143
ext:: tt:: macro_rules:: add_new_extension) ) ;
135
- syntax_expanders. insert ( @~ "fmt",
144
+ syntax_expanders. insert ( intern ( & "fmt" ) ,
136
145
builtin_normal_tt ( ext:: fmt:: expand_syntax_ext) ) ;
137
146
syntax_expanders. insert (
138
- @~ "auto_encode",
147
+ intern ( & "auto_encode" ) ,
139
148
@SE ( ItemDecorator ( ext:: auto_encode:: expand_auto_encode) ) ) ;
140
149
syntax_expanders. insert (
141
- @~ "auto_decode",
150
+ intern ( & "auto_decode" ) ,
142
151
@SE ( ItemDecorator ( ext:: auto_encode:: expand_auto_decode) ) ) ;
143
- syntax_expanders. insert ( @~ "env",
152
+ syntax_expanders. insert ( intern ( & "env" ) ,
144
153
builtin_normal_tt ( ext:: env:: expand_syntax_ext) ) ;
145
- syntax_expanders. insert ( @~ "bytes",
154
+ syntax_expanders. insert ( intern ( "bytes" ) ,
146
155
builtin_normal_tt ( ext:: bytes:: expand_syntax_ext) ) ;
147
- syntax_expanders. insert ( @~ "concat_idents",
156
+ syntax_expanders. insert ( intern ( "concat_idents" ) ,
148
157
builtin_normal_tt (
149
158
ext:: concat_idents:: expand_syntax_ext) ) ;
150
- syntax_expanders. insert ( @~ "log_syntax",
159
+ syntax_expanders. insert ( intern ( & "log_syntax" ) ,
151
160
builtin_normal_tt (
152
161
ext:: log_syntax:: expand_syntax_ext) ) ;
153
- syntax_expanders. insert ( @~ "deriving",
162
+ syntax_expanders. insert ( intern ( & "deriving" ) ,
154
163
@SE ( ItemDecorator (
155
164
ext:: deriving:: expand_meta_deriving) ) ) ;
156
165
157
166
// Quasi-quoting expanders
158
- syntax_expanders. insert ( @~ "quote_tokens",
167
+ syntax_expanders. insert ( intern ( & "quote_tokens" ) ,
159
168
builtin_normal_tt ( ext:: quote:: expand_quote_tokens) ) ;
160
- syntax_expanders. insert ( @~ "quote_expr",
169
+ syntax_expanders. insert ( intern ( & "quote_expr" ) ,
161
170
builtin_normal_tt ( ext:: quote:: expand_quote_expr) ) ;
162
- syntax_expanders. insert ( @~ "quote_ty",
171
+ syntax_expanders. insert ( intern ( & "quote_ty" ) ,
163
172
builtin_normal_tt ( ext:: quote:: expand_quote_ty) ) ;
164
- syntax_expanders. insert ( @~ "quote_item",
173
+ syntax_expanders. insert ( intern ( & "quote_item" ) ,
165
174
builtin_normal_tt ( ext:: quote:: expand_quote_item) ) ;
166
- syntax_expanders. insert ( @~ "quote_pat",
175
+ syntax_expanders. insert ( intern ( & "quote_pat" ) ,
167
176
builtin_normal_tt ( ext:: quote:: expand_quote_pat) ) ;
168
- syntax_expanders. insert ( @~ "quote_stmt",
177
+ syntax_expanders. insert ( intern ( & "quote_stmt" ) ,
169
178
builtin_normal_tt ( ext:: quote:: expand_quote_stmt) ) ;
170
179
171
- syntax_expanders. insert ( @~ "line",
180
+ syntax_expanders. insert ( intern ( & "line" ) ,
172
181
builtin_normal_tt (
173
182
ext:: source_util:: expand_line) ) ;
174
- syntax_expanders. insert ( @~ "col",
183
+ syntax_expanders. insert ( intern ( & "col" ) ,
175
184
builtin_normal_tt (
176
185
ext:: source_util:: expand_col) ) ;
177
- syntax_expanders. insert ( @~ "file",
186
+ syntax_expanders. insert ( intern ( & "file" ) ,
178
187
builtin_normal_tt (
179
188
ext:: source_util:: expand_file) ) ;
180
- syntax_expanders. insert ( @~ "stringify",
189
+ syntax_expanders. insert ( intern ( & "stringify" ) ,
181
190
builtin_normal_tt (
182
191
ext:: source_util:: expand_stringify) ) ;
183
- syntax_expanders. insert ( @~ "include",
192
+ syntax_expanders. insert ( intern ( & "include" ) ,
184
193
builtin_normal_tt (
185
194
ext:: source_util:: expand_include) ) ;
186
- syntax_expanders. insert ( @~ "include_str",
195
+ syntax_expanders. insert ( intern ( & "include_str" ) ,
187
196
builtin_normal_tt (
188
197
ext:: source_util:: expand_include_str) ) ;
189
- syntax_expanders. insert ( @~ "include_bin",
198
+ syntax_expanders. insert ( intern ( & "include_bin" ) ,
190
199
builtin_normal_tt (
191
200
ext:: source_util:: expand_include_bin) ) ;
192
- syntax_expanders. insert ( @~ "module_path",
201
+ syntax_expanders. insert ( intern ( & "module_path" ) ,
193
202
builtin_normal_tt (
194
203
ext:: source_util:: expand_mod) ) ;
195
- syntax_expanders. insert ( @~ "proto",
204
+ syntax_expanders. insert ( intern ( & "proto" ) ,
196
205
builtin_item_tt ( ext:: pipes:: expand_proto) ) ;
197
- syntax_expanders. insert ( @~ "asm",
206
+ syntax_expanders. insert ( intern ( & "asm" ) ,
198
207
builtin_normal_tt ( ext:: asm:: expand_asm) ) ;
199
208
syntax_expanders. insert (
200
- @~ "trace_macros",
209
+ intern ( & "trace_macros" ) ,
201
210
builtin_normal_tt ( ext:: trace_macros:: expand_trace_macros) ) ;
202
211
MapChain :: new ( ~syntax_expanders)
203
212
}
@@ -478,7 +487,39 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
478
487
ConsMapChain ( ~ref mut map, _) => map. insert ( key, ext)
479
488
}
480
489
}
490
+ // insert the binding into the topmost frame for which the binding
491
+ // associated with 'n' exists and satisfies pred
492
+ // ... there are definitely some opportunities for abstraction
493
+ // here that I'm ignoring. (e.g., manufacturing a predicate on
494
+ // the maps in the chain, and using an abstract "find".
495
+ fn insert_into_frame( & mut self , key : K , ext : @V , n : K , pred : & fn ( & @V ) ->bool ) {
496
+ match * self {
497
+ BaseMapChain ( ~ref mut map) => {
498
+ if satisfies_pred ( map, & n, pred) {
499
+ map. insert ( key, ext) ;
500
+ } else {
501
+ fail ! ( ~"expected map chain containing satisfying frame")
502
+ }
503
+ },
504
+ ConsMapChain (~ref mut map, rest) => {
505
+ if satisfies_pred(map,&n,pred) {
506
+ map.insert(key,ext);
507
+ } else {
508
+ rest.insert_into_frame(key,ext,n,pred)
509
+ }
510
+ }
511
+ }
512
+ }
513
+ }
481
514
515
+ fn satisfies_pred<K : Eq + Hash + IterBytes,V>(map : &mut HashMap<K,V>,
516
+ n: &K,
517
+ pred: &fn(&V)->bool)
518
+ -> bool {
519
+ match map.find(n) {
520
+ Some(ref v) => (pred(*v)),
521
+ None => false
522
+ }
482
523
}
483
524
484
525
#[cfg(test)]
0 commit comments