14
14
15
15
from mypyc .irbuild .prepare import RegisterImplInfo
16
16
from typing import Callable , Dict , List , Tuple , Optional , Union , Sequence , Set , Any , Iterator
17
- from typing_extensions import overload
17
+ from typing_extensions import overload , Final
18
18
from mypy .backports import OrderedDict
19
19
20
20
from mypy .build import Graph
21
21
from mypy .nodes import (
22
22
MypyFile , SymbolNode , Statement , OpExpr , IntExpr , NameExpr , LDEF , Var , UnaryExpr ,
23
23
CallExpr , IndexExpr , Expression , MemberExpr , RefExpr , Lvalue , TupleExpr ,
24
- TypeInfo , Decorator , OverloadedFuncDef , StarExpr , ComparisonExpr , GDEF ,
25
- ArgKind , ARG_POS , ARG_NAMED , FuncDef ,
24
+ TypeInfo , Decorator , OverloadedFuncDef , StarExpr ,
25
+ GDEF , ArgKind , ARG_POS , ARG_NAMED , FuncDef ,
26
26
)
27
27
from mypy .types import (
28
28
Type , Instance , TupleType , UninhabitedType , get_proper_type
40
40
from mypyc .ir .rtypes import (
41
41
RType , RTuple , RInstance , c_int_rprimitive , int_rprimitive , dict_rprimitive ,
42
42
none_rprimitive , is_none_rprimitive , object_rprimitive , is_object_rprimitive ,
43
- str_rprimitive , is_tagged , is_list_rprimitive , is_tuple_rprimitive , c_pyssize_t_rprimitive
43
+ str_rprimitive , is_list_rprimitive , is_tuple_rprimitive , c_pyssize_t_rprimitive
44
44
)
45
45
from mypyc .ir .func_ir import FuncIR , INVALID_FUNC_DEF , RuntimeArg , FuncSignature , FuncDecl
46
46
from mypyc .ir .class_ir import ClassIR , NonExtClassInfo
67
67
from mypyc .irbuild .util import is_constant
68
68
69
69
70
+ # These int binary operations can borrow their operands safely, since the
71
+ # primitives take this into consideration.
72
+ int_borrow_friendly_op : Final = {'+' , '-' , '==' , '!=' , '<' , '<=' , '>' , '>=' }
73
+
74
+
70
75
class IRVisitor (ExpressionVisitor [Value ], StatementVisitor [None ]):
71
76
pass
72
77
@@ -287,7 +292,7 @@ def gen_method_call(self,
287
292
arg_kinds : Optional [List [ArgKind ]] = None ,
288
293
arg_names : Optional [List [Optional [str ]]] = None ) -> Value :
289
294
return self .builder .gen_method_call (
290
- base , name , arg_values , result_type , line , arg_kinds , arg_names
295
+ base , name , arg_values , result_type , line , arg_kinds , arg_names , self . can_borrow
291
296
)
292
297
293
298
def load_module (self , name : str ) -> Value :
@@ -515,7 +520,7 @@ def get_assignment_target(self, lvalue: Lvalue,
515
520
# Attribute assignment x.y = e
516
521
can_borrow = self .is_native_attr_ref (lvalue )
517
522
obj = self .accept (lvalue .expr , can_borrow = can_borrow )
518
- return AssignmentTargetAttr (obj , lvalue .name )
523
+ return AssignmentTargetAttr (obj , lvalue .name , can_borrow = can_borrow )
519
524
elif isinstance (lvalue , TupleExpr ):
520
525
# Multiple assignment a, ..., b = e
521
526
star_idx : Optional [int ] = None
@@ -535,7 +540,10 @@ def get_assignment_target(self, lvalue: Lvalue,
535
540
536
541
assert False , 'Unsupported lvalue: %r' % lvalue
537
542
538
- def read (self , target : Union [Value , AssignmentTarget ], line : int = - 1 ) -> Value :
543
+ def read (self ,
544
+ target : Union [Value , AssignmentTarget ],
545
+ line : int = - 1 ,
546
+ can_borrow : bool = False ) -> Value :
539
547
if isinstance (target , Value ):
540
548
return target
541
549
if isinstance (target , AssignmentTargetRegister ):
@@ -548,7 +556,8 @@ def read(self, target: Union[Value, AssignmentTarget], line: int = -1) -> Value:
548
556
assert False , target .base .type
549
557
if isinstance (target , AssignmentTargetAttr ):
550
558
if isinstance (target .obj .type , RInstance ) and target .obj .type .class_ir .is_ext_class :
551
- return self .add (GetAttr (target .obj , target .attr , line ))
559
+ borrow = can_borrow and target .can_borrow
560
+ return self .add (GetAttr (target .obj , target .attr , line , borrow = borrow ))
552
561
else :
553
562
return self .py_get_attr (target .obj , target .attr , line )
554
563
@@ -915,61 +924,6 @@ def shortcircuit_expr(self, expr: OpExpr) -> Value:
915
924
expr .line
916
925
)
917
926
918
- # Conditional expressions
919
-
920
- def process_conditional (self , e : Expression , true : BasicBlock , false : BasicBlock ) -> None :
921
- if isinstance (e , OpExpr ) and e .op in ['and' , 'or' ]:
922
- if e .op == 'and' :
923
- # Short circuit 'and' in a conditional context.
924
- new = BasicBlock ()
925
- self .process_conditional (e .left , new , false )
926
- self .activate_block (new )
927
- self .process_conditional (e .right , true , false )
928
- else :
929
- # Short circuit 'or' in a conditional context.
930
- new = BasicBlock ()
931
- self .process_conditional (e .left , true , new )
932
- self .activate_block (new )
933
- self .process_conditional (e .right , true , false )
934
- elif isinstance (e , UnaryExpr ) and e .op == 'not' :
935
- self .process_conditional (e .expr , false , true )
936
- else :
937
- res = self .maybe_process_conditional_comparison (e , true , false )
938
- if res :
939
- return
940
- # Catch-all for arbitrary expressions.
941
- reg = self .accept (e )
942
- self .add_bool_branch (reg , true , false )
943
-
944
- def maybe_process_conditional_comparison (self ,
945
- e : Expression ,
946
- true : BasicBlock ,
947
- false : BasicBlock ) -> bool :
948
- """Transform simple tagged integer comparisons in a conditional context.
949
-
950
- Return True if the operation is supported (and was transformed). Otherwise,
951
- do nothing and return False.
952
-
953
- Args:
954
- e: Arbitrary expression
955
- true: Branch target if comparison is true
956
- false: Branch target if comparison is false
957
- """
958
- if not isinstance (e , ComparisonExpr ) or len (e .operands ) != 2 :
959
- return False
960
- ltype = self .node_type (e .operands [0 ])
961
- rtype = self .node_type (e .operands [1 ])
962
- if not is_tagged (ltype ) or not is_tagged (rtype ):
963
- return False
964
- op = e .operators [0 ]
965
- if op not in ('==' , '!=' , '<' , '<=' , '>' , '>=' ):
966
- return False
967
- left = self .accept (e .operands [0 ])
968
- right = self .accept (e .operands [1 ])
969
- # "left op right" for two tagged integers
970
- self .builder .compare_tagged_condition (left , right , op , true , false , e .line )
971
- return True
972
-
973
927
# Basic helpers
974
928
975
929
def flatten_classes (self , arg : Union [RefExpr , TupleExpr ]) -> Optional [List [ClassIR ]]:
0 commit comments