4040 */
4141package com .oracle .graal .python .builtins .modules .ast ;
4242
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 ;
4346import 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 ;
4449import static com .oracle .graal .python .nodes .ErrorMessages .REQUIRED_FIELD_S_MISSING_FROM_S ;
4550import static com .oracle .graal .python .nodes .ErrorMessages .S_FIELD_S_CHANGED_SIZE_DURING_ITERATION ;
4651import static com .oracle .graal .python .nodes .ErrorMessages .S_FIELD_S_MUST_BE_A_LIST_NOT_P ;
5257import com .oracle .graal .python .builtins .objects .list .PList ;
5358import com .oracle .graal .python .builtins .objects .type .PythonAbstractClass ;
5459import com .oracle .graal .python .lib .PyLongAsIntNode ;
60+ import com .oracle .graal .python .lib .PyLongCheckNode ;
5561import com .oracle .graal .python .lib .PyObjectLookupAttr ;
5662import com .oracle .graal .python .lib .PyObjectReprAsTruffleStringNode ;
5763import com .oracle .graal .python .nodes .PRaiseNode ;
5864import com .oracle .graal .python .nodes .SpecialMethodNames ;
5965import com .oracle .graal .python .nodes .call .CallNode ;
66+ import com .oracle .graal .python .nodes .util .CannotCastException ;
6067import com .oracle .graal .python .nodes .util .CastToJavaBooleanNode ;
6168import com .oracle .graal .python .nodes .util .CastToJavaStringNode ;
6269import com .oracle .graal .python .pegparser .sst .ConstantValue ;
@@ -78,50 +85,64 @@ interface Conversion<T> {
7885 }
7986
8087 <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 );
8289 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 );
85103 }
86- return null ;
87104 }
88105 // Py_EnterRecursiveCall(" while traversing '%s' node")
89106 return conversion .convert (tmp );
90107 }
91108
92109 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 );
94111 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 ) {
98113 return 0 ;
99114 }
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)
100119 }
101120 // Py_EnterRecursiveCall(" while traversing '%s' node")
102121 return obj2int (tmp );
103122 }
104123
105124 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 );
107126 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 ) {
111128 return false ;
112129 }
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)
113134 }
114135 // Py_EnterRecursiveCall(" while traversing '%s' node")
115136 return obj2boolean (tmp );
116137 }
117138
118139 <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 );
120141 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 );
122143 }
123144 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 );
125146 }
126147 SequenceStorage seq = ((PList ) tmp ).getSequenceStorage ();
127148 T [] result = arrayFactory .apply (seq .length ());
@@ -130,20 +151,22 @@ <T> T[] lookupAndConvertSequence(Object obj, TruffleString attrName, TruffleStri
130151 // Py_EnterRecursiveCall(" while traversing '%s' node")
131152 result [i ] = conversion .convert (tmp );
132153 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 );
134155 }
135156 }
136157 return result ;
137158 }
138159
139160 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__ );
141162 Object result = CallNode .getUncached ().execute (check , o );
142163 return CastToJavaBooleanNode .getUncached ().execute (result );
143164 }
144165
145166 int obj2int (Object o ) {
146- // TODO PyLong_Check
167+ if (!PyLongCheckNode .getUncached ().execute (o )) {
168+ throw raiseValueError (INVALID_INTEGER_VALUE , repr (o ));
169+ }
147170 return PyLongAsIntNode .getUncached ().execute (null , o );
148171 }
149172
@@ -160,11 +183,14 @@ String obj2String(Object obj) { // TODO support str and bytes
160183 }
161184
162185 String obj2identifier (Object obj ) {
163- // TODO if (!PyUnicode_CheckExact(obj) && obj != Py_None) {
164186 if (obj == PNone .NONE ) {
165187 return null ;
166188 }
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+ }
168194 }
169195
170196 ConstantValue obj2ConstantValue (Object obj ) {
@@ -173,7 +199,26 @@ ConstantValue obj2ConstantValue(Object obj) {
173199 }
174200
175201 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 );
178223 }
179224}
0 commit comments