45
45
import com .oracle .graal .python .nodes .PNodeWithContext ;
46
46
import com .oracle .graal .python .nodes .attributes .LookupInheritedAttributeNode ;
47
47
import com .oracle .graal .python .nodes .call .special .CallBinaryMethodNode ;
48
+ import com .oracle .graal .python .nodes .call .special .CallTernaryMethodNode ;
48
49
import com .oracle .graal .python .nodes .call .special .LookupAndCallBinaryNode ;
50
+ import com .oracle .graal .python .nodes .call .special .LookupAndCallTernaryNode ;
51
+ import com .oracle .graal .python .nodes .literal .ObjectLiteralNode ;
49
52
import com .oracle .graal .python .util .Supplier ;
50
53
import com .oracle .truffle .api .CompilerDirectives ;
51
54
import com .oracle .truffle .api .dsl .Cached ;
55
58
56
59
@ NodeChild ("arg" )
57
60
@ NodeChild ("arg2" )
61
+ @ NodeChild ("arg3" )
58
62
public abstract class LookupAndCallInplaceNode extends ExpressionNode {
59
63
60
64
public abstract static class NotImplementedHandler extends PNodeWithContext {
@@ -66,7 +70,10 @@ public abstract static class NotImplementedHandler extends PNodeWithContext {
66
70
protected final String reverseBinaryOpName ;
67
71
protected final Supplier <NotImplementedHandler > handlerFactory ;
68
72
69
- @ Child private CallBinaryMethodNode dispatchNode ;
73
+ @ Child private CallBinaryMethodNode callBinaryMethodNode ;
74
+ @ Child private CallTernaryMethodNode callTernaryMethodNode ;
75
+ @ Child private LookupAndCallBinaryNode lookupAndCallBinaryNode ;
76
+ @ Child private LookupAndCallTernaryNode lookupAndCallTernaryNode ;
70
77
@ Child private NotImplementedHandler handler ;
71
78
72
79
LookupAndCallInplaceNode (String inplaceOpName , String binaryOpName , String reverseBinaryOpName , Supplier <NotImplementedHandler > handlerFactory ) {
@@ -76,45 +83,82 @@ public abstract static class NotImplementedHandler extends PNodeWithContext {
76
83
this .handlerFactory = handlerFactory ;
77
84
}
78
85
79
- public static LookupAndCallInplaceNode create (String inplaceOpName ) {
80
- return LookupAndCallInplaceNodeGen .create (inplaceOpName , null , null , null , null , null );
86
+ public static LookupAndCallInplaceNode createWithBinary (String inplaceOpName , ExpressionNode left , ExpressionNode right , Supplier <LookupAndCallInplaceNode .NotImplementedHandler > handlerFactory ) {
87
+ String binaryOpName = inplaceOpName .replaceFirst ("__i" , "__" );
88
+ String reverseBinaryOpName = inplaceOpName .replaceFirst ("__i" , "__r" );
89
+ return LookupAndCallInplaceNodeGen .create (inplaceOpName , binaryOpName , reverseBinaryOpName , handlerFactory , left , right , new ObjectLiteralNode (PNone .NO_VALUE ));
81
90
}
82
91
83
- public static LookupAndCallInplaceNode createWithBinary (String inplaceOpName , ExpressionNode left , ExpressionNode right , Supplier <LookupAndCallInplaceNode .NotImplementedHandler > handlerFactory ) {
84
- return LookupAndCallInplaceNodeGen .create (inplaceOpName , inplaceOpName .replaceFirst ("__i" , "__" ), inplaceOpName .replaceFirst ("__i" , "__r" ), handlerFactory , left , right );
92
+ public static LookupAndCallInplaceNode createWithTernary (String inplaceOpName , ExpressionNode x , ExpressionNode y , ExpressionNode z ,
93
+ Supplier <LookupAndCallInplaceNode .NotImplementedHandler > handlerFactory ) {
94
+ String binaryOpName = inplaceOpName .replaceFirst ("__i" , "__" );
95
+ String reverseBinaryOpName = inplaceOpName .replaceFirst ("__i" , "__r" );
96
+ return LookupAndCallInplaceNodeGen .create (inplaceOpName , binaryOpName , reverseBinaryOpName , handlerFactory , x , y , z );
85
97
}
86
98
87
99
public static LookupAndCallInplaceNode create (String inplaceOpName , String binaryOpName ) {
88
- return LookupAndCallInplaceNodeGen .create (inplaceOpName , binaryOpName , null , null , null , null );
100
+ return LookupAndCallInplaceNodeGen .create (inplaceOpName , binaryOpName , null , null , null , null , null );
89
101
}
90
102
91
103
public static LookupAndCallInplaceNode create (String inplaceOpName , String binaryOpName , String reverseBinaryOpName , Supplier <NotImplementedHandler > handlerFactory ) {
92
- return LookupAndCallInplaceNodeGen .create (inplaceOpName , binaryOpName , reverseBinaryOpName , handlerFactory , null , null );
104
+ return LookupAndCallInplaceNodeGen .create (inplaceOpName , binaryOpName , reverseBinaryOpName , handlerFactory , null , null , null );
105
+ }
106
+
107
+ private CallBinaryMethodNode ensureBinaryCallNode () {
108
+ if (callBinaryMethodNode == null ) {
109
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
110
+ callBinaryMethodNode = insert (CallBinaryMethodNode .create ());
111
+ }
112
+ return callBinaryMethodNode ;
113
+ }
114
+
115
+ private CallTernaryMethodNode ensureTernaryCallNode () {
116
+ if (callTernaryMethodNode == null ) {
117
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
118
+ callTernaryMethodNode = insert (CallTernaryMethodNode .create ());
119
+ }
120
+ return callTernaryMethodNode ;
121
+ }
122
+
123
+ private LookupAndCallBinaryNode ensureLookupAndCallBinaryNode () {
124
+ if (lookupAndCallBinaryNode == null ) {
125
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
126
+ lookupAndCallBinaryNode = insert (LookupAndCallBinaryNode .create (binaryOpName , reverseBinaryOpName ));
127
+ }
128
+ return lookupAndCallBinaryNode ;
93
129
}
94
130
95
- private CallBinaryMethodNode ensureDispatch () {
96
- if (dispatchNode == null ) {
131
+ private LookupAndCallTernaryNode ensureLookupAndCallTernaryNode () {
132
+ if (lookupAndCallTernaryNode == null ) {
97
133
CompilerDirectives .transferToInterpreterAndInvalidate ();
98
- dispatchNode = insert (CallBinaryMethodNode . create ( ));
134
+ lookupAndCallTernaryNode = insert (LookupAndCallTernaryNode . createReversible ( binaryOpName , null ));
99
135
}
100
- return dispatchNode ;
136
+ return lookupAndCallTernaryNode ;
101
137
}
102
138
103
- protected boolean hasBinaryVersion () {
139
+ protected boolean hasNonInplaceOperator () {
104
140
return binaryOpName != null ;
105
141
}
106
142
107
- public abstract Object execute (VirtualFrame frame , Object left , Object right );
143
+ public final Object execute (VirtualFrame frame , Object left , Object right ) {
144
+ return executeTernary (frame , left , right , PNone .NO_VALUE );
145
+ }
146
+
147
+ public abstract Object executeTernary (VirtualFrame frame , Object x , Object y , Object z );
108
148
109
- @ Specialization (guards = "!hasBinaryVersion ()" )
110
- Object callObject (VirtualFrame frame , Object left , Object right ,
149
+ @ Specialization (guards = "!hasNonInplaceOperator ()" )
150
+ Object doInplaceOnly (VirtualFrame frame , Object left , Object right , Object z ,
111
151
@ Cached ("create(inplaceOpName)" ) LookupInheritedAttributeNode getattr ) {
112
152
Object leftCallable = getattr .execute (left );
113
153
Object result ;
114
154
if (leftCallable == PNone .NO_VALUE ) {
115
155
result = PNotImplemented .NOT_IMPLEMENTED ;
116
156
} else {
117
- result = ensureDispatch ().executeObject (frame , leftCallable , left , right );
157
+ if (z == PNone .NO_VALUE ) {
158
+ result = ensureBinaryCallNode ().executeObject (frame , leftCallable , left , right );
159
+ } else {
160
+ result = ensureTernaryCallNode ().execute (frame , leftCallable , left , right , z );
161
+ }
118
162
}
119
163
if (handlerFactory != null && result == PNotImplemented .NOT_IMPLEMENTED ) {
120
164
if (handler == null ) {
@@ -126,25 +170,35 @@ Object callObject(VirtualFrame frame, Object left, Object right,
126
170
return result ;
127
171
}
128
172
129
- @ Specialization (guards = "hasBinaryVersion()" )
130
- Object callObject (VirtualFrame frame , Object left , Object right ,
131
- @ Cached ("create(inplaceOpName)" ) LookupInheritedAttributeNode getattrInplace ,
132
- @ Cached ("create(binaryOpName, reverseBinaryOpName)" ) LookupAndCallBinaryNode binaryNode ) {
173
+ @ Specialization (guards = "hasNonInplaceOperator()" )
174
+ Object doBinary (VirtualFrame frame , Object left , Object right , Object z ,
175
+ @ Cached ("create(inplaceOpName)" ) LookupInheritedAttributeNode getattrInplace ) {
133
176
Object result = PNotImplemented .NOT_IMPLEMENTED ;
134
177
Object inplaceCallable = getattrInplace .execute (left );
178
+ boolean isBinary = z == PNone .NO_VALUE ;
135
179
if (inplaceCallable != PNone .NO_VALUE ) {
136
- result = ensureDispatch ().executeObject (frame , inplaceCallable , left , right );
137
- if (result != PNotImplemented .NOT_IMPLEMENTED ) {
138
- return result ;
180
+ if (isBinary ) {
181
+ result = ensureBinaryCallNode ().executeObject (frame , inplaceCallable , left , right );
182
+ } else {
183
+ result = ensureTernaryCallNode ().execute (frame , inplaceCallable , left , right , z );
139
184
}
140
- }
141
- if (binaryNode != null ) {
142
- result = binaryNode .executeObject (frame , left , right );
143
185
if (result != PNotImplemented .NOT_IMPLEMENTED ) {
144
186
return result ;
145
187
}
146
188
}
147
- if (handlerFactory != null && result == PNotImplemented .NOT_IMPLEMENTED ) {
189
+
190
+ // try non-inplace variant
191
+ if (isBinary ) {
192
+ result = ensureLookupAndCallBinaryNode ().executeObject (frame , left , right );
193
+ } else {
194
+ result = ensureLookupAndCallTernaryNode ().execute (frame , left , right , z );
195
+ }
196
+ if (result != PNotImplemented .NOT_IMPLEMENTED ) {
197
+ return result ;
198
+ }
199
+
200
+ if (handlerFactory != null ) {
201
+ assert result == PNotImplemented .NOT_IMPLEMENTED ;
148
202
if (handler == null ) {
149
203
CompilerDirectives .transferToInterpreterAndInvalidate ();
150
204
handler = insert (handlerFactory .get ());
0 commit comments