Skip to content

Commit a80e486

Browse files
committed
[GR-38885] Add missing inplace set operations
PullRequest: graalpython/2279
2 parents 8652fcd + 67e5896 commit a80e486

File tree

2 files changed

+94
-3
lines changed
  • graalpython
    • com.oracle.graal.python.test/src/tests
    • com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set

2 files changed

+94
-3
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_set.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -519,3 +519,12 @@ def __repr__(self):
519519
assert v2 in l
520520
assert v1 != v2
521521
assert len(s) == 0
522+
523+
def test_inplace_ops_mutate():
524+
for op in ('-', '&', '|', '^'):
525+
s1 = {1, 2}
526+
s2 = {1, 3}
527+
v = {'a': s1, 'b': s2}
528+
exec(f"a {op}= b", v)
529+
assert v['a'] is s1
530+
assert s1 == eval(f"a {op} b", {'a': {1, 2}, 'b': {1, 3}})

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/set/SetBuiltins.java

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@
2727

2828
import static com.oracle.graal.python.nodes.SpecialMethodNames.__AND__;
2929
import static com.oracle.graal.python.nodes.SpecialMethodNames.__HASH__;
30+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__IAND__;
3031
import static com.oracle.graal.python.nodes.SpecialMethodNames.__INIT__;
32+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__IOR__;
33+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ISUB__;
34+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__IXOR__;
3135
import static com.oracle.graal.python.nodes.SpecialMethodNames.__OR__;
3236
import static com.oracle.graal.python.nodes.SpecialMethodNames.__RAND__;
3337
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ROR__;
@@ -183,6 +187,24 @@ Object doOr(Object self, Object other) {
183187
}
184188
}
185189

