Skip to content

Commit 6ed8307

Browse files
committed
Address review feedback
1 parent 02e054d commit 6ed8307

File tree

1 file changed

+95
-21
lines changed

1 file changed

+95
-21
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyObjectIsTrueNode.java

Lines changed: 95 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,29 +46,42 @@
4646
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__;
4747

4848
import com.oracle.graal.python.builtins.objects.PNone;
49+
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
50+
import com.oracle.graal.python.builtins.objects.list.PList;
51+
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
4952
import com.oracle.graal.python.nodes.ErrorMessages;
5053
import com.oracle.graal.python.nodes.PNodeWithContext;
5154
import com.oracle.graal.python.nodes.PRaiseNode;
55+
import com.oracle.graal.python.nodes.SpecialMethodNames;
5256
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
5357
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodNode;
58+
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodSlotNode;
5459
import com.oracle.graal.python.nodes.object.GetClassNode;
60+
import com.oracle.graal.python.nodes.util.CannotCastException;
61+
import com.oracle.graal.python.nodes.util.CastToJavaBooleanNode;
5562
import com.oracle.graal.python.nodes.util.CastToJavaIntLossyNode;
5663
import com.oracle.graal.python.runtime.exception.PException;
5764
import com.oracle.truffle.api.dsl.Cached;
65+
import com.oracle.truffle.api.dsl.Cached.Shared;
5866
import com.oracle.truffle.api.dsl.GenerateUncached;
67+
import com.oracle.truffle.api.dsl.ImportStatic;
5968
import com.oracle.truffle.api.dsl.Specialization;
6069
import com.oracle.truffle.api.frame.Frame;
6170
import com.oracle.truffle.api.frame.VirtualFrame;
71+
import com.oracle.truffle.api.nodes.UnexpectedResultException;
6272

