Skip to content

Commit b0c8f99

Browse files
committed
Fixes for Truffle TCK tests.
1 parent 60b0938 commit b0c8f99

File tree

4 files changed

+144
-28
lines changed

4 files changed

+144
-28
lines changed

graalpython/com.oracle.graal.python.tck/src/com/oracle/graal/python/tck/PythonProvider.java

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,8 @@ public Collection<? extends Snippet> createValueConstructors(Context context) {
129129
addValueSnippet(context, snippets, "DictType:KeyString", OBJECT, "lambda: {'Bacon':1, 'Ham': 0}");
130130
addValueSnippet(context, snippets, "DictType:KeyNumber", OBJECT, "lambda: {1: 'Bacon', 0: 'Ham'}");
131131

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");
135134

136135
// @formatter:on
137136
return snippets;
@@ -150,11 +149,9 @@ public Collection<? extends Snippet> createExpressions(Context context) {
150149
addExpressionSnippet(context, snippets, "-", "lambda x, y: x - y", NUMBER_OBJECT, PNUMBER, PNUMBER);
151150

152151
// 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);
158155

159156
// division
160157
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 {
332329
Value par1 = parameters.get(1);
333330

334331
// 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+
}
338341
}
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();
342361
}
343362
} else {
344363
ResultVerifier.getDefaultResultVerifier().accept(snippetRun);
345364
}
346365
}
347366

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");
350381
}
351382

