Skip to content

Commit 28ce99e

Browse files
committed
[GR-23206] Make test_bool pass
PullRequest: graalpython/1040
2 parents 58ee9a9 + c7757be commit 28ce99e

29 files changed

+746
-252
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/PythonModuleTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -40,7 +40,7 @@
4040
import com.oracle.graal.python.builtins.objects.module.PythonModule;
4141
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
4242
import com.oracle.graal.python.nodes.BuiltinNames;
43-
import com.oracle.graal.python.nodes.SpecialAttributeNames;
43+
import com.oracle.graal.python.nodes.SpecialMethodNames;
4444
import com.oracle.graal.python.nodes.call.CallNode;
4545
import com.oracle.graal.python.runtime.PythonContext;
4646
import com.oracle.graal.python.test.PythonTests;
@@ -101,7 +101,7 @@ public void builtinsMinTest() {
101101
public void builtinsIntTest() {
102102
final PythonModule builtins = context.getBuiltins();
103103
PythonBuiltinClass intClass = (PythonBuiltinClass) builtins.getAttribute(BuiltinNames.INT);
104-
Object intNew = intClass.getAttribute(SpecialAttributeNames.__NEW__);
104+
Object intNew = intClass.getAttribute(SpecialMethodNames.__NEW__);
105105
Object returnValue = callBuiltin(intNew, PythonBuiltinClassType.PInt, "42");
106106
assertEquals(42, returnValue);
107107
}

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_bool.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@
2323
*graalpython.lib-python.3.test.test_bool.BoolTest.test_repr
2424
*graalpython.lib-python.3.test.test_bool.BoolTest.test_sane_len
2525
*graalpython.lib-python.3.test.test_bool.BoolTest.test_str
26+
*graalpython.lib-python.3.test.test_bool.BoolTest.test_string
27+
*graalpython.lib-python.3.test.test_bool.BoolTest.test_subclass
2628
*graalpython.lib-python.3.test.test_bool.BoolTest.test_types

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Builtin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
String doc() default "";
3939

40-
PythonBuiltinClassType[] constructsClass() default {};
40+
PythonBuiltinClassType constructsClass() default PythonBuiltinClassType.nil;
4141

4242
PythonBuiltinClassType[] base() default {};
4343

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626
package com.oracle.graal.python.builtins;
2727

28+
import java.util.Arrays;
2829
import java.util.HashSet;
2930

3031
import com.oracle.graal.python.PythonLanguage;
@@ -205,7 +206,10 @@ public enum PythonBuiltinClassType implements LazyPythonClass {
205206
RuntimeWarning("RuntimeWarning", BuiltinNames.BUILTINS),
206207
SyntaxWarning("SyntaxWarning", BuiltinNames.BUILTINS),
207208
UnicodeWarning("UnicodeWarning", BuiltinNames.BUILTINS),
208-
UserWarning("UserWarning", BuiltinNames.BUILTINS);
209+
UserWarning("UserWarning", BuiltinNames.BUILTINS),
210+
211+
// A marker for @Builtin that is not a class. Must always come last.
212+
nil(null);
209213

210214
private final String name;
211215
private final Shape instanceShape;
@@ -224,7 +228,11 @@ public enum PythonBuiltinClassType implements LazyPythonClass {
224228
} else {
225229
qualifiedName = name;
226230
}
227-
this.instanceShape = com.oracle.graal.python.builtins.objects.object.PythonObject.freshShape(this);
231+
if (name != null) {
232+
this.instanceShape = com.oracle.graal.python.builtins.objects.object.PythonObject.freshShape(this);
233+
} else {
234+
this.instanceShape = null;
235+
}
228236
this.basetype = basetype;
229237
}
230238

@@ -271,7 +279,7 @@ public final DynamicObject newInstance() {
271279
return instanceShape.newInstance();
272280
}
273281

274-
public static final PythonBuiltinClassType[] VALUES = values();
282+
public static final PythonBuiltinClassType[] VALUES = Arrays.copyOf(values(), values().length - 1);
275283
public static final PythonBuiltinClassType[] EXCEPTIONS;
276284

277285
static {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ public void initialize(PythonCore core) {
6565
initializeEachFactoryWith((factory, builtin) -> {
6666
CoreFunctions annotation = getClass().getAnnotation(CoreFunctions.class);
6767
final boolean declaresExplicitSelf;
68-
if (annotation.defineModule().length() > 0 && builtin.constructsClass().length == 0) {
68+
PythonBuiltinClassType constructsClass = builtin.constructsClass();
69+
if (annotation.defineModule().length() > 0 && constructsClass == PythonBuiltinClassType.nil) {
6970
assert !builtin.isGetter();
7071
assert !builtin.isSetter();
7172
assert annotation.extendClasses().length == 0;
@@ -75,16 +76,16 @@ public void initialize(PythonCore core) {
7576
declaresExplicitSelf = true;
7677
}
7778
RootCallTarget callTarget = core.getLanguage().getOrComputeBuiltinCallTarget(builtin, factory.getNodeClass(),
78-
(b) -> Truffle.getRuntime().createCallTarget(new BuiltinFunctionRootNode(core.getLanguage(), builtin, factory, declaresExplicitSelf, builtin.reverseOperation())));
79+
(b) -> Truffle.getRuntime().createCallTarget(new BuiltinFunctionRootNode(core.getLanguage(), builtin, factory, declaresExplicitSelf)));
7980
Object builtinDoc = builtin.doc().isEmpty() ? PNone.NONE : builtin.doc();
80-
if (builtin.constructsClass().length > 0) {
81+
if (constructsClass != PythonBuiltinClassType.nil) {
8182
assert !builtin.isGetter() && !builtin.isSetter() && !builtin.isClassmethod() && !builtin.isStaticmethod();
82-
PBuiltinFunction newFunc = core.factory().createBuiltinFunction(__NEW__, null, numDefaults(builtin), callTarget);
83-
for (PythonBuiltinClassType type : builtin.constructsClass()) {
84-
PythonBuiltinClass builtinClass = core.lookupType(type);
85-
builtinClass.setAttributeUnsafe(__NEW__, newFunc);
86-
builtinClass.setAttribute(__DOC__, builtinDoc);
87-
}
83+
// we explicitly do not make these "staticmethods" here, since CPython also doesn't
84+
// for builtin types
85+
PBuiltinFunction newFunc = core.factory().createBuiltinFunction(__NEW__, constructsClass, numDefaults(builtin), callTarget);
86+
PythonBuiltinClass builtinClass = core.lookupType(constructsClass);
87+
builtinClass.setAttributeUnsafe(__NEW__, newFunc);
88+
builtinClass.setAttribute(__DOC__, builtinDoc);
8889
} else {
8990
PBuiltinFunction function = core.factory().createBuiltinFunction(builtin.name(), null, numDefaults(builtin), callTarget);
9091
function.setAttribute(__DOC__, builtinDoc);
@@ -118,12 +119,19 @@ private void initializeEachFactoryWith(BiConsumer<NodeFactory<? extends PythonBu
118119
assert factories != null : "No factories found. Override getFactories() to resolve this.";
119120
for (NodeFactory<? extends PythonBuiltinBaseNode> factory : factories) {
120121
Boolean needsFrame = null;
122+
boolean constructsClass = false;
121123
for (Builtin builtin : factory.getNodeClass().getAnnotationsByType(Builtin.class)) {
122124
if (needsFrame == null) {
123125
needsFrame = builtin.needsFrame();
124126
} else if (needsFrame != builtin.needsFrame()) {
125127
throw new IllegalStateException(String.format("Implementation error in %s: all @Builtin annotations must agree if the node needs a frame.", factory.getNodeClass().getName()));
126128
}
129+
if (!constructsClass) {
130+
constructsClass = builtin.constructsClass() != PythonBuiltinClassType.nil;
131+
} else {
132+
// we rely on this in WrapTpNew#getOwner
133+
throw new IllegalStateException(String.format("Implementation error in %s: only one @Builtin annotation can declare a class constructor.", factory.getNodeClass().getName()));
134+
}
127135
func.accept(factory, builtin);
128136
}
129137
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,7 @@ private HashingCollectionNodes.SetItemNode getSetItemNode() {
11411141
// int(x, base=10)
11421142
@Builtin(name = INT, minNumOfPositionalArgs = 1, parameterNames = {"cls", "x", "base"}, numOfPositionalOnlyArgs = 2, constructsClass = PythonBuiltinClassType.PInt)
11431143
@GenerateNodeFactory
1144-
public abstract static class IntNode extends PythonBuiltinNode {
1144+
public abstract static class IntNode extends PythonTernaryBuiltinNode {
11451145

11461146
private final ConditionProfile invalidBase = ConditionProfile.createBinaryProfile();
11471147
private final BranchProfile invalidValueProfile = BranchProfile.create();
@@ -1155,8 +1155,6 @@ public abstract static class IntNode extends PythonBuiltinNode {
11551155
@Child private LookupAndCallUnaryNode callTruncNode;
11561156
@Child private LookupAndCallUnaryNode callReprNode;
11571157

1158-
public abstract Object executeWith(VirtualFrame frame, Object cls, Object arg, Object base);
1159-
11601158
@TruffleBoundary
11611159
private static Object stringToIntInternal(String num, int base) {
11621160
String s = num.replace("_", "");
@@ -2304,12 +2302,12 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
23042302
if (__SLOTS__.equals(key)) {
23052303
slots = value;
23062304
} else if (SpecialMethodNames.__NEW__.equals(key)) {
2307-
// TODO: see CPython: if it's a plain function, make it a
2308-
// static function
2309-
2310-
// tfel: this requires a little bit of refactoring on our
2311-
// side that I don't want to do now
2312-
pythonClass.setAttribute(key, value);
2305+
// see CPython: if it's a plain function, make it a static function
2306+
if (value instanceof PFunction) {
2307+
pythonClass.setAttribute(key, factory().createStaticmethodFromCallableObj(value));
2308+
} else {
2309+
pythonClass.setAttribute(key, value);
2310+
}
23132311
} else if (SpecialMethodNames.__INIT_SUBCLASS__.equals(key) ||
23142312
SpecialMethodNames.__CLASS_GETITEM__.equals(key)) {
23152313
// see CPython: Special-case __init_subclass__ and
@@ -2785,13 +2783,26 @@ public Object dictKeys(Object args, Object kwargs) {
27852783
}
27862784
}
27872785

2788-
@Builtin(name = "iterator", takesVarArgs = true, takesVarKeywordArgs = true, constructsClass = {PythonBuiltinClassType.PIterator, PythonBuiltinClassType.PArrayIterator}, isPublic = false)
2786+
@Builtin(name = "iterator", takesVarArgs = true, takesVarKeywordArgs = true, constructsClass = PythonBuiltinClassType.PIterator, isPublic = false)
27892787
@GenerateNodeFactory
27902788
public abstract static class IteratorTypeNode extends PythonBuiltinNode {
27912789
@SuppressWarnings("unused")
27922790
@Specialization
2793-
public Object iterator(Object args, Object kwargs) {
2794-
throw raise(TypeError, ErrorMessages.CANNOT_CREATE_INSTANCES, "'iterator'");
2791+
Object iterator(Object args, Object kwargs) {
2792+
throw raise(TypeError, ErrorMessages.CANNOT_CREATE_INSTANCES, className());
2793+
}
2794+
2795+
protected String className() {
2796+
return "'iterator'";
2797+
}
2798+
}
2799+
2800+
@Builtin(name = "arrayiterator", takesVarArgs = true, takesVarKeywordArgs = true, constructsClass = PythonBuiltinClassType.PArrayIterator, isPublic = false)
2801+
@GenerateNodeFactory
2802+
public abstract static class ArrayIteratorTypeNode extends IteratorTypeNode {
2803+
@Override
2804+
protected String className() {
2805+
return "'arrayiterator'";
27952806
}
27962807
}
27972808

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PythonCextBuiltins.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@
6969
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
7070
import com.oracle.graal.python.builtins.PythonBuiltins;
7171
import com.oracle.graal.python.builtins.modules.BuiltinConstructors.IntNode;
72-
import com.oracle.graal.python.builtins.modules.BuiltinConstructorsFactory.IntNodeFactory;
7372
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.AllocFuncRootNode;
7473
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.GetAttrFuncRootNode;
7574
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.MethDirectRoot;
@@ -1119,26 +1118,22 @@ static Object doGeneric(VirtualFrame frame, Object object, int signed, long targ
11191118
@Shared("toJavaNode") @Cached ToJavaNode toJavaNode,
11201119
@Cached CastToNativeLongNode castToNativeLongNode,
11211120
@Cached("createClassProfile()") ValueProfile pointerClassProfile,
1122-
@Cached("createIntNode()") IntNode constructIntNode,
1121+
@Cached IntNode constructIntNode,
11231122
@Shared("converPIntToPrimitiveNode") @Cached ConvertPIntToPrimitiveNode convertPIntToPrimitiveNode,
11241123
@Shared("transformExceptionToNativeNode") @Cached TransformExceptionToNativeNode transformExceptionToNativeNode) {
11251124
Object resolvedPointer = pointerClassProfile.profile(resolveHandleNode.execute(object));
11261125
try {
11271126
if (resolvedPointer instanceof PrimitiveNativeWrapper) {
11281127
return convertPIntToPrimitiveNode.execute(frame, resolvedPointer, signed, targetTypeSize);
11291128
}
1130-
Object coerced = constructIntNode.executeWith(frame, PythonBuiltinClassType.PInt, toJavaNode.execute(resolvedPointer), PNone.NO_VALUE);
1129+
Object coerced = constructIntNode.execute(frame, PythonBuiltinClassType.PInt, toJavaNode.execute(resolvedPointer), PNone.NO_VALUE);
11311130
return castToNativeLongNode.execute(convertPIntToPrimitiveNode.execute(frame, coerced, signed, targetTypeSize));
11321131
} catch (PException e) {
11331132
transformExceptionToNativeNode.execute(frame, e);
11341133
return -1;
11351134
}
11361135
}
11371136

1138-
static IntNode createIntNode() {
1139-
return IntNodeFactory.create(null);
1140-
}
1141-
11421137
static final class UnexpectedWrapperException extends ControlFlowException {
11431138
private static final long serialVersionUID = 1L;
11441139
static final UnexpectedWrapperException INSTANCE = new UnexpectedWrapperException();
@@ -2382,17 +2377,17 @@ Object make(PFunction func, Object errorResult,
23822377
case 1:
23832378
rootNode = new BuiltinFunctionRootNode(lang, unaryBuiltin,
23842379
new MayRaiseNodeFactory<PythonUnaryBuiltinNode>(MayRaiseUnaryNodeGen.create(func, errorResult)),
2385-
true, false);
2380+
true);
23862381
break;
23872382
case 2:
23882383
rootNode = new BuiltinFunctionRootNode(lang, binaryBuiltin,
23892384
new MayRaiseNodeFactory<PythonBinaryBuiltinNode>(MayRaiseBinaryNodeGen.create(func, errorResult)),
2390-
true, false);
2385+
true);
23912386
break;
23922387
case 3:
23932388
rootNode = new BuiltinFunctionRootNode(lang, ternaryBuiltin,
23942389
new MayRaiseNodeFactory<PythonTernaryBuiltinNode>(MayRaiseTernaryNodeGen.create(func, errorResult)),
2395-
true, false);
2390+
true);
23962391
break;
23972392
default:
23982393
break;
@@ -2401,7 +2396,7 @@ Object make(PFunction func, Object errorResult,
24012396
if (rootNode == null) {
24022397
rootNode = new BuiltinFunctionRootNode(lang, varargsBuiltin,
24032398
new MayRaiseNodeFactory<PythonBuiltinNode>(new MayRaiseNode(func, errorResult)),
2404-
true, false);
2399+
true);
24052400
}
24062401

24072402
return factory().createBuiltinFunction(func.getName(), null, 0, Truffle.getRuntime().createCallTarget(rootNode));

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2461,26 +2461,29 @@ public static PCallCapiFunction getUncached() {
24612461
// -----------------------------------------------------------------------------------------------------------------
24622462
public static class MayRaiseNodeFactory<T extends PythonBuiltinBaseNode> implements NodeFactory<T> {
24632463
private final T node;
2464-
private Class<T> nodeClass;
2464+
private final Class<T> nodeClass;
24652465

24662466
public MayRaiseNodeFactory(T node) {
24672467
this.node = node;
2468+
this.nodeClass = determineNodeClass(node);
24682469
}
24692470

24702471
public T createNode(Object... arguments) {
24712472
return NodeUtil.cloneNode(node);
24722473
}
24732474

2474-
@SuppressWarnings("unchecked")
24752475
public Class<T> getNodeClass() {
2476+
return nodeClass;
2477+
}
2478+
2479+
@SuppressWarnings("unchecked")
2480+
private static <T> Class<T> determineNodeClass(T node) {
24762481
CompilerAsserts.neverPartOfCompilation();
2477-
if (nodeClass == null) {
2478-
nodeClass = (Class<T>) node.getClass();
2479-
GeneratedBy genBy = nodeClass.getAnnotation(GeneratedBy.class);
2480-
if (genBy != null) {
2481-
nodeClass = (Class<T>) genBy.value();
2482-
assert nodeClass.isAssignableFrom(node.getClass());
2483-
}
2482+
Class<T> nodeClass = (Class<T>) node.getClass();
2483+
GeneratedBy genBy = nodeClass.getAnnotation(GeneratedBy.class);
2484+
if (genBy != null) {
2485+
nodeClass = (Class<T>) genBy.value();
2486+
assert nodeClass.isAssignableFrom(node.getClass());
24842487
}
24852488
return nodeClass;
24862489
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/DynamicObjectNativeWrapper.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
import com.oracle.graal.python.builtins.objects.memoryview.PBuffer;
103103
import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView;
104104
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
105+
import com.oracle.graal.python.builtins.objects.method.PDecoratedMethod;
105106
import com.oracle.graal.python.builtins.objects.method.PMethod;
106107
import com.oracle.graal.python.builtins.objects.mmap.PMMap;
107108
import com.oracle.graal.python.builtins.objects.module.PythonModule;
@@ -462,9 +463,16 @@ static Object doTpAsMapping(PythonManagedClass object, @SuppressWarnings("unused
462463

463464
@Specialization(guards = "eq(TP_NEW, key)")
464465
static Object doTpNew(PythonManagedClass object, @SuppressWarnings("unused") PythonNativeWrapper nativeWrapper, @SuppressWarnings("unused") String key,
466+
@Cached ConditionProfile profileNewType,
465467
@Cached LookupAttributeInMRONode.Dynamic getAttrNode,
466468
@Cached PCallCapiFunction callGetNewfuncTypeidNode) {
467-
return ManagedMethodWrappers.createKeywords(getAttrNode.execute(object, __NEW__), callGetNewfuncTypeidNode.call(NativeCAPISymbols.FUN_GET_NEWFUNC_TYPE_ID));
469+
// __new__ is magically a staticmethod for Python types. The tp_new slot lookup expects
470+
// to get the function
471+
Object newFunction = getAttrNode.execute(object, __NEW__);
472+
if (profileNewType.profile(newFunction instanceof PDecoratedMethod)) {
473+
newFunction = ((PDecoratedMethod) newFunction).getCallable();
474+
}
475+
return ManagedMethodWrappers.createKeywords(newFunction, callGetNewfuncTypeidNode.call(NativeCAPISymbols.FUN_GET_NEWFUNC_TYPE_ID));
468476
}
469477

470478
@Specialization(guards = "eq(TP_HASH, key)")

0 commit comments

Comments
 (0)