@@ -1176,7 +1176,7 @@ def visit_method(self, cdef: ClassDef, fdef: FuncDef) -> None:
1176
1176
else :
1177
1177
self .handle_non_ext_method (cdef , fdef )
1178
1178
1179
- def is_approximately_constant (self , e : Expression ) -> bool :
1179
+ def is_constant (self , e : Expression ) -> bool :
1180
1180
"""Check whether we allow an expression to appear as a default value.
1181
1181
1182
1182
We don't currently properly support storing the evaluated
@@ -1189,7 +1189,7 @@ def is_approximately_constant(self, e: Expression) -> bool:
1189
1189
or (isinstance (e , UnaryExpr ) and e .op == '-'
1190
1190
and isinstance (e .expr , (IntExpr , FloatExpr )))
1191
1191
or (isinstance (e , TupleExpr )
1192
- and all (self .is_approximately_constant (e ) for e in e .items ))
1192
+ and all (self .is_constant (e ) for e in e .items ))
1193
1193
or (isinstance (e , RefExpr ) and e .kind == GDEF
1194
1194
and (e .fullname in ('builtins.True' , 'builtins.False' , 'builtins.None' )
1195
1195
or (isinstance (e .node , Var ) and e .node .is_final ))))
@@ -1228,7 +1228,7 @@ def generate_attr_defaults(self, cdef: ClassDef) -> None:
1228
1228
for stmt in default_assignments :
1229
1229
lvalue = stmt .lvalues [0 ]
1230
1230
assert isinstance (lvalue , NameExpr )
1231
- if not stmt .is_final_def and not self .is_approximately_constant (stmt .rvalue ):
1231
+ if not stmt .is_final_def and not self .is_constant (stmt .rvalue ):
1232
1232
self .warning ('Unsupported default attribute value' , stmt .rvalue .line )
1233
1233
1234
1234
# If the attribute is initialized to None and type isn't optional,
@@ -1693,20 +1693,61 @@ def create_ne_from_eq(self, cdef: ClassDef) -> None:
1693
1693
cls .methods ['__ne__' ] = f
1694
1694
self .functions .append (f )
1695
1695
1696
- def gen_arg_default (self ) -> None :
1696
+ def calculate_arg_defaults (self ,
1697
+ fn_info : FuncInfo ,
1698
+ env : Environment ,
1699
+ func_reg : Optional [Value ]) -> None :
1700
+ """Calculate default argument values and store them.
1701
+
1702
+ They are stored in statics for top level functions and in
1703
+ the function objects for nested functions (while constants are
1704
+ still stored computed on demand).
1705
+ """
1706
+ fitem = fn_info .fitem
1707
+ for arg in fitem .arguments :
1708
+ # Constant values don't get stored but just recomputed
1709
+ if arg .initializer and not self .is_constant (arg .initializer ):
1710
+ value = self .coerce (self .accept (arg .initializer ),
1711
+ env .lookup (arg .variable ).type , arg .line )
1712
+ if not fn_info .is_nested :
1713
+ name = fitem .fullname () + '.' + arg .variable .name ()
1714
+ self .add (InitStatic (value , name , 'final' ))
1715
+ else :
1716
+ assert func_reg is not None
1717
+ self .add (SetAttr (func_reg , arg .variable .name (), value , arg .line ))
1718
+
1719
+ def gen_arg_defaults (self ) -> None :
1697
1720
"""Generate blocks for arguments that have default values.
1698
1721
1699
- If the passed value is an error value, then assign the default value to the argument.
1722
+ If the passed value is an error value, then assign the default
1723
+ value to the argument.
1700
1724
"""
1701
1725
fitem = self .fn_info .fitem
1702
1726
for arg in fitem .arguments :
1703
1727
if arg .initializer :
1704
- if not self .is_approximately_constant (arg .initializer ):
1705
- self .warning ('Unsupported default argument value' , arg .initializer .line )
1706
1728
target = self .environment .lookup (arg .variable )
1729
+
1730
+ def get_default () -> Value :
1731
+ assert arg .initializer is not None
1732
+
1733
+ # If it is constant, don't bother storing it
1734
+ if self .is_constant (arg .initializer ):
1735
+ return self .accept (arg .initializer )
1736
+
1737
+ # Because gen_arg_defaults runs before calculate_arg_defaults, we
1738
+ # add the static/attribute to final_names/the class here.
1739
+ elif not self .fn_info .is_nested :
1740
+ name = fitem .fullname () + '.' + arg .variable .name ()
1741
+ self .final_names .append ((name , target .type ))
1742
+ return self .add (LoadStatic (target .type , name , 'final' ))
1743
+ else :
1744
+ name = arg .variable .name ()
1745
+ self .fn_info .callable_class .ir .attributes [name ] = target .type
1746
+ return self .add (
1747
+ GetAttr (self .fn_info .callable_class .self_reg , name , arg .line ))
1707
1748
assert isinstance (target , AssignmentTargetRegister )
1708
1749
self .assign_if_null (target ,
1709
- lambda : self . accept ( cast ( Expression , arg . initializer )) ,
1750
+ get_default ,
1710
1751
arg .initializer .line )
1711
1752
1712
1753
def gen_func_item (self ,
@@ -1793,7 +1834,7 @@ def c() -> None:
1793
1834
self .add_raise_exception_blocks_to_generator_class (fitem .line )
1794
1835
else :
1795
1836
self .load_env_registers ()
1796
- self .gen_arg_default ()
1837
+ self .gen_arg_defaults ()
1797
1838
1798
1839
if self .fn_info .contains_nested and not self .fn_info .is_generator :
1799
1840
self .finalize_env_class ()
@@ -1850,6 +1891,8 @@ def c() -> None:
1850
1891
else :
1851
1892
func_ir , func_reg = self .gen_func_ir (blocks , sig , env , fn_info , cdef )
1852
1893
1894
+ self .calculate_arg_defaults (fn_info , env , func_reg )
1895
+
1853
1896
return (func_ir , func_reg )
1854
1897
1855
1898
def gen_func_ir (self ,
@@ -3776,7 +3819,8 @@ def visit_lambda_expr(self, expr: LambdaExpr) -> Value:
3776
3819
runtime_args = []
3777
3820
for arg , arg_type in zip (expr .arguments , typ .arg_types ):
3778
3821
arg .variable .type = arg_type
3779
- runtime_args .append (RuntimeArg (arg .variable .name (), self .type_to_rtype (arg_type )))
3822
+ runtime_args .append (
3823
+ RuntimeArg (arg .variable .name (), self .type_to_rtype (arg_type ), arg .kind ))
3780
3824
ret_type = self .type_to_rtype (typ .ret_type )
3781
3825
3782
3826
fsig = FuncSignature (runtime_args , ret_type )
@@ -4857,7 +4901,7 @@ def instantiate_env_class(self) -> Value:
4857
4901
def gen_generator_func (self ) -> None :
4858
4902
self .setup_generator_class ()
4859
4903
self .load_env_registers ()
4860
- self .gen_arg_default ()
4904
+ self .gen_arg_defaults ()
4861
4905
self .finalize_env_class ()
4862
4906
self .add (Return (self .instantiate_generator_class ()))
4863
4907
0 commit comments