40
40
*/
41
41
package com .oracle .graal .python .builtins .objects .ints ;
42
42
43
- import static com .oracle .graal .python .builtins .PythonBuiltinClassType .TypeError ;
44
43
import static com .oracle .graal .python .nodes .SpecialMethodNames .__FORMAT__ ;
45
44
import static com .oracle .graal .python .nodes .SpecialMethodNames .__LT__ ;
46
45
import static com .oracle .graal .python .runtime .exception .PythonErrorType .OverflowError ;
56
55
import com .oracle .graal .python .builtins .CoreFunctions ;
57
56
import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
58
57
import com .oracle .graal .python .builtins .PythonBuiltins ;
58
+ import com .oracle .graal .python .builtins .modules .BuiltinConstructors ;
59
+ import com .oracle .graal .python .builtins .modules .BuiltinConstructorsFactory ;
59
60
import com .oracle .graal .python .builtins .modules .MathGuards ;
60
61
import com .oracle .graal .python .builtins .objects .PNone ;
61
62
import com .oracle .graal .python .builtins .objects .PNotImplemented ;
68
69
import com .oracle .graal .python .builtins .objects .cext .CExtNodes .FromNativeSubclassNode ;
69
70
import com .oracle .graal .python .builtins .objects .cext .PythonNativeObject ;
70
71
import com .oracle .graal .python .builtins .objects .cext .PythonNativeVoidPtr ;
72
+ import com .oracle .graal .python .builtins .objects .common .FormatNodeBase ;
71
73
import com .oracle .graal .python .builtins .objects .function .PArguments ;
72
74
import com .oracle .graal .python .builtins .objects .list .PList ;
73
75
import com .oracle .graal .python .builtins .objects .memoryview .PMemoryView ;
90
92
import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
91
93
import com .oracle .graal .python .nodes .object .GetClassNode ;
92
94
import com .oracle .graal .python .nodes .truffle .PythonArithmeticTypes ;
95
+ import com .oracle .graal .python .nodes .util .CastToJavaStringNode ;
93
96
import com .oracle .graal .python .runtime .PythonContext ;
94
97
import com .oracle .graal .python .runtime .PythonCore ;
95
98
import com .oracle .graal .python .runtime .exception .PythonErrorType ;
@@ -2560,53 +2563,70 @@ abstract static class ReprNode extends StrNode {
2560
2563
2561
2564
@ Builtin (name = __FORMAT__ , minNumOfPositionalArgs = 2 )
2562
2565
@ GenerateNodeFactory
2563
- @ TypeSystemReference ( PythonArithmeticTypes . class )
2564
- abstract static class FormatNode extends PythonBinaryBuiltinNode {
2566
+ abstract static class FormatNode extends FormatNodeBase {
2567
+ @ Child private BuiltinConstructors . FloatNode floatNode ;
2565
2568
2566
- @ Specialization (guards = "formatString.isEmpty()" )
2567
- Object emptyFormat (VirtualFrame frame , Object self , @ SuppressWarnings ("unused" ) String formatString ,
2568
- @ Cached ("create(__STR__)" ) LookupAndCallUnaryNode strCall ) {
2569
- return strCall .executeObject (frame , self );
2569
+ // We cannot use PythonArithmeticTypes, because for empty format string we need to call the
2570
+ // boolean's __str__ and not int's __str__
2571
+ @ Specialization
2572
+ Object formatB (VirtualFrame frame , boolean self , Object formatStringObj ,
2573
+ @ Shared ("cast" ) @ Cached CastToJavaStringNode castToStringNode ) {
2574
+ String formatString = castFormatString (formatStringObj , castToStringNode );
2575
+ if (formatString .isEmpty ()) {
2576
+ return ensureStrCallNode ().executeObject (frame , self );
2577
+ }
2578
+ return doFormatInt (self ? 1 : 0 , formatString );
2570
2579
}
2571
2580
2572
- @ Specialization (guards = "!formatString.isEmpty()" )
2573
- @ TruffleBoundary
2574
- String formatI (int self , String formatString ) {
2581
+ @ Specialization
2582
+ Object formatI (VirtualFrame frame , int self , Object formatStringObj ,
2583
+ @ Shared ("cast" ) @ Cached CastToJavaStringNode castToStringNode ) {
2584
+ String formatString = castFormatString (formatStringObj , castToStringNode );
2585
+ if (formatString .isEmpty ()) {
2586
+ return ensureStrCallNode ().executeObject (frame , self );
2587
+ }
2588
+ return doFormatInt (self , formatString );
2589
+ }
2590
+
2591
+ private String doFormatInt (int self , String formatString ) {
2575
2592
PythonCore core = getCore ();
2576
2593
Spec spec = getSpec (formatString , core );
2577
2594
if (isDoubleSpec (spec )) {
2578
2595
return formatDouble (core , spec , self );
2579
2596
}
2580
2597
validateIntegerSpec (core , spec );
2581
- IntegerFormatter formatter = new IntegerFormatter (core , spec );
2582
- formatter .format (self );
2583
- return formatter .pad ().getResult ();
2598
+ return formatInt (self , core , spec );
2584
2599
}
2585
2600
2586
- @ Specialization (guards = "!formatString.isEmpty()" )
2587
- String formatL (long self , String formatString ) {
2588
- return formatPI (factory ().createInt (self ), formatString );
2601
+ @ Specialization
2602
+ Object formatL (VirtualFrame frame , long self , Object formatString ,
2603
+ @ Shared ("cast" ) @ Cached CastToJavaStringNode castToStringNode ) {
2604
+ return formatPI (frame , factory ().createInt (self ), formatString , castToStringNode );
2589
2605
}
2590
2606
2591
- @ Specialization (guards = "!formatString.isEmpty()" )
2592
- @ TruffleBoundary
2593
- String formatPI (PInt self , String formatString ) {
2607
+ @ Specialization
2608
+ Object formatPI (VirtualFrame frame , PInt self , Object formatStringObj ,
2609
+ @ Shared ("cast" ) @ Cached CastToJavaStringNode castToStringNode ) {
2610
+ String formatString = castFormatString (formatStringObj , castToStringNode );
2611
+ if (formatString .isEmpty ()) {
2612
+ return ensureStrCallNode ().executeObject (frame , self );
2613
+ }
2594
2614
PythonCore core = getCore ();
2595
2615
Spec spec = getSpec (formatString , core );
2596
2616
if (isDoubleSpec (spec )) {
2597
- // Note: this should really call PyNumber_Float
2598
- double doubleVal = PythonObjectLibrary .getUncached ().asJavaDouble (self );
2599
- return formatDouble (core , spec , doubleVal );
2617
+ return formatDouble (core , spec , asDouble (frame , self ));
2600
2618
}
2601
2619
validateIntegerSpec (core , spec );
2602
- IntegerFormatter formatter = new IntegerFormatter (core , spec );
2603
- formatter .format (self .getValue ());
2604
- return formatter .pad ().getResult ();
2620
+ return formatPInt (self , core , spec );
2605
2621
}
2606
2622
2607
- @ Fallback
2608
- Object doOther (@ SuppressWarnings ("unused" ) Object self , Object format ) {
2609
- throw raise (TypeError , ErrorMessages .ARG_D_MUST_BE_S_NOT_P , "format()" , 2 , "str" , format );
2623
+ private double asDouble (VirtualFrame frame , Object self ) {
2624
+ if (floatNode == null ) {
2625
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
2626
+ floatNode = insert (BuiltinConstructorsFactory .FloatNodeFactory .create ());
2627
+ }
2628
+ // We cannot use asJavaDouble, because this should have the semantics of PyNumber_Float
2629
+ return (double ) floatNode .executeWith (frame , PythonBuiltinClassType .PFloat , self );
2610
2630
}
2611
2631
2612
2632
private static Spec getSpec (String formatString , PythonCore core ) {
@@ -2620,12 +2640,27 @@ private static boolean isDoubleSpec(Spec spec) {
2620
2640
spec .type == 'G' || spec .type == '%' ;
2621
2641
}
2622
2642
2643
+ @ TruffleBoundary
2623
2644
private static String formatDouble (PythonCore core , Spec spec , double value ) {
2624
2645
FloatFormatter formatter = new FloatFormatter (core , spec );
2625
2646
formatter .format (value );
2626
2647
return formatter .pad ().getResult ();
2627
2648
}
2628
2649
2650
+ @ TruffleBoundary
2651
+ private static String formatInt (int self , PythonCore core , Spec spec ) {
2652
+ IntegerFormatter formatter = new IntegerFormatter (core , spec );
2653
+ formatter .format (self );
2654
+ return formatter .pad ().getResult ();
2655
+ }
2656
+
2657
+ @ TruffleBoundary
2658
+ private static String formatPInt (PInt self , PythonCore core , Spec spec ) {
2659
+ IntegerFormatter formatter = new IntegerFormatter (core , spec );
2660
+ formatter .format (self .getValue ());
2661
+ return formatter .pad ().getResult ();
2662
+ }
2663
+
2629
2664
private static void validateIntegerSpec (PythonCore core , Spec spec ) {
2630
2665
if (Spec .specified (spec .precision )) {
2631
2666
throw core .raise (ValueError , ErrorMessages .PRECISION_NOT_ALLOWED_FOR_INT );
0 commit comments