40
40
*/
41
41
package com .oracle .graal .python .builtins .modules .ast ;
42
42
43
+ import static com .oracle .graal .python .builtins .modules .ast .AstState .T_C_CONSTANT ;
44
+ import static com .oracle .graal .python .builtins .modules .ast .AstState .T_F_VALUE ;
45
+ import static com .oracle .graal .python .nodes .ErrorMessages .AST_IDENTIFIER_MUST_BE_OF_TYPE_STR ;
43
46
import static com .oracle .graal .python .nodes .ErrorMessages .EXPECTED_SOME_SORT_OF_S_BUT_GOT_S ;
47
+ import static com .oracle .graal .python .nodes .ErrorMessages .FIELD_S_IS_REQUIRED_FOR_S ;
48
+ import static com .oracle .graal .python .nodes .ErrorMessages .INVALID_INTEGER_VALUE ;
44
49
import static com .oracle .graal .python .nodes .ErrorMessages .REQUIRED_FIELD_S_MISSING_FROM_S ;
45
50
import static com .oracle .graal .python .nodes .ErrorMessages .S_FIELD_S_CHANGED_SIZE_DURING_ITERATION ;
46
51
import static com .oracle .graal .python .nodes .ErrorMessages .S_FIELD_S_MUST_BE_A_LIST_NOT_P ;
52
57
import com .oracle .graal .python .builtins .objects .list .PList ;
53
58
import com .oracle .graal .python .builtins .objects .type .PythonAbstractClass ;
54
59
import com .oracle .graal .python .lib .PyLongAsIntNode ;
60
+ import com .oracle .graal .python .lib .PyLongCheckNode ;
55
61
import com .oracle .graal .python .lib .PyObjectLookupAttr ;
56
62
import com .oracle .graal .python .lib .PyObjectReprAsTruffleStringNode ;
57
63
import com .oracle .graal .python .nodes .PRaiseNode ;
58
64
import com .oracle .graal .python .nodes .SpecialMethodNames ;
59
65
import com .oracle .graal .python .nodes .call .CallNode ;
66
+ import com .oracle .graal .python .nodes .util .CannotCastException ;
60
67
import com .oracle .graal .python .nodes .util .CastToJavaBooleanNode ;
61
68
import com .oracle .graal .python .nodes .util .CastToJavaStringNode ;
62
69
import com .oracle .graal .python .pegparser .sst .ConstantValue ;
@@ -78,50 +85,64 @@ interface Conversion<T> {
78
85
}
79
86
80
87
<T > T lookupAndConvert (Object obj , TruffleString attrName , TruffleString nodeName , Conversion <T > conversion , boolean required ) {
81
- Object tmp = PyObjectLookupAttr . getUncached (). execute ( null , obj , attrName );
88
+ Object tmp = lookupAttr ( obj , attrName );
82
89
if (tmp instanceof PNone ) {
83
- if (required ) {
84
- throw PRaiseNode .getUncached ().raise (PythonBuiltinClassType .TypeError , REQUIRED_FIELD_S_MISSING_FROM_S , attrName , nodeName );
90
+ if (!required ) {
91
+ return null ;
92
+ }
93
+ if (tmp == PNone .NO_VALUE ) {
94
+ throw raiseTypeError (REQUIRED_FIELD_S_MISSING_FROM_S , attrName , nodeName );
95
+ }
96
+ // In CPython, None values for required attributes are not checked here, but converted
97
+ // to C NULL and later checked in _PyAST_* constructor. This is not convenient for us,
98
+ // since our SST nodes are in the pegparser project which does not have access to Python
99
+ // exceptions. So we handle PNone.NONE here, but there is one exception - None is a
100
+ // valid value for the required field ExprTy.Constant.value.
101
+ if (!(nodeName == T_C_CONSTANT && attrName == T_F_VALUE )) {
102
+ throw raiseValueError (FIELD_S_IS_REQUIRED_FOR_S , attrName , nodeName );
85
103
}
86
- return null ;
87
104
}
88
105
// Py_EnterRecursiveCall(" while traversing '%s' node")
89
106
return conversion .convert (tmp );
90
107
}
91
108
92
109
int lookupAndConvertInt (Object obj , TruffleString attrName , TruffleString nodeName , boolean required ) {
93
- Object tmp = PyObjectLookupAttr . getUncached (). execute ( null , obj , attrName );
110
+ Object tmp = lookupAttr ( obj , attrName );
94
111
if (tmp instanceof PNone ) {
95
- if (required ) {
96
- throw PRaiseNode .getUncached ().raise (PythonBuiltinClassType .TypeError , REQUIRED_FIELD_S_MISSING_FROM_S , attrName , nodeName );
97
- } else {
112
+ if (!required ) {
98
113
return 0 ;
99
114
}
115
+ if (tmp == PNone .NO_VALUE ) {
116
+ throw raiseTypeError (REQUIRED_FIELD_S_MISSING_FROM_S , attrName , nodeName );
117
+ }
118
+ // PNone.NONE is handled by obj2int() (produces a different error message)
100
119
}
101
120
// Py_EnterRecursiveCall(" while traversing '%s' node")
102
121
return obj2int (tmp );
103
122
}
104
123
105
124
boolean lookupAndConvertBoolean (Object obj , TruffleString attrName , TruffleString nodeName , boolean required ) {
106
- Object tmp = PyObjectLookupAttr . getUncached (). execute ( null , obj , attrName );
125
+ Object tmp = lookupAttr ( obj , attrName );
107
126
if (tmp instanceof PNone ) {
108
- if (required ) {
109
- throw PRaiseNode .getUncached ().raise (PythonBuiltinClassType .TypeError , REQUIRED_FIELD_S_MISSING_FROM_S , attrName , nodeName );
110
- } else {
127
+ if (!required ) {
111
128
return false ;
112
129
}
130
+ if (tmp == PNone .NO_VALUE ) {
131
+ throw raiseTypeError (REQUIRED_FIELD_S_MISSING_FROM_S , attrName , nodeName );
132
+ }
133
+ // PNone.NONE is handled by obj2boolean() (produces a different error message)
113
134
}
114
135
// Py_EnterRecursiveCall(" while traversing '%s' node")
115
136
return obj2boolean (tmp );
116
137
}
117
138
118
139
<T > T [] lookupAndConvertSequence (Object obj , TruffleString attrName , TruffleString nodeName , Conversion <T > conversion , IntFunction <T []> arrayFactory ) {
119
- Object tmp = PyObjectLookupAttr . getUncached (). execute ( null , obj , attrName );
140
+ Object tmp = lookupAttr ( obj , attrName );
120
141
if (tmp instanceof PNone ) {
121
- throw PRaiseNode . getUncached (). raise ( PythonBuiltinClassType . TypeError , REQUIRED_FIELD_S_MISSING_FROM_S , attrName , nodeName );
142
+ throw raiseTypeError ( REQUIRED_FIELD_S_MISSING_FROM_S , attrName , nodeName );
122
143
}
123
144
if (!(tmp instanceof PList )) {
124
- throw PRaiseNode . getUncached (). raise ( PythonBuiltinClassType . TypeError , S_FIELD_S_MUST_BE_A_LIST_NOT_P , nodeName , attrName , tmp );
145
+ throw raiseTypeError ( S_FIELD_S_MUST_BE_A_LIST_NOT_P , nodeName , attrName , tmp );
125
146
}
126
147
SequenceStorage seq = ((PList ) tmp ).getSequenceStorage ();
127
148
T [] result = arrayFactory .apply (seq .length ());
@@ -130,20 +151,22 @@ <T> T[] lookupAndConvertSequence(Object obj, TruffleString attrName, TruffleStri
130
151
// Py_EnterRecursiveCall(" while traversing '%s' node")
131
152
result [i ] = conversion .convert (tmp );
132
153
if (result .length != seq .length ()) {
133
- throw PRaiseNode . getUncached (). raise ( PythonBuiltinClassType . TypeError , S_FIELD_S_CHANGED_SIZE_DURING_ITERATION , nodeName , attrName );
154
+ throw raiseTypeError ( S_FIELD_S_CHANGED_SIZE_DURING_ITERATION , nodeName , attrName );
134
155
}
135
156
}
136
157
return result ;
137
158
}
138
159
139
160
static boolean isInstanceOf (Object o , PythonAbstractClass cls ) {
140
- Object check = PyObjectLookupAttr . getUncached (). execute ( null , cls , SpecialMethodNames .T___INSTANCECHECK__ );
161
+ Object check = lookupAttr ( cls , SpecialMethodNames .T___INSTANCECHECK__ );
141
162
Object result = CallNode .getUncached ().execute (check , o );
142
163
return CastToJavaBooleanNode .getUncached ().execute (result );
143
164
}
144
165
145
166
int obj2int (Object o ) {
146
- // TODO PyLong_Check
167
+ if (!PyLongCheckNode .getUncached ().execute (o )) {
168
+ throw raiseValueError (INVALID_INTEGER_VALUE , repr (o ));
169
+ }
147
170
return PyLongAsIntNode .getUncached ().execute (null , o );
148
171
}
149
172
@@ -160,11 +183,14 @@ String obj2String(Object obj) { // TODO support str and bytes
160
183
}
161
184
162
185
String obj2identifier (Object obj ) {
163
- // TODO if (!PyUnicode_CheckExact(obj) && obj != Py_None) {
164
186
if (obj == PNone .NONE ) {
165
187
return null ;
166
188
}
167
- return CastToJavaStringNode .getUncached ().execute (obj );
189
+ try {
190
+ return CastToJavaStringNode .getUncached ().execute (obj );
191
+ } catch (CannotCastException e ) {
192
+ throw raiseTypeError (AST_IDENTIFIER_MUST_BE_OF_TYPE_STR );
193
+ }
168
194
}
169
195
170
196
ConstantValue obj2ConstantValue (Object obj ) {
@@ -173,7 +199,26 @@ ConstantValue obj2ConstantValue(Object obj) {
173
199
}
174
200
175
201
static PException unexpectedNodeType (TruffleString expected , Object obj ) {
176
- TruffleString repr = PyObjectReprAsTruffleStringNode .getUncached ().execute (null , obj );
177
- throw PRaiseNode .getUncached ().raise (PythonBuiltinClassType .TypeError , EXPECTED_SOME_SORT_OF_S_BUT_GOT_S , expected , repr );
202
+ throw raiseTypeError (EXPECTED_SOME_SORT_OF_S_BUT_GOT_S , expected , repr (obj ));
203
+ }
204
+
205
+ private static Object lookupAttr (Object o , TruffleString attrName ) {
206
+ return PyObjectLookupAttr .getUncached ().execute (null , o , attrName );
207
+ }
208
+
209
+ private static TruffleString repr (Object o ) {
210
+ return PyObjectReprAsTruffleStringNode .getUncached ().execute (null , o );
211
+ }
212
+
213
+ private static PException raise (PythonBuiltinClassType type , TruffleString format , Object ... arguments ) {
214
+ throw PRaiseNode .getUncached ().raise (type , format , arguments );
215
+ }
216
+
217
+ private static PException raiseTypeError (TruffleString format , Object ... arguments ) {
218
+ throw raise (PythonBuiltinClassType .TypeError , format , arguments );
219
+ }
220
+
221
+ private static PException raiseValueError (TruffleString format , Object ... arguments ) {
222
+ throw raise (PythonBuiltinClassType .ValueError , format , arguments );
178
223
}
179
224
}
0 commit comments