Skip to content

Commit ab7d4dd

Browse files
committed
[GR-23203] Fix test_binop
PullRequest: graalpython/1031
2 parents 61c4aeb + d8c3718 commit ab7d4dd

File tree

6 files changed

+50
-21
lines changed

6 files changed

+50
-21
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_binop.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
*graalpython.lib-python.3.test.test_binop.FallbackBlockingTests.test_fallback_ne_blocking
2+
*graalpython.lib-python.3.test.test_binop.FallbackBlockingTests.test_fallback_rmethod_blocking
3+
*graalpython.lib-python.3.test.test_binop.OperationOrderTests.test_comparison_orders
24
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_add
5+
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_constructor
36
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_div
47
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_eq
58
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_floordiv

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,15 @@ public int hash(Object self) {
234234
public abstract static class EqNode extends PythonBinaryBuiltinNode {
235235
@Specialization
236236
Object eq(Object self, Object other,
237+
@Cached ConditionProfile isEq,
237238
@Cached IsNode isNode) {
238-
return isNode.execute(self, other);
239+
if (isEq.profile(isNode.execute(self, other))) {
240+
return true;
241+
} else {
242+
// Return NotImplemented instead of False, so if two objects are compared, both get
243+
// a chance at the comparison
244+
return PNotImplemented.NOT_IMPLEMENTED;
245+
}
239246
}
240247
}
241248

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringBuiltins.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
import com.oracle.graal.python.builtins.objects.str.StringNodes.StringLenNode;
8585
import com.oracle.graal.python.builtins.objects.str.StringUtils.StripKind;
8686
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
87+
import com.oracle.graal.python.builtins.objects.tuple.TupleBuiltins;
8788
import com.oracle.graal.python.nodes.ErrorMessages;
8889
import com.oracle.graal.python.nodes.PGuards;
8990
import com.oracle.graal.python.nodes.SpecialMethodNames;
@@ -1512,10 +1513,12 @@ Object doStringObject(VirtualFrame frame, String self, Object right,
15121513
@CachedLibrary(limit = "3") PythonObjectLibrary plib,
15131514
@Shared("lookupAttrNode") @Cached LookupAttributeInMRONode.Dynamic lookupAttrNode,
15141515
@Shared("getItemNode") @Cached("create(__GETITEM__)") LookupAndCallBinaryNode getItemNode,
1516+
@Shared("getTupleItemNode") @Cached TupleBuiltins.GetItemNode getTupleItemNode,
15151517
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
15161518
Object state = IndirectCallContext.enter(frame, context, this);
15171519
try {
1518-
return new StringFormatter(context.getCore(), self).format(right, callNode, (object, key) -> lookupAttrNode.execute(plib.getLazyPythonClass(object), key), getItemNode);
1520+
return new StringFormatter(context.getCore(), self).format(right, callNode, (object, key) -> lookupAttrNode.execute(plib.getLazyPythonClass(object), key), getItemNode,
1521+
getTupleItemNode);
15191522
} finally {
15201523
IndirectCallContext.exit(frame, context, state);
15211524
}
@@ -1528,10 +1531,11 @@ Object doGeneric(VirtualFrame frame, Object self, Object right,
15281531
@CachedLibrary(limit = "3") PythonObjectLibrary plib,
15291532
@Shared("lookupAttrNode") @Cached LookupAttributeInMRONode.Dynamic lookupAttrNode,
15301533
@Shared("getItemNode") @Cached("create(__GETITEM__)") LookupAndCallBinaryNode getItemNode,
1534+
@Shared("getTupleItemNode") @Cached TupleBuiltins.GetItemNode getTupleItemNode,
15311535
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
15321536

15331537
String selfStr = castSelfNode.cast(self, INVALID_RECEIVER, __MOD__, self);
1534-
return doStringObject(frame, selfStr, right, callNode, plib, lookupAttrNode, getItemNode, context);
1538+
return doStringObject(frame, selfStr, right, callNode, plib, lookupAttrNode, getItemNode, getTupleItemNode, context);
15351539
}
15361540
}
15371541

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallBinaryNode.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ public abstract static class NotImplementedHandler extends PNodeWithContext {
7474
protected final String name;
7575
protected final String rname;
7676
protected final Supplier<NotImplementedHandler> handlerFactory;
77+
private final boolean alwaysCheckReverse;
7778

7879
@Child private CallBinaryMethodNode dispatchNode;
7980
@Child private CallBinaryMethodNode reverseDispatchNode;
@@ -103,27 +104,32 @@ public abstract static class NotImplementedHandler extends PNodeWithContext {
103104

104105
public abstract Object executeObject(VirtualFrame frame, Object arg, Object arg2);
105106

106-
LookupAndCallBinaryNode(String name, String rname, Supplier<NotImplementedHandler> handlerFactory) {
107+
LookupAndCallBinaryNode(String name, String rname, Supplier<NotImplementedHandler> handlerFactory, boolean alwaysCheckReverse) {
107108
this.name = name;
108109
this.rname = rname;
109110
this.handlerFactory = handlerFactory;
111+
this.alwaysCheckReverse = alwaysCheckReverse;
110112
}
111113

112114
public static LookupAndCallBinaryNode create(String name) {
113-
return LookupAndCallBinaryNodeGen.create(name, null, null);
115+
return LookupAndCallBinaryNodeGen.create(name, null, null, false);
114116
}
115117

116118
public static LookupAndCallBinaryNode createReversible(String name, String reverseName, Supplier<NotImplementedHandler> handlerFactory) {
117119
assert name.startsWith("__") && reverseName.startsWith("__r");
118-
return LookupAndCallBinaryNodeGen.create(name, reverseName, handlerFactory);
120+
return LookupAndCallBinaryNodeGen.create(name, reverseName, handlerFactory, false);
119121
}
120122

121123
public static LookupAndCallBinaryNode create(String name, String rname) {
122-
return LookupAndCallBinaryNodeGen.create(name, rname, null);
124+
return LookupAndCallBinaryNodeGen.create(name, rname, null, false);
125+
}
126+
127+
public static LookupAndCallBinaryNode create(String name, String rname, boolean alwaysCheckReverse) {
128+
return LookupAndCallBinaryNodeGen.create(name, rname, null, alwaysCheckReverse);
123129
}
124130

125131
public static LookupAndCallBinaryNode create(String name, String rname, Supplier<NotImplementedHandler> handlerFactory) {
126-
return LookupAndCallBinaryNodeGen.create(name, rname, handlerFactory);
132+
return LookupAndCallBinaryNodeGen.create(name, rname, handlerFactory, false);
127133
}
128134

129135
protected Object getMethod(Object receiver, String methodName) {
@@ -316,7 +322,7 @@ Object callObject(VirtualFrame frame, Object left, Object right,
316322
Object leftCallable = getattr.execute(leftClass);
317323
Object rightClass = libRight.getLazyPythonClass(right);
318324
Object rightCallable = getattrR.execute(rightClass);
319-
if (leftCallable == rightCallable) {
325+
if (!alwaysCheckReverse && leftCallable == rightCallable) {
320326
rightCallable = PNone.NO_VALUE;
321327
}
322328
if (leftCallable != PNone.NO_VALUE) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/BinaryComparisonNode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ public abstract class BinaryComparisonNode extends BinaryOpNode {
5656
this.magicMethod = magicMethod;
5757
this.magicReverseMethod = magicReverseMethod;
5858
this.operation = operation;
59-
this.callNode = LookupAndCallBinaryNode.create(magicMethod, magicReverseMethod);
59+
// see cpython://Objects/object.c#do_richcompare - CPython always calls the reverse method
60+
this.callNode = LookupAndCallBinaryNode.create(magicMethod, magicReverseMethod, true);
6061
}
6162

6263
public static BinaryComparisonNode create(String magicMethod, String magicReverseMethod, String operation, ExpressionNode left, ExpressionNode right) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.oracle.graal.python.builtins.objects.ints.PInt;
2727
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
2828
import com.oracle.graal.python.builtins.objects.str.PString;
29+
import com.oracle.graal.python.builtins.objects.tuple.TupleBuiltins;
2930
import com.oracle.graal.python.nodes.ErrorMessages;
3031
import com.oracle.graal.python.nodes.PGuards;
3132
import com.oracle.graal.python.nodes.call.CallNode;
@@ -67,7 +68,7 @@ public StringFormatter(PythonCore core, String format) {
6768
buffer = new StringBuilder(format.length() + 100);
6869
}
6970

70-
Object getarg(LookupAndCallBinaryNode getItemNode) {
71+
Object getarg(TupleBuiltins.GetItemNode getTupleItemNode) {
7172
Object ret = null;
7273
switch (argIndex) {
7374
case -3: // special index indicating a mapping
@@ -79,7 +80,14 @@ Object getarg(LookupAndCallBinaryNode getItemNode) {
7980
return args;
8081
default:
8182
// NOTE: passing 'null' frame means we already took care of the global state earlier
82-
ret = getItemNode.executeObject(null, args, argIndex++);
83+
// args is definitely a tuple at this point. CPython access the tuple storage
84+
// directly, so the only error can be IndexError, which we ignore and transform into
85+
// the TypeError below.
86+
try {
87+
ret = getTupleItemNode.execute(null, args, argIndex++);
88+
} catch (PException e) {
89+
// fall through
90+
}
8391
break;
8492
}
8593
if (ret == null) {
@@ -88,10 +96,10 @@ Object getarg(LookupAndCallBinaryNode getItemNode) {
8896
return ret;
8997
}
9098

91-
int getNumber(LookupAndCallBinaryNode getItemNode) {
99+
int getNumber(TupleBuiltins.GetItemNode getTupleItemNode) {
92100
char c = pop();
93101
if (c == '*') {
94-
Object o = getarg(getItemNode);
102+
Object o = getarg(getTupleItemNode);
95103
if (o instanceof Long) {
96104
return ((Long) o).intValue();
97105
} else if (o instanceof Integer) {
@@ -164,7 +172,7 @@ private static Object asFloat(Object arg, CallNode callNode, BiFunction<Object,
164172
* construction.
165173
*/
166174
@TruffleBoundary
167-
public Object format(Object args1, CallNode callNode, BiFunction<Object, String, Object> lookupAttribute, LookupAndCallBinaryNode getItemNode) {
175+
public Object format(Object args1, CallNode callNode, BiFunction<Object, String, Object> lookupAttribute, LookupAndCallBinaryNode getItemNode, TupleBuiltins.GetItemNode getTupleItemNode) {
168176
Object mapping = null;
169177
this.args = args1;
170178

@@ -272,7 +280,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
272280
* after the minimum field width and optional precision. A custom getNumber() takes care
273281
* of the '*' case.
274282
*/
275-
width = getNumber(getItemNode);
283+
width = getNumber(getTupleItemNode);
276284
if (width < 0) {
277285
width = -width;
278286
align = '<';
@@ -286,7 +294,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
286294
*/
287295
c = pop();
288296
if (c == '.') {
289-
precision = getNumber(getItemNode);
297+
precision = getNumber(getTupleItemNode);
290298
if (precision < -1) {
291299
precision = 0;
292300
}
@@ -341,7 +349,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
341349

342350
switch (spec.type) {
343351
case 'b':
344-
Object arg = getarg(getItemNode);
352+
Object arg = getarg(getTupleItemNode);
345353
f = ft = new TextFormatter(core, buffer, spec);
346354
ft.setBytes(true);
347355
Object bytesAttribute;
@@ -360,7 +368,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
360368
break;
361369
case 's': // String: converts any object using __str__(), __unicode__() ...
362370
case 'r': // ... or repr().
363-
arg = getarg(getItemNode);
371+
arg = getarg(getTupleItemNode);
364372
// Get hold of the actual object to display (may set needUnicode)
365373
Object attribute = spec.type == 's' ? lookupAttribute.apply(arg, __STR__) : lookupAttribute.apply(arg, __REPR__);
366374
if (attribute != PNone.NO_VALUE) {
@@ -383,7 +391,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
383391
case 'i': // Compatibility with scanf().
384392
// Format the argument using this Spec.
385393

386-
arg = getarg(getItemNode);
394+
arg = getarg(getTupleItemNode);
387395

388396
// Note various types accepted here as long as they have an __int__ method.
389397
Object argAsNumber = asNumber(arg, callNode, lookupAttribute);
@@ -422,7 +430,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
422430
f = ff = new FloatFormatter(core, buffer, spec);
423431

424432
// Note various types accepted here as long as they have a __float__ method.
425-
arg = getarg(getItemNode);
433+
arg = getarg(getTupleItemNode);
426434
Object argAsFloat = asFloat(arg, callNode, lookupAttribute);
427435

428436
// We have to check what we got back..

0 commit comments

Comments
 (0)