352383
private static boolean hasMemoryError(SnippetRun snippetRun) {
@@ -358,7 +389,7 @@ private static boolean hasMemoryError(SnippetRun snippetRun) {
358389
}
359390

360391
private static boolean isInteger(Value par0) {
361-
return par0.isNumber() && par0.fitsInInt();
392+
return (par0.isNumber() && par0.fitsInInt() || par0.isBoolean()) && !isSequence(par0);
362393
}
363394

364395
private static final PSequenceMultiplicationVerifier INSTANCE = new PSequenceMultiplicationVerifier();
@@ -391,6 +422,35 @@ public void accept(SnippetRun snippetRun) throws PolyglotException {
391422
private static final PNoListCoercionVerifier INSTANCE = new PNoListCoercionVerifier();
392423
}
393424

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+
394454
/**
395455
* Only accepts exact matches of types.
396456
*/

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/TruffleObjectBuiltins.java

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__;
3737
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GE__;
3838
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GT__;
39-
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ITER__;
4039
import static com.oracle.graal.python.nodes.SpecialMethodNames.__INDEX__;
40+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ITER__;
4141
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__;
4242
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LE__;
4343
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LT__;
@@ -65,6 +65,7 @@
6565
import com.oracle.graal.python.builtins.PythonBuiltins;
6666
import com.oracle.graal.python.builtins.objects.PNone;
6767
import com.oracle.graal.python.builtins.objects.PNotImplemented;
68+
import com.oracle.graal.python.builtins.objects.foreign.TruffleObjectBuiltinsFactory.MulNodeFactory;
6869
import com.oracle.graal.python.builtins.objects.function.PKeyword;
6970
import com.oracle.graal.python.builtins.objects.list.PList;
7071
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins;
@@ -265,8 +266,11 @@ Object doGeneric(Object self) {
265266
@GenerateNodeFactory
266267
abstract static class MulNode extends UnboxNode {
267268
@Child private LookupAndCallBinaryNode mulNode = BinaryArithmetic.Mul.create();
269+
@Child private MulNode recursive;
268270

269-
@Specialization(guards = {"isBoxed(left)", "!isForeignObject(right)"})
271+
public abstract Object executeWith(Object left, Object right);
272+
273+
@Specialization(guards = {"isBoxed(left)", "!isForeignArray(left)", "!isForeignObject(right)"})
270274
Object doForeignBoxed(TruffleObject left, Object right) {
271275
try {
272276
return mulNode.executeObject(unboxLeft(left), right);
@@ -275,10 +279,10 @@ Object doForeignBoxed(TruffleObject left, Object right) {
275279
}
276280
}
277281

278-
@Specialization(guards = {"isBoxed(left)", "isBoxed(right)"})
282+
@Specialization(guards = {"isBoxed(left)", "!isForeignArray(left)", "isBoxed(right)", "!isForeignArray(right)"})
279283
Object doForeignBoxed(TruffleObject left, TruffleObject right) {
280284
try {
281-
return doForeignBoxed(left, unboxRight(right));
285+
return getRecursiveNode().executeWith(left, unboxRight(right));
282286
} catch (UnsupportedMessageException e) {
283287
// fall through
284288
}
@@ -308,7 +312,7 @@ Object doForeignArray(TruffleObject left, int right,
308312
}
309313
}
310314

311-
@Specialization(guards = {"isForeignArray(left)", "isBoxed(right)"})
315+
@Specialization(guards = {"isForeignArray(left)", "isBoxed(right)", "!isForeignArray(right)"})
312316
Object doForeignArray(TruffleObject left, TruffleObject right,
313317
@Cached("READ.createNode()") Node readNode,
314318
@Cached("GET_SIZE.createNode()") Node sizeNode) {
@@ -339,14 +343,20 @@ Object doForeignArray(TruffleObject left, @SuppressWarnings("unused") boolean ri
339343
}
340344

341345
@SuppressWarnings("unused")
342-
@Specialization(guards = {"isForeignArray(left)", "!isPositive(right)"})
346+
@Specialization(guards = {"isForeignArray(left)", "!right"})
347+
Object doForeignArrayEmpty(TruffleObject left, boolean right) {
348+
return factory().createList();
349+
}
350+
351+
@SuppressWarnings("unused")
352+
@Specialization(guards = {"isForeignArray(left)", "right <= 0"})
343353
Object doForeignArrayEmpty(TruffleObject left, int right) {
344354
return factory().createList();
345355
}
346356

347357
@SuppressWarnings("unused")
348-
@Specialization(guards = {"isForeignArray(left)", "!right"})
349-
Object doForeignArrayEmpty(TruffleObject left, boolean right) {
358+
@Specialization(guards = {"isForeignArray(left)", "right <= 0"})
359+
Object doForeignArrayEmpty(TruffleObject left, long right) {
350360
return factory().createList();
351361
}
352362

@@ -359,6 +369,14 @@ PNotImplemented doGeneric(Object left, Object right) {
359369
protected boolean isPositive(int right) {
360370
return right > 0;
361371
}
372+
373+
private MulNode getRecursiveNode() {
374+
if (recursive == null) {
375+
CompilerDirectives.transferToInterpreterAndInvalidate();
376+
recursive = insert(MulNodeFactory.create(null));
377+
}
378+
return recursive;
379+
}
362380
}
363381

364382
@Builtin(name = __RMUL__, fixedNumOfArguments = 2)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/PInt.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ public boolean isZeroOrPositive() {
129129
return value.compareTo(BigInteger.ZERO) >= 0;
130130
}
131131

132+
@TruffleBoundary
133+
public boolean isZeroOrNegative() {
134+
return value.compareTo(BigInteger.ZERO) <= 0;
135+
}
136+
132137
public static int intValue(boolean bool) {
133138
return bool ? 1 : 0;
134139
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
import com.oracle.truffle.api.dsl.ImportStatic;
106106
import com.oracle.truffle.api.dsl.Specialization;
107107
import com.oracle.truffle.api.dsl.TypeSystemReference;
108+
import com.oracle.truffle.api.profiles.BranchProfile;
108109
import com.oracle.truffle.api.profiles.ConditionProfile;
109110
import com.oracle.truffle.api.profiles.ValueProfile;
110111

@@ -1183,19 +1184,51 @@ PList doPListInt(PList left, int right,
11831184
}
11841185
}
11851186

1186-
@Specialization(rewriteOn = ArithmeticException.class)
1187-
PList doPListBigInt(PList left, long right,
1187+
@Specialization(guards = "right <= 0")
1188+
PList doPListLongNegative(@SuppressWarnings("unused") PList left, @SuppressWarnings("unused") long right) {
1189+
return factory().createList();
1190+
}
1191+
1192+
@Specialization(guards = "right > 0", rewriteOn = ArithmeticException.class)
1193+
PList doPListLong(PList left, long right,
1194+
@Cached("createClassProfile()") ValueProfile profile) {
1195+
return doPListInt(left, PInt.intValueExact(right), profile);
1196+
}
1197+
1198+
@Specialization(replaces = "doPListLong")
1199+
PList doPListLongOvf(PList left, long right,
1200+
@Cached("create()") BranchProfile notPositiveProfile,
11881201
@Cached("createClassProfile()") ValueProfile profile) {
1202+
if (right <= 0) {
1203+
notPositiveProfile.enter();
1204+
return factory().createList();
1205+
}
11891206
try {
11901207
return doPListInt(left, PInt.intValueExact(right), profile);
11911208
} catch (ArithmeticException e) {
11921209
throw raise(OverflowError, CANNOT_FIT_MESSAGE);
11931210
}
11941211
}
11951212

1196-
@Specialization(rewriteOn = ArithmeticException.class)
1213+
@Specialization(guards = "right.isZeroOrNegative()", rewriteOn = ArithmeticException.class)
1214+
PList doPListBigIntNegative(@SuppressWarnings("unused") PList left, @SuppressWarnings("unused") PInt right) {
1215+
return factory().createList();
1216+
}
1217+
1218+
@Specialization(guards = "!right.isZeroOrNegative()", rewriteOn = ArithmeticException.class)
11971219
PList doPListBigInt(PList left, PInt right,
11981220
@Cached("createClassProfile()") ValueProfile profile) {
1221+
return doPListInt(left, right.intValueExact(), profile);
1222+
}
1223+
1224+
@Specialization(replaces = "doPListBigInt")
1225+
PList doPListBigIntOvf(PList left, PInt right,
1226+
@Cached("create()") BranchProfile notPositiveProfile,
1227+
@Cached("createClassProfile()") ValueProfile profile) {
1228+
if (right.isZeroOrNegative()) {
1229+
notPositiveProfile.enter();
1230+
return factory().createList();
1231+
}
11991232
try {
12001233
return doPListInt(left, right.intValueExact(), profile);
12011234
} catch (ArithmeticException | OutOfMemoryError e) {

0 commit comments

Comments
 (0)