6666import com .oracle .graal .python .builtins .objects .bytes .PBytes ;
6767import com .oracle .graal .python .builtins .objects .bytes .PIBytesLike ;
6868import com .oracle .graal .python .builtins .objects .cell .PCell ;
69+ import com .oracle .graal .python .builtins .objects .cext .CExtNodes ;
70+ import com .oracle .graal .python .builtins .objects .cext .PythonNativeClass ;
6971import com .oracle .graal .python .builtins .objects .code .PCode ;
7072import com .oracle .graal .python .builtins .objects .common .HashingStorage .DictEntry ;
7173import com .oracle .graal .python .builtins .objects .common .HashingStorageNodes ;
128130import com .oracle .graal .python .nodes .call .special .CallUnaryMethodNode ;
129131import com .oracle .graal .python .nodes .call .special .LookupAndCallTernaryNode ;
130132import com .oracle .graal .python .nodes .call .special .LookupAndCallUnaryNode ;
133+ import com .oracle .graal .python .nodes .classes .IsSubtypeNode ;
131134import com .oracle .graal .python .nodes .control .GetIteratorNode ;
132135import com .oracle .graal .python .nodes .control .GetNextNode ;
133136import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
@@ -426,51 +429,55 @@ public Object reversed(PythonClass cls, Object sequence,
426429 public abstract static class FloatNode extends PythonBuiltinNode {
427430 private final ConditionProfile isPrimitiveProfile = ConditionProfile .createBinaryProfile ();
428431
429- private boolean isPrimitiveFloat (Object cls ) {
430- return isPrimitiveProfile .profile (cls == getCore (). lookupType ( PythonBuiltinClassType . PFloat ));
432+ protected boolean isPrimitiveFloat (Object cls ) {
433+ return isPrimitiveProfile .profile (cls == getBuiltinFloatClass ( ));
431434 }
432435
433- @ Specialization
436+ protected PythonBuiltinClass getBuiltinFloatClass () {
437+ return getCore ().lookupType (PythonBuiltinClassType .PFloat );
438+ }
439+
440+ @ Specialization (guards = "!isNativeClass(cls)" )
434441 public Object floatFromInt (PythonClass cls , int arg ) {
435442 if (isPrimitiveFloat (cls )) {
436443 return (double ) arg ;
437444 }
438445 return factory ().createFloat (cls , arg );
439446 }
440447
441- @ Specialization
448+ @ Specialization ( guards = "!isNativeClass(cls)" )
442449 public Object floatFromBoolean (PythonClass cls , boolean arg ) {
443450 if (isPrimitiveFloat (cls )) {
444451 return arg ? 1d : 0d ;
445452 }
446453 return factory ().createFloat (cls , arg ? 1d : 0d );
447454 }
448455
449- @ Specialization
456+ @ Specialization ( guards = "!isNativeClass(cls)" )
450457 public Object floatFromLong (PythonClass cls , long arg ) {
451458 if (isPrimitiveFloat (cls )) {
452459 return (double ) arg ;
453460 }
454461 return factory ().createFloat (cls , arg );
455462 }
456463
457- @ Specialization
464+ @ Specialization ( guards = "!isNativeClass(cls)" )
458465 public Object floatFromPInt (PythonClass cls , PInt arg ) {
459466 if (isPrimitiveFloat (cls )) {
460467 return arg .doubleValue ();
461468 }
462469 return factory ().createFloat (cls , arg .doubleValue ());
463470 }
464471
465- @ Specialization
472+ @ Specialization ( guards = "!isNativeClass(cls)" )
466473 public Object floatFromFloat (PythonClass cls , double arg ) {
467474 if (isPrimitiveFloat (cls )) {
468475 return arg ;
469476 }
470477 return factory ().createFloat (cls , arg );
471478 }
472479
473- @ Specialization
480+ @ Specialization ( guards = "!isNativeClass(cls)" )
474481 public Object floatFromString (PythonClass cls , String arg ) {
475482 double value = JavaTypeConversions .convertStringToDouble (arg );
476483 if (isPrimitiveFloat (cls )) {
@@ -479,34 +486,59 @@ public Object floatFromString(PythonClass cls, String arg) {
479486 return factory ().createFloat (cls , value );
480487 }
481488
482- @ Specialization
489+ @ Specialization ( guards = "!isNativeClass(cls)" )
483490 public Object floatFromNone (PythonClass cls , @ SuppressWarnings ("unused" ) PNone arg ) {
484491 if (isPrimitiveFloat (cls )) {
485492 return 0.0 ;
486493 }
487494 return factory ().createFloat (cls , 0.0 );
488495 }
489496
490- @ Specialization
491- Object doPythonObject ( PythonClass cls , Object obj ,
497+ @ Specialization ( guards = "isPrimitiveFloat(cls)" )
498+ double doubleFromObject ( @ SuppressWarnings ( "unused" ) PythonClass cls , Object obj ,
492499 @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode callFloatNode ,
493500 @ Cached ("create()" ) BranchProfile gotException ) {
494501 try {
495- return floatFromFloat ( cls , callFloatNode .executeDouble (obj ) );
502+ return callFloatNode .executeDouble (obj );
496503 } catch (UnexpectedResultException e ) {
497504 gotException .enter ();
498505 Object result = e .getResult ();
499506 if (result == PNone .NO_VALUE ) {
500507 throw raise (TypeError , "must be real number, not %p" , obj );
501- } else if (PGuards . isPFloat ( result ) ) {
508+ } else if (result instanceof PFloat ) {
502509 // TODO Issue warning if 'result' is a subclass of Python type 'float'
503- return result ;
510+ return (( PFloat ) result ). getValue () ;
504511 } else {
505512 throw raise (TypeError , "%p.__float__ returned non-float (type %p)" , obj , result );
506513 }
507514 }
508515 }
509516
517+ @ Specialization (guards = "!isNativeClass(cls)" )
518+ Object doPythonObject (PythonClass cls , Object obj ,
519+ @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode callFloatNode ,
520+ @ Cached ("create()" ) BranchProfile gotException ) {
521+ return floatFromFloat (cls , doubleFromObject (cls , obj , callFloatNode , gotException ));
522+ }
523+
524+ protected CExtNodes .SubtypeNew createSubtypeNew () {
525+ return new CExtNodes .SubtypeNew ("float" );
526+ }
527+
528+ // logic similar to float_subtype_new(PyTypeObject *type, PyObject *x) from CPython
529+ // floatobject.c we have to first create a temporary float, then fill it into
530+ // a natively allocated subtype structure
531+ @ Specialization (guards = "isSubtype.execute(cls, floatCls)" , limit = "1" )
532+ Object doPythonObject (PythonNativeClass cls , Object obj ,
533+ @ Cached ("getBuiltinFloatClass()" ) PythonBuiltinClass floatCls ,
534+ @ SuppressWarnings ("unused" ) @ Cached ("create()" ) IsSubtypeNode isSubtype ,
535+ @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode callFloatNode ,
536+ @ Cached ("create()" ) BranchProfile gotException ,
537+ @ Cached ("createSubtypeNew()" ) CExtNodes .SubtypeNew subtypeNew ) {
538+ double realFloat = doubleFromObject (floatCls , obj , callFloatNode , gotException );
539+ return subtypeNew .execute (cls , realFloat );
540+ }
541+
510542 @ Fallback
511543 @ TruffleBoundary
512544 public Object floatFromObject (@ SuppressWarnings ("unused" ) Object cls , Object arg ) {
0 commit comments