15
15
BindableExpression = Union [IndexExpr , MemberExpr , NameExpr ]
16
16
17
17
18
- class Frame (Dict [Optional [ Key ] , Type ]):
18
+ class Frame (Dict [Key , Type ]):
19
19
"""A Frame represents a specific point in the execution of a program.
20
20
It carries information about the current types of expressions at
21
21
that point, arising either from assignments to those expressions
@@ -31,7 +31,7 @@ def __init__(self) -> None:
31
31
self .unreachable = False
32
32
33
33
34
- class DeclarationsFrame (Dict [Optional [ Key ] , Optional [Type ]]):
34
+ class DeclarationsFrame (Dict [Key , Optional [Type ]]):
35
35
"""Same as above, but allowed to have None values."""
36
36
37
37
def __init__ (self ) -> None :
@@ -80,7 +80,7 @@ def __init__(self) -> None:
80
80
self .declarations = DeclarationsFrame ()
81
81
# Set of other keys to invalidate if a key is changed, e.g. x -> {x.a, x[0]}
82
82
# Whenever a new key (e.g. x.a.b) is added, we update this
83
- self .dependencies = {} # type: Dict[Optional[ Key] , Set[Key]]
83
+ self .dependencies = {} # type: Dict[Key, Set[Key]]
84
84
85
85
# Whether the last pop changed the newly top frame on exit
86
86
self .last_pop_changed = False
@@ -105,10 +105,10 @@ def push_frame(self) -> Frame:
105
105
self .options_on_return .append ([])
106
106
return f
107
107
108
- def _put (self , key : Optional [ Key ] , type : Type , index : int = - 1 ) -> None :
108
+ def _put (self , key : Key , type : Type , index : int = - 1 ) -> None :
109
109
self .frames [index ][key ] = type
110
110
111
- def _get (self , key : Optional [ Key ] , index : int = - 1 ) -> Optional [Type ]:
111
+ def _get (self , key : Key , index : int = - 1 ) -> Optional [Type ]:
112
112
if index < 0 :
113
113
index += len (self .frames )
114
114
for i in range (index , - 1 , - 1 ):
@@ -122,17 +122,18 @@ def put(self, expr: Expression, typ: Type) -> None:
122
122
if not expr .literal :
123
123
return
124
124
key = expr .literal_hash
125
+ assert key is not None
125
126
if key not in self .declarations :
126
127
assert isinstance (expr , BindableTypes )
127
128
self .declarations [key ] = get_declaration (expr )
128
- if key is not None :
129
- self ._add_dependencies (key )
129
+ self ._add_dependencies (key )
130
130
self ._put (key , typ )
131
131
132
132
def unreachable (self ) -> None :
133
133
self .frames [- 1 ].unreachable = True
134
134
135
135
def get (self , expr : Expression ) -> Optional [Type ]:
136
+ assert expr .literal_hash is not None
136
137
return self ._get (expr .literal_hash )
137
138
138
139
def is_unreachable (self ) -> bool :
@@ -142,9 +143,10 @@ def is_unreachable(self) -> bool:
142
143
143
144
def cleanse (self , expr : Expression ) -> None :
144
145
"""Remove all references to a Node from the binder."""
146
+ assert expr .literal_hash is not None
145
147
self ._cleanse_key (expr .literal_hash )
146
148
147
- def _cleanse_key (self , key : Optional [ Key ] ) -> None :
149
+ def _cleanse_key (self , key : Key ) -> None :
148
150
"""Remove all references to a key from the binder."""
149
151
for frame in self .frames :
150
152
if key in frame :
@@ -259,13 +261,15 @@ def invalidate_dependencies(self, expr: BindableExpression) -> None:
259
261
It is overly conservative: it invalidates globally, including
260
262
in code paths unreachable from here.
261
263
"""
264
+ assert expr .literal_hash is not None
262
265
for dep in self .dependencies .get (expr .literal_hash , set ()):
263
266
self ._cleanse_key (dep )
264
267
265
268
def most_recent_enclosing_type (self , expr : BindableExpression , type : Type ) -> Optional [Type ]:
266
269
if isinstance (type , AnyType ):
267
270
return get_declaration (expr )
268
271
key = expr .literal_hash
272
+ assert key is not None
269
273
enclosers = ([get_declaration (expr )] +
270
274
[f [key ] for f in self .frames
271
275
if key in f and is_subtype (type , f [key ])])
0 commit comments