@@ -30,51 +30,84 @@ use crate::vm::VirtualMachine;
30
30
* When a name is looked up, it is check in its scope.
31
31
*/
32
32
#[ derive( Debug ) ]
33
- pub struct Locals {
34
- dict : PyObjectRef ,
35
- parent : Option < Rc < Locals > > ,
33
+ struct RcListNode < T > {
34
+ elem : T ,
35
+ next : Option < Rc < RcListNode < T > > > ,
36
+ }
37
+
38
+ #[ derive( Debug , Clone ) ]
39
+ struct RcList < T > {
40
+ head : Option < Rc < RcListNode < T > > > ,
41
+ }
42
+
43
+ struct Iter < ' a , T : ' a > {
44
+ next : Option < & ' a RcListNode < T > > ,
45
+ }
46
+
47
+ impl < T > RcList < T > {
48
+ pub fn new ( ) -> Self {
49
+ RcList { head : None }
50
+ }
51
+
52
+ pub fn insert ( self , elem : T ) -> Self {
53
+ RcList {
54
+ head : Some ( Rc :: new ( RcListNode {
55
+ elem,
56
+ next : self . head ,
57
+ } ) ) ,
58
+ }
59
+ }
60
+
61
+ pub fn iter ( & self ) -> Iter < T > {
62
+ Iter {
63
+ next : self . head . as_ref ( ) . map ( |node| & * * node) ,
64
+ }
65
+ }
66
+ }
67
+
68
+ impl < ' a , T > Iterator for Iter < ' a , T > {
69
+ type Item = & ' a T ;
70
+
71
+ fn next ( & mut self ) -> Option < Self :: Item > {
72
+ self . next . map ( |node| {
73
+ self . next = node. next . as_ref ( ) . map ( |node| & * * node) ;
74
+ & node. elem
75
+ } )
76
+ }
36
77
}
37
78
38
79
#[ derive( Debug , Clone ) ]
39
80
pub struct Scope {
40
- pub locals : Option < Rc < Locals > > , // Variables
81
+ locals : RcList < PyObjectRef > ,
41
82
pub globals : PyObjectRef ,
42
- // TODO: pub locals: RefCell<PyAttributes>, // Variables
43
- // pub parent: Option<Rc<Scope>>, // Parent scope
44
83
}
45
84
46
85
impl Scope {
47
86
pub fn new ( locals : Option < PyObjectRef > , globals : PyObjectRef ) -> Scope {
48
87
let locals = match locals {
49
- Some ( dict) => Some ( Rc :: new ( Locals {
50
- dict : dict,
51
- parent : None ,
52
- } ) ) ,
53
- None => None ,
88
+ Some ( dict) => RcList :: new ( ) . insert ( dict) ,
89
+ None => RcList :: new ( ) ,
54
90
} ;
55
91
Scope { locals, globals }
56
92
}
57
93
58
94
pub fn get_locals ( & self ) -> PyObjectRef {
59
- match self . locals {
60
- Some ( ref locals ) => locals . dict . clone ( ) ,
95
+ match self . locals . iter ( ) . next ( ) {
96
+ Some ( dict ) => dict. clone ( ) ,
61
97
None => self . globals . clone ( ) ,
62
98
}
63
99
}
64
100
65
101
pub fn get_only_locals ( & self ) -> Option < PyObjectRef > {
66
- match self . locals {
67
- Some ( ref locals ) => Some ( locals . dict . clone ( ) ) ,
102
+ match self . locals . iter ( ) . next ( ) {
103
+ Some ( dict ) => Some ( dict. clone ( ) ) ,
68
104
None => None ,
69
105
}
70
106
}
71
107
72
108
pub fn child_scope_with_locals ( & self , locals : PyObjectRef ) -> Scope {
73
109
Scope {
74
- locals : Some ( Rc :: new ( Locals {
75
- dict : locals,
76
- parent : self . locals . clone ( ) ,
77
- } ) ) ,
110
+ locals : self . locals . clone ( ) . insert ( locals) ,
78
111
globals : self . globals . clone ( ) ,
79
112
}
80
113
}
@@ -93,18 +126,9 @@ pub trait AttributeProtocol2 {
93
126
94
127
impl AttributeProtocol2 for Scope {
95
128
fn get_attr ( & self , vm : & VirtualMachine , name : & str ) -> Option < PyObjectRef > {
96
- // Lookup name in scope and put it onto the stack!
97
- let mut locals = self . locals . clone ( ) ;
98
- loop {
99
- match locals {
100
- Some ( new_locals) => {
101
- if let Some ( value) = new_locals. dict . get_item ( name) {
102
- return Some ( value) ;
103
- } else {
104
- locals = new_locals. parent . clone ( )
105
- }
106
- }
107
- None => break ,
129
+ for dict in self . locals . iter ( ) {
130
+ if let Some ( value) = dict. get_item ( name) {
131
+ return Some ( value) ;
108
132
}
109
133
}
110
134
0 commit comments