@@ -129,9 +129,8 @@ public Collection<? extends Snippet> createValueConstructors(Context context) {
129
129
addValueSnippet (context , snippets , "DictType:KeyString" , OBJECT , "lambda: {'Bacon':1, 'Ham': 0}" );
130
130
addValueSnippet (context , snippets , "DictType:KeyNumber" , OBJECT , "lambda: {1: 'Bacon', 0: 'Ham'}" );
131
131
132
- // TODO remove '*args' from following value constructors once this is fixed in Truffle TCK
133
- addValueSnippet (context , snippets , "LambdaType:Id" , executable (ANY , ANY ), "lambda: lambda x, *args: x" );
134
- addValueSnippet (context , snippets , "LambdaType:+1" , executable (NUMBER , NUMBER ), "lambda: lambda x, *args: x + 1" );
132
+ addValueSnippet (context , snippets , "LambdaType:Id" , executable (ANY , ANY ), "lambda: lambda x: x" );
133
+ addValueSnippet (context , snippets , "LambdaType:+1" , executable (NUMBER , NUMBER ), "lambda: lambda x: x + 1" );
135
134
136
135
// @formatter:on
137
136
return snippets ;
@@ -150,11 +149,9 @@ public Collection<? extends Snippet> createExpressions(Context context) {
150
149
addExpressionSnippet (context , snippets , "-" , "lambda x, y: x - y" , NUMBER_OBJECT , PNUMBER , PNUMBER );
151
150
152
151
// multiplication
153
- addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , NUMBER_OBJECT , PNUMBER , PNUMBER );
154
- addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , STRING , PSequenceMultiplicationVerifier .INSTANCE , PNUMBER , STRING );
155
- addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , STRING , PSequenceMultiplicationVerifier .INSTANCE , STRING , PNUMBER );
156
- addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , array (ANY ), PSequenceMultiplicationVerifier .INSTANCE , array (ANY ), PNUMBER );
157
- addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , array (ANY ), PSequenceMultiplicationVerifier .INSTANCE , PNUMBER , array (ANY ));
152
+ addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , NUMBER_OBJECT , PNoArrayVerifier .INSTANCE , PNUMBER , PNUMBER );
153
+ addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , PSEQUENCE_OBJECT , PSequenceMultiplicationVerifier .INSTANCE , PNUMBER , PSEQUENCE_OBJECT );
154
+ addExpressionSnippet (context , snippets , "*" , "lambda x, y: x * y" , PSEQUENCE_OBJECT , PSequenceMultiplicationVerifier .INSTANCE , PSEQUENCE_OBJECT , PNUMBER );
158
155
159
156
// division
160
157
addExpressionSnippet (context , snippets , "/" , "lambda x, y: x / y" , NUMBER_OBJECT , PDivByZeroVerifier .INSTANCE , PNUMBER , PNUMBER );
@@ -332,21 +329,55 @@ public void accept(SnippetRun snippetRun) throws PolyglotException {
332
329
Value par1 = parameters .get (1 );
333
330
334
331
// Just restrict 'number' to integer value space
335
- if (isSequence (par0 ) && par1 .isNumber ()) {
336
- if (isInteger (par1 ) && !hasMemoryError (snippetRun )) {
337
- ResultVerifier .getDefaultResultVerifier ().accept (snippetRun );
332
+ if (isSequence (par0 ) && isNumber (par1 )) {
333
+ if (!hasMemoryError (snippetRun )) {
334
+ if (isInteger (par1 ) || isNegativeNumber (par1 )) {
335
+ ResultVerifier .getDefaultResultVerifier ().accept (snippetRun );
336
+ } else {
337
+ if (snippetRun .getException () == null ) {
338
+ throw new AssertionError ("<sequence> * <non-integer> should give an error." );
339
+ }
340
+ }
338
341
}
339
- } else if (par0 .isNumber () && isSequence (par1 )) {
340
- if (isInteger (par0 ) && !hasMemoryError (snippetRun )) {
341
- ResultVerifier .getDefaultResultVerifier ().accept (snippetRun );
342
+ } else if (isNumber (par0 ) && isSequence (par1 )) {
343
+ if (!hasMemoryError (snippetRun )) {
344
+ if (isInteger (par0 ) || isNegativeNumber (par0 )) {
345
+ ResultVerifier .getDefaultResultVerifier ().accept (snippetRun );
346
+ } else {
347
+ if (snippetRun .getException () == null ) {
348
+ throw new AssertionError ("<non-integer> * <sequence> should give an error." );
349
+ }
350
+ }
351
+ }
352
+ } else if (isNumber (par0 ) && isMapping (par1 ) || isNumber (par1 ) && isMapping (par0 )) {
353
+ if (snippetRun .getException () != null ) {
354
+ throw new AssertionError ("Multipliation with mapping should give an error." );
355
+ }
356
+ } else if (isSequence (par0 ) && isSequence (par1 )) {
357
+ if (snippetRun .getException () == null ) {
358
+ throw new AssertionError ("<sequence> * <sequence> should give an error." );
359
+ } else {
360
+ throw snippetRun .getException ();
342
361
}
343
362
} else {
344
363
ResultVerifier .getDefaultResultVerifier ().accept (snippetRun );
345
364
}
346
365
}
347
366
348
- protected boolean isSequence (Value par0 ) {
349
- return par0 .isString () || par0 .hasArrayElements ();
367
+ protected static boolean isNumber (Value par0 ) {
368
+ return par0 .isNumber () || par0 .isBoolean ();
369
+ }
370
+
371
+ protected static boolean isNegativeNumber (Value par0 ) {
372
+ return par0 .isNumber () && par0 .fitsInLong () && par0 .asLong () < 0L ;
373
+ }
374
+
375
+ protected static boolean isSequence (Value par0 ) {
376
+ return par0 .isString () || (par0 .hasArrayElements () && !isMapping (par0 ));
377
+ }
378
+
379
+ protected static boolean isMapping (Value par0 ) {
380
+ return par0 .hasMembers () && par0 .getMetaObject ().toString ().contains ("dict" );
350
381
}
351
382
352
383
private static boolean hasMemoryError (SnippetRun snippetRun ) {
@@ -358,7 +389,7 @@ private static boolean hasMemoryError(SnippetRun snippetRun) {
358
389
}
359
390
360
391
private static boolean isInteger (Value par0 ) {
361
- return par0 .isNumber () && par0 .fitsInInt ();
392
+ return ( par0 .isNumber () && par0 .fitsInInt () || par0 . isBoolean ()) && ! isSequence ( par0 );
362
393
}
363
394
364
395
private static final PSequenceMultiplicationVerifier INSTANCE = new PSequenceMultiplicationVerifier ();
@@ -391,6 +422,35 @@ public void accept(SnippetRun snippetRun) throws PolyglotException {
391
422
private static final PNoListCoercionVerifier INSTANCE = new PNoListCoercionVerifier ();
392
423
}
393
424
425
+ /**
426
+ * Foreign objects may be array-ish and boxed (e.g. if they have just one element). In this
427
+ * case, we still treat them as arrays.
428
+ */
429
+ private static class PNoArrayVerifier extends PResultVerifier {
430
+
431
+ public void accept (SnippetRun snippetRun ) throws PolyglotException {
432
+ List <? extends Value > parameters = snippetRun .getParameters ();
433
+ assert parameters .size () == 2 ;
434
+
435
+ Value par0 = parameters .get (0 );
436
+ Value par1 = parameters .get (1 );
437
+
438
+ if (isNumber (par0 ) && isNumber (par1 )) {
439
+ if (!(par0 .hasArrayElements () || par1 .hasArrayElements ())) {
440
+ ResultVerifier .getDefaultResultVerifier ().accept (snippetRun );
441
+ }
442
+ } else {
443
+ ResultVerifier .getDefaultResultVerifier ().accept (snippetRun );
444
+ }
445
+ }
446
+
447
+ private static boolean isNumber (Value val ) {
448
+ return val .isNumber () || val .isBoolean ();
449
+ }
450
+
451
+ private static final PNoArrayVerifier INSTANCE = new PNoArrayVerifier ();
452
+ }
453
+
394
454
/**
395
455
* Only accepts exact matches of types.
396
456
*/
0 commit comments