@@ -392,7 +392,6 @@ static final class CallArithmeticRootNode extends PRootNode {
392
392
private static final Signature SIGNATURE_UNARY = new Signature (1 , false , -1 , false , new String []{"$self" }, null );
393
393
private static final Signature SIGNATURE_BINARY = new Signature (2 , false , -1 , false , new String []{"$self" , "other" }, null );
394
394
private static final Signature SIGNATURE_TERNARY = new Signature (3 , false , -1 , false , new String []{"x" , "y" , "z" }, null );
395
- private static final Signature SIGNATURE_INPLACE = new Signature (3 , false , -1 , false , new String []{"x" , "y" }, null );
396
395
397
396
@ Child private LookupAndCallUnaryNode callUnaryNode ;
398
397
@ Child private LookupAndCallBinaryNode callBinaryNode ;
@@ -422,9 +421,7 @@ public Signature getSignature() {
422
421
return SIGNATURE_UNARY ;
423
422
} else if (binaryOperator != null ) {
424
423
return SIGNATURE_BINARY ;
425
- } else if (inplaceOperator != null ) {
426
- return SIGNATURE_INPLACE ;
427
- } else if (ternaryOperator != null ) {
424
+ } else if (inplaceOperator != null || ternaryOperator != null ) {
428
425
return SIGNATURE_TERNARY ;
429
426
} else {
430
427
throw CompilerDirectives .shouldNotReachHere ();
@@ -455,7 +452,13 @@ public Object execute(VirtualFrame frame) {
455
452
} else if (binaryOperator != null ) {
456
453
return callBinaryNode .executeObject (frame , PArguments .getArgument (frame , 0 ), PArguments .getArgument (frame , 1 ));
457
454
} else if (inplaceOperator != null ) {
458
- return callInplaceNode .execute (frame , PArguments .getArgument (frame , 0 ), PArguments .getArgument (frame , 1 ));
455
+ // most of the in-place operators are binary but there can also be ternary
456
+ if (PArguments .getUserArgumentLength (frame ) == 2 ) {
457
+ return callInplaceNode .execute (frame , PArguments .getArgument (frame , 0 ), PArguments .getArgument (frame , 1 ));
458
+ } else if (PArguments .getUserArgumentLength (frame ) == 3 ) {
459
+ return callInplaceNode .executeTernary (frame , PArguments .getArgument (frame , 0 ), PArguments .getArgument (frame , 1 ), PArguments .getArgument (frame , 2 ));
460
+ }
461
+ throw CompilerDirectives .shouldNotReachHere ();
459
462
} else if (ternaryOperator != null ) {
460
463
return callTernaryNode .execute (frame , PArguments .getArgument (frame , 0 ), PArguments .getArgument (frame , 1 ), PArguments .getArgument (frame , 2 ));
461
464
} else {
@@ -531,7 +534,13 @@ Object execute(Object[] arguments,
531
534
@ Cached HPyAsPythonObjectNode asPythonObjectNode ,
532
535
@ Cached HPyAsHandleNode asHandleNode ,
533
536
@ Cached GenericInvokeNode invokeNode ,
534
- @ Cached TransformExceptionToNativeNode transformExceptionToNativeNode ) {
537
+ @ Cached TransformExceptionToNativeNode transformExceptionToNativeNode ) throws ArityException {
538
+
539
+ // We need to do argument checking at this position because our helper root node that
540
+ // just dispatches to the appropriate 'LookupAndCallXXXNode' won't do any arguemnt
541
+ // checking. So it would just crash if there are too few arguments or just ignore if
542
+ // there are too many.
543
+ checkArguments (arguments );
535
544
536
545
GraalHPyContext context = asContextNode .execute (arguments [0 ]);
537
546
Object [] pythonArguments = PArguments .create (arguments .length - 1 );
@@ -549,6 +558,29 @@ Object execute(Object[] arguments,
549
558
}
550
559
}
551
560
561
+ private void checkArguments (Object [] arguments ) throws ArityException {
562
+ // note: we always add 1 for the context
563
+ int min ;
564
+ int max ;
565
+ if (unaryOperator != null ) {
566
+ min = max = 2 ;
567
+ } else if (binaryOperator != null ) {
568
+ min = max = 3 ;
569
+ } else if (inplaceOperator != null ) {
570
+ min = 3 ;
571
+ max = 4 ;
572
+ } else if (ternaryOperator != null ) {
573
+ min = max = 4 ;
574
+ } else {
575
+ throw CompilerDirectives .shouldNotReachHere ();
576
+ }
577
+ if (min > arguments .length || max < arguments .length ) {
578
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
579
+ int expected = min > arguments .length ? min : max ;
580
+ throw ArityException .create (expected , arguments .length );
581
+ }
582
+ }
583
+
552
584
private RootCallTarget getCallTarget (GraalHPyArithmetic receiver , PythonLanguage language ) {
553
585
RootCallTarget callTarget = receiver .callTarget ;
554
586
if (callTarget == null ) {
0 commit comments