Skip to content

Commit 417dca1

Browse files
committed
Annotations for converter factory method parameters
1 parent 2b08b7e commit 417dca1

File tree

5 files changed

+135
-74
lines changed

5 files changed

+135
-74
lines changed

graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/ClinicConverterFactory.java

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@
1010
@Target(ElementType.METHOD)
1111
public @interface ClinicConverterFactory {
1212

13-
/**
14-
* Specifies which arguments will be provided by the clinic. These are passed to the factory
15-
* method before the argument supplied in {@link ArgumentClinic#args()}.
16-
*/
17-
ClinicArgument[] clinicArgs() default {};
18-
1913
/**
2014
* The boxing optimized execute method variants will not attempt to cast the listed
2115
* primitive types and will just pass them directly to the specializations. This does not
@@ -24,26 +18,38 @@
2418
*/
2519
ArgumentClinic.PrimitiveType[] shortCircuitPrimitive() default {};
2620

27-
enum ClinicArgument {
28-
/**
29-
* The default value {@link ArgumentClinic#defaultValue()}.
30-
*/
31-
DefaultValue,
32-
/**
33-
* The flag {@link ArgumentClinic#useDefaultForNone()}.
34-
*/
35-
UseDefaultForNone,
36-
/**
37-
* The name of the builtin function.
38-
*/
39-
BuiltinName,
40-
/**
41-
* The index of the argument.
42-
*/
43-
ArgumentIndex,
44-
/**
45-
* The name of the argument.
46-
*/
47-
ArgumentName,
21+
/**
22+
* Annotates parameter of the factory method which will receive the default value {@link ArgumentClinic#defaultValue()}.
23+
*/
24+
@Target(ElementType.PARAMETER)
25+
@interface DefaultValue {
26+
}
27+
28+
/**
29+
* Annotates parameter of the factory method which will receive the value of {@link ArgumentClinic#useDefaultForNone()}.
30+
*/
31+
@Target(ElementType.PARAMETER)
32+
@interface UseDefaultForNone {
33+
}
34+
35+
/**
36+
* Annotates parameter of the factory method which will receive the name of the builtin function.
37+
*/
38+
@Target(ElementType.PARAMETER)
39+
@interface BuiltinName {
40+
}
41+
42+
/**
43+
* Annotates parameter of the factory method which will receive the index of the argument of the builtin functions.
44+
*/
45+
@Target(ElementType.PARAMETER)
46+
@interface ArgumentIndex {
47+
}
48+
49+
/**
50+
* Annotates parameter of the factory method which will receive the name of the argument of the builtin functions.
51+
*/
52+
@Target(ElementType.PARAMETER)
53+
@interface ArgumentName {
4854
}
4955
}

graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/ArgumentClinicModel.java

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@
4646
import java.util.List;
4747
import java.util.Set;
4848
import java.util.function.Predicate;
49-
import java.util.stream.Collectors;
50-
import java.util.stream.Stream;
5149

5250
import javax.lang.model.element.TypeElement;
5351

@@ -142,8 +140,8 @@ public static ArgumentClinicData create(ArgumentClinic annotation, TypeElement t
142140
return new ArgumentClinicData(null, index, new HashSet<>(Arrays.asList(PrimitiveType.values())), null, Collections.emptySet());
143141
}
144142
ConverterFactory factory = getFactory(annotation, type, ofactory);
145-
if (annotation.args().length != factory.paramCount) {
146-
throw new ProcessingError(type, "Conversion %s.%s expects %d arguments", factory.fullClassName, factory.methodName, factory.paramCount);
143+
if (annotation.args().length != factory.extraParamCount) {
144+
throw new ProcessingError(type, "Conversion %s.%s expects %d arguments", factory.fullClassName, factory.methodName, factory.extraParamCount);
147145
}
148146

149147
PrimitiveType[] acceptedPrimitives;
@@ -153,26 +151,33 @@ public static ArgumentClinicData create(ArgumentClinic annotation, TypeElement t
153151
acceptedPrimitives = factory.acceptedPrimitiveTypes;
154152
}
155153

156-
String args = Stream.concat(
157-
Arrays.stream(factory.clinicArgs).map(ca -> {
158-
switch (ca) {
159-
case BuiltinName:
160-
return String.format("\"%s\"", builtinAnnotation.name);
161-
case ArgumentIndex:
162-
return String.valueOf(index);
163-
case ArgumentName:
164-
return String.format("\"%s\"", builtinAnnotation.argumentNames[index]);
165-
case DefaultValue:
166-
return annotation.defaultValue();
167-
case UseDefaultForNone:
168-
return String.valueOf(annotation.useDefaultForNone());
169-
default:
170-
throw new IllegalStateException("Unsupported ClinicArgument: " + ca);
171-
}
172-
}),
173-
Arrays.stream(annotation.args())).collect(Collectors.joining(", "));
174-
String castNodeFactory = String.format("%s.%s(%s)", factory.className, factory.methodName, args);
175-
154+
String[] args = new String[factory.params.length];
155+
int extraParamIndex = 0;
156+
for (int i = 0; i < args.length; ++i) {
157+
switch (factory.params[i]) {
158+
case BuiltinName:
159+
args[i] = String.format("\"%s\"", builtinAnnotation.name);
160+
break;
161+
case ArgumentIndex:
162+
args[i] = String.valueOf(index);
163+
break;
164+
case ArgumentName:
165+
args[i] = String.format("\"%s\"", builtinAnnotation.argumentNames[index]);
166+
break;
167+
case DefaultValue:
168+
args[i] = annotation.defaultValue();
169+
break;
170+
case UseDefaultForNone:
171+
args[i] = String.valueOf(annotation.useDefaultForNone());
172+
break;
173+
case Extra:
174+
args[i] = annotation.args()[extraParamIndex++];
175+
break;
176+
default:
177+
throw new IllegalStateException("Unsupported ClinicArgument: " + factory.params[i]);
178+
}
179+
}
180+
String castNodeFactory = String.format("%s.%s(%s)", factory.className, factory.methodName, String.join(", ", args));
176181
Set<String> imports = new HashSet<>();
177182
imports.add(factory.fullClassName);
178183
if (annotation.defaultValue().startsWith("PNone.")) {

graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/ConverterFactory.java

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,71 +43,100 @@
4343
import com.oracle.graal.python.annotations.ArgumentClinic;
4444
import com.oracle.graal.python.annotations.ArgumentClinic.PrimitiveType;
4545
import com.oracle.graal.python.annotations.ClinicConverterFactory;
46-
import com.oracle.graal.python.annotations.ClinicConverterFactory.ClinicArgument;
4746

4847
import javax.lang.model.element.Element;
4948
import javax.lang.model.element.ElementKind;
5049
import javax.lang.model.element.ExecutableElement;
5150
import javax.lang.model.element.Modifier;
5251
import javax.lang.model.element.TypeElement;
52+
import javax.lang.model.element.VariableElement;
5353
import java.util.HashMap;
54+
import java.util.List;
5455
import java.util.Map;
5556

5657
public class ConverterFactory {
5758
public static final String CLINIC_PACKAGE = "com.oracle.graal.python.nodes.function.builtins.clinic";
5859

60+
enum Param {
61+
/**
62+
* The default value {@link ArgumentClinic#defaultValue()}.
63+
*/
64+
DefaultValue,
65+
/**
66+
* The flag {@link ArgumentClinic#useDefaultForNone()}.
67+
*/
68+
UseDefaultForNone,
69+
/**
70+
* The name of the builtin function.
71+
*/
72+
BuiltinName,
73+
/**
74+
* The index of the argument.
75+
*/
76+
ArgumentIndex,
77+
/**
78+
* The name of the argument.
79+
*/
80+
ArgumentName,
81+
/**
82+
* Extra argument provided in {@link ArgumentClinic#args()}.
83+
*/
84+
Extra,
85+
}
86+
87+
5988
private static final Map<TypeElement, ConverterFactory> cache = new HashMap<>();
6089

6190
public final String fullClassName;
6291
public final String className;
6392
public final String methodName;
64-
public final int paramCount;
65-
public final ClinicArgument[] clinicArgs;
93+
public final int extraParamCount;
94+
public final Param[] params;
6695
public final PrimitiveType[] acceptedPrimitiveTypes;
6796

68-
private ConverterFactory(String fullClassName, String className, String methodName, int paramCount, ClinicArgument[] clinicArgs, PrimitiveType[] acceptedPrimitiveTypes) {
97+
private ConverterFactory(String fullClassName, String className, String methodName, int extraParamCount, Param[] params, PrimitiveType[] acceptedPrimitiveTypes) {
6998
this.fullClassName = fullClassName;
7099
this.className = className;
71100
this.methodName = methodName;
72-
this.paramCount = paramCount;
73-
this.clinicArgs = clinicArgs;
101+
this.extraParamCount = extraParamCount;
102+
this.params = params;
74103
this.acceptedPrimitiveTypes = acceptedPrimitiveTypes;
75104
}
76105

77-
private ConverterFactory(String className, ClinicArgument[] clinicArgs, PrimitiveType[] acceptedPrimitiveTypes) {
78-
this(CLINIC_PACKAGE + "." + className, className, "create", 0, clinicArgs, acceptedPrimitiveTypes);
106+
private ConverterFactory(String className, Param[] params, PrimitiveType[] acceptedPrimitiveTypes) {
107+
this(CLINIC_PACKAGE + "." + className, className, "create", 0, params, acceptedPrimitiveTypes);
79108
}
80109

81110
private static final ConverterFactory BuiltinBoolean = new ConverterFactory("JavaBooleanConvertorNodeGen",
82-
new ClinicArgument[]{ClinicArgument.DefaultValue},
111+
new Param[]{Param.DefaultValue},
83112
new PrimitiveType[]{PrimitiveType.Boolean});
84113

85114
private static final ConverterFactory BuiltinString = new ConverterFactory("JavaStringConvertorNodeGen",
86-
new ClinicArgument[]{ClinicArgument.BuiltinName},
115+
new Param[]{Param.BuiltinName},
87116
new PrimitiveType[]{});
88117

89118
private static final ConverterFactory BuiltinStringWithDefault = new ConverterFactory("JavaStringConvertorWithDefaultValueNodeGen",
90-
new ClinicArgument[]{ClinicArgument.BuiltinName, ClinicArgument.DefaultValue, ClinicArgument.UseDefaultForNone},
119+
new Param[]{Param.BuiltinName, Param.DefaultValue, Param.UseDefaultForNone},
91120
new PrimitiveType[]{});
92121

93122
private static final ConverterFactory BuiltinInt = new ConverterFactory("JavaIntConversionNodeGen",
94-
new ClinicArgument[]{ClinicArgument.DefaultValue, ClinicArgument.UseDefaultForNone},
123+
new Param[]{Param.DefaultValue, Param.UseDefaultForNone},
95124
new PrimitiveType[]{PrimitiveType.Int});
96125

97126
private static final ConverterFactory BuiltinCodePoint = new ConverterFactory("CodePointConversionNodeGen",
98-
new ClinicArgument[]{ClinicArgument.BuiltinName, ClinicArgument.DefaultValue, ClinicArgument.UseDefaultForNone},
127+
new Param[]{Param.BuiltinName, Param.DefaultValue, Param.UseDefaultForNone},
99128
new PrimitiveType[]{});
100129

101130
private static final ConverterFactory BuiltinBuffer = new ConverterFactory("BufferConversionNodeGen",
102-
new ClinicArgument[]{},
131+
new Param[]{},
103132
new PrimitiveType[]{});
104133

105134
private static final ConverterFactory BuiltinIndex = new ConverterFactory("IndexConversionNodeGen",
106-
new ClinicArgument[]{ClinicArgument.DefaultValue, ClinicArgument.UseDefaultForNone},
135+
new Param[]{Param.DefaultValue, Param.UseDefaultForNone},
107136
new PrimitiveType[]{PrimitiveType.Int});
108137

109138
private static final ConverterFactory BuiltinNone = new ConverterFactory("DefaultValueNode",
110-
new ClinicArgument[]{ClinicArgument.DefaultValue, ClinicArgument.UseDefaultForNone},
139+
new Param[]{Param.DefaultValue, Param.UseDefaultForNone},
111140
new PrimitiveType[]{PrimitiveType.Boolean, PrimitiveType.Int, PrimitiveType.Long, PrimitiveType.Double});
112141

113142
public static ConverterFactory getBuiltin(ArgumentClinic annotation) {
@@ -149,8 +178,27 @@ public static ConverterFactory getForClass(TypeElement conversionClass) throws P
149178
String fullClassName = conversionClass.toString();
150179
String className = conversionClass.getSimpleName().toString();
151180
String methodName = e.getSimpleName().toString();
152-
int paramCount = ((ExecutableElement) e).getParameters().size() - annot.clinicArgs().length;
153-
factory = new ConverterFactory(fullClassName, className, methodName, paramCount, annot.clinicArgs(), annot.shortCircuitPrimitive());
181+
List<? extends VariableElement> params = ((ExecutableElement) e).getParameters();
182+
Param[] args = new Param[params.size()];
183+
int extraParamCount = 0;
184+
for (int i = 0; i < args.length; ++i) {
185+
VariableElement param = params.get(i);
186+
if (param.getAnnotation(ClinicConverterFactory.ArgumentIndex.class) != null) {
187+
args[i] = Param.ArgumentIndex;
188+
} else if (param.getAnnotation(ClinicConverterFactory.ArgumentName.class) != null) {
189+
args[i] = Param.ArgumentName;
190+
} else if (param.getAnnotation(ClinicConverterFactory.BuiltinName.class) != null) {
191+
args[i] = Param.BuiltinName;
192+
} else if (param.getAnnotation(ClinicConverterFactory.DefaultValue.class) != null) {
193+
args[i] = Param.DefaultValue;
194+
} else if (param.getAnnotation(ClinicConverterFactory.UseDefaultForNone.class) != null) {
195+
args[i] = Param.UseDefaultForNone;
196+
} else {
197+
args[i] = Param.Extra;
198+
extraParamCount++;
199+
}
200+
}
201+
factory = new ConverterFactory(fullClassName, className, methodName, extraParamCount, args, annot.shortCircuitPrimitive());
154202
}
155203
}
156204
if (factory == null) {
@@ -163,6 +211,6 @@ public static ConverterFactory getForClass(TypeElement conversionClass) throws P
163211
public static ConverterFactory forCustomConversion(TypeElement type, String methodName) {
164212
String fullClassName = type.getQualifiedName().toString();
165213
String className = type.getSimpleName().toString();
166-
return new ConverterFactory(fullClassName, className, methodName, 0, new ClinicArgument[0], new PrimitiveType[0]);
214+
return new ConverterFactory(fullClassName, className, methodName, 0, new Param[0], new PrimitiveType[0]);
167215
}
168216
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesNodes.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050

5151
import com.oracle.graal.python.PythonLanguage;
5252
import com.oracle.graal.python.annotations.ClinicConverterFactory;
53+
import com.oracle.graal.python.annotations.ClinicConverterFactory.ArgumentIndex;
5354
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5455
import com.oracle.graal.python.builtins.modules.SysModuleBuiltins;
5556
import com.oracle.graal.python.builtins.objects.PNone;
@@ -580,8 +581,8 @@ Object doOthers(@SuppressWarnings("unused") VirtualFrame frame, Object value) {
580581
throw raise(TypeError, ErrorMessages.ARG_D_MUST_BE_S_NOT_P, className(), argNum, PythonBuiltinClassType.PString, value);
581582
}
582583

583-
@ClinicConverterFactory(clinicArgs = {ClinicConverterFactory.ClinicArgument.ArgumentIndex})
584-
public static ExpectStringNode create(int argNum, String className) {
584+
@ClinicConverterFactory
585+
public static ExpectStringNode create(@ArgumentIndex int argNum, String className) {
585586
return BytesNodesFactory.ExpectStringNodeGen.create(argNum, className);
586587
}
587588
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/TupleBuiltins.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import com.oracle.graal.python.annotations.ArgumentClinic;
4949
import com.oracle.graal.python.annotations.ArgumentClinic.PrimitiveType;
5050
import com.oracle.graal.python.annotations.ClinicConverterFactory;
51+
import com.oracle.graal.python.annotations.ClinicConverterFactory.DefaultValue;
5152
import com.oracle.graal.python.builtins.Builtin;
5253
import com.oracle.graal.python.builtins.CoreFunctions;
5354
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
@@ -136,8 +137,8 @@ int doOthers(VirtualFrame frame, Object value,
136137
throw raise(TypeError, ErrorMessages.SLICE_INDICES_TYPE_ERROR);
137138
}
138139

139-
@ClinicConverterFactory(shortCircuitPrimitive = PrimitiveType.Int, clinicArgs = {ClinicConverterFactory.ClinicArgument.DefaultValue})
140-
public static SliceIndexNode create(int defaultValue) {
140+
@ClinicConverterFactory(shortCircuitPrimitive = PrimitiveType.Int)
141+
public static SliceIndexNode create(@DefaultValue int defaultValue) {
141142
return SliceIndexNodeGen.create(defaultValue);
142143
}
143144
}

0 commit comments

Comments
 (0)