Skip to content

Commit 5841baf

Browse files
committed
[GR-20785] Add support to xor for sets
PullRequest: graalpython/885
2 parents 7ae65a9 + cbc25a0 commit 5841baf

File tree

3 files changed

+121
-18
lines changed

3 files changed

+121
-18
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/builtin/HashingTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,10 @@ public void dictEqualTest3() {
195195
assertPrints("", source);
196196
}
197197

198+
@Test
199+
public void setAndTest() {
200+
assertPrints("{2}\n", "print({2, 3} ^ {3})\n");
201+
assertPrints("{'c', 'b'}\n", "print({'a', 'c'} ^ frozenset({'a', 'b'}))\n");
202+
assertPrints("frozenset({'b'})\n", "print(frozenset({'a', 'c'}) ^ {'a', 'b', 'c'})\n");
203+
}
198204
}

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

Lines changed: 81 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import static com.oracle.graal.python.nodes.SpecialMethodNames.__OR__;
3939
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REDUCE__;
4040
import static com.oracle.graal.python.nodes.SpecialMethodNames.__SUB__;
41+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__XOR__;
4142

4243
import java.util.Iterator;
4344
import java.util.List;
@@ -193,19 +194,19 @@ PBaseSet doPBaseSet(VirtualFrame frame, PFrozenSet left, String right,
193194
}
194195

