Skip to content

Commit 8f7bc52

Browse files
committed
Refactor complex constructor
1 parent 3bca7cb commit 8f7bc52

File tree

2 files changed

+90
-180
lines changed

2 files changed

+90
-180
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 85 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -336,168 +336,128 @@ protected Object create(LazyPythonClass cls, byte[] barr) {
336336
public abstract static class ComplexNode extends PythonBuiltinNode {
337337

338338
@Child private GetLazyClassNode getClassNode;
339-
@Child private CoerceToDoubleNode castRealNode;
340-
@Child private CoerceToDoubleNode castImagNode;
341339
@Child private LookupAndCallUnaryNode callComplexFunc;
342-
@Child private CoerceToDoubleNode fallbackCoerce;
340+
@Child private CoerceToDoubleNode firstArgCoerceToDouble;
341+
@Child private CoerceToDoubleNode secondArgCoerceToDouble;
343342

344343
private final IsBuiltinClassProfile isPrimitiveProfile = IsBuiltinClassProfile.create();
345-
private IsBuiltinClassProfile isComplexTypeProfile;
346-
private IsBuiltinClassProfile profile;
347-
private BranchProfile errorProfile;
344+
@CompilationFinal private IsBuiltinClassProfile isComplexTypeProfile;
348345

349-
protected boolean isPrimitiveComplex(LazyPythonClass cls) {
350-
return isPrimitiveProfile.profileClass(cls, PythonBuiltinClassType.PComplex);
346+
private PComplex createComplex(LazyPythonClass cls, double real, double imaginary) {
347+
if (isPrimitiveProfile.profileClass(cls, PythonBuiltinClassType.PComplex)) {
348+
return factory().createComplex(real, imaginary);
349+
}
350+
return factory().createComplex(cls, real, imaginary);
351+
}
352+
353+
private PComplex createComplex(LazyPythonClass cls, PComplex value) {
354+
if (isPrimitiveProfile.profileClass(cls, PythonBuiltinClassType.PComplex)) {
355+
return value;
356+
}
357+
return factory().createComplex(cls, value.getReal(), value.getImag());
358+
}
359+
360+
@Specialization(guards = {"isNoValue(real)", "isNoValue(imag)"})
361+
@SuppressWarnings("unused")
362+
PComplex complexFromNone(LazyPythonClass cls, PNone real, PNone imag) {
363+
return createComplex(cls, 0, 0);
351364
}
352365

353366
@Specialization
354367
PComplex complexFromIntInt(LazyPythonClass cls, int real, int imaginary) {
355-
if (isPrimitiveComplex(cls)) {
356-
return factory().createComplex(real, imaginary);
357-
}
358-
return factory().createComplex(cls, real, imaginary);
368+
return createComplex(cls, real, imaginary);
359369
}
360370

361371
@Specialization
362372
PComplex complexFromLongLong(LazyPythonClass cls, long real, long imaginary) {
363-
if (isPrimitiveComplex(cls)) {
364-
return factory().createComplex(real, imaginary);
365-
}
366-
return factory().createComplex(cls, real, imaginary);
373+
return createComplex(cls, real, imaginary);
367374
}
368375

369376
@Specialization
370377
PComplex complexFromLongLong(LazyPythonClass cls, PInt real, PInt imaginary) {
371-
if (isPrimitiveComplex(cls)) {
372-
return factory().createComplex(real.doubleValue(), imaginary.doubleValue());
373-
}
374-
return factory().createComplex(cls, real.doubleValue(), imaginary.doubleValue());
378+
return createComplex(cls, real.doubleValue(), imaginary.doubleValue());
375379
}
376380

377381
@Specialization
378382
PComplex complexFromDoubleDouble(LazyPythonClass cls, double real, double imaginary) {
379-
if (isPrimitiveComplex(cls)) {
380-
return factory().createComplex(real, imaginary);
381-
}
382-
return factory().createComplex(cls, real, imaginary);
383+
return createComplex(cls, real, imaginary);
383384
}
384385

385-
@Specialization
386-
PComplex complexFromDouble(LazyPythonClass cls, double real, @SuppressWarnings("unused") PNone image) {
387-
if (isPrimitiveComplex(cls)) {
388-
return factory().createComplex(real, 0);
389-
}
390-
return factory().createComplex(cls, real, 0);
386+
@Specialization(guards = "isNoValue(imag)")
387+
PComplex complexFromDouble(LazyPythonClass cls, double real, @SuppressWarnings("unused") PNone imag) {
388+
return createComplex(cls, real, 0);
391389
}
392390

393-
@Specialization
394-
PComplex complexFromInt(LazyPythonClass cls, int real, @SuppressWarnings("unused") PNone image) {
395-
if (isPrimitiveComplex(cls)) {
396-
return factory().createComplex(real, 0);
397-
}
398-
return factory().createComplex(cls, real, 0);
391+
@Specialization(guards = "isNoValue(imag)")
392+
PComplex complexFromInt(LazyPythonClass cls, int real, @SuppressWarnings("unused") PNone imag) {
393+
return createComplex(cls, real, 0);
399394
}
400395

401-
@Specialization
402-
PComplex complexFromLong(LazyPythonClass cls, long real, @SuppressWarnings("unused") PNone image) {
403-
if (isPrimitiveComplex(cls)) {
404-
return factory().createComplex(real, 0);
405-
}
406-
return factory().createComplex(cls, real, 0);
396+
@Specialization(guards = "isNoValue(imag)")
397+
PComplex complexFromLong(LazyPythonClass cls, long real, @SuppressWarnings("unused") PNone imag) {
398+
return createComplex(cls, real, 0);
407399
}
408400

409-
@Specialization
410-
PComplex complexFromLong(LazyPythonClass cls, PInt real, @SuppressWarnings("unused") PNone image) {
411-
if (isPrimitiveComplex(cls)) {
412-
return factory().createComplex(real.doubleValue(), 0);
413-
}
414-
return factory().createComplex(cls, real.doubleValue(), 0);
401+
@Specialization(guards = "isNoValue(imag)")
402+
PComplex complexFromLong(LazyPythonClass cls, PInt real, @SuppressWarnings("unused") PNone imag) {
403+
return createComplex(cls, real.doubleValue(), 0);
404+
}
405+
406+
@Specialization(guards = {"isNoValue(imag)", "!isNoValue(number)", "!isString(number)"})
407+
PComplex complexFromObject(VirtualFrame frame, LazyPythonClass cls, Object number, @SuppressWarnings("unused") PNone imag) {
408+
PComplex value = getComplexNumberFromObject(frame, number);
409+
return createComplex(cls, value);
415410
}
416411

417412
@Specialization
418413
PComplex complexFromLongComplex(LazyPythonClass cls, long one, PComplex two) {
419-
if (isPrimitiveComplex(cls)) {
420-
return factory().createComplex(one - two.getImag(), two.getReal());
421-
}
422-
return factory().createComplex(cls, one - two.getImag(), two.getReal());
414+
return createComplex(cls, one - two.getImag(), two.getReal());
423415
}
424416

425417
@Specialization
426418
PComplex complexFromPIntComplex(LazyPythonClass cls, PInt one, PComplex two) {
427-
if (isPrimitiveComplex(cls)) {
428-
return factory().createComplex(one.doubleValue() - two.getImag(), two.getReal());
429-
}
430-
return factory().createComplex(cls, one.doubleValue() - two.getImag(), two.getReal());
419+
return createComplex(cls, one.doubleValue() - two.getImag(), two.getReal());
431420
}
432421

433422
@Specialization
434423
PComplex complexFromDoubleComplex(LazyPythonClass cls, double one, PComplex two) {
435-
if (isPrimitiveComplex(cls)) {
436-
return factory().createComplex(one - two.getImag(), two.getReal());
437-
}
438-
return factory().createComplex(cls, one - two.getImag(), two.getReal());
424+
return createComplex(cls, one - two.getImag(), two.getReal());
439425
}
440426

441-
@Specialization
442-
PComplex complexFromComplexLong(VirtualFrame frame, LazyPythonClass cls, PComplex one, long two) {
427+
@Specialization(guards = "!isString(one)")
428+
PComplex complexFromComplexLong(VirtualFrame frame, LazyPythonClass cls, Object one, long two) {
443429
PComplex value = getComplexNumberFromObject(frame, one);
444-
if (isPrimitiveComplex(cls)) {
445-
return factory().createComplex(value.getReal(), value.getImag() + two);
446-
}
447-
return factory().createComplex(cls, value.getReal(), value.getImag() + two);
430+
return createComplex(cls, value.getReal(), value.getImag() + two);
448431
}
449432

450-
@Specialization
451-
PComplex complexFromComplexDouble(VirtualFrame frame, LazyPythonClass cls, PComplex one, double two) {
433+
@Specialization(guards = "!isString(one)")
434+
PComplex complexFromComplexDouble(VirtualFrame frame, LazyPythonClass cls, Object one, double two) {
452435
PComplex value = getComplexNumberFromObject(frame, one);
453-
if (isPrimitiveComplex(cls)) {
454-
return factory().createComplex(value.getReal(), value.getImag() + two);
455-
}
456-
return factory().createComplex(cls, value.getReal(), value.getImag() + two);
436+
return createComplex(cls, value.getReal(), value.getImag() + two);
457437
}
458438

459-
@Specialization
460-
PComplex complexFromComplexPInt(VirtualFrame frame, LazyPythonClass cls, PComplex one, PInt two) {
439+
@Specialization(guards = "!isString(one)")
440+
PComplex complexFromComplexPInt(VirtualFrame frame, LazyPythonClass cls, Object one, PInt two) {
461441
PComplex value = getComplexNumberFromObject(frame, one);
462-
if (isPrimitiveComplex(cls)) {
463-
return factory().createComplex(value.getReal(), value.getImag() + two.doubleValue());
464-
}
465-
return factory().createComplex(cls, value.getReal(), value.getImag() + two.doubleValue());
442+
return createComplex(cls, value.getReal(), value.getImag() + two.doubleValue());
466443
}
467444

468-
@Specialization
469-
PComplex complexFromComplex(VirtualFrame frame, LazyPythonClass cls, PComplex number, @SuppressWarnings("unused") PNone image) {
470-
PComplex value = getComplexNumberFromObject(frame, number);
471-
if (isPrimitiveComplex(cls)) {
472-
return value;
473-
}
474-
return factory().createComplex(cls, value.getReal(), value.getImag());
475-
}
476-
477-
@Specialization
478-
PComplex complexFromComplexComplex(VirtualFrame frame, LazyPythonClass cls, PComplex one, PComplex two) {
445+
@Specialization(guards = "!isString(one)")
446+
PComplex complexFromComplexComplex(VirtualFrame frame, LazyPythonClass cls, Object one, PComplex two) {
479447
PComplex value = getComplexNumberFromObject(frame, one);
480-
if (isPrimitiveComplex(cls)) {
481-
return factory().createComplex(value.getReal() - two.getImag(), value.getImag() + two.getReal());
482-
}
483-
return factory().createComplex(cls, value.getReal() - two.getImag(), value.getImag() + two.getReal());
448+
return createComplex(cls, value.getReal() - two.getImag(), value.getImag() + two.getReal());
484449
}
485450

486-
@Specialization
487-
@SuppressWarnings("unused")
488-
PComplex complexFromNone(LazyPythonClass cls, PNone real, PNone image) {
489-
if (real == PNone.NONE) {
490-
throw raise(TypeError, "complex() first argument must be a string or a number, not '%p'", real);
491-
}
492-
if (isPrimitiveComplex(cls)) {
493-
return factory().createComplex(0, 0);
494-
}
495-
return factory().createComplex(cls, 0, 0);
451+
@Specialization(guards = {"!isString(one)", "!isNoValue(two)", "!isPComplex(two)"})
452+
PComplex complexFromComplexObject(VirtualFrame frame, LazyPythonClass cls, Object one, Object two) {
453+
PComplex oneValue = getComplexNumberFromObject(frame, one);
454+
double twoValue = getSecondArgCoerceToDouble().execute(frame, two);
455+
return createComplex(cls, oneValue.getReal(), oneValue.getImag() + twoValue);
496456
}
497457

498458
@Specialization
499-
PComplex complexFromObjectObject(LazyPythonClass cls, String real, Object imaginary) {
500-
if (!(imaginary instanceof PNone)) {
459+
PComplex complexFromString(LazyPythonClass cls, String real, Object imaginary) {
460+
if (imaginary != PNone.NO_VALUE) {
501461
throw raise(TypeError, "complex() can't take second arg if first is a string");
502462
}
503463
return convertStringToComplex(real, cls);
@@ -513,41 +473,12 @@ private GetLazyClassNode getGetClassNode() {
513473

514474
private IsBuiltinClassProfile getIsComplexTypeProfile() {
515475
if (isComplexTypeProfile == null) {
476+
CompilerDirectives.transferToInterpreterAndInvalidate();
516477
isComplexTypeProfile = IsBuiltinClassProfile.create();
517478
}
518479
return isComplexTypeProfile;
519480
}
520481

521-
private BranchProfile getErrorProfile() {
522-
if (errorProfile == null) {
523-
errorProfile = BranchProfile.create();
524-
}
525-
return errorProfile;
526-
}
527-
528-
private CoerceToDoubleNode getCastRealNode() {
529-
if (castRealNode == null) {
530-
CompilerDirectives.transferToInterpreterAndInvalidate();
531-
castRealNode = insert(CoerceToDoubleNode.create());
532-
}
533-
return castRealNode;
534-
}
535-
536-
private CoerceToDoubleNode getCastImagNode() {
537-
if (castImagNode == null) {
538-
CompilerDirectives.transferToInterpreterAndInvalidate();
539-
castImagNode = insert(CoerceToDoubleNode.create());
540-
}
541-
return castImagNode;
542-
}
543-
544-
private IsBuiltinClassProfile getProfile() {
545-
if (profile == null) {
546-
profile = IsBuiltinClassProfile.create();
547-
}
548-
return profile;
549-
}
550-
551482
private LookupAndCallUnaryNode getCallComplexFunc() {
552483
if (callComplexFunc == null) {
553484
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -556,14 +487,24 @@ private LookupAndCallUnaryNode getCallComplexFunc() {
556487
return callComplexFunc;
557488
}
558489

559-
private CoerceToDoubleNode getFallbackCoerce() {
560-
if (fallbackCoerce == null) {
490+
private CoerceToDoubleNode getFirstArgCoerceToDouble() {
491+
if (firstArgCoerceToDouble == null) {
561492
CompilerDirectives.transferToInterpreterAndInvalidate();
562-
fallbackCoerce = insert(CoerceToDoubleNode.create(val -> {
493+
firstArgCoerceToDouble = insert(CoerceToDoubleNode.create(val -> {
563494
throw raise(PythonBuiltinClassType.TypeError, "complex() first argument must be a string or a number, not '%p'", val);
564495
}));
565496
}
566-
return fallbackCoerce;
497+
return firstArgCoerceToDouble;
498+
}
499+
500+
private CoerceToDoubleNode getSecondArgCoerceToDouble() {
501+
if (secondArgCoerceToDouble == null) {
502+
CompilerDirectives.transferToInterpreterAndInvalidate();
503+
secondArgCoerceToDouble = insert(CoerceToDoubleNode.create(val -> {
504+
throw raise(PythonBuiltinClassType.TypeError, "complex() second argument must be a number, not '%p'", val);
505+
}));
506+
}
507+
return secondArgCoerceToDouble;
567508
}
568509

569510
private PComplex getComplexNumberFromObject(VirtualFrame frame, Object object) {
@@ -572,9 +513,6 @@ private PComplex getComplexNumberFromObject(VirtualFrame frame, Object object) {
572513
} else {
573514
Object result = getCallComplexFunc().executeObject(frame, object);
574515
if (result != PNone.NO_VALUE) {
575-
if (getIsComplexTypeProfile().profileClass(getGetClassNode().execute(object), PythonBuiltinClassType.PComplex)) {
576-
return (PComplex) result;
577-
}
578516
if (result instanceof PComplex) {
579517
// TODO we need pass here deprecation warning
580518
// DeprecationWarning: __complex__ returned non-complex (type %p).
@@ -590,44 +528,14 @@ private PComplex getComplexNumberFromObject(VirtualFrame frame, Object object) {
590528
// the class extending PComplex but doesn't have __complex__ method
591529
return (PComplex) object;
592530
}
593-
return factory().createComplex(getFallbackCoerce().execute(frame, object), 0.0);
531+
return factory().createComplex(getFirstArgCoerceToDouble().execute(frame, object), 0.0);
594532
}
595533
}
596534

597535
@Fallback
598-
Object complexGeneric(VirtualFrame frame, @SuppressWarnings("unused") Object cls, Object realObj, Object imaginaryObj) {
599-
boolean noImag = PGuards.isNoValue(imaginaryObj);
600-
if (noImag) {
601-
if (getIsComplexTypeProfile().profileClass(getGetClassNode().execute(realObj), PythonBuiltinClassType.PComplex)) {
602-
return realObj;
603-
}
604-
Object result = getCallComplexFunc().executeObject(frame, realObj);
605-
if (result != PNone.NO_VALUE && result instanceof PComplex) {
606-
return result;
607-
}
608-
}
609-
try {
610-
double real = getCastRealNode().execute(frame, realObj);
611-
double imag = !noImag ? getCastImagNode().execute(frame, imaginaryObj) : 0.0;
612-
if (isPrimitiveComplex((LazyPythonClass) cls)) {
613-
return factory().createComplex(real, imag);
614-
}
615-
return factory().createComplex((LazyPythonClass) cls, real, imag);
616-
} catch (PException e) {
617-
getErrorProfile().enter();
618-
e.expect(PythonBuiltinClassType.TypeError, getProfile());
619-
if (!(PGuards.isString(realObj) || PGuards.isInteger(realObj) || PGuards.isPInt(realObj) || PGuards.isDouble(realObj))) {
620-
throw raise(TypeError, "complex() first argument must be a string or a number, not '%p'", realObj);
621-
}
622-
if (!((PGuards.isInteger(imaginaryObj) || PGuards.isPInt(imaginaryObj) || PGuards.isDouble(imaginaryObj)))) {
623-
throw raise(TypeError, "complex() second argument must be a number, not '%p'", imaginaryObj);
624-
}
625-
throw raise(TypeError, "can't convert real %s imag %s", realObj, imaginaryObj);
626-
}
627-
}
628-
629-
protected static boolean isExactComplexType(GetLazyClassNode getClassNode, PComplex obj) {
630-
return getClassNode.execute(obj) == PythonBuiltinClassType.PComplex;
536+
@SuppressWarnings("unused")
537+
Object complexGeneric(Object cls, Object realObj, Object imaginaryObj) {
538+
throw raise(TypeError, "complex.__new__(X): X is not a type object (%p)", cls);
631539
}
632540

633541
// Taken from Jython PyString's __complex__() method
@@ -794,10 +702,7 @@ private PComplex convertStringToComplex(String str, LazyPythonClass cls) {
794702
throw raise(ValueError, "malformed string for complex() %s", str.substring(s));
795703
}
796704

797-
if (isPrimitiveComplex(cls)) {
798-
return factory().createComplex(x, y);
799-
}
800-
return factory().createComplex(cls, x, y);
705+
return createComplex(cls, x, y);
801706
}
802707

803708
// Taken from Jython PyString directly

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
5050
import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject;
5151
import com.oracle.graal.python.builtins.objects.code.PCode;
52+
import com.oracle.graal.python.builtins.objects.complex.PComplex;
5253
import com.oracle.graal.python.builtins.objects.dict.PDict;
5354
import com.oracle.graal.python.builtins.objects.dict.PDictView;
5455
import com.oracle.graal.python.builtins.objects.floats.PFloat;
@@ -360,6 +361,10 @@ public static boolean isPNone(Object obj) {
360361
return obj instanceof PNone;
361362
}
362363

364+
public static boolean isPComplex(Object obj) {
365+
return obj instanceof PComplex;
366+
}
367+
363368
public static boolean isPTuple(Object obj) {
364369
return obj instanceof PTuple;
365370
}

0 commit comments

Comments
 (0)