6373
/**
6474
* Equivalent of CPython's {@code PyObject_IsTrue}. Converts object to a boolean value using its
6575
* {@code __bool__} special method. Falls back to comparing {@code __len__} result with 0. Defaults
6676
* to true if neither is defined.
6777
*/
6878
@GenerateUncached
79+
@ImportStatic(SpecialMethodNames.class)
6980
public abstract class PyObjectIsTrueNode extends PNodeWithContext {
7081
public abstract boolean execute(Frame frame, Object object);
7182

83+
protected abstract Object executeObject(Frame frame, Object object);
84+
7285
@Specialization
7386
static boolean doBoolean(boolean object) {
7487
return object;
@@ -99,13 +112,60 @@ static boolean doString(String object) {
99112
return object.length() != 0;
100113
}
101114

102-
@Specialization(guards = {"!isBoolean(object)", "!isPNone(object)", "!isInteger(object)", "!isDouble(object)"})
115+
@Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1")
116+
static boolean doList(PList object,
117+
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode,
118+
@Cached SequenceStorageNodes.LenNode lenNode) {
119+
return lenNode.execute(object.getSequenceStorage()) != 0;
120+
}
121+
122+
@Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1")
123+
static boolean doTuple(PTuple object,
124+
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode,
125+
@Cached SequenceStorageNodes.LenNode lenNode) {
126+
return lenNode.execute(object.getSequenceStorage()) != 0;
127+
}
128+
129+
@Specialization(guards = {"!isBoolean(object)", "!isPNone(object)", "!isInteger(object)", "!isDouble(object)"}, rewriteOn = UnexpectedResultException.class)
130+
static boolean doObjectUnboxed(VirtualFrame frame, Object object,
131+
@Shared("getClassNode") @Cached GetClassNode getClassNode,
132+
@Cached("create(__BOOL__)") LookupSpecialMethodSlotNode lookupBool,
133+
@Cached("create(__LEN__)") LookupSpecialMethodSlotNode lookupLen,
134+
@Cached CallUnaryMethodNode callBool,
135+
@Cached CallUnaryMethodNode callLen,
136+
@Cached CastToJavaBooleanNode cast,
137+
@Cached PyNumberIndexNode indexNode,
138+
@Cached CastToJavaIntLossyNode castLossy,
139+
@Cached PyNumberAsSizeNode asSizeNode,
140+
@Cached PRaiseNode raiseNode) throws UnexpectedResultException {
141+
Object type = getClassNode.execute(object);
142+
Object boolDescr = lookupBool.execute(frame, type, object);
143+
if (boolDescr != PNone.NO_VALUE) {
144+
try {
145+
return callBool.executeBoolean(frame, boolDescr, object);
146+
} catch (UnexpectedResultException e) {
147+
throw new UnexpectedResultException(checkBoolResult(cast, raiseNode, e.getResult()));
148+
}
149+
}
150+
Object lenDescr = lookupLen.execute(frame, type, object);
151+
if (lenDescr != PNone.NO_VALUE) {
152+
try {
153+
return checkLen(raiseNode, callLen.executeInt(frame, lenDescr, object));
154+
} catch (UnexpectedResultException e) {
155+
throw new UnexpectedResultException(checkLen(raiseNode, convertLen(frame, indexNode, castLossy, asSizeNode, e.getResult())));
156+
}
157+
}
158+
return true;
159+
}
160+
161+
@Specialization(guards = {"!isBoolean(object)", "!isPNone(object)", "!isInteger(object)", "!isDouble(object)"}, replaces = "doObjectUnboxed")
103162
static boolean doObject(VirtualFrame frame, Object object,
104-
@Cached GetClassNode getClassNode,
163+
@Shared("getClassNode") @Cached GetClassNode getClassNode,
105164
@Cached LookupSpecialMethodNode.Dynamic lookupBool,
106165
@Cached LookupSpecialMethodNode.Dynamic lookupLen,
107166
@Cached CallUnaryMethodNode callBool,
108167
@Cached CallUnaryMethodNode callLen,
168+
@Cached CastToJavaBooleanNode cast,
109169
@Cached PyNumberIndexNode indexNode,
110170
@Cached CastToJavaIntLossyNode castLossy,
111171
@Cached PyNumberAsSizeNode asSizeNode,
@@ -114,32 +174,46 @@ static boolean doObject(VirtualFrame frame, Object object,
114174
Object boolDescr = lookupBool.execute(frame, type, __BOOL__, object, false);
115175
if (boolDescr != PNone.NO_VALUE) {
116176
Object result = callBool.executeObject(frame, boolDescr, object);
117-
if (result instanceof Boolean) {
118-
return (boolean) result;
119-
} else {
120-
throw raiseNode.raise(TypeError, ErrorMessages.BOOL_SHOULD_RETURN_BOOL, result);
121-
}
177+
return checkBoolResult(cast, raiseNode, result);
122178
}
123179
Object lenDescr = lookupLen.execute(frame, type, __LEN__, object, false);
124180
if (lenDescr != PNone.NO_VALUE) {
125-
Object result = indexNode.execute(frame, callLen.executeObject(frame, lenDescr, object));
126-
int len;
127-
try {
128-
len = asSizeNode.executeExact(frame, result);
129-
} catch (PException e) {
130-
len = castLossy.execute(result);
131-
if (len >= 0) {
132-
throw e;
133-
}
134-
}
135-
if (len < 0) {
136-
throw raiseNode.raise(ValueError, ErrorMessages.LEN_SHOULD_RETURN_GT_ZERO);
137-
}
138-
return len != 0;
181+
Object result = callLen.executeObject(frame, lenDescr, object);
182+
int len = convertLen(frame, indexNode, castLossy, asSizeNode, result);
183+
return checkLen(raiseNode, len);
139184
}
140185
return true;
141186
}
142187

188+
private static boolean checkLen(PRaiseNode raiseNode, int len) {
189+
if (len < 0) {
190+
throw raiseNode.raise(ValueError, ErrorMessages.LEN_SHOULD_RETURN_GT_ZERO);
191+
}
192+
return len != 0;
193+
}
194+
195+
private static int convertLen(VirtualFrame frame, PyNumberIndexNode indexNode, CastToJavaIntLossyNode castLossy, PyNumberAsSizeNode asSizeNode, Object result) {
196+
int len;
197+
Object index = indexNode.execute(frame, result);
198+
try {
199+
len = asSizeNode.executeExact(frame, index);
200+
} catch (PException e) {
201+
len = castLossy.execute(index);
202+
if (len >= 0) {
203+
throw e;
204+
}
205+
}
206+
return len;
207+
}
208+
209+
private static boolean checkBoolResult(CastToJavaBooleanNode cast, PRaiseNode raiseNode, Object result) {
210+
try {
211+
return cast.execute(result);
212+
} catch (CannotCastException e) {
213+
throw raiseNode.raise(TypeError, ErrorMessages.BOOL_SHOULD_RETURN_BOOL, result);
214+
}
215+
}
216+
143217
public static PyObjectIsTrueNode create() {
144218
return PyObjectIsTrueNodeGen.create();
145219
}

0 commit comments

Comments
 (0)