@@ -48,8 +48,8 @@ enum Block {
4848}
4949
5050struct Stacks {
51- var_stack : VectorStack < ObjectRef > ,
52- block_stack : VectorStack < Block > ,
51+ variables : VectorStack < ObjectRef > ,
52+ blocks : VectorStack < Block > ,
5353}
5454
5555/// Like try!, but for PyResult instead of Result
@@ -87,22 +87,22 @@ macro_rules! pop_stack {
8787macro_rules! raise {
8888 ( $stacks: expr, $program_counter: ident, $traceback: expr, $exception: expr, $exc_type: expr, $value: expr) => { {
8989 loop {
90- match $stacks. block_stack . pop( ) {
90+ match $stacks. blocks . pop( ) {
9191 None => { // Root block; raise exception to calling function
9292 return PyResult :: Raise ( $exception, $exc_type)
9393 }
9494 Some ( Block :: TryExcept ( begin, end) ) => { // Found a try…except block
95- $stacks. block_stack . push( Block :: TryExcept ( begin, end) ) ; // Push it back, it will be poped by PopExcept.
95+ $stacks. blocks . push( Block :: TryExcept ( begin, end) ) ; // Push it back, it will be poped by PopExcept.
9696 $program_counter = end;
9797 let traceback = $traceback;
9898 let exception = $exception;
99- $stacks. var_stack . push( traceback. clone( ) ) ; // traceback
100- $stacks. var_stack . push( exception. clone( ) ) ; // exception
101- $stacks. var_stack . push( $exc_type) ; // exception type
99+ $stacks. variables . push( traceback. clone( ) ) ; // traceback
100+ $stacks. variables . push( exception. clone( ) ) ; // exception
101+ $stacks. variables . push( $exc_type) ; // exception type
102102
103- $stacks. var_stack . push( traceback) ; // traceback
104- $stacks. var_stack . push( $value) ; // value
105- $stacks. var_stack . push( exception) ; // exception
103+ $stacks. variables . push( traceback) ; // traceback
104+ $stacks. variables . push( $value) ; // value
105+ $stacks. variables . push( exception) ; // exception
106106 break
107107 }
108108 Some ( _) => { // Non-try…except block, exit it.
@@ -178,31 +178,27 @@ impl<EP: EnvProxy> Processor<EP> {
178178 PyResult :: Return ( self . store . allocate ( Object :: new_instance ( None , func_ref. clone ( ) , ObjectContent :: OtherObject ) ) )
179179 } ,
180180 ObjectContent :: Function ( ref code_ref) => {
181- match self . store . deref ( code_ref) . content . clone ( ) {
182- ObjectContent :: Code ( code) => {
181+ let code = self . store . deref ( code_ref) . content . clone ( ) ;
182+ if let ObjectContent :: Code ( code) = code {
183183 let mut namespace = namespace. clone ( ) ; // TODO: costly, try maybe copy-on-write?
184- if code. co_varargs ( ) { // If it has a *args argument
185- if code. argcount > args. len ( ) {
186- panic ! ( format!( "Function {} expected at least {} arguments, but got {}." , code. name, code. argcount, args. len( ) ) )
187- } ;
188- let to_vararg = args. drain ( code. argcount ..) . collect ( ) ;
189- let obj_ref = self . store . allocate ( self . primitive_objects . new_tuple ( to_vararg) ) ;
190- args. push ( obj_ref) ;
191- }
192- else if code. argcount != args. len ( ) {
193- panic ! ( format!( "Function {} expected {} arguments, but got {}." , code. name, code. argcount, args. len( ) ) )
194- } ;
195- for ( argname, argvalue) in code. varnames . iter ( ) . zip ( args) {
196- namespace. insert ( argname. clone ( ) , argvalue) ;
184+ if code. co_varargs ( ) { // If it has a *args argument
185+ if code. argcount > args. len ( ) {
186+ panic ! ( format!( "Function {} expected at least {} arguments, but got {}." , code. name, code. argcount, args. len( ) ) )
197187 } ;
198- self . run_code ( & mut namespace, ( * code) . clone ( ) )
199- } ,
200- ref o => {
201- match self . store . deref ( func_ref) . name {
202- None => return PyResult :: Error ( ProcessorError :: NotACodeObject ( format ! ( "anonymous function has code {:?}" , o) ) ) ,
203- Some ( ref name) => return PyResult :: Error ( ProcessorError :: NotACodeObject ( format ! ( "function {} has code {:?}" , name, o) ) ) ,
204- }
188+ let to_vararg = args. drain ( code. argcount ..) . collect ( ) ;
189+ let obj_ref = self . store . allocate ( self . primitive_objects . new_tuple ( to_vararg) ) ;
190+ args. push ( obj_ref) ;
205191 }
192+ else if code. argcount != args. len ( ) {
193+ panic ! ( format!( "Function {} expected {} arguments, but got {}." , code. name, code. argcount, args. len( ) ) )
194+ } ;
195+ for ( argname, argvalue) in code. varnames . iter ( ) . zip ( args) {
196+ namespace. insert ( argname. clone ( ) , argvalue) ;
197+ } ;
198+ self . run_code ( & mut namespace, ( * code) . clone ( ) )
199+ }
200+ else {
201+ return PyResult :: Error ( ProcessorError :: NotACodeObject ( func_ref. repr ( & self . store ) ) )
206202 }
207203 } ,
208204 ObjectContent :: PrimitiveFunction ( ref name) => {
@@ -224,44 +220,44 @@ impl<EP: EnvProxy> Processor<EP> {
224220 let bytecode: Vec < u8 > = code. code ;
225221 let instructions: Vec < Instruction > = instructions:: InstructionDecoder :: new ( bytecode. iter ( ) ) . into_iter ( ) . collect ( ) ;
226222 let mut program_counter = 0 as usize ;
227- let mut stacks = Stacks { var_stack : VectorStack :: new ( ) , block_stack : VectorStack :: new ( ) } ;
223+ let mut stacks = Stacks { variables : VectorStack :: new ( ) , blocks : VectorStack :: new ( ) } ;
228224 loop {
229225 let instruction = py_unwrap ! ( instructions. get( program_counter) , ProcessorError :: InvalidProgramCounter ) ;
230226 program_counter += 1 ;
231227 match * instruction {
232228 Instruction :: PopTop => {
233- pop_stack ! ( stacks. var_stack ) ;
229+ pop_stack ! ( stacks. variables ) ;
234230 ( )
235231 } ,
236232 Instruction :: DupTop => {
237- let val = pop_stack ! ( stacks. var_stack ) ;
238- stacks. var_stack . push ( val. clone ( ) ) ;
239- stacks. var_stack . push ( val) ;
233+ let val = pop_stack ! ( stacks. variables ) ;
234+ stacks. variables . push ( val. clone ( ) ) ;
235+ stacks. variables . push ( val) ;
240236 }
241237 Instruction :: Nop => ( ) ,
242238 Instruction :: BinarySubscr => {
243- let index_ref = pop_stack ! ( stacks. var_stack ) ;
239+ let index_ref = pop_stack ! ( stacks. variables ) ;
244240 let index = self . store . deref ( & index_ref) . content . clone ( ) ;
245- let container_ref = pop_stack ! ( stacks. var_stack ) ;
241+ let container_ref = pop_stack ! ( stacks. variables ) ;
246242 let container = self . store . deref ( & container_ref) . content . clone ( ) ;
247243 match ( container, index) {
248244 ( ObjectContent :: Tuple ( v) , ObjectContent :: Int ( i) ) | ( ObjectContent :: List ( v) , ObjectContent :: Int ( i) ) => {
249245 match v. get ( i as usize ) { // TODO: overflow check
250246 None => panic ! ( "Out of bound" ) ,
251- Some ( obj_ref) => stacks. var_stack . push ( obj_ref. clone ( ) ) ,
247+ Some ( obj_ref) => stacks. variables . push ( obj_ref. clone ( ) ) ,
252248 }
253249 }
254250 _ => panic ! ( "Indexing only supported for tuples/lists with an integer." )
255251 }
256252 }
257253 Instruction :: LoadBuildClass => {
258254 let obj = Object { name : Some ( "__build_class__" . to_string ( ) ) , content : ObjectContent :: PrimitiveFunction ( "build_class" . to_string ( ) ) , class : self . primitive_objects . function_type . clone ( ) , bases : None } ;
259- stacks. var_stack . push ( self . store . allocate ( obj) ) ;
255+ stacks. variables . push ( self . store . allocate ( obj) ) ;
260256 }
261- Instruction :: ReturnValue => return PyResult :: Return ( pop_stack ! ( stacks. var_stack ) ) ,
262- Instruction :: PopBlock => { pop_stack ! ( stacks. block_stack ) ; } ,
257+ Instruction :: ReturnValue => return PyResult :: Return ( pop_stack ! ( stacks. variables ) ) ,
258+ Instruction :: PopBlock => { pop_stack ! ( stacks. blocks ) ; } ,
263259 Instruction :: EndFinally => {
264- let status_ref = pop_stack ! ( stacks. var_stack ) ;
260+ let status_ref = pop_stack ! ( stacks. variables ) ;
265261 let status = self . store . deref ( & status_ref) ;
266262 match status. content {
267263 ObjectContent :: Int ( i) => panic ! ( "TODO: finally int status" ) , // TODO
@@ -270,64 +266,64 @@ impl<EP: EnvProxy> Processor<EP> {
270266 }
271267 }
272268 Instruction :: PopExcept => {
273- let mut three_last = stacks. var_stack . pop_all_and_get_n_last ( 3 ) . unwrap ( ) ; // TODO: check
269+ let mut three_last = stacks. variables . pop_all_and_get_n_last ( 3 ) . unwrap ( ) ; // TODO: check
274270 let exc_type = three_last. pop ( ) ;
275271 let exc_value = three_last. pop ( ) ;
276272 let exc_traceback = three_last. pop ( ) ;
277273 // TODO: do something with exc_*
278- pop_stack ! ( stacks. block_stack ) ;
274+ pop_stack ! ( stacks. blocks ) ;
279275 } ,
280276 Instruction :: StoreName ( i) => {
281277 let name = py_unwrap ! ( code. names. get( i) , ProcessorError :: InvalidNameIndex ) . clone ( ) ;
282- let obj_ref = pop_stack ! ( stacks. var_stack ) ;
278+ let obj_ref = pop_stack ! ( stacks. variables ) ;
283279 namespace. insert ( name, obj_ref) ;
284280 }
285- Instruction :: LoadConst ( i) => stacks. var_stack . push ( py_unwrap ! ( code. consts. get( i) , ProcessorError :: InvalidConstIndex ) . clone ( ) ) ,
281+ Instruction :: LoadConst ( i) => stacks. variables . push ( py_unwrap ! ( code. consts. get( i) , ProcessorError :: InvalidConstIndex ) . clone ( ) ) ,
286282 Instruction :: LoadName ( i) | Instruction :: LoadGlobal ( i) => {
287283 let name = py_unwrap ! ( code. names. get( i) , ProcessorError :: InvalidNameIndex ) . clone ( ) ;
288- stacks. var_stack . push ( py_try ! ( self . load_name( namespace, name) ) )
284+ stacks. variables . push ( py_try ! ( self . load_name( namespace, name) ) )
289285 }
290286 Instruction :: LoadAttr ( i) => {
291287 let obj = {
292- let obj_ref = py_unwrap ! ( stacks. var_stack . pop( ) , ProcessorError :: StackTooSmall ) ;
288+ let obj_ref = py_unwrap ! ( stacks. variables . pop( ) , ProcessorError :: StackTooSmall ) ;
293289 self . store . deref ( & obj_ref) . clone ( )
294290 } ;
295291 let name = py_unwrap ! ( code. names. get( i) , ProcessorError :: InvalidNameIndex ) . clone ( ) ;
296- stacks. var_stack . push ( py_try ! ( self . load_attr( & obj, name) ) )
292+ stacks. variables . push ( py_try ! ( self . load_attr( & obj, name) ) )
297293 } ,
298294 Instruction :: SetupLoop ( i) => {
299- stacks. block_stack . push ( Block :: Loop ( program_counter, program_counter+i) )
295+ stacks. blocks . push ( Block :: Loop ( program_counter, program_counter+i) )
300296 }
301297 Instruction :: SetupExcept ( i) => {
302- stacks. block_stack . push ( Block :: TryExcept ( program_counter, program_counter+i) )
298+ stacks. blocks . push ( Block :: TryExcept ( program_counter, program_counter+i) )
303299 }
304300 Instruction :: CompareOp ( CmpOperator :: Eq ) => {
305301 // TODO: enrich this (support __eq__)
306- let obj1 = self . store . deref ( & pop_stack ! ( stacks. var_stack ) ) ;
307- let obj2 = self . store . deref ( & pop_stack ! ( stacks. var_stack ) ) ;
302+ let obj1 = self . store . deref ( & pop_stack ! ( stacks. variables ) ) ;
303+ let obj2 = self . store . deref ( & pop_stack ! ( stacks. variables ) ) ;
308304 if obj1. name == obj2. name && obj1. content == obj2. content {
309- stacks. var_stack . push ( self . primitive_objects . true_obj . clone ( ) )
305+ stacks. variables . push ( self . primitive_objects . true_obj . clone ( ) )
310306 }
311307 else {
312- stacks. var_stack . push ( self . primitive_objects . false_obj . clone ( ) )
308+ stacks. variables . push ( self . primitive_objects . false_obj . clone ( ) )
313309 } ;
314310 }
315311 Instruction :: CompareOp ( CmpOperator :: ExceptionMatch ) => {
316312 // TODO: add support for tuples
317- let pattern_ref = pop_stack ! ( stacks. var_stack ) ;
318- let exc_ref = pop_stack ! ( stacks. var_stack ) ;
313+ let pattern_ref = pop_stack ! ( stacks. variables ) ;
314+ let exc_ref = pop_stack ! ( stacks. variables ) ;
319315 let isinstance = self . primitive_functions . get ( "isinstance" ) . unwrap ( ) . clone ( ) ;
320- stacks. var_stack . push ( py_try ! ( isinstance( self , vec![ exc_ref, pattern_ref] ) ) ) ;
316+ stacks. variables . push ( py_try ! ( isinstance( self , vec![ exc_ref, pattern_ref] ) ) ) ;
321317 }
322318 Instruction :: JumpForward ( delta) => {
323319 program_counter += delta
324320 }
325321 Instruction :: LoadFast ( i) => {
326322 let name = py_unwrap ! ( code. varnames. get( i) , ProcessorError :: InvalidVarnameIndex ) . clone ( ) ;
327- stacks. var_stack . push ( py_try ! ( self . load_name( namespace, name) ) )
323+ stacks. variables . push ( py_try ! ( self . load_name( namespace, name) ) )
328324 }
329325 Instruction :: PopJumpIfFalse ( target) => {
330- let obj = self . store . deref ( & pop_stack ! ( stacks. var_stack ) ) ;
326+ let obj = self . store . deref ( & pop_stack ! ( stacks. variables ) ) ;
331327 match obj. content {
332328 ObjectContent :: True => ( ) ,
333329 ObjectContent :: False => program_counter = target,
@@ -339,7 +335,7 @@ impl<EP: EnvProxy> Processor<EP> {
339335 panic ! ( "RaiseVarargs(0) not implemented." )
340336 }
341337 Instruction :: RaiseVarargs ( 1 ) => {
342- let exception = pop_stack ! ( stacks. var_stack ) ;
338+ let exception = pop_stack ! ( stacks. variables ) ;
343339 let exc_type = exception. clone ( ) ;
344340 // TODO: add traceback
345341 raise ! ( stacks, program_counter, self . primitive_objects. none. clone( ) , exception, exc_type, self . primitive_objects. none. clone( ) ) ;
@@ -355,12 +351,12 @@ impl<EP: EnvProxy> Processor<EP> {
355351 Instruction :: CallFunction ( nb_args, nb_kwargs) => {
356352 // See “Call constructs” at:
357353 // http://security.coverity.com/blog/2014/Nov/understanding-python-bytecode.html
358- let kwargs = py_unwrap ! ( stacks. var_stack . pop_many( nb_kwargs* 2 ) , ProcessorError :: StackTooSmall ) ;
359- let args = py_unwrap ! ( stacks. var_stack . pop_many( nb_args) , ProcessorError :: StackTooSmall ) ;
360- let func = pop_stack ! ( stacks. var_stack ) ;
354+ let kwargs = py_unwrap ! ( stacks. variables . pop_many( nb_kwargs* 2 ) , ProcessorError :: StackTooSmall ) ;
355+ let args = py_unwrap ! ( stacks. variables . pop_many( nb_args) , ProcessorError :: StackTooSmall ) ;
356+ let func = pop_stack ! ( stacks. variables ) ;
361357 let ret = self . call_function ( namespace, & func, args, kwargs) ;
362358 match ret {
363- PyResult :: Return ( obj_ref) => stacks. var_stack . push ( obj_ref) ,
359+ PyResult :: Return ( obj_ref) => stacks. variables . push ( obj_ref) ,
364360 PyResult :: Raise ( exception, exc_type) => {
365361 // TODO: add frame to traceback
366362 raise ! ( stacks, program_counter, self . primitive_objects. none. clone( ) , exception, exc_type, self . primitive_objects. none. clone( ) )
@@ -370,12 +366,12 @@ impl<EP: EnvProxy> Processor<EP> {
370366 } ,
371367 Instruction :: MakeFunction ( 0 , 0 , 0 ) => {
372368 // TODO: consume default arguments and annotations
373- let func_name = match self . store . deref ( & pop_stack ! ( stacks. var_stack ) ) . content {
369+ let func_name = match self . store . deref ( & pop_stack ! ( stacks. variables ) ) . content {
374370 ObjectContent :: String ( ref s) => s. clone ( ) ,
375371 _ => panic ! ( "Function names must be strings." ) ,
376372 } ;
377- let code = pop_stack ! ( stacks. var_stack ) ;
378- stacks. var_stack . push ( self . store . allocate ( Object { name : Some ( func_name) , content : ObjectContent :: Function ( code) , class : self . primitive_objects . function_type . clone ( ) , bases : None } ) )
373+ let code = pop_stack ! ( stacks. variables ) ;
374+ stacks. variables . push ( self . store . allocate ( Object { name : Some ( func_name) , content : ObjectContent :: Function ( code) , class : self . primitive_objects . function_type . clone ( ) , bases : None } ) )
379375 } ,
380376 _ => panic ! ( format!( "todo: instruction {:?}" , * instruction) ) ,
381377 }
0 commit comments