@@ -87,56 +87,27 @@ impl<'a> CycleState<'a> {
87
87
}
88
88
}
89
89
90
- #[ derive( Default ) ]
91
- pub struct Context {
92
- stack : Vec < Object > ,
90
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
91
+ pub struct Stack {
93
92
globals : Object ,
94
-
95
- interrupt : InterruptState ,
96
- cycles : CycleStateInner ,
97
-
98
- filters : sync:: Arc < HashMap < & ' static str , BoxedValueFilter > > ,
93
+ stack : Vec < Object > ,
99
94
}
100
95
101
- impl Context {
102
- /// Creates a new, empty rendering context.
96
+ impl Stack {
103
97
pub fn new ( ) -> Self {
104
- Default :: default ( )
98
+ Self {
99
+ globals : Object :: new ( ) ,
100
+ // Mutable frame for globals.
101
+ stack : vec ! [ Object :: new( ) ] ,
102
+ }
105
103
}
106
104
107
- pub fn with_values ( mut self , values : Object ) -> Self {
105
+ pub fn with_globals ( & mut self , values : Object ) {
108
106
self . globals = values;
109
- self
110
- }
111
-
112
- pub fn with_filters ( mut self , filters : & sync:: Arc < HashMap < & ' static str , BoxedValueFilter > > ) -> Self {
113
- self . filters = sync:: Arc :: clone ( filters) ;
114
- self
115
- }
116
-
117
- pub fn get_filter < ' b > ( & ' b self , name : & str ) -> Option < & ' b FilterValue > {
118
- self . filters . get ( name) . map ( |f| {
119
- let f: & FilterValue = f;
120
- f
121
- } )
122
- }
123
-
124
- pub fn interrupt ( & self ) -> & InterruptState {
125
- & self . interrupt
126
- }
127
-
128
- pub fn interrupt_mut ( & mut self ) -> & mut InterruptState {
129
- & mut self . interrupt
130
- }
131
-
132
- pub fn cycles < ' a > ( & ' a mut self ) -> CycleState < ' a > {
133
- CycleState {
134
- context : self ,
135
- }
136
107
}
137
108
138
109
/// Creates a new variable scope chained to a parent scope.
139
- fn push_scope ( & mut self ) {
110
+ fn push_frame ( & mut self ) {
140
111
self . stack . push ( Object :: new ( ) ) ;
141
112
}
142
113
@@ -148,25 +119,12 @@ impl Context {
148
119
/// empty stack. Given that a context is created with a top-level stack
149
120
/// frame already in place, empyting the stack should never happen in a
150
121
/// well-formed program.
151
- fn pop_scope ( & mut self ) {
122
+ fn pop_frame ( & mut self ) {
152
123
if self . stack . pop ( ) . is_none ( ) {
153
124
panic ! ( "Pop leaves empty stack" )
154
125
} ;
155
126
}
156
127
157
- /// Sets up a new stack frame, executes the supplied function and then
158
- /// tears the stack frame down before returning the function's result
159
- /// to the caller.
160
- pub fn run_in_scope < RvalT , FnT > ( & mut self , f : FnT ) -> RvalT
161
- where
162
- FnT : FnOnce ( & mut Context ) -> RvalT ,
163
- {
164
- self . push_scope ( ) ;
165
- let result = f ( self ) ;
166
- self . pop_scope ( ) ;
167
- result
168
- }
169
-
170
128
/// Gets a value from the rendering context.
171
129
pub fn get_val < ' a > ( & ' a self , name : & str ) -> Option < & ' a Value > {
172
130
for frame in self . stack . iter ( ) . rev ( ) {
@@ -204,7 +162,7 @@ impl Context {
204
162
where
205
163
S : Into < borrow:: Cow < ' static , str > > ,
206
164
{
207
- self . globals . insert ( name. into ( ) , val)
165
+ self . global_frame ( ) . insert ( name. into ( ) , val)
208
166
}
209
167
210
168
/// Sets a value to the rendering context.
@@ -219,11 +177,97 @@ impl Context {
219
177
where
220
178
S : Into < borrow:: Cow < ' static , str > > ,
221
179
{
180
+ self . current_frame ( ) . insert ( name. into ( ) , val)
181
+ }
182
+
183
+ fn current_frame ( & mut self ) -> & mut Object {
222
184
match self . stack . last_mut ( ) {
223
- Some ( frame) => frame. insert ( name . into ( ) , val ) ,
224
- None => panic ! ( "Cannot insert into an empty stack " ) ,
185
+ Some ( frame) => frame,
186
+ None => panic ! ( "Global frame removed. " ) ,
225
187
}
226
188
}
189
+
190
+ fn global_frame ( & mut self ) -> & mut Object {
191
+ match self . stack . first_mut ( ) {
192
+ Some ( frame) => frame,
193
+ None => panic ! ( "Global frame removed." ) ,
194
+ }
195
+ }
196
+ }
197
+
198
+ impl Default for Stack {
199
+ fn default ( ) -> Self {
200
+ Self :: new ( )
201
+ }
202
+ }
203
+
204
+ #[ derive( Default ) ]
205
+ pub struct Context {
206
+ stack : Stack ,
207
+
208
+ interrupt : InterruptState ,
209
+ cycles : CycleStateInner ,
210
+
211
+ filters : sync:: Arc < HashMap < & ' static str , BoxedValueFilter > > ,
212
+ }
213
+
214
+ impl Context {
215
+ /// Creates a new, empty rendering context.
216
+ pub fn new ( ) -> Self {
217
+ Default :: default ( )
218
+ }
219
+
220
+ pub fn with_values ( mut self , values : Object ) -> Self {
221
+ self . stack . with_globals ( values) ;
222
+ self
223
+ }
224
+
225
+ pub fn with_filters ( mut self , filters : & sync:: Arc < HashMap < & ' static str , BoxedValueFilter > > ) -> Self {
226
+ self . filters = sync:: Arc :: clone ( filters) ;
227
+ self
228
+ }
229
+
230
+ pub fn get_filter < ' b > ( & ' b self , name : & str ) -> Option < & ' b FilterValue > {
231
+ self . filters . get ( name) . map ( |f| {
232
+ let f: & FilterValue = f;
233
+ f
234
+ } )
235
+ }
236
+
237
+ pub fn interrupt ( & self ) -> & InterruptState {
238
+ & self . interrupt
239
+ }
240
+
241
+ pub fn interrupt_mut ( & mut self ) -> & mut InterruptState {
242
+ & mut self . interrupt
243
+ }
244
+
245
+ pub fn cycles < ' a > ( & ' a mut self ) -> CycleState < ' a > {
246
+ CycleState {
247
+ context : self ,
248
+ }
249
+ }
250
+
251
+ pub fn stack ( & self ) -> & Stack {
252
+ & self . stack
253
+ }
254
+
255
+ pub fn stack_mut ( & mut self ) -> & mut Stack {
256
+ & mut self . stack
257
+ }
258
+
259
+ /// Sets up a new stack frame, executes the supplied function and then
260
+ /// tears the stack frame down before returning the function's result
261
+ /// to the caller.
262
+ pub fn run_in_scope < RvalT , FnT > ( & mut self , f : FnT ) -> RvalT
263
+ where
264
+ FnT : FnOnce ( & mut Context ) -> RvalT ,
265
+ {
266
+ self . stack . push_frame ( ) ;
267
+ let result = f ( self ) ;
268
+ self . stack . pop_frame ( ) ;
269
+ result
270
+ }
227
271
}
228
272
229
273
#[ cfg( test) ]
@@ -233,52 +277,52 @@ mod test {
233
277
#[ test]
234
278
fn get_val ( ) {
235
279
let mut ctx = Context :: new ( ) ;
236
- ctx. set_global_val ( "number" , Value :: scalar ( 42f64 ) ) ;
237
- assert_eq ! ( ctx. get_val( "number" ) . unwrap( ) , & Value :: scalar( 42f64 ) ) ;
280
+ ctx. stack_mut ( ) . set_global_val ( "number" , Value :: scalar ( 42f64 ) ) ;
281
+ assert_eq ! ( ctx. stack ( ) . get_val( "number" ) . unwrap( ) , & Value :: scalar( 42f64 ) ) ;
238
282
}
239
283
240
284
#[ test]
241
285
fn get_val_failure ( ) {
242
286
let mut ctx = Context :: new ( ) ;
243
287
let mut post = Object :: new ( ) ;
244
288
post. insert ( "number" . into ( ) , Value :: scalar ( 42f64 ) ) ;
245
- ctx. set_global_val ( "post" , Value :: Object ( post) ) ;
246
- assert ! ( ctx. get_val( "post.number" ) . is_none( ) ) ;
289
+ ctx. stack_mut ( ) . set_global_val ( "post" , Value :: Object ( post) ) ;
290
+ assert ! ( ctx. stack ( ) . get_val( "post.number" ) . is_none( ) ) ;
247
291
}
248
292
249
293
#[ test]
250
294
fn get_val_by_index ( ) {
251
295
let mut ctx = Context :: new ( ) ;
252
296
let mut post = Object :: new ( ) ;
253
297
post. insert ( "number" . into ( ) , Value :: scalar ( 42f64 ) ) ;
254
- ctx. set_global_val ( "post" , Value :: Object ( post) ) ;
298
+ ctx. stack_mut ( ) . set_global_val ( "post" , Value :: Object ( post) ) ;
255
299
let indexes = vec ! [ Index :: with_key( "post" ) , Index :: with_key( "number" ) ] ;
256
300
assert_eq ! (
257
- ctx. get_val_by_index( indexes. iter( ) ) . unwrap( ) ,
301
+ ctx. stack ( ) . get_val_by_index( indexes. iter( ) ) . unwrap( ) ,
258
302
& Value :: scalar( 42f64 )
259
303
) ;
260
304
}
261
305
262
306
#[ test]
263
307
fn scoped_variables ( ) {
264
308
let mut ctx = Context :: new ( ) ;
265
- ctx. set_global_val ( "test" , Value :: scalar ( 42f64 ) ) ;
266
- assert_eq ! ( ctx. get_val( "test" ) . unwrap( ) , & Value :: scalar( 42f64 ) ) ;
309
+ ctx. stack_mut ( ) . set_global_val ( "test" , Value :: scalar ( 42f64 ) ) ;
310
+ assert_eq ! ( ctx. stack ( ) . get_val( "test" ) . unwrap( ) , & Value :: scalar( 42f64 ) ) ;
267
311
268
312
ctx. run_in_scope ( |new_scope| {
269
313
// assert that values are chained to the parent scope
270
- assert_eq ! ( new_scope. get_val( "test" ) . unwrap( ) , & Value :: scalar( 42f64 ) ) ;
314
+ assert_eq ! ( new_scope. stack ( ) . get_val( "test" ) . unwrap( ) , & Value :: scalar( 42f64 ) ) ;
271
315
272
316
// set a new local value, and assert that it overrides the previous value
273
- new_scope. set_val ( "test" , Value :: scalar ( 3.14f64 ) ) ;
274
- assert_eq ! ( new_scope. get_val( "test" ) . unwrap( ) , & Value :: scalar( 3.14f64 ) ) ;
317
+ new_scope. stack_mut ( ) . set_val ( "test" , Value :: scalar ( 3.14f64 ) ) ;
318
+ assert_eq ! ( new_scope. stack ( ) . get_val( "test" ) . unwrap( ) , & Value :: scalar( 3.14f64 ) ) ;
275
319
276
320
// sat a new val that we will pick up outside the scope
277
- new_scope. set_global_val ( "global" , Value :: scalar ( "some value" ) ) ;
321
+ new_scope. stack_mut ( ) . set_global_val ( "global" , Value :: scalar ( "some value" ) ) ;
278
322
} ) ;
279
323
280
324
// assert that the value has reverted to the old one
281
- assert_eq ! ( ctx. get_val( "test" ) . unwrap( ) , & Value :: scalar( 42f64 ) ) ;
282
- assert_eq ! ( ctx. get_val( "global" ) . unwrap( ) , & Value :: scalar( "some value" ) ) ;
325
+ assert_eq ! ( ctx. stack ( ) . get_val( "test" ) . unwrap( ) , & Value :: scalar( 42f64 ) ) ;
326
+ assert_eq ! ( ctx. stack ( ) . get_val( "global" ) . unwrap( ) , & Value :: scalar( "some value" ) ) ;
283
327
}
284
328
}
0 commit comments