123
123
import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
124
124
import com .oracle .graal .python .builtins .objects .type .TypeBuiltins ;
125
125
import com .oracle .graal .python .builtins .objects .type .TypeNodes ;
126
+ import com .oracle .graal .python .builtins .objects .type .TypeNodes .IsTypeNode ;
126
127
import com .oracle .graal .python .lib .PyNumberAsSizeNode ;
127
128
import com .oracle .graal .python .lib .PyNumberIndexNode ;
128
129
import com .oracle .graal .python .nodes .BuiltinNames ;
@@ -1957,19 +1958,18 @@ protected ArgumentClinicProvider getArgumentClinic() {
1957
1958
@ ImportStatic (SpecialMethodNames .class )
1958
1959
abstract static class UpdateBasesNode extends PNodeWithRaise {
1959
1960
1960
- abstract PTuple execute (VirtualFrame frame , PTuple bases , Object [] arguments , int nargs );
1961
+ abstract PTuple execute (PTuple bases , Object [] arguments , int nargs );
1961
1962
1962
1963
@ Specialization
1963
- PTuple update (VirtualFrame frame , PTuple bases , Object [] arguments , int nargs ,
1964
+ PTuple update (PTuple bases , Object [] arguments , int nargs ,
1964
1965
@ Cached PythonObjectFactory factory ,
1965
- @ CachedLibrary (limit = "3" ) InteropLibrary interop ,
1966
1966
@ Cached GetClassNode getMroClass ,
1967
1967
@ Cached (parameters = "__MRO_ENTRIES__" ) LookupAttributeInMRONode getMroEntries ,
1968
1968
@ Cached CallBinaryMethodNode callMroEntries ) {
1969
1969
ArrayList <Object > newBases = null ;
1970
1970
for (int i = 0 ; i < nargs ; i ++) {
1971
1971
Object base = arguments [i ];
1972
- if (PGuards . isClass ( base , interop )) {
1972
+ if (IsTypeNode . getUncached (). execute ( base )) {
1973
1973
if (newBases != null ) {
1974
1974
// If we already have made a replacement, then we append every normal base,
1975
1975
// otherwise just skip it.
@@ -1985,7 +1985,7 @@ PTuple update(VirtualFrame frame, PTuple bases, Object[] arguments, int nargs,
1985
1985
}
1986
1986
continue ;
1987
1987
}
1988
- Object newBase = callMroEntries .executeObject (frame , meth , base , bases );
1988
+ Object newBase = callMroEntries .executeObject (null , meth , base , bases );
1989
1989
if (newBase == null ) {
1990
1990
// error
1991
1991
return null ;
@@ -2051,13 +2051,10 @@ Object calculate(Object metatype, PTuple bases,
2051
2051
@ Builtin (name = BuiltinNames .__BUILD_CLASS__ , minNumOfPositionalArgs = 1 , takesVarArgs = true , takesVarKeywordArgs = true )
2052
2052
@ GenerateNodeFactory
2053
2053
public abstract static class BuildClassNode extends PythonVarargsBuiltinNode {
2054
- @ Child private com .oracle .graal .python .nodes .call .CallNode callNode = com .oracle .graal .python .nodes .call .CallNode .create ();
2055
2054
2056
2055
@ Specialization
2057
2056
protected Object doItNonFunction (VirtualFrame frame , Object function , Object [] arguments , PKeyword [] keywords ,
2058
2057
@ CachedContext (PythonLanguage .class ) ContextReference <PythonContext > contextRef ,
2059
- @ CachedLibrary (limit = "3" ) InteropLibrary interop ,
2060
- @ Cached CastToJavaStringNode castToString ,
2061
2058
@ Cached PythonObjectFactory factory ,
2062
2059
@ Cached CalculateMetaclassNode calculateMetaClass ,
2063
2060
@ Cached (parameters = "__PREPARE__" ) LookupAttributeInMRONode getPrepare ,
@@ -2070,84 +2067,91 @@ protected Object doItNonFunction(VirtualFrame frame, Object function, Object[] a
2070
2067
@ Cached SetItemNode setOrigBases ,
2071
2068
@ Cached GetClassNode getClass ) {
2072
2069
2073
- boolean isClass = false ;
2070
+ class InitializeBuildClass {
2071
+ String name ;
2072
+ boolean isClass ;
2073
+ Object meta ;
2074
+ PKeyword [] mkw ;
2075
+ PTuple bases ;
2076
+ PTuple origBases ;
2077
+
2078
+ @ TruffleBoundary
2079
+ InitializeBuildClass () {
2080
+ if (arguments .length < 1 ) {
2081
+ throw raise (PythonErrorType .TypeError , "__build_class__: not enough arguments" );
2082
+ }
2074
2083
2075
- if (arguments .length < 1 ) {
2076
- throw raise (PythonErrorType .TypeError , "__build_class__: not enough arguments" );
2077
- }
2084
+ if (!PGuards .isFunction (function )) {
2085
+ throw raise (PythonErrorType .TypeError , "__build_class__: func must be a function" );
2086
+ }
2087
+ try {
2088
+ name = CastToJavaStringNode .getUncached ().execute (arguments [0 ]);
2089
+ } catch (CannotCastException e ) {
2090
+ throw raise (PythonErrorType .TypeError , "__build_class__: name is not a string" );
2091
+ }
2078
2092
2079
- if (!PGuards .isFunction (function )) {
2080
- throw raise (PythonErrorType .TypeError , "__build_class__: func must be a function" );
2081
- }
2082
- String name ;
2083
- try {
2084
- name = castToString .execute (arguments [0 ]);
2085
- } catch (CannotCastException e ) {
2086
- throw raise (PythonErrorType .TypeError , "__build_class__: name is not a string" );
2087
- }
2093
+ Object [] basesArray = Arrays .copyOfRange (arguments , 1 , arguments .length );
2094
+ origBases = factory .createTuple (basesArray );
2088
2095
2089
- Object [] basesArray = Arrays .copyOfRange (arguments , 1 , arguments .length );
2090
- PTuple origBases = factory .createTuple (basesArray );
2096
+ bases = update .execute (origBases , basesArray , basesArray .length );
2091
2097
2092
- PTuple bases = update .execute (frame , origBases , basesArray , basesArray .length );
2098
+ mkw = keywords ;
2099
+ for (int i = 0 ; i < keywords .length ; i ++) {
2100
+ if ("metaclass" .equals (keywords [i ].getName ())) {
2101
+ meta = keywords [i ].getValue ();
2102
+ mkw = new PKeyword [keywords .length - 1 ];
2093
2103
2094
- Object meta = null ;
2095
- PKeyword [] mkw = keywords ;
2096
- if (keywords .length > 0 ) {
2097
- for (int i = 0 ; i < keywords .length ; i ++) {
2098
- if ("metaclass" .equals (keywords [i ].getName ())) {
2099
- meta = keywords [i ].getValue ();
2100
- mkw = new PKeyword [keywords .length - 1 ];
2101
- System .arraycopy (keywords , 0 , mkw , 0 , i );
2102
- System .arraycopy (keywords , i + 1 , mkw , i , mkw .length - i );
2104
+ PythonUtils .arraycopy (keywords , 0 , mkw , 0 , i );
2105
+ PythonUtils .arraycopy (keywords , i + 1 , mkw , i , mkw .length - i );
2103
2106
2104
- // metaclass is explicitly given, check if it's indeed a class
2105
- isClass = PGuards .isClass (meta , interop );
2106
- break ;
2107
+ // metaclass is explicitly given, check if it's indeed a class
2108
+ isClass = IsTypeNode .getUncached ().equals (meta );
2109
+ break ;
2110
+ }
2107
2111
}
2112
+ if (meta == null ) {
2113
+ // if there are no bases, use type:
2114
+ if (bases .getSequenceStorage ().length () == 0 ) {
2115
+ meta = contextRef .get ().getCore ().lookupType (PythonBuiltinClassType .PythonClass );
2116
+ } else {
2117
+ // else get the type of the first base
2118
+ meta = getClass .execute (bases .getSequenceStorage ().getItemNormalized (0 ));
2119
+ }
2120
+ isClass = true ; // meta is really a class
2121
+ }
2122
+ if (isClass ) {
2123
+ // meta is really a class, so check for a more derived metaclass, or
2124
+ // possible
2125
+ // metaclass conflicts:
2126
+ meta = calculateMetaClass .execute (meta , bases );
2127
+ }
2128
+ // else: meta is not a class, so we cannot do the metaclass calculation, so we
2129
+ // will
2130
+ // use the explicitly given object as it is
2108
2131
}
2109
2132
}
2110
- if (meta == null ) {
2111
- // if there are no bases, use type:
2112
- if (bases .getSequenceStorage ().length () == 0 ) {
2113
- meta = contextRef .get ().getCore ().lookupType (PythonBuiltinClassType .PythonClass );
2114
- } else {
2115
- // else get the type of the first base
2116
- meta = getClass .execute (bases .getSequenceStorage ().getItemNormalized (0 ));
2117
- }
2118
- isClass = true ; // meta is really a class
2119
- }
2133
+ InitializeBuildClass init = new InitializeBuildClass ();
2120
2134
2121
- if (isClass ) {
2122
- // meta is really a class, so check for a more derived metaclass, or possible
2123
- // metaclass conflicts:
2124
- meta = calculateMetaClass .execute (meta , bases );
2125
- }
2126
- // else: meta is not a class, so we cannot do the metaclass calculation, so we will
2127
- // use the explicitly given object as it is
2128
- Object prep = getPrepare .execute (meta );
2135
+ Object prep = getPrepare .execute (init .meta );
2129
2136
Object ns ;
2130
2137
if (PGuards .isNoValue (prep )) {
2131
2138
ns = factory .createDict ();
2132
2139
} else {
2133
- if (PGuards .isFunction (prep )) {
2134
- ns = callPrep .execute (frame , prep , new Object []{name , bases }, mkw );
2135
- } else {
2136
- ns = callPrep .execute (frame , prep , new Object []{meta , name , bases }, mkw );
2137
- }
2140
+ Object [] args = PGuards .isFunction (prep ) ? new Object []{init .name , init .bases } : new Object []{init .meta , init .name , init .bases };
2141
+ ns = callPrep .execute (frame , prep , args , init .mkw );
2138
2142
}
2139
2143
if (PGuards .isNoValue (getGetItem .execute (getGetItemClass .execute (ns )))) {
2140
- if (isClass ) {
2141
- throw raise (PythonErrorType .TypeError , "%p.__prepare__() must return a mapping, not %p" , meta , ns );
2144
+ if (init . isClass ) {
2145
+ throw raise (PythonErrorType .TypeError , "%p.__prepare__() must return a mapping, not %p" , init . meta , ns );
2142
2146
} else {
2143
2147
throw raise (PythonErrorType .TypeError , "<metaclass>.__prepare__() must return a mapping, not %p" , ns );
2144
2148
}
2145
2149
}
2146
2150
callBody .executeObject (frame , function , ns );
2147
- if (bases != origBases ) {
2148
- setOrigBases .executeWith (frame , ns , SpecialAttributeNames .__ORIG_BASES__ , origBases );
2151
+ if (init . bases != init . origBases ) {
2152
+ setOrigBases .executeWith (frame , ns , SpecialAttributeNames .__ORIG_BASES__ , init . origBases );
2149
2153
}
2150
- Object cls = callType .execute (frame , meta , new Object []{name , bases , ns }, mkw );
2154
+ Object cls = callType .execute (frame , init . meta , new Object []{init . name , init . bases , ns }, init . mkw );
2151
2155
2152
2156
/*
2153
2157
* We could check here and throw "__class__ not set defining..." errors.
0 commit comments