40
40
*/
41
41
package com .oracle .graal .python .builtins .objects .function ;
42
42
43
- import static com .oracle .graal .python .nodes .SpecialMethodNames .__GETATTRIBUTE__ ;
44
-
45
43
import java .util .Objects ;
46
44
import java .util .concurrent .ConcurrentHashMap ;
47
45
48
46
import com .oracle .graal .python .builtins .Builtin ;
49
47
import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
50
- import com .oracle .graal .python .builtins .objects .module .ModuleBuiltinsFactory ;
51
- import com .oracle .graal .python .builtins .objects .object .ObjectBuiltinsFactory ;
52
48
import com .oracle .graal .python .builtins .objects .type .PythonBuiltinClass ;
53
- import com .oracle .graal .python .builtins .objects .type .TypeBuiltinsFactory ;
54
49
import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
55
50
import com .oracle .graal .python .nodes .function .builtins .PythonBinaryBuiltinNode ;
56
51
import com .oracle .graal .python .nodes .function .builtins .PythonTernaryBuiltinNode ;
@@ -79,14 +74,18 @@ public abstract class BuiltinMethodDescriptor {
79
74
*/
80
75
private static final ConcurrentHashMap <BuiltinMethodDescriptor , BuiltinMethodDescriptor > CACHE = new ConcurrentHashMap <>();
81
76
82
- public static final BuiltinMethodDescriptor OBJ_GET_ATTRIBUTE = get ( __GETATTRIBUTE__ , ObjectBuiltinsFactory . GetAttributeNodeFactory . getInstance (), PythonBuiltinClassType . PythonObject );
83
- public static final BuiltinMethodDescriptor MODULE_GET_ATTRIBUTE = get ( __GETATTRIBUTE__ , ModuleBuiltinsFactory . ModuleGetattritbuteNodeFactory . getInstance (), PythonBuiltinClassType . PythonModule );
84
- public static final BuiltinMethodDescriptor TYPE_GET_ATTRIBUTE = get ( __GETATTRIBUTE__ , TypeBuiltinsFactory . GetattributeNodeFactory . getInstance (), PythonBuiltinClassType . PythonClass );
85
-
77
+ /**
78
+ * First caller of this method within given {@code PythonLanguage} instance should add a cache
79
+ * entry for this builtin's call target.
80
+ */
86
81
public static BuiltinMethodDescriptor get (PBuiltinFunction function ) {
87
82
CompilerAsserts .neverPartOfCompilation ();
88
83
NodeFactory <? extends PythonBuiltinBaseNode > factory = function .getBuiltinNodeFactory ();
89
- if (factory == null || needsFrame (factory )) {
84
+ if (factory == null ) {
85
+ return null ;
86
+ }
87
+ Builtin builtinAnnotation = findBuiltinAnnotation (function .getName (), factory );
88
+ if (builtinAnnotation .needsFrame ()) {
90
89
return null ;
91
90
}
92
91
@@ -103,18 +102,24 @@ public static BuiltinMethodDescriptor get(PBuiltinFunction function) {
103
102
return get (function .getName (), factory , type );
104
103
}
105
104
106
- private static BuiltinMethodDescriptor get (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type ) {
105
+ static BuiltinMethodDescriptor get (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type ) {
106
+ Builtin builtinAnnotation = findBuiltinAnnotation (name , factory );
107
+ assert !builtinAnnotation .needsFrame ();
108
+ return get (name , factory , type , builtinAnnotation );
109
+ }
110
+
111
+ private static BuiltinMethodDescriptor get (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type , Builtin builtinAnnotation ) {
107
112
CompilerAsserts .neverPartOfCompilation ();
108
113
Class <? extends PythonBuiltinBaseNode > nodeClass = factory .getNodeClass ();
109
114
BuiltinMethodDescriptor result = null ;
110
115
if (PythonUnaryBuiltinNode .class .isAssignableFrom (nodeClass )) {
111
- result = new UnaryBuiltinDescriptor (name , factory , type );
116
+ result = new UnaryBuiltinDescriptor (name , factory , type , builtinAnnotation );
112
117
assert result .getBuiltinAnnotation ().minNumOfPositionalArgs () <= 1 : name ;
113
118
} else if (PythonBinaryBuiltinNode .class .isAssignableFrom (nodeClass )) {
114
- result = new BinaryBuiltinDescriptor (name , factory , type );
119
+ result = new BinaryBuiltinDescriptor (name , factory , type , builtinAnnotation );
115
120
assert result .getBuiltinAnnotation ().minNumOfPositionalArgs () <= 2 : name ;
116
121
} else if (PythonTernaryBuiltinNode .class .isAssignableFrom (nodeClass )) {
117
- result = new TernaryBuiltinDescriptor (name , factory , type );
122
+ result = new TernaryBuiltinDescriptor (name , factory , type , builtinAnnotation );
118
123
assert result .getBuiltinAnnotation ().minNumOfPositionalArgs () <= 3 : name ;
119
124
}
120
125
if (result != null ) {
@@ -127,31 +132,53 @@ public static boolean isInstance(Object obj) {
127
132
return obj instanceof BuiltinMethodDescriptor ;
128
133
}
129
134
130
- private static boolean needsFrame ( NodeFactory <? extends PythonBuiltinBaseNode > factory ) {
135
+ private static Builtin findBuiltinAnnotation ( String name , NodeFactory <? extends PythonBuiltinBaseNode > factory ) {
131
136
for (Builtin builtin : factory .getNodeClass ().getAnnotationsByType (Builtin .class )) {
132
- if (builtin .needsFrame ( )) {
133
- return true ;
137
+ if (builtin .name (). equals ( name )) {
138
+ return builtin ;
134
139
}
135
140
}
136
- return false ;
141
+ throw new IllegalStateException (String .format (
142
+ "Cannot find corresponding builtin annotation on class %s for builtin '%s'" ,
143
+ factory .getNodeClass ().getSimpleName (), name ));
137
144
}
138
145
139
146
private final NodeFactory <? extends PythonBuiltinBaseNode > factory ;
140
147
private final PythonBuiltinClassType type ;
141
- // Name allows us to differentiate between builtins shared for reversible operations, such as
142
- // int.__mul__ and int.__rmul__, which have the same node factory
148
+ // The builtin annotation allows us to differentiate between builtins shared for reversible
149
+ // operations, such as int.__mul__ and int.__rmul__, which have the same node factory
150
+ private final Builtin builtinAnnotation ;
151
+ // Name and isReverseOperation are shortcuts for builtinAnnotation.name()/reverseOperation()
143
152
private final String name ;
153
+ private final boolean isReverseOperation ;
144
154
145
- private BuiltinMethodDescriptor (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type ) {
155
+ private BuiltinMethodDescriptor (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type , Builtin builtinAnnotation ) {
156
+ assert name .equals (builtinAnnotation .name ());
146
157
this .name = name ;
147
158
this .factory = factory ;
148
159
this .type = type ;
160
+ this .builtinAnnotation = builtinAnnotation ;
161
+ this .isReverseOperation = builtinAnnotation .reverseOperation ();
149
162
}
150
163
151
- public final NodeFactory <? extends PythonBuiltinBaseNode > getFactory () {
164
+ protected final NodeFactory <? extends PythonBuiltinBaseNode > getFactory () {
152
165
return factory ;
153
166
}
154
167
168
+ public final <T extends NodeFactory <? extends PythonBuiltinBaseNode >> boolean isSameFactory (Class <T > builtinNodeFactoryClass ) {
169
+ // The assertion is possibly not strictly necessary, but this situation should get an
170
+ // attention: it can be dangerous to rely only on factory identity for reverse operations,
171
+ // because the factory cannot be used to create a functional node, we may also need to swap
172
+ // the arguments.
173
+ assert !getBuiltinAnnotation ().reverseOperation () : this ;
174
+ return builtinNodeFactoryClass .isInstance (getFactory ());
175
+ }
176
+
177
+ public final boolean isDescriptorOf (PBuiltinFunction fun ) {
178
+ assert fun .getEnclosingType () instanceof PythonBuiltinClassType ;
179
+ return fun .getName ().equals (name ) && fun .getBuiltinNodeFactory () == getFactory () && fun .getEnclosingType () == type ;
180
+ }
181
+
155
182
public final PythonBuiltinClassType getEnclosingType () {
156
183
return type ;
157
184
}
@@ -160,34 +187,45 @@ public final String getName() {
160
187
return name ;
161
188
}
162
189
190
+ public final boolean isReverseOperation () {
191
+ return isReverseOperation ;
192
+ }
193
+
163
194
public final Builtin getBuiltinAnnotation () {
164
- return factory . getNodeClass (). getAnnotationsByType ( Builtin . class )[ 0 ] ;
195
+ return builtinAnnotation ;
165
196
}
166
197
167
- @ SuppressWarnings ("StringEquality" )
168
198
@ Override
169
199
public final boolean equals (Object o ) {
200
+ CompilerAsserts .neverPartOfCompilation ();
170
201
if (this == o ) {
171
202
return true ;
172
203
}
173
204
if (o == null || getClass () != o .getClass ()) {
174
205
return false ;
175
206
}
176
207
BuiltinMethodDescriptor that = (BuiltinMethodDescriptor ) o ;
177
- return factory == that .factory && type == that .type && name == that .name ;
208
+ return factory == that .factory && type == that .type && name . equals ( that .name ) ;
178
209
}
179
210
180
211
@ Override
181
212
public final int hashCode () {
182
- return Objects .hash (factory , type , System .identityHashCode (name ));
213
+ CompilerAsserts .neverPartOfCompilation ();
214
+ return Objects .hash (factory , type , name );
215
+ }
216
+
217
+ @ Override
218
+ public String toString () {
219
+ CompilerAsserts .neverPartOfCompilation ();
220
+ return getClass ().getSimpleName () + "{" + type + "." + name + '}' ;
183
221
}
184
222
185
223
// Note: manually written subclass for each builtin works better with Truffle DSL than one
186
224
// generic class that would parametrize the 'factory' field
187
225
188
226
public static final class UnaryBuiltinDescriptor extends BuiltinMethodDescriptor {
189
- public UnaryBuiltinDescriptor (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type ) {
190
- super (name , factory , type );
227
+ public UnaryBuiltinDescriptor (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type , Builtin builtinAnnotation ) {
228
+ super (name , factory , type , builtinAnnotation );
191
229
}
192
230
193
231
public PythonUnaryBuiltinNode createNode () {
@@ -196,8 +234,8 @@ public PythonUnaryBuiltinNode createNode() {
196
234
}
197
235
198
236
public static final class BinaryBuiltinDescriptor extends BuiltinMethodDescriptor {
199
- public BinaryBuiltinDescriptor (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type ) {
200
- super (name , factory , type );
237
+ public BinaryBuiltinDescriptor (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type , Builtin builtinAnnotation ) {
238
+ super (name , factory , type , builtinAnnotation );
201
239
}
202
240
203
241
public PythonBinaryBuiltinNode createNode () {
@@ -206,8 +244,8 @@ public PythonBinaryBuiltinNode createNode() {
206
244
}
207
245
208
246
public static final class TernaryBuiltinDescriptor extends BuiltinMethodDescriptor {
209
- public TernaryBuiltinDescriptor (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type ) {
210
- super (name , factory , type );
247
+ public TernaryBuiltinDescriptor (String name , NodeFactory <? extends PythonBuiltinBaseNode > factory , PythonBuiltinClassType type , Builtin builtinAnnotation ) {
248
+ super (name , factory , type , builtinAnnotation );
211
249
}
212
250
213
251
public PythonTernaryBuiltinNode createNode () {
0 commit comments