195196
@Specialization(limit = "1")
196-
PBaseSet doPBaseSet(@SuppressWarnings("unused") VirtualFrame frame, PSet left, PBaseSet right,
197+
PBaseSet doPBaseSet(VirtualFrame frame, PSet left, PBaseSet right,
197198
@Cached("createBinaryProfile()") ConditionProfile hasFrame,
198199
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
199-
HashingStorage intersectedStorage = intersect(leftLib, left.getDictStorage(), right.getDictStorage(), frame, hasFrame);
200-
return factory().createSet(intersectedStorage);
200+
HashingStorage storage = intersect(leftLib, left.getDictStorage(), right.getDictStorage(), frame, hasFrame);
201+
return factory().createSet(storage);
201202
}
202203

203204
@Specialization(limit = "1")
204-
PBaseSet doPBaseSet(@SuppressWarnings("unused") VirtualFrame frame, PFrozenSet left, PBaseSet right,
205+
PBaseSet doPBaseSet(VirtualFrame frame, PFrozenSet left, PBaseSet right,
205206
@Cached("createBinaryProfile()") ConditionProfile hasFrame,
206207
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
207-
HashingStorage intersectedStorage = intersect(leftLib, left.getDictStorage(), right.getDictStorage(), frame, hasFrame);
208-
return factory().createFrozenSet(intersectedStorage);
208+
HashingStorage storage = intersect(leftLib, left.getDictStorage(), right.getDictStorage(), frame, hasFrame);
209+
return factory().createFrozenSet(storage);
209210
}
210211

211212
@Specialization(limit = "1")
@@ -214,8 +215,8 @@ PBaseSet doPBaseSet(VirtualFrame frame, PSet left, PDictView right,
214215
@Cached("createBinaryProfile()") ConditionProfile hasFrame,
215216
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
216217
PSet rightSet = constructSetNode.executeWith(frame, right);
217-
HashingStorage intersectedStorage = intersect(leftLib, left.getDictStorage(), rightSet.getDictStorage(), frame, hasFrame);
218-
return factory().createSet(intersectedStorage);
218+
HashingStorage storage = intersect(leftLib, left.getDictStorage(), rightSet.getDictStorage(), frame, hasFrame);
219+
return factory().createSet(storage);
219220
}
220221

221222
@Specialization(limit = "1")
@@ -224,8 +225,8 @@ PBaseSet doPBaseSet(VirtualFrame frame, PFrozenSet left, PDictView right,
224225
@Cached("createBinaryProfile()") ConditionProfile hasFrame,
225226
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
226227
PSet rightSet = constructSetNode.executeWith(frame, right);
227-
HashingStorage intersectedStorage = intersect(leftLib, left.getDictStorage(), rightSet.getDictStorage(), frame, hasFrame);
228-
return factory().createSet(intersectedStorage);
228+
HashingStorage storage = intersect(leftLib, left.getDictStorage(), rightSet.getDictStorage(), frame, hasFrame);
229+
return factory().createSet(storage);
229230
}
230231

231232
@Fallback
@@ -261,33 +262,33 @@ PBaseSet doPBaseSet(VirtualFrame frame, PFrozenSet left, String right,
261262
@Specialization(limit = "1")
262263
PBaseSet doPBaseSet(@SuppressWarnings("unused") VirtualFrame frame, PSet left, PBaseSet right,
263264
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
264-
HashingStorage intersectedStorage = union(leftLib, left.getDictStorage(), right.getDictStorage());
265-
return factory().createSet(intersectedStorage);
265+
HashingStorage storage = union(leftLib, left.getDictStorage(), right.getDictStorage());
266+
return factory().createSet(storage);
266267
}
267268

268269
@Specialization(limit = "1")
269270
PBaseSet doPBaseSet(@SuppressWarnings("unused") VirtualFrame frame, PFrozenSet left, PBaseSet right,
270271
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
271-
HashingStorage intersectedStorage = union(leftLib, left.getDictStorage(), right.getDictStorage());
272-
return factory().createFrozenSet(intersectedStorage);
272+
HashingStorage storage = union(leftLib, left.getDictStorage(), right.getDictStorage());
273+
return factory().createFrozenSet(storage);
273274
}
274275

275276
@Specialization(limit = "1")
276277
PBaseSet doPBaseSet(VirtualFrame frame, PSet left, PDictView right,
277278
@Cached("create()") SetNodes.ConstructSetNode constructSetNode,
278279
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
279280
PSet rightSet = constructSetNode.executeWith(frame, right);
280-
HashingStorage intersectedStorage = union(leftLib, left.getDictStorage(), rightSet.getDictStorage());
281-
return factory().createSet(intersectedStorage);
281+
HashingStorage storage = union(leftLib, left.getDictStorage(), rightSet.getDictStorage());
282+
return factory().createSet(storage);
282283
}
283284

284285
@Specialization(limit = "1")
285286
PBaseSet doPBaseSet(VirtualFrame frame, PFrozenSet left, PDictView right,
286287
@Cached("create()") SetNodes.ConstructSetNode constructSetNode,
287288
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
288289
PSet rightSet = constructSetNode.executeWith(frame, right);
289-
HashingStorage intersectedStorage = union(leftLib, left.getDictStorage(), rightSet.getDictStorage());
290-
return factory().createSet(intersectedStorage);
290+
HashingStorage storage = union(leftLib, left.getDictStorage(), rightSet.getDictStorage());
291+
return factory().createSet(storage);
291292
}
292293

293294
@Fallback
@@ -296,6 +297,68 @@ Object doOr(Object self, Object other) {
296297
}
297298
}
298299

300+
@Builtin(name = __XOR__, minNumOfPositionalArgs = 2)
301+
@GenerateNodeFactory
302+
abstract static class XorNode extends PythonBinaryBuiltinNode {
303+
304+
protected static HashingStorage xor(HashingStorageLibrary lib, HashingStorage left, HashingStorage right) {
305+
return lib.xor(left, right);
306+
}
307+
308+
@Specialization(limit = "1")
309+
PBaseSet doPBaseSet(VirtualFrame frame, PSet left, String right,
310+
@Cached("createBinaryProfile()") ConditionProfile hasFrame,
311+
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib,
312+
@CachedLibrary(limit = "1") HashingStorageLibrary lib) {
313+
return factory().createSet(xor(leftLib, left.getDictStorage(), getStringAsHashingStorage(frame, right, lib, hasFrame)));
314+
}
315+
316+
@Specialization(limit = "1")
317+
PBaseSet doPBaseSet(VirtualFrame frame, PFrozenSet left, String right,
318+
@Cached("createBinaryProfile()") ConditionProfile hasFrame,
319+
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib,
320+
@CachedLibrary(limit = "1") HashingStorageLibrary lib) {
321+
return factory().createFrozenSet(xor(leftLib, left.getDictStorage(), getStringAsHashingStorage(frame, right, lib, hasFrame)));
322+
}
323+
324+
@Specialization(limit = "1")
325+
PBaseSet doPBaseSet(@SuppressWarnings("unused") VirtualFrame frame, PSet left, PBaseSet right,
326+
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
327+
HashingStorage storage = xor(leftLib, left.getDictStorage(), right.getDictStorage());
328+
return factory().createSet(storage);
329+
}
330+
331+
@Specialization(limit = "1")
332+
PBaseSet doPBaseSet(@SuppressWarnings("unused") VirtualFrame frame, PFrozenSet left, PBaseSet right,
333+
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
334+
HashingStorage storage = xor(leftLib, left.getDictStorage(), right.getDictStorage());
335+
return factory().createFrozenSet(storage);
336+
}
337+
338+
@Specialization(limit = "1")
339+
PBaseSet doPBaseSet(VirtualFrame frame, PSet left, PDictView right,
340+
@Cached("create()") SetNodes.ConstructSetNode constructSetNode,
341+
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
342+
PSet rightSet = constructSetNode.executeWith(frame, right);
343+
HashingStorage storage = xor(leftLib, left.getDictStorage(), rightSet.getDictStorage());
344+
return factory().createSet(storage);
345+
}
346+
347+
@Specialization(limit = "1")
348+
PBaseSet doPBaseSet(VirtualFrame frame, PFrozenSet left, PDictView right,
349+
@Cached("create()") SetNodes.ConstructSetNode constructSetNode,
350+
@CachedLibrary("left.getDictStorage()") HashingStorageLibrary leftLib) {
351+
PSet rightSet = constructSetNode.executeWith(frame, right);
352+
HashingStorage storage = xor(leftLib, left.getDictStorage(), rightSet.getDictStorage());
353+
return factory().createSet(storage);
354+
}
355+
356+
@Fallback
357+
Object doOr(Object self, Object other) {
358+
throw raise(PythonErrorType.TypeError, "unsupported operand type(s) for ^: '%p' and '%p'", self, other);
359+
}
360+
}
361+
299362
@Builtin(name = __SUB__, minNumOfPositionalArgs = 2)
300363
@GenerateNodeFactory
301364
abstract static class SubNode extends PythonBinaryBuiltinNode {

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
*/
2626
package com.oracle.graal.python.builtins.objects.set;
2727

28+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__AND__;
2829
import static com.oracle.graal.python.nodes.SpecialMethodNames.__HASH__;
2930
import static com.oracle.graal.python.nodes.SpecialMethodNames.__OR__;
31+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__XOR__;
3032

3133
import java.util.List;
3234

@@ -108,6 +110,38 @@ Object doReverse(VirtualFrame frame, PBaseSet self, Object other,
108110
}
109111
}
110112

113+
@Builtin(name = __AND__, minNumOfPositionalArgs = 2)
114+
@GenerateNodeFactory
115+
public abstract static class AndNode extends PythonBinaryBuiltinNode {
116+
@Specialization(limit = "1")
117+
Object doSet(@SuppressWarnings("unused") VirtualFrame frame, PBaseSet self, PBaseSet other,
118+
@CachedLibrary("self.getDictStorage()") HashingStorageLibrary lib) {
119+
return factory().createSet(lib.intersect(self.getDictStorage(), other.getDictStorage()));
120+
}
121+
122+
@Specialization
123+
Object doReverse(VirtualFrame frame, PBaseSet self, Object other,
124+
@Cached("create(__AND__)") LookupAndCallBinaryNode callAnd) {
125+
return callAnd.executeObject(frame, other, self);
126+
}
127+
}
128+
129+
@Builtin(name = __XOR__, minNumOfPositionalArgs = 2)
130+
@GenerateNodeFactory
131+
public abstract static class XorNode extends PythonBinaryBuiltinNode {
132+
@Specialization(limit = "1")
133+
Object doSet(@SuppressWarnings("unused") VirtualFrame frame, PBaseSet self, PBaseSet other,
134+
@CachedLibrary("self.getDictStorage()") HashingStorageLibrary lib) {
135+
return factory().createSet(lib.xor(self.getDictStorage(), other.getDictStorage()));
136+
}
137+
138+
@Specialization
139+
Object doReverse(VirtualFrame frame, PBaseSet self, Object other,
140+
@Cached("create(__XOR__)") LookupAndCallBinaryNode callXor) {
141+
return callXor.executeObject(frame, other, self);
142+
}
143+
}
144+
111145
@Builtin(name = "remove", minNumOfPositionalArgs = 2)
112146
@GenerateNodeFactory
113147
abstract static class RemoveNode extends PythonBinaryBuiltinNode {

0 commit comments

Comments
 (0)