@@ -18,7 +18,13 @@ def g() -> int:
18
18
from __future__ import annotations
19
19
20
20
from mypy .nodes import Argument , FuncDef , SymbolNode , Var
21
- from mypyc .common import BITMAP_BITS , ENV_ATTR_NAME , SELF_NAME , bitmap_name
21
+ from mypyc .common import (
22
+ BITMAP_BITS ,
23
+ ENV_ATTR_NAME ,
24
+ GENERATOR_ATTRIBUTE_PREFIX ,
25
+ SELF_NAME ,
26
+ bitmap_name ,
27
+ )
22
28
from mypyc .ir .class_ir import ClassIR
23
29
from mypyc .ir .ops import Call , GetAttr , SetAttr , Value
24
30
from mypyc .ir .rtypes import RInstance , bitmap_rprimitive , object_rprimitive
@@ -60,7 +66,7 @@ class is generated, the function environment has not yet been
60
66
return env_class
61
67
62
68
63
- def finalize_env_class (builder : IRBuilder ) -> None :
69
+ def finalize_env_class (builder : IRBuilder , prefix : str = "" ) -> None :
64
70
"""Generate, instantiate, and set up the environment of an environment class."""
65
71
if not builder .fn_info .can_merge_generator_and_env_classes ():
66
72
instantiate_env_class (builder )
@@ -69,9 +75,9 @@ def finalize_env_class(builder: IRBuilder) -> None:
69
75
# that were previously added to the environment with references to the function's
70
76
# environment class.
71
77
if builder .fn_info .is_nested :
72
- add_args_to_env (builder , local = False , base = builder .fn_info .callable_class )
78
+ add_args_to_env (builder , local = False , base = builder .fn_info .callable_class , prefix = prefix )
73
79
else :
74
- add_args_to_env (builder , local = False , base = builder .fn_info )
80
+ add_args_to_env (builder , local = False , base = builder .fn_info , prefix = prefix )
75
81
76
82
77
83
def instantiate_env_class (builder : IRBuilder ) -> Value :
@@ -96,15 +102,15 @@ def instantiate_env_class(builder: IRBuilder) -> Value:
96
102
return curr_env_reg
97
103
98
104
99
- def load_env_registers (builder : IRBuilder ) -> None :
105
+ def load_env_registers (builder : IRBuilder , prefix : str = "" ) -> None :
100
106
"""Load the registers for the current FuncItem being visited.
101
107
102
108
Adds the arguments of the FuncItem to the environment. If the
103
109
FuncItem is nested inside of another function, then this also
104
110
loads all of the outer environments of the FuncItem into registers
105
111
so that they can be used when accessing free variables.
106
112
"""
107
- add_args_to_env (builder , local = True )
113
+ add_args_to_env (builder , local = True , prefix = prefix )
108
114
109
115
fn_info = builder .fn_info
110
116
fitem = fn_info .fitem
@@ -113,7 +119,7 @@ def load_env_registers(builder: IRBuilder) -> None:
113
119
# If this is a FuncDef, then make sure to load the FuncDef into its own environment
114
120
# class so that the function can be called recursively.
115
121
if isinstance (fitem , FuncDef ) and fn_info .add_nested_funcs_to_env :
116
- setup_func_for_recursive_call (builder , fitem , fn_info .callable_class )
122
+ setup_func_for_recursive_call (builder , fitem , fn_info .callable_class , prefix = prefix )
117
123
118
124
119
125
def load_outer_env (
@@ -134,8 +140,11 @@ def load_outer_env(
134
140
assert isinstance (env .type , RInstance ), f"{ env } must be of type RInstance"
135
141
136
142
for symbol , target in outer_env .items ():
137
- env .type .class_ir .attributes [symbol .name ] = target .type
138
- symbol_target = AssignmentTargetAttr (env , symbol .name )
143
+ attr_name = symbol .name
144
+ if isinstance (target , AssignmentTargetAttr ):
145
+ attr_name = target .attr
146
+ env .type .class_ir .attributes [attr_name ] = target .type
147
+ symbol_target = AssignmentTargetAttr (env , attr_name )
139
148
builder .add_target (symbol , symbol_target )
140
149
141
150
return env
@@ -178,6 +187,7 @@ def add_args_to_env(
178
187
local : bool = True ,
179
188
base : FuncInfo | ImplicitClass | None = None ,
180
189
reassign : bool = True ,
190
+ prefix : str = "" ,
181
191
) -> None :
182
192
fn_info = builder .fn_info
183
193
args = fn_info .fitem .arguments
@@ -193,10 +203,12 @@ def add_args_to_env(
193
203
if is_free_variable (builder , arg .variable ) or fn_info .is_generator :
194
204
rtype = builder .type_to_rtype (arg .variable .type )
195
205
assert base is not None , "base cannot be None for adding nonlocal args"
196
- builder .add_var_to_env_class (arg .variable , rtype , base , reassign = reassign )
206
+ builder .add_var_to_env_class (
207
+ arg .variable , rtype , base , reassign = reassign , prefix = prefix
208
+ )
197
209
198
210
199
- def add_vars_to_env (builder : IRBuilder ) -> None :
211
+ def add_vars_to_env (builder : IRBuilder , prefix : str = "" ) -> None :
200
212
"""Add relevant local variables and nested functions to the environment class.
201
213
202
214
Add all variables and functions that are declared/defined within current
@@ -216,7 +228,9 @@ def add_vars_to_env(builder: IRBuilder) -> None:
216
228
for var in sorted (builder .free_variables [builder .fn_info .fitem ], key = lambda x : x .name ):
217
229
if isinstance (var , Var ):
218
230
rtype = builder .type_to_rtype (var .type )
219
- builder .add_var_to_env_class (var , rtype , env_for_func , reassign = False )
231
+ builder .add_var_to_env_class (
232
+ var , rtype , env_for_func , reassign = False , prefix = prefix
233
+ )
220
234
221
235
if builder .fn_info .fitem in builder .encapsulating_funcs :
222
236
for nested_fn in builder .encapsulating_funcs [builder .fn_info .fitem ]:
@@ -226,12 +240,16 @@ def add_vars_to_env(builder: IRBuilder) -> None:
226
240
# the same name and signature across conditional blocks
227
241
# will generate different callable classes, so the callable
228
242
# class that gets instantiated must be generic.
243
+ if nested_fn .is_generator :
244
+ prefix = GENERATOR_ATTRIBUTE_PREFIX
229
245
builder .add_var_to_env_class (
230
- nested_fn , object_rprimitive , env_for_func , reassign = False
246
+ nested_fn , object_rprimitive , env_for_func , reassign = False , prefix = prefix
231
247
)
232
248
233
249
234
- def setup_func_for_recursive_call (builder : IRBuilder , fdef : FuncDef , base : ImplicitClass ) -> None :
250
+ def setup_func_for_recursive_call (
251
+ builder : IRBuilder , fdef : FuncDef , base : ImplicitClass , prefix : str = ""
252
+ ) -> None :
235
253
"""Enable calling a nested function (with a callable class) recursively.
236
254
237
255
Adds the instance of the callable class representing the given
@@ -241,7 +259,8 @@ def setup_func_for_recursive_call(builder: IRBuilder, fdef: FuncDef, base: Impli
241
259
"""
242
260
# First, set the attribute of the environment class so that GetAttr can be called on it.
243
261
prev_env = builder .fn_infos [- 2 ].env_class
244
- prev_env .attributes [fdef .name ] = builder .type_to_rtype (fdef .type )
262
+ attr_name = prefix + fdef .name
263
+ prev_env .attributes [attr_name ] = builder .type_to_rtype (fdef .type )
245
264
246
265
if isinstance (base , GeneratorClass ):
247
266
# If we are dealing with a generator class, then we need to first get the register
@@ -253,7 +272,7 @@ def setup_func_for_recursive_call(builder: IRBuilder, fdef: FuncDef, base: Impli
253
272
254
273
# Obtain the instance of the callable class representing the FuncDef, and add it to the
255
274
# current environment.
256
- val = builder .add (GetAttr (prev_env_reg , fdef . name , - 1 ))
275
+ val = builder .add (GetAttr (prev_env_reg , attr_name , - 1 ))
257
276
target = builder .add_local_reg (fdef , object_rprimitive )
258
277
builder .assign (target , val , - 1 )
259
278
0 commit comments