190+
@Builtin(name = __IOR__, minNumOfPositionalArgs = 2)
191+
@GenerateNodeFactory
192+
public abstract static class IOrNode extends PythonBinaryBuiltinNode {
193+
@Specialization(guards = "canDoSetBinOp(other)", limit = "3")
194+
Object doSet(VirtualFrame frame, PSet self, Object other,
195+
@Cached GetHashingStorageNode getHashingStorageNode,
196+
@CachedLibrary("self.getDictStorage()") HashingStorageLibrary lib) {
197+
self.setDictStorage(lib.addAllToOther(self.getDictStorage(), getHashingStorageNode.execute(frame, other)));
198+
return self;
199+
}
200+
201+
@SuppressWarnings("unused")
202+
@Fallback
203+
Object doOr(Object self, Object other) {
204+
return PNotImplemented.NOT_IMPLEMENTED;
205+
}
206+
}
207+
186208
@Builtin(name = "union", minNumOfPositionalArgs = 1, takesVarArgs = true)
187209
@GenerateNodeFactory
188210
abstract static class UnionNode extends PythonBuiltinNode {
@@ -342,7 +364,7 @@ static PNone doSet(VirtualFrame frame, PSet self, Object other,
342364
@ImportStatic(PGuards.class)
343365
public abstract static class AndNode extends PythonBinaryBuiltinNode {
344366

345-
@Specialization(guards = "canDoSetBinOp(right)", limit = "1")
367+
@Specialization(guards = "canDoSetBinOp(right)", limit = "3")
346368
PBaseSet doPBaseSet(VirtualFrame frame, PSet left, Object right,
347369
@Cached ConditionProfile hasFrame,
348370
@Cached GetHashingStorageNode getHashingStorageNode,
@@ -358,6 +380,27 @@ Object doAnd(Object self, Object other) {
358380
}
359381
}
360382

383+
@Builtin(name = __IAND__, minNumOfPositionalArgs = 2)
384+
@GenerateNodeFactory
385+
public abstract static class IAndNode extends PythonBinaryBuiltinNode {
386+
387+
@Specialization(guards = "canDoSetBinOp(right)", limit = "3")
388+
PBaseSet doPBaseSet(VirtualFrame frame, PSet left, Object right,
389+
@Cached ConditionProfile hasFrame,
390+
@Cached GetHashingStorageNode getHashingStorageNode,
391+
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
392+
HashingStorage storage = leftLib.intersectWithFrame(left.getDictStorage(), getHashingStorageNode.execute(frame, right), hasFrame, frame);
393+
left.setDictStorage(storage);
394+
return left;
395+
}
396+
397+
@SuppressWarnings("unused")
398+
@Fallback
399+
Object doAnd(Object self, Object other) {
400+
return PNotImplemented.NOT_IMPLEMENTED;
401+
}
402+
}
403+
361404
@Builtin(name = "intersection", minNumOfPositionalArgs = 1, takesVarArgs = true)
362405
@GenerateNodeFactory
363406
public abstract static class IntersectNode extends PythonBuiltinNode {
@@ -472,6 +515,25 @@ Object doOr(Object self, Object other) {
472515
}
473516
}
474517

518+
@Builtin(name = __IXOR__, minNumOfPositionalArgs = 2)
519+
@GenerateNodeFactory
520+
public abstract static class IXorNode extends PythonBinaryBuiltinNode {
521+
522+
@Specialization(guards = "canDoSetBinOp(other)", limit = "3")
523+
Object doSet(VirtualFrame frame, PSet self, Object other,
524+
@Cached GetHashingStorageNode getHashingStorageNode,
525+
@CachedLibrary("self.getDictStorage()") HashingStorageLibrary lib) {
526+
self.setDictStorage(lib.xor(self.getDictStorage(), getHashingStorageNode.execute(frame, other)));
527+
return self;
528+
}
529+
530+
@SuppressWarnings("unused")
531+
@Fallback
532+
Object doOr(Object self, Object other) {
533+
return PNotImplemented.NOT_IMPLEMENTED;
534+
}
535+
}
536+
475537
@Builtin(name = "symmetric_difference", minNumOfPositionalArgs = 2)
476538
@GenerateNodeFactory
477539
public abstract static class SymmetricDifferenceNode extends PythonBuiltinNode {
@@ -535,7 +597,7 @@ static PNone doSet(VirtualFrame frame, PSet self, Object other,
535597
@GenerateNodeFactory
536598
@ImportStatic(PGuards.class)
537599
abstract static class SubNode extends PythonBinaryBuiltinNode {
538-
@Specialization(guards = "canDoSetBinOp(right)", limit = "1")
600+
@Specialization(guards = "canDoSetBinOp(right)", limit = "3")
539601
PBaseSet doPBaseSet(VirtualFrame frame, PSet left, Object right,
540602
@Cached ConditionProfile hasFrame,
541603
@Cached GetHashingStorageNode getHashingStorageNode,
@@ -551,6 +613,26 @@ Object doSub(Object self, Object other) {
551613
}
552614
}
553615

616+
@Builtin(name = __ISUB__, minNumOfPositionalArgs = 2)
617+
@GenerateNodeFactory
618+
abstract static class ISubNode extends PythonBinaryBuiltinNode {
619+
@Specialization(guards = "canDoSetBinOp(right)", limit = "3")
620+
PBaseSet doPBaseSet(VirtualFrame frame, PSet left, Object right,
621+
@Cached ConditionProfile hasFrame,
622+
@Cached GetHashingStorageNode getHashingStorageNode,
623+
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary lib) {
624+
HashingStorage storage = lib.diffWithFrame(left.getDictStorage(), getHashingStorageNode.execute(frame, right), hasFrame, frame);
625+
left.setDictStorage(storage);
626+
return left;
627+
}
628+
629+
@SuppressWarnings("unused")
630+
@Fallback
631+
Object doSub(Object self, Object other) {
632+
return PNotImplemented.NOT_IMPLEMENTED;
633+
}
634+
}
635+
554636
@Builtin(name = "difference", minNumOfPositionalArgs = 1, takesVarArgs = true)
555637
@GenerateNodeFactory
556638
public abstract static class DifferenceNode extends PythonBuiltinNode {

0 commit comments

Comments
 (0)