4242 Integer ,
4343 RaiseStandardError ,
4444 Register ,
45+ SetAttr ,
4546 Truncate ,
4647 Unreachable ,
4748 Value ,
9798 isinstance_dict ,
9899)
99100from mypyc .primitives .float_ops import isinstance_float
101+ from mypyc .primitives .generic_ops import generic_setattr
100102from mypyc .primitives .int_ops import isinstance_int
101103from mypyc .primitives .list_ops import isinstance_list , new_list_set_item_op
102104from mypyc .primitives .misc_ops import isinstance_bool
@@ -1007,19 +1009,28 @@ def translate_ord(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Value
10071009 return None
10081010
10091011
1010- @specialize_function ("__new__" , object_rprimitive )
1011- def translate_object_new (builder : IRBuilder , expr : CallExpr , callee : RefExpr ) -> Value | None :
1012- fn = builder .fn_info
1013- if fn .name != "__new__" :
1014- return None
1015-
1016- is_super_new = isinstance (expr .callee , SuperExpr )
1017- is_object_new = (
1012+ def is_object (callee : RefExpr ) -> bool :
1013+ """
1014+ Returns True for object.<name> calls
1015+ """
1016+ return (
10181017 isinstance (callee , MemberExpr )
10191018 and isinstance (callee .expr , NameExpr )
10201019 and callee .expr .fullname == "builtins.object"
10211020 )
1022- if not (is_super_new or is_object_new ):
1021+
1022+
1023+ def is_super_or_object (expr : CallExpr , callee : RefExpr ) -> bool :
1024+ """
1025+ Returns True for super().<name> or object.<name> calls.
1026+ """
1027+ return isinstance (expr .callee , SuperExpr ) or is_object (callee )
1028+
1029+
1030+ @specialize_function ("__new__" , object_rprimitive )
1031+ def translate_object_new (builder : IRBuilder , expr : CallExpr , callee : RefExpr ) -> Value | None :
1032+ fn = builder .fn_info
1033+ if fn .name != "__new__" or not is_super_or_object (expr , callee ):
10231034 return None
10241035
10251036 ir = builder .get_current_class_ir ()
@@ -1046,3 +1057,28 @@ def translate_object_new(builder: IRBuilder, expr: CallExpr, callee: RefExpr) ->
10461057 return builder .add (Call (ir .setup , [subtype ], expr .line ))
10471058
10481059 return None
1060+
1061+
1062+ @specialize_function ("__setattr__" , object_rprimitive )
1063+ def translate_object_setattr (builder : IRBuilder , expr : CallExpr , callee : RefExpr ) -> Value | None :
1064+ is_super = isinstance (expr .callee , SuperExpr )
1065+ is_object_callee = is_object (callee )
1066+ if not ((is_super and len (expr .args ) >= 2 ) or (is_object_callee and len (expr .args ) >= 3 )):
1067+ return None
1068+
1069+ self_reg = builder .accept (expr .args [0 ]) if is_object_callee else builder .self ()
1070+ ir = builder .get_current_class_ir ()
1071+ # Need to offset by 1 for super().__setattr__ calls because there is no self arg in this case.
1072+ name_idx = 0 if is_super else 1
1073+ value_idx = 1 if is_super else 2
1074+ attr_name = expr .args [name_idx ]
1075+ attr_value = expr .args [value_idx ]
1076+ value = builder .accept (attr_value )
1077+
1078+ if isinstance (attr_name , StrExpr ) and ir and ir .has_attr (attr_name .value ):
1079+ name = attr_name .value
1080+ value = builder .coerce (value , ir .attributes [name ], expr .line )
1081+ return builder .add (SetAttr (self_reg , name , value , expr .line ))
1082+
1083+ name_reg = builder .accept (attr_name )
1084+ return builder .call_c (generic_setattr , [self_reg , name_reg , value ], expr .line )
0 commit comments