Skip to content

Commit 55b5ccb

Browse files
committed
[GR-25979] Use argument clinic in format nodes.
PullRequest: graalpython/1254
2 parents cf52b22 + c44d82f commit 55b5ccb

File tree

6 files changed

+87
-114
lines changed

6 files changed

+87
-114
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/FormatNodeBase.java

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,32 +40,26 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.common;
4242

43-
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
44-
import static com.oracle.graal.python.nodes.SpecialMethodNames.__STR__;
45-
46-
import com.oracle.graal.python.nodes.ErrorMessages;
4743
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
48-
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
49-
import com.oracle.graal.python.nodes.util.CannotCastException;
50-
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
44+
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode;
45+
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
5146
import com.oracle.truffle.api.CompilerDirectives;
47+
import com.oracle.truffle.api.dsl.Cached;
48+
import com.oracle.truffle.api.dsl.Specialization;
49+
import com.oracle.truffle.api.frame.VirtualFrame;
5250

53-
public abstract class FormatNodeBase extends PythonBinaryBuiltinNode {
54-
@Child private LookupAndCallUnaryNode strCall;
55-
56-
protected LookupAndCallUnaryNode ensureStrCallNode() {
57-
if (strCall == null) {
58-
CompilerDirectives.transferToInterpreterAndInvalidate();
59-
strCall = insert(LookupAndCallUnaryNode.create(__STR__));
60-
}
61-
return strCall;
51+
public abstract class FormatNodeBase extends PythonBinaryClinicBuiltinNode {
52+
@Override
53+
protected ArgumentClinicProvider getArgumentClinic() {
54+
// must be implemented here, because DSL creates a generated node for this class
55+
CompilerDirectives.transferToInterpreterAndInvalidate();
56+
throw new AbstractMethodError();
6257
}
6358

64-
protected String castFormatString(Object obj, CastToJavaStringNode castNode) {
65-
try {
66-
return castNode.execute(obj);
67-
} catch (CannotCastException ex) {
68-
throw raise(TypeError, ErrorMessages.ARG_D_MUST_BE_S_NOT_P, "format()", 2, "str", obj);
69-
}
59+
// applies to all types: empty format string => use __str__
60+
@Specialization(guards = "formatString.isEmpty()")
61+
public static Object formatEmptyString(VirtualFrame frame, Object self, @SuppressWarnings("unused") String formatString,
62+
@Cached("create(__STR__)") LookupAndCallUnaryNode lookupAndCallNode) {
63+
return lookupAndCallNode.executeObject(frame, self);
7064
}
7165
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,16 @@
8686
import com.oracle.graal.python.builtins.modules.SysModuleBuiltins;
8787
import com.oracle.graal.python.builtins.objects.PNone;
8888
import com.oracle.graal.python.builtins.objects.PNotImplemented;
89+
import com.oracle.graal.python.builtins.objects.common.FormatNodeBase;
8990
import com.oracle.graal.python.builtins.objects.complex.ComplexBuiltinsClinicProviders.FormatNodeClinicProviderGen;
9091
import com.oracle.graal.python.builtins.objects.floats.FloatBuiltins;
9192
import com.oracle.graal.python.builtins.objects.ints.PInt;
9293
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
9394
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
9495
import com.oracle.graal.python.nodes.ErrorMessages;
95-
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
9696
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
9797
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
9898
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
99-
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode;
10099
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
101100
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
102101
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
@@ -743,18 +742,12 @@ abstract static class StrNode extends ReprNode {
743742
@ArgumentClinic(name = "format_spec", conversion = ClinicConversion.String)
744743
@GenerateNodeFactory
745744
@TypeSystemReference(PythonArithmeticTypes.class)
746-
abstract static class FormatNode extends PythonBinaryClinicBuiltinNode {
745+
abstract static class FormatNode extends FormatNodeBase {
747746
@Override
748747
protected ArgumentClinicProvider getArgumentClinic() {
749748
return FormatNodeClinicProviderGen.INSTANCE;
750749
}
751750

752-
@Specialization(guards = "formatString.isEmpty()")
753-
Object format(VirtualFrame frame, PComplex self, @SuppressWarnings("unused") String formatString,
754-
@Cached("create(__STR__)") LookupAndCallUnaryNode lookupAndCallNode) {
755-
return lookupAndCallNode.executeObject(frame, self);
756-
}
757-
758751
@Specialization(guards = "!formatString.isEmpty()")
759752
Object format(PComplex self, String formatString) {
760753
PythonCore core = getCore();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
import java.util.List;
7272

7373
import com.oracle.graal.python.PythonLanguage;
74+
import com.oracle.graal.python.annotations.ArgumentClinic;
75+
import com.oracle.graal.python.annotations.ArgumentClinic.ClinicConversion;
7476
import com.oracle.graal.python.builtins.Builtin;
7577
import com.oracle.graal.python.builtins.CoreFunctions;
7678
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
@@ -81,6 +83,7 @@
8183
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.FromNativeSubclassNode;
8284
import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject;
8385
import com.oracle.graal.python.builtins.objects.common.FormatNodeBase;
86+
import com.oracle.graal.python.builtins.objects.floats.FloatBuiltinsClinicProviders.FormatNodeClinicProviderGen;
8487
import com.oracle.graal.python.builtins.objects.ints.PInt;
8588
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
8689
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
@@ -94,9 +97,9 @@
9497
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
9598
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
9699
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
100+
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
97101
import com.oracle.graal.python.nodes.object.GetClassNode;
98102
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
99-
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
100103
import com.oracle.graal.python.runtime.PythonContext;
101104
import com.oracle.graal.python.runtime.PythonCore;
102105
import com.oracle.graal.python.runtime.exception.PythonErrorType;
@@ -168,26 +171,18 @@ private static String doFormat(double d, FloatFormatter f) {
168171
abstract static class ReprNode extends StrNode {
169172
}
170173

171-
@Builtin(name = __FORMAT__, minNumOfPositionalArgs = 2)
174+
@Builtin(name = __FORMAT__, minNumOfPositionalArgs = 2, parameterNames = {"$self", "format_spec"})
175+
@TypeSystemReference(PythonArithmeticTypes.class)
176+
@ArgumentClinic(name = "format_spec", conversion = ClinicConversion.String)
172177
@GenerateNodeFactory
173178
abstract static class FormatNode extends FormatNodeBase {
174-
@Specialization
175-
Object formatPF(VirtualFrame frame, PFloat self, Object formatStringObj,
176-
@Shared("cast") @Cached CastToJavaStringNode castToStringNode) {
177-
String formatString = castFormatString(formatStringObj, castToStringNode);
178-
if (formatString.isEmpty()) {
179-
return ensureStrCallNode().executeObject(frame, self);
180-
}
181-
return doFormat(self.getValue(), formatString, getCore());
179+
@Override
180+
protected ArgumentClinicProvider getArgumentClinic() {
181+
return FormatNodeClinicProviderGen.INSTANCE;
182182
}
183183

184-
@Specialization
185-
Object formatD(VirtualFrame frame, double self, Object formatStringObj,
186-
@Shared("cast") @Cached CastToJavaStringNode castToStringNode) {
187-
String formatString = castFormatString(formatStringObj, castToStringNode);
188-
if (formatString.isEmpty()) {
189-
return ensureStrCallNode().executeObject(frame, self);
190-
}
184+
@Specialization(guards = "!formatString.isEmpty()")
185+
Object formatPF(double self, String formatString) {
191186
return doFormat(self, formatString, getCore());
192187
}
193188

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
import java.util.List;
5252

5353
import com.oracle.graal.python.PythonLanguage;
54+
import com.oracle.graal.python.annotations.ArgumentClinic;
55+
import com.oracle.graal.python.annotations.ArgumentClinic.ClinicConversion;
5456
import com.oracle.graal.python.builtins.Builtin;
5557
import com.oracle.graal.python.builtins.CoreFunctions;
5658
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
@@ -70,6 +72,7 @@
7072
import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr;
7173
import com.oracle.graal.python.builtins.objects.common.FormatNodeBase;
7274
import com.oracle.graal.python.builtins.objects.function.PArguments;
75+
import com.oracle.graal.python.builtins.objects.ints.IntBuiltinsClinicProviders.FormatNodeClinicProviderGen;
7376
import com.oracle.graal.python.builtins.objects.list.PList;
7477
import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView;
7578
import com.oracle.graal.python.builtins.objects.object.PythonObject;
@@ -88,9 +91,9 @@
8891
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
8992
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
9093
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
94+
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
9195
import com.oracle.graal.python.nodes.object.GetClassNode;
9296
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
93-
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
9497
import com.oracle.graal.python.runtime.PythonContext;
9598
import com.oracle.graal.python.runtime.PythonCore;
9699
import com.oracle.graal.python.runtime.exception.PythonErrorType;
@@ -2542,34 +2545,26 @@ static String doNativeVoidPtr(PythonNativeVoidPtr self,
25422545
abstract static class ReprNode extends StrNode {
25432546
}
25442547

2545-
@Builtin(name = __FORMAT__, minNumOfPositionalArgs = 2)
2548+
@Builtin(name = __FORMAT__, minNumOfPositionalArgs = 2, parameterNames = {"$self", "format_spec"})
2549+
@ArgumentClinic(name = "format_spec", conversion = ClinicConversion.String)
25462550
@GenerateNodeFactory
25472551
abstract static class FormatNode extends FormatNodeBase {
25482552
@Child private BuiltinConstructors.FloatNode floatNode;
25492553

2550-
// We cannot use PythonArithmeticTypes, because for empty format string we need to call the
2551-
// boolean's __str__ and not int's __str__
2552-
@Specialization
2553-
Object formatB(VirtualFrame frame, boolean self, Object formatStringObj,
2554-
@Shared("cast") @Cached CastToJavaStringNode castToStringNode) {
2555-
String formatString = castFormatString(formatStringObj, castToStringNode);
2556-
if (formatString.isEmpty()) {
2557-
return ensureStrCallNode().executeObject(frame, self);
2558-
}
2559-
return doFormatInt(self ? 1 : 0, formatString);
2554+
@Override
2555+
protected ArgumentClinicProvider getArgumentClinic() {
2556+
return FormatNodeClinicProviderGen.INSTANCE;
25602557
}
25612558

2562-
@Specialization
2563-
Object formatI(VirtualFrame frame, int self, Object formatStringObj,
2564-
@Shared("cast") @Cached CastToJavaStringNode castToStringNode) {
2565-
String formatString = castFormatString(formatStringObj, castToStringNode);
2566-
if (formatString.isEmpty()) {
2567-
return ensureStrCallNode().executeObject(frame, self);
2568-
}
2569-
return doFormatInt(self, formatString);
2559+
// We cannot use PythonArithmeticTypes, because for empty format string we need to call the
2560+
// boolean's __str__ and not int's __str__ (that specialization is inherited)
2561+
@Specialization(guards = "!formatString.isEmpty()")
2562+
Object formatB(boolean self, String formatString) {
2563+
return formatI(self ? 1 : 0, formatString);
25702564
}
25712565

2572-
private String doFormatInt(int self, String formatString) {
2566+
@Specialization(guards = "!formatString.isEmpty()")
2567+
Object formatI(int self, String formatString) {
25732568
PythonCore core = getCore();
25742569
Spec spec = getSpec(formatString, core);
25752570
if (isDoubleSpec(spec)) {
@@ -2579,23 +2574,19 @@ private String doFormatInt(int self, String formatString) {
25792574
return formatInt(self, core, spec);
25802575
}
25812576

2582-
@Specialization
2583-
Object formatL(VirtualFrame frame, long self, Object formatString,
2584-
@Shared("cast") @Cached CastToJavaStringNode castToStringNode) {
2585-
return formatPI(frame, factory().createInt(self), formatString, castToStringNode);
2577+
@Specialization(guards = "!formatString.isEmpty()")
2578+
Object formatL(VirtualFrame frame, long self, String formatString) {
2579+
return formatPI(frame, factory().createInt(self), formatString);
25862580
}
25872581

2588-
@Specialization
2589-
Object formatPI(VirtualFrame frame, PInt self, Object formatStringObj,
2590-
@Shared("cast") @Cached CastToJavaStringNode castToStringNode) {
2591-
String formatString = castFormatString(formatStringObj, castToStringNode);
2592-
if (formatString.isEmpty()) {
2593-
return ensureStrCallNode().executeObject(frame, self);
2594-
}
2582+
@Specialization(guards = "!formatString.isEmpty()")
2583+
Object formatPI(VirtualFrame frame, PInt self, String formatString) {
25952584
PythonCore core = getCore();
25962585
Spec spec = getSpec(formatString, core);
25972586
if (isDoubleSpec(spec)) {
2598-
return formatDouble(core, spec, asDouble(frame, self));
2587+
// lazy init of floatNode serves as branch profile
2588+
double doubleVal = asDouble(frame, self);
2589+
return formatDouble(core, spec, doubleVal);
25992590
}
26002591
validateIntegerSpec(core, spec);
26012592
return formatPInt(self, core, spec);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
import java.util.List;
5454

5555
import com.oracle.graal.python.PythonLanguage;
56+
import com.oracle.graal.python.annotations.ArgumentClinic;
57+
import com.oracle.graal.python.annotations.ArgumentClinic.ClinicConversion;
5658
import com.oracle.graal.python.builtins.Builtin;
5759
import com.oracle.graal.python.builtins.CoreFunctions;
5860
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
@@ -66,6 +68,7 @@
6668
import com.oracle.graal.python.builtins.objects.dict.PDict;
6769
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
6870
import com.oracle.graal.python.builtins.objects.function.PKeyword;
71+
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsClinicProviders.FormatNodeClinicProviderGen;
6972
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory.GetAttributeNodeFactory;
7073
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
7174
import com.oracle.graal.python.builtins.objects.type.TypeNodes.CheckCompatibleForAssigmentNode;
@@ -87,9 +90,11 @@
8790
import com.oracle.graal.python.nodes.expression.IsExpressionNode.IsNode;
8891
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
8992
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
93+
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode;
9094
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
9195
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
9296
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
97+
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
9398
import com.oracle.graal.python.nodes.object.GetClassNode;
9499
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
95100
import com.oracle.graal.python.nodes.util.CannotCastException;
@@ -617,22 +622,23 @@ Object raise(Object self, @SuppressWarnings("unused") Object dict) {
617622

618623
}
619624

620-
@Builtin(name = __FORMAT__, minNumOfPositionalArgs = 2)
625+
@Builtin(name = __FORMAT__, minNumOfPositionalArgs = 2, parameterNames = {"$self", "format_spec"})
626+
@ArgumentClinic(name = "format_spec", conversion = ClinicConversion.String)
621627
@GenerateNodeFactory
622-
abstract static class FormatNode extends PythonBinaryBuiltinNode {
623-
@Specialization
624-
Object format(VirtualFrame frame, Object self, Object formatStringObj,
625-
@Cached CastToJavaStringNode castToStringNode,
628+
abstract static class FormatNode extends PythonBinaryClinicBuiltinNode {
629+
@Override
630+
protected ArgumentClinicProvider getArgumentClinic() {
631+
return FormatNodeClinicProviderGen.INSTANCE;
632+
}
633+
634+
@Specialization(guards = "!formatString.isEmpty()")
635+
Object format(Object self, @SuppressWarnings("unused") String formatString) {
636+
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.UNSUPPORTED_FORMAT_STRING_PASSED_TO_P_FORMAT, self);
637+
}
638+
639+
@Specialization(guards = "formatString.isEmpty()")
640+
static Object format(VirtualFrame frame, Object self, @SuppressWarnings("unused") String formatString,
626641
@Cached("create(__STR__)") LookupAndCallUnaryNode strCall) {
627-
String formatString;
628-
try {
629-
formatString = castToStringNode.execute(formatStringObj);
630-
} catch (CannotCastException ex) {
631-
throw raise(TypeError, ErrorMessages.FORMAT_SPEC_MUST_BE_STRING);
632-
}
633-
if (formatString.length() > 0) {
634-
raise(PythonBuiltinClassType.TypeError, ErrorMessages.UNSUPPORTED_FORMAT_STRING_PASSED_TO_P_FORMAT, self);
635-
}
636642
return strCall.executeObject(frame, self);
637643
}
638644
}

0 commit comments

Comments
 (0)