132132import com .oracle .graal .python .lib .PyObjectIsTrueNode ;
133133import com .oracle .graal .python .lib .PyObjectLookupAttr ;
134134import com .oracle .graal .python .lib .PyObjectReprAsTruffleStringNode ;
135+ import com .oracle .graal .python .lib .PyTupleCheckNode ;
135136import com .oracle .graal .python .nodes .ErrorMessages ;
136137import com .oracle .graal .python .nodes .HiddenAttr ;
137138import com .oracle .graal .python .nodes .PConstructAndRaiseNode ;
144145import com .oracle .graal .python .nodes .attributes .ReadAttributeFromObjectNode ;
145146import com .oracle .graal .python .nodes .attributes .WriteAttributeToObjectNode ;
146147import com .oracle .graal .python .nodes .builtins .ListNodes .ConstructListNode ;
148+ import com .oracle .graal .python .nodes .builtins .TupleNodes .ConstructTupleNode ;
147149import com .oracle .graal .python .nodes .classes .IsSubtypeNode ;
148150import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
149151import com .oracle .graal .python .nodes .function .PythonBuiltinNode ;
@@ -413,22 +415,30 @@ public static TypeNode create() {
413415 }
414416
415417 @ Specialization (guards = {"!isNoValue(bases)" , "!isNoValue(dict)" })
416- Object typeGeneric (VirtualFrame frame , Object cls , Object name , Object bases , Object dict , PKeyword [] kwds ,
418+ static Object typeGeneric (VirtualFrame frame , Object cls , Object name , Object bases , Object dict , PKeyword [] kwds ,
417419 @ Bind Node inliningTarget ,
418420 @ Cached TypeNode nextTypeNode ,
419421 @ Cached PRaiseNode raiseNode ,
422+ @ Cached PyTupleCheckNode tupleCheck ,
423+ @ Cached ConstructTupleNode constructTupleNode ,
420424 @ Exclusive @ Cached IsTypeNode isTypeNode ) {
425+ Object basesTuple ;
421426 if (!(name instanceof TruffleString || name instanceof PString )) {
422427 throw raiseNode .raise (inliningTarget , TypeError , ErrorMessages .MUST_BE_STRINGS_NOT_P , "type() argument 1" , name );
423- } else if (!(bases instanceof PTuple )) {
428+ } else if (bases instanceof PTuple ) {
429+ basesTuple = bases ;
430+ } else if (tupleCheck .execute (inliningTarget , bases )) {
431+ basesTuple = constructTupleNode .execute (frame , bases );
432+ } else {
424433 throw raiseNode .raise (inliningTarget , TypeError , ErrorMessages .MUST_BE_STRINGS_NOT_P , "type() argument 2" , bases );
425- } else if (!(dict instanceof PDict )) {
434+ }
435+ if (!(dict instanceof PDict )) {
426436 throw raiseNode .raise (inliningTarget , TypeError , ErrorMessages .MUST_BE_STRINGS_NOT_P , "type() argument 3" , dict );
427437 } else if (!isTypeNode .execute (inliningTarget , cls )) {
428438 // TODO: this is actually allowed, deal with it
429439 throw raiseNode .raise (inliningTarget , NotImplementedError , ErrorMessages .CREATING_CLASS_NON_CLS_META_CLS );
430440 }
431- return nextTypeNode .execute (frame , cls , name , bases , dict , kwds );
441+ return nextTypeNode .execute (frame , cls , name , basesTuple , dict , kwds );
432442 }
433443
434444 private TypeNodes .IsAcceptableBaseNode ensureIsAcceptableBaseNode () {
@@ -674,9 +684,11 @@ static Object getBases(Object self, @SuppressWarnings("unused") PNone value,
674684 return PFactory .createTuple (language , getBaseClassesNode .execute (inliningTarget , self ));
675685 }
676686
677- @ Specialization
678- static Object setBases (VirtualFrame frame , PythonClass cls , PTuple value ,
687+ @ Specialization ( guards = "tupleCheck.execute(inliningTarget, value)" , limit = "1" )
688+ static Object setBases (VirtualFrame frame , PythonClass cls , Object value ,
679689 @ Bind Node inliningTarget ,
690+ @ SuppressWarnings ("unused" ) @ Exclusive @ Cached PyTupleCheckNode tupleCheck ,
691+ @ Cached ConstructTupleNode constructTupleNode ,
680692 @ Cached GetObjectArrayNode getArray ,
681693 @ Cached GetBaseClassNode getBase ,
682694 @ Cached GetBestBaseClassNode getBestBase ,
@@ -687,7 +699,8 @@ static Object setBases(VirtualFrame frame, PythonClass cls, PTuple value,
687699 @ Cached GetMroNode getMroNode ,
688700 @ Cached PRaiseNode raiseNode ) {
689701
690- Object [] a = getArray .execute (inliningTarget , value );
702+ PTuple bases = value instanceof PTuple ? (PTuple ) value : constructTupleNode .execute (frame , value );
703+ Object [] a = getArray .execute (inliningTarget , bases );
691704 if (a .length == 0 ) {
692705 throw raiseNode .raise (inliningTarget , TypeError , ErrorMessages .CAN_ONLY_ASSIGN_NON_EMPTY_TUPLE_TO_P , cls );
693706 }
@@ -744,9 +757,10 @@ private static boolean typeIsSubtypeBaseChain(Node inliningTarget, Object a, Obj
744757 return (isSameTypeNode .execute (inliningTarget , b , PythonBuiltinClassType .PythonObject ));
745758 }
746759
747- @ Specialization (guards = "!isPTuple( value)" )
760+ @ Specialization (guards = "!tupleCheck.execute(inliningTarget, value)" , limit = "1 " )
748761 static Object setObject (@ SuppressWarnings ("unused" ) PythonClass cls , @ SuppressWarnings ("unused" ) Object value ,
749- @ Bind Node inliningTarget ) {
762+ @ Bind Node inliningTarget ,
763+ @ SuppressWarnings ("unused" ) @ Exclusive @ Cached PyTupleCheckNode tupleCheck ) {
750764 throw PRaiseNode .raiseStatic (inliningTarget , TypeError , ErrorMessages .CAN_ONLY_ASSIGN_S_TO_S_S_NOT_P , "tuple" , GetNameNode .executeUncached (cls ), "__bases__" , value );
751765 }
752766
@@ -1241,8 +1255,9 @@ public static void dir(PSet names, Object klass) {
12411255 updateSingleNode .execute (null , names , ns );
12421256 }
12431257 Object basesAttr = PyObjectLookupAttr .executeUncached (klass , T___BASES__ );
1244- if (basesAttr instanceof PTuple ) {
1245- Object [] bases = ToArrayNode .executeUncached (((PTuple ) basesAttr ).getSequenceStorage ());
1258+ if (basesAttr instanceof PTuple || PyTupleCheckNode .executeUncached (basesAttr )) {
1259+ PTuple basesTuple = basesAttr instanceof PTuple ? (PTuple ) basesAttr : ConstructTupleNode .getUncached ().execute (null , basesAttr );
1260+ Object [] bases = ToArrayNode .executeUncached (basesTuple .getSequenceStorage ());
12461261 for (Object cls : bases ) {
12471262 // Note that since we are only interested in the keys, the order
12481263 // we merge classes is unimportant
0 commit comments