Skip to content

Commit d960ae3

Browse files
committed
proper implementation of __eq__ and __ne__ for the PReferenceType builtin
- GR-10393: test_weakset.py runs (not all tests tests pass yet)
1 parent bcd953a commit d960ae3

File tree

5 files changed

+104
-41
lines changed

5 files changed

+104
-41
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public PReferenceType refType(Object cls, PythonObject pythonObject, PFunction c
7979
}
8080

8181
@Fallback
82-
public PReferenceType refType(@SuppressWarnings("unused") Object cls, @SuppressWarnings("unused") Object object, @SuppressWarnings("unused") Object callback) {
82+
public PReferenceType refType(@SuppressWarnings("unused") Object cls, @SuppressWarnings("unused") Object object, @SuppressWarnings("unused") Object callback) {
8383
throw raise(PythonErrorType.TypeError, "cannot create weak reference to '%p' object", object);
8484
}
8585
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/PReferenceType.java

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,10 @@
3838
*/
3939
package com.oracle.graal.python.builtins.objects.referencetype;
4040

41-
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
42-
4341
import java.lang.ref.WeakReference;
4442

45-
import com.oracle.graal.python.PythonLanguage;
4643
import com.oracle.graal.python.builtins.objects.PNone;
44+
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
4745
import com.oracle.graal.python.builtins.objects.function.PArguments;
4846
import com.oracle.graal.python.builtins.objects.function.PFunction;
4947
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
@@ -89,54 +87,44 @@ protected void finalize() throws Throwable {
8987
}
9088

9189
private final WeakRefStorage store;
90+
private int hash = -1;
9291

9392
@TruffleBoundary
9493
public PReferenceType(PythonClass cls, PythonObject pythonObject, PFunction callback) {
9594
super(cls);
9695
this.store = new WeakRefStorage(this, pythonObject, callback);
9796
}
9897

99-
public Object __callback__() {
98+
public Object getCallback() {
10099
if (this.store.callback == null) {
101100
return PNone.NONE;
102101
}
103102
return this.store.callback;
104103
}
105104

106105
@TruffleBoundary
107-
public Object __call__() {
108-
Object referent = this.store.get();
109-
return (referent == null) ? PNone.NONE : referent;
106+
public PythonObject getObject() {
107+
return this.store.get();
110108
}
111109

112-
@TruffleBoundary
113-
public int getWeakRefCount() {
114-
return (this.store.get() == null) ? 0 : 1;
110+
public PythonAbstractObject getPyObject() {
111+
PythonObject object = getObject();
112+
return (object == null) ? PNone.NONE : object;
115113
}
116114

117-
@Override
118-
public String toString() {
119-
return "<" + pythonClass.getName() + " object at " + hashCode() + ">";
115+
public int getWeakRefCount() {
116+
return (this.getObject() == null) ? 0 : 1;
120117
}
121118

122-
@Override
123-
@TruffleBoundary
124-
public int hashCode() {
125-
PythonObject referent = store.get();
126-
if (referent != null) {
127-
return referent.hashCode();
119+
public int getHash() {
120+
if (this.hash != -1) {
121+
return this.hash;
128122
}
129-
throw PythonLanguage.getCore().raise(TypeError);
130-
}
131123

132-
@Override
133-
@TruffleBoundary
134-
public boolean equals(Object obj) {
135-
PythonObject referent = store.get();
136-
if (referent != null) {
137-
return referent.equals(obj);
124+
PythonObject object = getObject();
125+
if (object != null) {
126+
this.hash = object.hashCode();
138127
}
139-
throw PythonLanguage.getCore().raise(TypeError);
128+
return this.hash;
140129
}
141-
142130
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/ReferenceTypeBuiltins.java

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,27 @@
3838
*/
3939
package com.oracle.graal.python.builtins.objects.referencetype;
4040

41+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__;
42+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__CALLBACK__;
4143
import static com.oracle.graal.python.nodes.SpecialMethodNames.__CALL__;
44+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__;
4245
import static com.oracle.graal.python.nodes.SpecialMethodNames.__HASH__;
46+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NE__;
47+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
4348

4449
import java.util.List;
4550

4651
import com.oracle.graal.python.builtins.Builtin;
4752
import com.oracle.graal.python.builtins.CoreFunctions;
4853
import com.oracle.graal.python.builtins.PythonBuiltins;
54+
import com.oracle.graal.python.builtins.objects.PNone;
55+
import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
56+
import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
4957
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
58+
import com.oracle.graal.python.runtime.exception.PythonErrorType;
59+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
60+
import com.oracle.truffle.api.dsl.Cached;
61+
import com.oracle.truffle.api.dsl.Fallback;
5062
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
5163
import com.oracle.truffle.api.dsl.NodeFactory;
5264
import com.oracle.truffle.api.dsl.Specialization;
@@ -59,12 +71,12 @@ protected List<? extends NodeFactory<? extends PythonBuiltinNode>> getNodeFactor
5971
}
6072

6173
// ref.__callback__
62-
@Builtin(name = "__callback__", fixedNumOfArguments = 1)
74+
@Builtin(name = __CALLBACK__, fixedNumOfArguments = 1)
6375
@GenerateNodeFactory
6476
public abstract static class RefTypeCallbackPropertyNode extends PythonBuiltinNode {
6577
@Specialization
66-
public Object getCallback(PReferenceType referenceType) {
67-
return referenceType.__callback__();
78+
public Object getCallback(PReferenceType self) {
79+
return self.getCallback();
6880
}
6981
}
7082

@@ -73,18 +85,79 @@ public Object getCallback(PReferenceType referenceType) {
7385
@GenerateNodeFactory
7486
public abstract static class RefTypeCallNode extends PythonBuiltinNode {
7587
@Specialization
76-
public Object call(PReferenceType referenceType) {
77-
return referenceType.__call__();
88+
public Object call(PReferenceType self) {
89+
return self.getPyObject();
7890
}
7991
}
8092

8193
// ref.__hash__
8294
@Builtin(name = __HASH__, fixedNumOfArguments = 1)
8395
@GenerateNodeFactory
8496
public abstract static class RefTypeHashNode extends PythonBuiltinNode {
85-
@Specialization
86-
public Object hash(PReferenceType referenceType) {
87-
return referenceType.hashCode();
97+
@Specialization(guards = "self.getObject() != null")
98+
public int hash(PReferenceType self) {
99+
return self.getHash();
100+
}
101+
102+
@Fallback
103+
public int hash(@SuppressWarnings("unused") Object self) {
104+
throw raise(PythonErrorType.TypeError, "weak object has gone away");
105+
}
106+
}
107+
108+
// ref.__repr__
109+
@Builtin(name = __REPR__, fixedNumOfArguments = 1)
110+
@GenerateNodeFactory
111+
public abstract static class RefTypeReprNode extends PythonBuiltinNode {
112+
@Specialization(guards = "self.getObject() == null")
113+
@TruffleBoundary
114+
public String repr(PReferenceType self) {
115+
return String.format("<weakref at %s; dead>", self.hashCode());
116+
}
117+
118+
@Specialization(guards = "self.getObject() != null")
119+
@TruffleBoundary
120+
public String repr(PReferenceType self,
121+
@Cached("create()") LookupInheritedAttributeNode getNameNode) {
122+
Object object = self.getObject();
123+
Object name = getNameNode.execute(object, __NAME__);
124+
if (name == PNone.NO_VALUE) {
125+
return String.format("<weakref at %s; to '%s' at %s>", self.hashCode(), object, object.hashCode());
126+
} else {
127+
return String.format("<weakref at %s; to '%s' at %s (%s)>", self.hashCode(), object, object.hashCode(), name);
128+
}
129+
}
130+
}
131+
132+
// ref.__eq__
133+
@Builtin(name = __EQ__, fixedNumOfArguments = 2)
134+
@GenerateNodeFactory
135+
public abstract static class RefTypeEqNode extends PythonBuiltinNode {
136+
@Specialization(guards = {"self.getObject() != null", "other.getObject() != null"})
137+
public boolean eq(PReferenceType self, PReferenceType other,
138+
@Cached("create(__EQ__, __EQ__, __EQ__)") BinaryComparisonNode eqNode) {
139+
return eqNode.executeBool(self.getObject(), other.getObject());
140+
}
141+
142+
@Specialization(guards = "self.getObject() == null || other.getObject() == null")
143+
public boolean eq(PReferenceType self, PReferenceType other) {
144+
return self == other;
145+
}
146+
}
147+
148+
// ref.__ne__
149+
@Builtin(name = __NE__, fixedNumOfArguments = 2)
150+
@GenerateNodeFactory
151+
public abstract static class RefTypeNeNode extends PythonBuiltinNode {
152+
@Specialization(guards = {"self.getObject() != null", "other.getObject() != null"})
153+
public boolean ne(PReferenceType self, PReferenceType other,
154+
@Cached("create(__NE__, __NE__, __NE__)") BinaryComparisonNode neNode) {
155+
return neNode.executeBool(self.getObject(), other.getObject());
156+
}
157+
158+
@Specialization(guards = "self.getObject() == null || other.getObject() == null")
159+
public boolean ne(PReferenceType self, PReferenceType other) {
160+
return self != other;
88161
}
89162
}
90163
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/SpecialMethodNames.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public abstract class SpecialMethodNames {
7373
public static final String __SUBCLASSES__ = "__subclasses__";
7474
public static final String __SUBCLASSHOOK__ = "__subclasshook__";
7575
public static final String __CALL__ = "__call__";
76+
public static final String __CALLBACK__ = "__callback__";
7677
public static final String __LEN__ = "__len__";
7778
public static final String __LENGTH_HINT__ = "__length_hint__";
7879
public static final String __GETITEM__ = "__getitem__";

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@
2525
*/
2626
package com.oracle.graal.python.nodes.expression;
2727

28+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__;
29+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NE__;
2830
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
2931

3032
import com.oracle.graal.python.builtins.objects.PNotImplemented;
3133
import com.oracle.graal.python.nodes.PNode;
32-
import com.oracle.graal.python.nodes.SpecialMethodNames;
3334
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
3435
import com.oracle.truffle.api.CompilerAsserts;
3536
import com.oracle.truffle.api.dsl.Specialization;
@@ -66,9 +67,9 @@ public static BinaryComparisonNode create(String magicMethod, String magicRevers
6667
private Object handleNotImplemented(Object left, Object right) {
6768
// just like python, if no implementation is available, do something sensible for
6869
// == and !=
69-
if (magicMethod == SpecialMethodNames.__EQ__) {
70+
if (magicMethod == __EQ__) {
7071
return left == right;
71-
} else if (magicMethod == SpecialMethodNames.__NE__) {
72+
} else if (magicMethod == __NE__) {
7273
return left != right;
7374
} else {
7475
throw raise(TypeError, "'%s' not supported between instances of '%p' and '%p'", operation, left, right);

0 commit comments

Comments
 (0)