@@ -11,12 +11,12 @@ use crate::{
11
11
coroutine:: Coro ,
12
12
exceptions:: ExceptionCtor ,
13
13
function:: { FuncArgs , IntoPyResult } ,
14
- protocol:: { PyIter , PyIterReturn } ,
14
+ protocol:: { PyIter , PyIterReturn , PyMapping } ,
15
15
scope:: Scope ,
16
16
stdlib:: builtins,
17
17
types:: PyComparisonOp ,
18
- IdProtocol , ItemProtocol , PyMethod , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject ,
19
- TypeProtocol , VirtualMachine ,
18
+ IdProtocol , ItemProtocol , PyMethod , PyObjectRef , PyObjectWrap , PyRef , PyResult , PyValue ,
19
+ TryFromObject , TypeProtocol , VirtualMachine ,
20
20
} ;
21
21
use indexmap:: IndexMap ;
22
22
use itertools:: Itertools ;
@@ -99,7 +99,7 @@ pub struct Frame {
99
99
100
100
pub fastlocals : PyMutex < Box < [ Option < PyObjectRef > ] > > ,
101
101
pub ( crate ) cells_frees : Box < [ PyCellRef ] > ,
102
- pub locals : PyObjectRef ,
102
+ pub locals : PyMapping ,
103
103
pub globals : PyDictRef ,
104
104
pub builtins : PyDictRef ,
105
105
@@ -179,7 +179,7 @@ impl FrameRef {
179
179
f ( exec)
180
180
}
181
181
182
- pub fn locals ( & self , vm : & VirtualMachine ) -> PyResult < PyObjectRef > {
182
+ pub fn locals ( & self , vm : & VirtualMachine ) -> PyResult < PyMapping > {
183
183
let locals = & self . locals ;
184
184
let code = & * * self . code ;
185
185
let map = & code. varnames ;
@@ -188,9 +188,16 @@ impl FrameRef {
188
188
let fastlocals = self . fastlocals . lock ( ) ;
189
189
for ( k, v) in itertools:: zip ( & map[ ..j] , & * * fastlocals) {
190
190
if let Some ( v) = v {
191
- locals. set_item ( k. clone ( ) , v. clone ( ) , vm) ?;
191
+ match locals. as_object ( ) . clone ( ) . downcast_exact :: < PyDict > ( vm) {
192
+ Ok ( d) => d. set_item ( k. clone ( ) , v. clone ( ) , vm) ?,
193
+ Err ( o) => o. set_item ( k. clone ( ) , v. clone ( ) , vm) ?,
194
+ } ;
192
195
} else {
193
- match locals. del_item ( k. clone ( ) , vm) {
196
+ let res = match locals. as_object ( ) . clone ( ) . downcast_exact :: < PyDict > ( vm) {
197
+ Ok ( d) => d. del_item ( k. clone ( ) , vm) ,
198
+ Err ( o) => o. del_item ( k. clone ( ) , vm) ,
199
+ } ;
200
+ match res {
194
201
Ok ( ( ) ) => { }
195
202
Err ( e) if e. isinstance ( & vm. ctx . exceptions . key_error ) => { }
196
203
Err ( e) => return Err ( e) ,
@@ -202,9 +209,16 @@ impl FrameRef {
202
209
let map_to_dict = |keys : & [ PyStrRef ] , values : & [ PyCellRef ] | {
203
210
for ( k, v) in itertools:: zip ( keys, values) {
204
211
if let Some ( v) = v. get ( ) {
205
- locals. set_item ( k. clone ( ) , v, vm) ?;
212
+ match locals. into_object ( ) . downcast_exact :: < PyDict > ( vm) {
213
+ Ok ( d) => d. set_item ( k. clone ( ) , v, vm) ?,
214
+ Err ( o) => o. set_item ( k. clone ( ) , v, vm) ?,
215
+ } ;
206
216
} else {
207
- match locals. del_item ( k. clone ( ) , vm) {
217
+ let res = match locals. as_object ( ) . clone ( ) . downcast_exact :: < PyDict > ( vm) {
218
+ Ok ( d) => d. del_item ( k. clone ( ) , vm) ,
219
+ Err ( o) => o. del_item ( k. clone ( ) , vm) ,
220
+ } ;
221
+ match res {
208
222
Ok ( ( ) ) => { }
209
223
Err ( e) if e. isinstance ( & vm. ctx . exceptions . key_error ) => { }
210
224
Err ( e) => return Err ( e) ,
@@ -275,7 +289,7 @@ struct ExecutingFrame<'a> {
275
289
code : & ' a PyRef < PyCode > ,
276
290
fastlocals : & ' a PyMutex < Box < [ Option < PyObjectRef > ] > > ,
277
291
cells_frees : & ' a [ PyCellRef ] ,
278
- locals : & ' a PyObjectRef ,
292
+ locals : & ' a PyMapping ,
279
293
globals : & ' a PyDictRef ,
280
294
builtins : & ' a PyDictRef ,
281
295
object : & ' a FrameRef ,
@@ -497,7 +511,12 @@ impl ExecutingFrame<'_> {
497
511
bytecode:: Instruction :: LoadNameAny ( idx) => {
498
512
let name = & self . code . names [ * idx as usize ] ;
499
513
// Try using locals as dict first, if not, fallback to generic method.
500
- let x = match self . locals . clone ( ) . downcast_exact :: < PyDict > ( vm) {
514
+ let x = match self
515
+ . locals
516
+ . clone ( )
517
+ . into_object ( )
518
+ . downcast_exact :: < PyDict > ( vm)
519
+ {
501
520
Ok ( d) => d. get_item_option ( name. clone ( ) , vm) ?,
502
521
Err ( o) => o. get_item ( name. clone ( ) , vm) . ok ( ) ,
503
522
} ;
@@ -525,7 +544,12 @@ impl ExecutingFrame<'_> {
525
544
let i = * i as usize ;
526
545
let name = self . code . freevars [ i - self . code . cellvars . len ( ) ] . clone ( ) ;
527
546
// Try using locals as dict first, if not, fallback to generic method.
528
- let value = match self . locals . clone ( ) . downcast_exact :: < PyDict > ( vm) {
547
+ let value = match self
548
+ . locals
549
+ . clone ( )
550
+ . into_object ( )
551
+ . downcast_exact :: < PyDict > ( vm)
552
+ {
529
553
Ok ( d) => d. get_item_option ( name, vm) ?,
530
554
Err ( o) => o. get_item ( name, vm) . ok ( ) ,
531
555
} ;
@@ -544,8 +568,15 @@ impl ExecutingFrame<'_> {
544
568
}
545
569
bytecode:: Instruction :: StoreLocal ( idx) => {
546
570
let value = self . pop_value ( ) ;
547
- self . locals
548
- . set_item ( self . code . names [ * idx as usize ] . clone ( ) , value, vm) ?;
571
+ match self
572
+ . locals
573
+ . clone ( )
574
+ . into_object ( )
575
+ . downcast_exact :: < PyDict > ( vm)
576
+ {
577
+ Ok ( d) => d. set_item ( self . code . names [ * idx as usize ] . clone ( ) , value, vm) ?,
578
+ Err ( o) => o. set_item ( self . code . names [ * idx as usize ] . clone ( ) , value, vm) ?,
579
+ } ;
549
580
Ok ( None )
550
581
}
551
582
bytecode:: Instruction :: StoreGlobal ( idx) => {
@@ -565,7 +596,17 @@ impl ExecutingFrame<'_> {
565
596
}
566
597
bytecode:: Instruction :: DeleteLocal ( idx) => {
567
598
let name = & self . code . names [ * idx as usize ] ;
568
- match self . locals . del_item ( name. clone ( ) , vm) {
599
+ let res = match self
600
+ . locals
601
+ . clone ( )
602
+ . into_object ( )
603
+ . downcast_exact :: < PyDict > ( vm)
604
+ {
605
+ Ok ( d) => d. del_item ( name. clone ( ) , vm) ,
606
+ Err ( o) => o. del_item ( name. clone ( ) , vm) ,
607
+ } ;
608
+
609
+ match res {
569
610
Ok ( ( ) ) => { }
570
611
Err ( e) if e. isinstance ( & vm. ctx . exceptions . key_error ) => {
571
612
return Err ( vm. new_name_error ( format ! ( "name '{}' is not defined" , name) ) )
@@ -724,16 +765,24 @@ impl ExecutingFrame<'_> {
724
765
bytecode:: Instruction :: YieldFrom => self . execute_yield_from ( vm) ,
725
766
bytecode:: Instruction :: SetupAnnotation => {
726
767
// Try using locals as dict first, if not, fallback to generic method.
727
- let has_annotations = match self . locals . clone ( ) . downcast_exact :: < PyDict > ( vm) {
768
+ let has_annotations = match self
769
+ . locals
770
+ . clone ( )
771
+ . into_object ( )
772
+ . downcast_exact :: < PyDict > ( vm)
773
+ {
728
774
Ok ( d) => d. contains_key ( "__annotations__" , vm) ,
729
775
Err ( o) => {
730
776
let needle = vm. new_pyobj ( "__annotations__" ) ;
731
777
self . _in ( vm, needle, o) ?
732
778
}
733
779
} ;
734
780
if !has_annotations {
735
- self . locals
736
- . set_item ( "__annotations__" , vm. ctx . new_dict ( ) . into ( ) , vm) ?;
781
+ self . locals . as_object ( ) . set_item (
782
+ "__annotations__" ,
783
+ vm. ctx . new_dict ( ) . into ( ) ,
784
+ vm,
785
+ ) ?;
737
786
}
738
787
Ok ( None )
739
788
}
@@ -1146,7 +1195,15 @@ impl ExecutingFrame<'_> {
1146
1195
for ( k, v) in & dict {
1147
1196
let k = PyStrRef :: try_from_object ( vm, k) ?;
1148
1197
if filter_pred ( k. as_str ( ) ) {
1149
- self . locals . set_item ( k, v, vm) ?;
1198
+ match self
1199
+ . locals
1200
+ . clone ( )
1201
+ . into_object ( )
1202
+ . downcast_exact :: < PyDict > ( vm)
1203
+ {
1204
+ Ok ( d) => d. set_item ( k, v, vm) ?,
1205
+ Err ( o) => o. set_item ( k, v, vm) ?,
1206
+ } ;
1150
1207
}
1151
1208
}
1152
1209
}
0 commit comments