@@ -18,7 +18,13 @@ def g() -> int:
1818from __future__ import annotations
1919
2020from 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+ )
2228from mypyc .ir .class_ir import ClassIR
2329from mypyc .ir .ops import Call , GetAttr , SetAttr , Value
2430from mypyc .ir .rtypes import RInstance , bitmap_rprimitive , object_rprimitive
@@ -60,7 +66,7 @@ class is generated, the function environment has not yet been
6066 return env_class
6167
6268
63- def finalize_env_class (builder : IRBuilder ) -> None :
69+ def finalize_env_class (builder : IRBuilder , prefix : str = "" ) -> None :
6470 """Generate, instantiate, and set up the environment of an environment class."""
6571 if not builder .fn_info .can_merge_generator_and_env_classes ():
6672 instantiate_env_class (builder )
@@ -69,9 +75,9 @@ def finalize_env_class(builder: IRBuilder) -> None:
6975 # that were previously added to the environment with references to the function's
7076 # environment class.
7177 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 )
7379 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 )
7581
7682
7783def instantiate_env_class (builder : IRBuilder ) -> Value :
@@ -96,15 +102,15 @@ def instantiate_env_class(builder: IRBuilder) -> Value:
96102 return curr_env_reg
97103
98104
99- def load_env_registers (builder : IRBuilder ) -> None :
105+ def load_env_registers (builder : IRBuilder , prefix : str = "" ) -> None :
100106 """Load the registers for the current FuncItem being visited.
101107
102108 Adds the arguments of the FuncItem to the environment. If the
103109 FuncItem is nested inside of another function, then this also
104110 loads all of the outer environments of the FuncItem into registers
105111 so that they can be used when accessing free variables.
106112 """
107- add_args_to_env (builder , local = True )
113+ add_args_to_env (builder , local = True , prefix = prefix )
108114
109115 fn_info = builder .fn_info
110116 fitem = fn_info .fitem
@@ -113,7 +119,7 @@ def load_env_registers(builder: IRBuilder) -> None:
113119 # If this is a FuncDef, then make sure to load the FuncDef into its own environment
114120 # class so that the function can be called recursively.
115121 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 )
117123
118124
119125def load_outer_env (
@@ -134,8 +140,11 @@ def load_outer_env(
134140 assert isinstance (env .type , RInstance ), f"{ env } must be of type RInstance"
135141
136142 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 )
139148 builder .add_target (symbol , symbol_target )
140149
141150 return env
@@ -178,6 +187,7 @@ def add_args_to_env(
178187 local : bool = True ,
179188 base : FuncInfo | ImplicitClass | None = None ,
180189 reassign : bool = True ,
190+ prefix : str = "" ,
181191) -> None :
182192 fn_info = builder .fn_info
183193 args = fn_info .fitem .arguments
@@ -193,10 +203,12 @@ def add_args_to_env(
193203 if is_free_variable (builder , arg .variable ) or fn_info .is_generator :
194204 rtype = builder .type_to_rtype (arg .variable .type )
195205 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+ )
197209
198210
199- def add_vars_to_env (builder : IRBuilder ) -> None :
211+ def add_vars_to_env (builder : IRBuilder , prefix : str = "" ) -> None :
200212 """Add relevant local variables and nested functions to the environment class.
201213
202214 Add all variables and functions that are declared/defined within current
@@ -216,7 +228,9 @@ def add_vars_to_env(builder: IRBuilder) -> None:
216228 for var in sorted (builder .free_variables [builder .fn_info .fitem ], key = lambda x : x .name ):
217229 if isinstance (var , Var ):
218230 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+ )
220234
221235 if builder .fn_info .fitem in builder .encapsulating_funcs :
222236 for nested_fn in builder .encapsulating_funcs [builder .fn_info .fitem ]:
@@ -226,12 +240,16 @@ def add_vars_to_env(builder: IRBuilder) -> None:
226240 # the same name and signature across conditional blocks
227241 # will generate different callable classes, so the callable
228242 # class that gets instantiated must be generic.
243+ if nested_fn .is_generator :
244+ prefix = GENERATOR_ATTRIBUTE_PREFIX
229245 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
231247 )
232248
233249
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 :
235253 """Enable calling a nested function (with a callable class) recursively.
236254
237255 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
241259 """
242260 # First, set the attribute of the environment class so that GetAttr can be called on it.
243261 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 )
245264
246265 if isinstance (base , GeneratorClass ):
247266 # 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
253272
254273 # Obtain the instance of the callable class representing the FuncDef, and add it to the
255274 # current environment.
256- val = builder .add (GetAttr (prev_env_reg , fdef . name , - 1 ))
275+ val = builder .add (GetAttr (prev_env_reg , attr_name , - 1 ))
257276 target = builder .add_local_reg (fdef , object_rprimitive )
258277 builder .assign (target , val , - 1 )
259278
0 commit comments