52
52
import com .oracle .graal .python .nodes .call .special .LookupAndCallUnaryNode .NoAttributeHandler ;
53
53
import com .oracle .graal .python .util .Supplier ;
54
54
import com .oracle .truffle .api .CompilerDirectives ;
55
+ import com .oracle .truffle .api .dsl .Cached ;
56
+ import com .oracle .truffle .api .dsl .ImportStatic ;
57
+ import com .oracle .truffle .api .dsl .Specialization ;
55
58
import com .oracle .truffle .api .frame .VirtualFrame ;
56
- import com .oracle .truffle .api .nodes .NodeCost ;
57
59
import com .oracle .truffle .api .nodes .RootNode ;
58
60
59
61
public enum UnaryArithmetic {
60
- Pos (SpecialMethodNames .__POS__ , "+" ),
61
- Neg (SpecialMethodNames .__NEG__ , "-" ),
62
- Invert (SpecialMethodNames .__INVERT__ , "~" );
63
-
64
- private final String methodName ;
65
- private final String operator ;
66
- private final Supplier <NoAttributeHandler > noAttributeHandler ;
67
-
68
- UnaryArithmetic (String methodName , String operator ) {
69
- this .methodName = methodName ;
70
- this .operator = operator ;
71
- this .noAttributeHandler = () -> new NoAttributeHandler () {
72
- @ Child private PRaiseNode raiseNode = PRaiseNode .create ();
73
-
74
- @ Override
75
- public Object execute (Object receiver ) {
76
- throw raiseNode .raise (TypeError , ErrorMessages .BAD_OPERAND_FOR , "unary " , operator , receiver );
77
- }
78
- };
79
- }
80
-
81
- public String getMethodName () {
82
- return methodName ;
83
- }
62
+ Pos (UnaryArithmeticFactory .PosNodeGen ::create ),
63
+ Neg (UnaryArithmeticFactory .NegNodeGen ::create ),
64
+ Invert (UnaryArithmeticFactory .InvertNodeGen ::create );
84
65
85
- public String getOperator () {
86
- return operator ;
66
+ interface CreateUnaryOp {
67
+ UnaryOpNode create ( ExpressionNode left ) ;
87
68
}
88
69
89
- public static final class UnaryArithmeticExpression extends ExpressionNode {
90
- @ Child private LookupAndCallUnaryNode callNode ;
91
- @ Child private ExpressionNode operand ;
92
-
93
- private UnaryArithmeticExpression (LookupAndCallUnaryNode callNode , ExpressionNode operand ) {
94
- this .callNode = callNode ;
95
- this .operand = operand ;
96
- }
97
-
98
- @ Override
99
- public Object execute (VirtualFrame frame ) {
100
- return callNode .executeObject (frame , operand .execute (frame ));
101
- }
70
+ private final CreateUnaryOp create ;
102
71
103
- @ Override
104
- public NodeCost getCost () {
105
- return NodeCost .NONE ;
106
- }
72
+ UnaryArithmetic (CreateUnaryOp create ) {
73
+ this .create = create ;
107
74
}
108
75
109
76
/**
@@ -115,7 +82,7 @@ public NodeCost getCost() {
115
82
static final class CallUnaryArithmeticRootNode extends CallArithmeticRootNode {
116
83
private static final Signature SIGNATURE_UNARY = new Signature (1 , false , -1 , false , new String []{"$self" }, null );
117
84
118
- @ Child private LookupAndCallUnaryNode callUnaryNode ;
85
+ @ Child private UnaryOpNode callUnaryNode ;
119
86
120
87
private final UnaryArithmetic unaryOperator ;
121
88
@@ -135,16 +102,16 @@ protected Object doCall(VirtualFrame frame) {
135
102
CompilerDirectives .transferToInterpreterAndInvalidate ();
136
103
callUnaryNode = insert (unaryOperator .create ());
137
104
}
138
- return callUnaryNode .executeObject (frame , PArguments .getArgument (frame , 0 ));
105
+ return callUnaryNode .execute (frame , PArguments .getArgument (frame , 0 ));
139
106
}
140
107
}
141
108
142
109
public ExpressionNode create (ExpressionNode receiver ) {
143
- return new UnaryArithmeticExpression ( LookupAndCallUnaryNode .create (methodName , noAttributeHandler ), receiver );
110
+ return create .create (receiver );
144
111
}
145
112
146
- public LookupAndCallUnaryNode create () {
147
- return LookupAndCallUnaryNode .create (methodName , noAttributeHandler );
113
+ public UnaryOpNode create () {
114
+ return create .create (null );
148
115
}
149
116
150
117
/**
@@ -154,4 +121,114 @@ public LookupAndCallUnaryNode create() {
154
121
public RootNode createRootNode (PythonLanguage language ) {
155
122
return new CallUnaryArithmeticRootNode (language , this );
156
123
}
124
+
125
+ @ ImportStatic (SpecialMethodNames .class )
126
+ public abstract static class UnaryArithmeticNode extends UnaryOpNode {
127
+
128
+ static Supplier <NoAttributeHandler > createHandler (String operator ) {
129
+
130
+ return () -> new NoAttributeHandler () {
131
+ @ Child private PRaiseNode raiseNode = PRaiseNode .create ();
132
+
133
+ @ Override
134
+ public Object execute (Object receiver ) {
135
+ throw raiseNode .raise (TypeError , ErrorMessages .BAD_OPERAND_FOR , "unary " , operator , receiver );
136
+ }
137
+ };
138
+ }
139
+
140
+ static LookupAndCallUnaryNode createCallNode (String name , Supplier <NoAttributeHandler > handler ) {
141
+ return LookupAndCallUnaryNode .create (name , handler );
142
+ }
143
+ }
144
+
145
+ /*
146
+ *
147
+ * All the following fast paths need to be kept in sync with the corresponding builtin functions
148
+ * in IntBuiltins and FloatBuiltins.
149
+ *
150
+ */
151
+
152
+ public abstract static class PosNode extends UnaryArithmeticNode {
153
+
154
+ static final Supplier <NoAttributeHandler > NOT_IMPLEMENTED = createHandler ("+" );
155
+
156
+ @ Specialization
157
+ static int pos (int arg ) {
158
+ return arg ;
159
+ }
160
+
161
+ @ Specialization
162
+ static long pos (long arg ) {
163
+ return arg ;
164
+ }
165
+
166
+ @ Specialization
167
+ static double pos (double arg ) {
168
+ return arg ;
169
+ }
170
+
171
+ @ Specialization
172
+ static Object doGeneric (VirtualFrame frame , Object arg ,
173
+ @ Cached ("createCallNode(__POS__, NOT_IMPLEMENTED)" ) LookupAndCallUnaryNode callNode ) {
174
+ return callNode .executeObject (frame , arg );
175
+ }
176
+ }
177
+
178
+ public abstract static class NegNode extends UnaryArithmeticNode {
179
+
180
+ static final Supplier <NoAttributeHandler > NOT_IMPLEMENTED = createHandler ("-" );
181
+
182
+ @ Specialization (rewriteOn = ArithmeticException .class )
183
+ static int neg (int arg ) {
184
+ return Math .negateExact (arg );
185
+ }
186
+
187
+ @ Specialization
188
+ static long negOvf (int arg ) {
189
+ return -((long ) arg );
190
+ }
191
+
192
+ @ Specialization (rewriteOn = ArithmeticException .class )
193
+ static long neg (long arg ) {
194
+ return Math .negateExact (arg );
195
+ }
196
+
197
+ @ Specialization
198
+ static double neg (double arg ) {
199
+ return -arg ;
200
+ }
201
+
202
+ @ Specialization
203
+ static Object doGeneric (VirtualFrame frame , Object arg ,
204
+ @ Cached ("createCallNode(__NEG__, NOT_IMPLEMENTED)" ) LookupAndCallUnaryNode callNode ) {
205
+ return callNode .executeObject (frame , arg );
206
+ }
207
+ }
208
+
209
+ public abstract static class InvertNode extends UnaryArithmeticNode {
210
+
211
+ static final Supplier <NoAttributeHandler > NOT_IMPLEMENTED = createHandler ("~" );
212
+
213
+ @ Specialization
214
+ static int invert (boolean arg ) {
215
+ return ~(arg ? 1 : 0 );
216
+ }
217
+
218
+ @ Specialization
219
+ static int invert (int arg ) {
220
+ return ~arg ;
221
+ }
222
+
223
+ @ Specialization
224
+ static long invert (long arg ) {
225
+ return ~arg ;
226
+ }
227
+
228
+ @ Specialization
229
+ static Object doGeneric (VirtualFrame frame , Object arg ,
230
+ @ Cached ("createCallNode(__INVERT__, NOT_IMPLEMENTED)" ) LookupAndCallUnaryNode callNode ) {
231
+ return callNode .executeObject (frame , arg );
232
+ }
233
+ }
157
234
}
0 commit comments