1
1
/*
2
- * Copyright (c) 2018, 2023 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2018, 2024 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* The Universal Permissive License (UPL), Version 1.0
78
78
import org .graalvm .polyglot .tck .ResultVerifier ;
79
79
import org .graalvm .polyglot .tck .Snippet ;
80
80
import org .graalvm .polyglot .tck .TypeDescriptor ;
81
+ import org .junit .Assert ;
81
82
82
83
public class PythonProvider implements LanguageProvider {
83
84
@@ -226,28 +227,36 @@ public Collection<? extends Snippet> createValueConstructors(Context context) {
226
227
public Collection <? extends Snippet > createExpressions (Context context ) {
227
228
List <Snippet > snippets = new ArrayList <>();
228
229
230
+ TypeDescriptor numeric = union (BOOLEAN , NUMBER );
231
+ TypeDescriptor numericArray = array (numeric );
232
+
229
233
// @formatter:off
230
- addExpressionSnippet (context , snippets , "+" , "lambda x, y: x + y" , NUMBER , new NonPrimitiveNumberParameterThrows (AddVerifier .INSTANCE ), union ( BOOLEAN , NUMBER ), union ( BOOLEAN , NUMBER ) );
231
- addExpressionSnippet (context , snippets , "+" , "lambda x, y: x + y" , union (STRING , array (ANY )), AddVerifier .INSTANCE , union ( BOOLEAN , NUMBER ) , union (STRING , array (ANY )));
232
- addExpressionSnippet (context , snippets , "+" , "lambda x, y: x + y" , union (STRING , array (ANY )), AddVerifier .INSTANCE , union (STRING , array (ANY )), union ( BOOLEAN , NUMBER ) );
234
+ addExpressionSnippet (context , snippets , "+" , "lambda x, y: x + y" , NUMBER , new NonPrimitiveNumberParameterThrows (AddVerifier .INSTANCE ), numeric , numeric );
235
+ addExpressionSnippet (context , snippets , "+" , "lambda x, y: x + y" , union (STRING , array (ANY )), AddVerifier .INSTANCE , numeric , union (STRING , array (ANY )));
236
+ addExpressionSnippet (context , snippets , "+" , "lambda x, y: x + y" , union (STRING , array (ANY )), AddVerifier .INSTANCE , union (STRING , array (ANY )), numeric );
233
237
addExpressionSnippet (context , snippets , "+" , "lambda x, y: x + y" , union (STRING , array (ANY )), AddVerifier .INSTANCE , union (STRING , array (ANY )), union (STRING , array (ANY )));
234
- addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , NUMBER , new NonPrimitiveNumberParameterThrows (MulVerifier .INSTANCE ), union ( BOOLEAN , NUMBER ), union ( BOOLEAN , NUMBER ) );
235
- addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , union (STRING , array (ANY )), MulVerifier .INSTANCE , union ( BOOLEAN , NUMBER ) , union (STRING , array (ANY )));
236
- addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , union (STRING , array (ANY )), MulVerifier .INSTANCE , union (STRING , array (ANY )), union ( BOOLEAN , NUMBER ) );
238
+ addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , NUMBER , new NonPrimitiveNumberParameterThrows (MulVerifier .INSTANCE ), numeric , numeric );
239
+ addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , union (STRING , array (ANY )), MulVerifier .INSTANCE , numeric , union (STRING , array (ANY )));
240
+ addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , union (STRING , array (ANY )), MulVerifier .INSTANCE , union (STRING , array (ANY )), numeric );
237
241
addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , union (STRING , array (ANY )), MulVerifier .INSTANCE , union (STRING , array (ANY )), union (STRING , array (ANY )));
238
242
239
- addExpressionSnippet (context , snippets , "-" , "lambda x, y: x - y" , NUMBER , NonPrimitiveNumberParameterThrows .INSTANCE , union ( BOOLEAN , NUMBER ), union ( BOOLEAN , NUMBER ) );
243
+ addExpressionSnippet (context , snippets , "-" , "lambda x, y: x - y" , NUMBER , NonPrimitiveNumberParameterThrows .INSTANCE , numeric , numeric );
240
244
241
- addExpressionSnippet (context , snippets , "/" , "lambda x, y: x / y" , NUMBER , new NonPrimitiveNumberParameterThrows (PDivByZeroVerifier .INSTANCE ), union ( BOOLEAN , NUMBER ), union ( BOOLEAN , NUMBER ) );
245
+ addExpressionSnippet (context , snippets , "/" , "lambda x, y: x / y" , NUMBER , new NonPrimitiveNumberParameterThrows (PDivByZeroVerifier .INSTANCE ), numeric , numeric );
242
246
243
247
addExpressionSnippet (context , snippets , "list-from-foreign" , "lambda x: list(x)" , array (ANY ), union (STRING , iterable (ANY ), iterator (ANY ), array (ANY ), hash (ANY , ANY )));
244
248
245
249
addExpressionSnippet (context , snippets , "==" , "lambda x, y: x == y" , BOOLEAN , ANY , ANY );
246
250
addExpressionSnippet (context , snippets , "!=" , "lambda x, y: x != y" , BOOLEAN , ANY , ANY );
247
- addExpressionSnippet (context , snippets , ">" , "lambda x, y: x > y" , BOOLEAN , NonPrimitiveNumberParameterThrows .INSTANCE , union (BOOLEAN , NUMBER ), union (BOOLEAN , NUMBER ));
248
- addExpressionSnippet (context , snippets , ">=" , "lambda x, y: x >= y" , BOOLEAN , NonPrimitiveNumberParameterThrows .INSTANCE , union (BOOLEAN , NUMBER ), union (BOOLEAN , NUMBER ));
249
- addExpressionSnippet (context , snippets , "<" , "lambda x, y: x < y" , BOOLEAN , NonPrimitiveNumberParameterThrows .INSTANCE , union (BOOLEAN , NUMBER ), union (BOOLEAN , NUMBER ));
250
- addExpressionSnippet (context , snippets , "<=" , "lambda x, y: x <= y" , BOOLEAN , NonPrimitiveNumberParameterThrows .INSTANCE , union (BOOLEAN , NUMBER ), union (BOOLEAN , NUMBER ));
251
+
252
+ addExpressionSnippet (context , snippets , ">" , "lambda x, y: x > y" , BOOLEAN , NonPrimitiveNumberParameterThrows .INSTANCE , numeric , numeric );
253
+ addExpressionSnippet (context , snippets , ">" , "lambda x, y: x > y" , BOOLEAN , ExpectTypeErrorForDifferentPythonSequenceTypes .INSTANCE , numericArray , numericArray );
254
+ addExpressionSnippet (context , snippets , ">=" , "lambda x, y: x >= y" , BOOLEAN , NonPrimitiveNumberParameterThrows .INSTANCE , numeric , numeric );
255
+ addExpressionSnippet (context , snippets , ">=" , "lambda x, y: x >= y" , BOOLEAN , ExpectTypeErrorForDifferentPythonSequenceTypes .INSTANCE , numericArray , numericArray );
256
+ addExpressionSnippet (context , snippets , "<" , "lambda x, y: x < y" , BOOLEAN , NonPrimitiveNumberParameterThrows .INSTANCE , numeric , numeric );
257
+ addExpressionSnippet (context , snippets , "<" , "lambda x, y: x < y" , BOOLEAN , ExpectTypeErrorForDifferentPythonSequenceTypes .INSTANCE , numericArray , numericArray );
258
+ addExpressionSnippet (context , snippets , "<=" , "lambda x, y: x <= y" , BOOLEAN , NonPrimitiveNumberParameterThrows .INSTANCE , numeric , numeric );
259
+ addExpressionSnippet (context , snippets , "<=" , "lambda x, y: x <= y" , BOOLEAN , ExpectTypeErrorForDifferentPythonSequenceTypes .INSTANCE , numericArray , numericArray );
251
260
252
261
addExpressionSnippet (context , snippets , "isinstance" , "lambda x, y: isinstance(x, y)" , BOOLEAN , ANY , META_OBJECT );
253
262
addExpressionSnippet (context , snippets , "issubclass" , "lambda x, y: issubclass(x, y)" , BOOLEAN , META_OBJECT , META_OBJECT );
@@ -360,6 +369,35 @@ private static Source createSource(String resourceName) throws IOException {
360
369
private abstract static class PResultVerifier implements ResultVerifier {
361
370
}
362
371
372
+ private static class ExpectTypeErrorForDifferentPythonSequenceTypes extends PResultVerifier {
373
+
374
+ public void accept (SnippetRun snippetRun ) throws PolyglotException {
375
+ List <? extends Value > parameters = snippetRun .getParameters ();
376
+ assert parameters .size () == 2 ;
377
+
378
+ Value a = parameters .get (0 );
379
+ Value b = parameters .get (1 );
380
+
381
+ // If both parameter values are Python sequences, then ignore if they have different
382
+ // types. E.g. ignore '(1,2) < [3,4]'.
383
+ if (a .hasArrayElements () && b .hasArrayElements () && isPythonObject (a ) && isPythonObject (b ) && !a .getMetaObject ().equals (b .getMetaObject ())) {
384
+ // Expect TypeError
385
+ var exception = snippetRun .getException ();
386
+ assert exception != null ;
387
+ Assert .assertEquals ("TypeError" , exception .getGuestObject ().getMetaObject ().getMetaQualifiedName ());
388
+ } else {
389
+ ResultVerifier .getDefaultResultVerifier ().accept (snippetRun );
390
+ }
391
+ }
392
+
393
+ private static boolean isPythonObject (Value value ) {
394
+ var metaObject = value .getMetaObject ();
395
+ return metaObject .hasMember ("__mro__" );
396
+ }
397
+
398
+ private static final ExpectTypeErrorForDifferentPythonSequenceTypes INSTANCE = new ExpectTypeErrorForDifferentPythonSequenceTypes ();
399
+ }
400
+
363
401
/**
364
402
* Only accepts exact matches of types.
365
403
*/
@@ -378,16 +416,16 @@ public void accept(SnippetRun snippetRun) throws PolyglotException {
378
416
if (par0 .getMetaObject () == par1 .getMetaObject ()) {
379
417
assert snippetRun .getException () == null ;
380
418
TypeDescriptor resultType = TypeDescriptor .forValue (snippetRun .getResult ());
381
- assert array (ANY ).isAssignable (resultType );
419
+ assert array (ANY ).isAssignable (resultType ) : resultType ;
382
420
}
383
421
} else if (par0 .isString () && par1 .isString ()) {
384
422
assert snippetRun .getException () == null ;
385
423
TypeDescriptor resultType = TypeDescriptor .forValue (snippetRun .getResult ());
386
- assert STRING .isAssignable (resultType );
424
+ assert STRING .isAssignable (resultType ) : resultType ;
387
425
} else if ((par0 .isNumber () || par0 .isBoolean ()) && (par1 .isNumber () || par1 .isBoolean ())) {
388
426
assert snippetRun .getException () == null ;
389
427
TypeDescriptor resultType = TypeDescriptor .forValue (snippetRun .getResult ());
390
- assert NUMBER .isAssignable (resultType );
428
+ assert NUMBER .isAssignable (resultType ) : resultType ;
391
429
} else {
392
430
assert snippetRun .getException () != null ;
393
431
TypeDescriptor argType = union (STRING , BOOLEAN , NUMBER , array (ANY ));
@@ -426,17 +464,17 @@ public void accept(SnippetRun snippetRun) throws PolyglotException {
426
464
// string * number => string
427
465
assert snippetRun .getException () == null ;
428
466
TypeDescriptor resultType = TypeDescriptor .forValue (snippetRun .getResult ());
429
- assert STRING .isAssignable (resultType );
467
+ assert STRING .isAssignable (resultType ) : resultType ;
430
468
} else if ((par0 .isNumber () || par0 .isBoolean ()) && (par1 .isNumber () || par1 .isBoolean ())) {
431
- // number * number has greater precendence than array * number
469
+ // number * number has greater precedence than array * number
432
470
assert snippetRun .getException () == null ;
433
471
TypeDescriptor resultType = TypeDescriptor .forValue (snippetRun .getResult ());
434
- assert NUMBER .isAssignable (resultType ) : resultType . toString () ;
472
+ assert NUMBER .isAssignable (resultType ) : resultType ;
435
473
} else if (isArrayMul (par0 , par1 ) || isArrayMul (par1 , par0 )) {
436
474
// array * number => array
437
475
assert snippetRun .getException () == null ;
438
476
TypeDescriptor resultType = TypeDescriptor .forValue (snippetRun .getResult ());
439
- assert array (ANY ).isAssignable (resultType );
477
+ assert array (ANY ).isAssignable (resultType ) : resultType ;
440
478
} else {
441
479
assert snippetRun .getException () != null ;
442
480
TypeDescriptor argType = union (STRING , BOOLEAN , NUMBER , array (ANY ));
0 commit comments