46
46
import static com .oracle .graal .python .nodes .SpecialMethodNames .__LEN__ ;
47
47
48
48
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 ;
49
52
import com .oracle .graal .python .nodes .ErrorMessages ;
50
53
import com .oracle .graal .python .nodes .PNodeWithContext ;
51
54
import com .oracle .graal .python .nodes .PRaiseNode ;
55
+ import com .oracle .graal .python .nodes .SpecialMethodNames ;
52
56
import com .oracle .graal .python .nodes .call .special .CallUnaryMethodNode ;
53
57
import com .oracle .graal .python .nodes .call .special .LookupSpecialMethodNode ;
58
+ import com .oracle .graal .python .nodes .call .special .LookupSpecialMethodSlotNode ;
54
59
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 ;
55
62
import com .oracle .graal .python .nodes .util .CastToJavaIntLossyNode ;
56
63
import com .oracle .graal .python .runtime .exception .PException ;
57
64
import com .oracle .truffle .api .dsl .Cached ;
65
+ import com .oracle .truffle .api .dsl .Cached .Shared ;
58
66
import com .oracle .truffle .api .dsl .GenerateUncached ;
67
+ import com .oracle .truffle .api .dsl .ImportStatic ;
59
68
import com .oracle .truffle .api .dsl .Specialization ;
60
69
import com .oracle .truffle .api .frame .Frame ;
61
70
import com .oracle .truffle .api .frame .VirtualFrame ;
71
+ import com .oracle .truffle .api .nodes .UnexpectedResultException ;
62
72
63
73
/**
64
74
* Equivalent of CPython's {@code PyObject_IsTrue}. Converts object to a boolean value using its
65
75
* {@code __bool__} special method. Falls back to comparing {@code __len__} result with 0. Defaults
66
76
* to true if neither is defined.
67
77
*/
68
78
@ GenerateUncached
79
+ @ ImportStatic (SpecialMethodNames .class )
69
80
public abstract class PyObjectIsTrueNode extends PNodeWithContext {
70
81
public abstract boolean execute (Frame frame , Object object );
71
82
83
+ protected abstract Object executeObject (Frame frame , Object object );
84
+
72
85
@ Specialization
73
86
static boolean doBoolean (boolean object ) {
74
87
return object ;
@@ -99,13 +112,60 @@ static boolean doString(String object) {
99
112
return object .length () != 0 ;
100
113
}
101
114
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" )
103
162
static boolean doObject (VirtualFrame frame , Object object ,
104
- @ Cached GetClassNode getClassNode ,
163
+ @ Shared ( "getClassNode" ) @ Cached GetClassNode getClassNode ,
105
164
@ Cached LookupSpecialMethodNode .Dynamic lookupBool ,
106
165
@ Cached LookupSpecialMethodNode .Dynamic lookupLen ,
107
166
@ Cached CallUnaryMethodNode callBool ,
108
167
@ Cached CallUnaryMethodNode callLen ,
168
+ @ Cached CastToJavaBooleanNode cast ,
109
169
@ Cached PyNumberIndexNode indexNode ,
110
170
@ Cached CastToJavaIntLossyNode castLossy ,
111
171
@ Cached PyNumberAsSizeNode asSizeNode ,
@@ -114,32 +174,46 @@ static boolean doObject(VirtualFrame frame, Object object,
114
174
Object boolDescr = lookupBool .execute (frame , type , __BOOL__ , object , false );
115
175
if (boolDescr != PNone .NO_VALUE ) {
116
176
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 );
122
178
}
123
179
Object lenDescr = lookupLen .execute (frame , type , __LEN__ , object , false );
124
180
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 );
139
184
}
140
185
return true ;
141
186
}
142
187
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
+
143
217
public static PyObjectIsTrueNode create () {
144
218
return PyObjectIsTrueNodeGen .create ();
145
219
}
0 commit comments