Skip to content

Commit 87a6ef9

Browse files
committed
intrinsified python_cext PyNumber_XXX
1 parent 39207c8 commit 87a6ef9

File tree

7 files changed

+267
-66
lines changed

7 files changed

+267
-66
lines changed

graalpython/com.oracle.graal.python.cext/src/abstract.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,7 @@ static PyObject* null_error(void) {
5858

5959
UPCALL_ID(PyNumber_Check);
6060
int PyNumber_Check(PyObject *o) {
61-
PyObject *result = UPCALL_CEXT_O(_jls_PyNumber_Check, native_to_java(o));
62-
if(result == Py_True) {
63-
return 1;
64-
}
65-
return 0;
61+
return UPCALL_CEXT_I(_jls_PyNumber_Check, native_to_java(o));
6662
}
6763

6864
typedef PyObject *(*unaryop_fun_t)(PyObject *, int32_t);

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_abstract.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,26 @@ def _safe_check(v, type_check):
5151

5252
def _reference_checknumber(args):
5353
v = args[0]
54+
if isinstance(v, str):
55+
return False
5456
return _safe_check(v, lambda x: isinstance(int(x), int)) or _safe_check(v, lambda x: isinstance(float(x), float))
5557

58+
def _reference_tobase(args):
59+
n = args[0]
60+
base = args[1]
61+
if base not in (2, 8, 10, 16):
62+
raise SystemError("PyNumber_ToBase: base must be 2, 8, 10 or 16")
63+
if not hasattr(n, "__index__"):
64+
raise TypeError
65+
b_index = n.__index__()
66+
if base == 2:
67+
return bin(b_index)
68+
elif base == 8:
69+
return oct(b_index)
70+
elif base == 10:
71+
return str(b_index)
72+
elif base == 16:
73+
return hex(b_index)
5674

5775
def _reference_index(args):
5876
v = args[0]
@@ -205,6 +223,7 @@ def _default_unarop_args():
205223
(False,),
206224
(True,),
207225
("hello",),
226+
("1",),
208227
((1, 2, 3),),
209228
(0x7fffffff,),
210229
(0xffffffffffffffffffffffffffffffff,),
@@ -259,6 +278,55 @@ def compile_module(self, name):
259278
cmpfunc=unhandled_error_compare
260279
)
261280

281+
test_PyNumber_ToBase = CPyExtFunction(
282+
_reference_tobase,
283+
lambda: (
284+
(2, 0),
285+
("hello", 0),
286+
(1.1, 0),
287+
(NoNumber(), 0),
288+
(2, 0),
289+
(2, 0),
290+
(2, 2),
291+
(2, 8),
292+
(2, 10),
293+
(2, 16),
294+
("1", 2),
295+
("1", 8),
296+
("1", 10),
297+
("1", 16),
298+
(1.1, 2),
299+
(1.1, 8),
300+
(1.1, 10),
301+
(1.1, 16),
302+
(False, 2),
303+
(False, 8),
304+
(False, 10),
305+
(False, 16),
306+
(True, 16),
307+
("hello, ", 2),
308+
("hello, ", 8),
309+
("hello, ", 10),
310+
("hello, ", 16),
311+
(DummyIntable(), 2),
312+
(DummyIntable(), 8),
313+
(DummyIntable(), 10),
314+
(DummyIntable(), 16),
315+
(DummyIntSubclass(), 2),
316+
(DummyIntSubclass(), 8),
317+
(DummyIntSubclass(), 10),
318+
(DummyIntSubclass(), 16),
319+
(NoNumber(), 2),
320+
(NoNumber(), 8),
321+
(NoNumber(), 10),
322+
(NoNumber(), 16),
323+
),
324+
resultspec="O",
325+
argspec='Oi',
326+
arguments=["PyObject* n", "int base"],
327+
cmpfunc=unhandled_error_compare
328+
)
329+
262330
test_PyNumber_Add = CPyExtFunction(
263331
lambda args: args[0] + args[1],
264332
lambda: (
@@ -482,6 +550,7 @@ def compile_module(self, name):
482550
(1,),
483551
(-1,),
484552
(1.0,),
553+
("1",),
485554
(0x7FFFFFFF,),
486555
(0x7FFFFFFFFFFFFFFF,),
487556
(DummyIntable(),),
@@ -522,6 +591,7 @@ def compile_module(self, name):
522591
(1,),
523592
(-1,),
524593
(1.0,),
594+
("1",),
525595
(0x7FFFFFFF,),
526596
(0x7FFFFFFFFFFFFFFF,),
527597
(DummyIntable(),),

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
import com.oracle.graal.python.builtins.PythonBuiltins;
9292
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.GetAttrNodeFactory;
9393
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.GlobalsNodeFactory;
94+
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.HexNodeFactory;
95+
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.OctNodeFactory;
9496
import com.oracle.graal.python.builtins.modules.WarningsModuleBuiltins.WarnNode;
9597
import com.oracle.graal.python.builtins.modules.io.IOModuleBuiltins;
9698
import com.oracle.graal.python.builtins.modules.io.IONodes;
@@ -611,6 +613,10 @@ protected String longToString(long x) {
611613
protected String prefix() {
612614
return "0o";
613615
}
616+
617+
public static OctNode create() {
618+
return OctNodeFactory.create();
619+
}
614620
}
615621

616622
// hex(object)
@@ -634,6 +640,10 @@ protected String longToString(long x) {
634640
protected String prefix() {
635641
return "0x";
636642
}
643+
644+
public static HexNode create() {
645+
return HexNodeFactory.create();
646+
}
637647
}
638648

639649
// callable(object)

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

Lines changed: 184 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import static com.oracle.graal.python.builtins.objects.cext.common.CExtContext.isClassOrStaticMethod;
4848
import static com.oracle.graal.python.nodes.ErrorMessages.BAD_ARG_TO_INTERNAL_FUNC_S;
4949
import static com.oracle.graal.python.nodes.ErrorMessages.BAD_ARG_TO_INTERNAL_FUNC_WAS_S_P;
50+
import static com.oracle.graal.python.nodes.ErrorMessages.BASE_MUST_BE;
5051
import static com.oracle.graal.python.nodes.ErrorMessages.CANNOT_CONVERT_P_OBJ_TO_S;
5152
import static com.oracle.graal.python.nodes.ErrorMessages.HASH_MISMATCH;
5253
import static com.oracle.graal.python.nodes.ErrorMessages.LIST_INDEX_OUT_OF_RANGE;
@@ -58,8 +59,9 @@
5859
import static com.oracle.graal.python.nodes.SpecialMethodNames.ITEMS;
5960
import static com.oracle.graal.python.nodes.SpecialMethodNames.KEYS;
6061
import static com.oracle.graal.python.nodes.SpecialMethodNames.VALUES;
61-
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEW__;
62+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__FLOAT__;
6263
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ITER__;
64+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEW__;
6365
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
6466
import static com.oracle.graal.python.util.PythonUtils.EMPTY_BYTE_ARRAY;
6567
import static com.oracle.graal.python.util.PythonUtils.EMPTY_OBJECT_ARRAY;
@@ -94,6 +96,11 @@
9496
import com.oracle.graal.python.builtins.modules.BuiltinConstructors.FrozenSetNode;
9597
import com.oracle.graal.python.builtins.modules.BuiltinConstructors.MappingproxyNode;
9698
import com.oracle.graal.python.builtins.modules.BuiltinConstructors.StrNode;
99+
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.AbsNode;
100+
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.BinNode;
101+
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.DivModNode;
102+
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.HexNode;
103+
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.OctNode;
97104
import com.oracle.graal.python.builtins.modules.PythonCextBuiltinsFactory.CreateFunctionNodeGen;
98105
import com.oracle.graal.python.builtins.objects.PNone;
99106
import com.oracle.graal.python.builtins.objects.PNotImplemented;
@@ -284,7 +291,6 @@
284291
import com.oracle.graal.python.nodes.PRaiseNode;
285292
import com.oracle.graal.python.nodes.SpecialAttributeNames;
286293
import com.oracle.graal.python.nodes.SpecialMethodNames;
287-
import static com.oracle.graal.python.nodes.SpecialMethodNames.__FLOAT__;
288294
import com.oracle.graal.python.nodes.WriteUnraisableNode;
289295
import com.oracle.graal.python.nodes.argument.CreateArgumentsNode.CreateAndCheckArgumentsNode;
290296
import com.oracle.graal.python.nodes.argument.keywords.ExpandKeywordStarargsNode;
@@ -2304,7 +2310,7 @@ public Object signNative(VirtualFrame frame, Object obj,
23042310
}
23052311

23062312
@Specialization(guards = {"!isInteger(obj)", "!isPInt(obj)", "!isPIntSubtype(frame, obj,getClassNode,isSubtypeNode)"})
2307-
public Object sign(VirtualFrame frame, Object obj,
2313+
public Object sign(@SuppressWarnings("unused") VirtualFrame frame, @SuppressWarnings("unused") Object obj,
23082314
@SuppressWarnings("unused") @Cached GetClassNode getClassNode,
23092315
@SuppressWarnings("unused") @Cached IsSubtypeNode isSubtypeNode) {
23102316
// assert(PyLong_Check(v));
@@ -2505,6 +2511,181 @@ public PComplex asDouble(double r, double i) {
25052511
}
25062512
}
25072513

2514+
///////////// number /////////////
2515+
2516+
@Builtin(name = "PyNumber_Check", minNumOfPositionalArgs = 1)
2517+
@TypeSystemReference(PythonTypes.class)
2518+
@GenerateNodeFactory
2519+
abstract static class PyNumberCheckNode extends PythonUnaryBuiltinNode {
2520+
@Specialization
2521+
Object check(VirtualFrame frame, Object obj,
2522+
@Cached com.oracle.graal.python.lib.PyNumberCheckNode checkNode,
2523+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
2524+
@Cached GetNativeNullNode getNativeNullNode) {
2525+
try {
2526+
return checkNode.execute(frame, obj);
2527+
} catch (PException e) {
2528+
transformExceptionToNativeNode.execute(e);
2529+
return getNativeNullNode.execute();
2530+
}
2531+
}
2532+
}
2533+
2534+
@Builtin(name = "PyNumber_Index", minNumOfPositionalArgs = 1)
2535+
@GenerateNodeFactory
2536+
abstract static class PyNumberIndexNode extends PythonUnaryBuiltinNode {
2537+
@Specialization
2538+
Object index(VirtualFrame frame, Object obj,
2539+
@Cached com.oracle.graal.python.lib.PyNumberIndexNode indexNode,
2540+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
2541+
@Cached GetNativeNullNode getNativeNullNode) {
2542+
try {
2543+
return indexNode.execute(frame, obj);
2544+
} catch (PException e) {
2545+
transformExceptionToNativeNode.execute(e);
2546+
return getNativeNullNode.execute();
2547+
}
2548+
}
2549+
}
2550+
2551+
@Builtin(name = "PyNumber_Long", minNumOfPositionalArgs = 1)
2552+
@GenerateNodeFactory
2553+
abstract static class PyNumberLongNode extends PythonUnaryBuiltinNode {
2554+
2555+
@Specialization
2556+
int nlong(int i) {
2557+
return i;
2558+
}
2559+
2560+
@Specialization
2561+
long nlong(long i) {
2562+
return i;
2563+
}
2564+
2565+
@Fallback
2566+
Object nlong(VirtualFrame frame, Object obj,
2567+
@Cached com.oracle.graal.python.builtins.modules.BuiltinConstructors.IntNode intNode,
2568+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
2569+
@Cached GetNativeNullNode getNativeNullNode) {
2570+
try {
2571+
return intNode.executeWith(frame, obj, PNone.NO_VALUE);
2572+
} catch (PException e) {
2573+
transformExceptionToNativeNode.execute(e);
2574+
return getNativeNullNode.execute();
2575+
}
2576+
}
2577+
}
2578+
2579+
@Builtin(name = "PyNumber_Absolute", minNumOfPositionalArgs = 1)
2580+
@GenerateNodeFactory
2581+
abstract static class PyNumberAbsoluteNode extends PythonUnaryBuiltinNode {
2582+
@Specialization
2583+
Object abs(VirtualFrame frame, Object obj,
2584+
@Cached AbsNode absNode,
2585+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
2586+
@Cached GetNativeNullNode getNativeNullNode) {
2587+
try {
2588+
return absNode.execute(frame, obj);
2589+
} catch (PException e) {
2590+
transformExceptionToNativeNode.execute(e);
2591+
return getNativeNullNode.execute();
2592+
}
2593+
}
2594+
}
2595+
2596+
@Builtin(name = "PyNumber_Divmod", minNumOfPositionalArgs = 2)
2597+
@GenerateNodeFactory
2598+
abstract static class PyNumberDivmodeNode extends PythonBinaryBuiltinNode {
2599+
@Specialization
2600+
Object div(VirtualFrame frame, Object a, Object b,
2601+
@Cached DivModNode divNode,
2602+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
2603+
@Cached GetNativeNullNode getNativeNullNode) {
2604+
try {
2605+
return divNode.execute(frame, a, b);
2606+
} catch (PException e) {
2607+
transformExceptionToNativeNode.execute(e);
2608+
return getNativeNullNode.execute();
2609+
}
2610+
}
2611+
}
2612+
2613+
@Builtin(name = "PyNumber_ToBase", minNumOfPositionalArgs = 2)
2614+
@GenerateNodeFactory
2615+
abstract static class PyNumberToBaseNode extends PythonBinaryBuiltinNode {
2616+
@Specialization(guards = "base == 2")
2617+
Object toBase(VirtualFrame frame, Object n, @SuppressWarnings("unused") int base,
2618+
@Cached com.oracle.graal.python.lib.PyNumberIndexNode indexNode,
2619+
@Cached BinNode binNode,
2620+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
2621+
@Cached GetNativeNullNode getNativeNullNode) {
2622+
try {
2623+
Object i = indexNode.execute(frame, n);
2624+
return binNode.execute(frame, i);
2625+
} catch (PException e) {
2626+
transformExceptionToNativeNode.execute(e);
2627+
return getNativeNullNode.execute();
2628+
}
2629+
}
2630+
2631+
@Specialization(guards = "base == 8")
2632+
Object toBase(VirtualFrame frame, Object n, @SuppressWarnings("unused") int base,
2633+
@Cached OctNode octNode,
2634+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
2635+
@Cached GetNativeNullNode getNativeNullNode) {
2636+
try {
2637+
return octNode.execute(frame, n);
2638+
} catch (PException e) {
2639+
transformExceptionToNativeNode.execute(e);
2640+
return getNativeNullNode.execute();
2641+
}
2642+
}
2643+
2644+
@Specialization(guards = "base == 10")
2645+
Object toBase(VirtualFrame frame, Object n, @SuppressWarnings("unused") int base,
2646+
@Cached com.oracle.graal.python.lib.PyNumberIndexNode indexNode,
2647+
@Cached StrNode strNode,
2648+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
2649+
@Cached GetNativeNullNode getNativeNullNode) {
2650+
try {
2651+
Object i = indexNode.execute(frame, n);
2652+
if (i instanceof Boolean) {
2653+
i = ((boolean) i) ? 1 : 0;
2654+
}
2655+
return strNode.executeWith(frame, i);
2656+
} catch (PException e) {
2657+
transformExceptionToNativeNode.execute(e);
2658+
return getNativeNullNode.execute();
2659+
}
2660+
}
2661+
2662+
@Specialization(guards = "base == 16")
2663+
Object toBase(VirtualFrame frame, Object n, @SuppressWarnings("unused") int base,
2664+
@Cached PyNumberIndexNode indexNode,
2665+
@Cached HexNode hexNode,
2666+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode,
2667+
@Cached GetNativeNullNode getNativeNullNode) {
2668+
try {
2669+
Object i = indexNode.execute(frame, n);
2670+
return hexNode.execute(frame, i);
2671+
} catch (PException e) {
2672+
transformExceptionToNativeNode.execute(e);
2673+
return getNativeNullNode.execute();
2674+
}
2675+
}
2676+
2677+
@Specialization(guards = "!checkBase(base)")
2678+
Object toBase(VirtualFrame frame, @SuppressWarnings("unused") Object n, @SuppressWarnings("unused") int base,
2679+
@Cached GetNativeNullNode getNativeNullNode,
2680+
@Cached PRaiseNativeNode raiseNativeNode) {
2681+
return raiseNativeNode.raise(frame, getNativeNullNode.execute(), SystemError, BASE_MUST_BE);
2682+
}
2683+
2684+
protected boolean checkBase(int base) {
2685+
return base == 2 || base == 8 || base == 10 || base == 16;
2686+
}
2687+
}
2688+
25082689
/**
25092690
* This is used in the ExternalFunctionNode below, so all arguments passed from Python code into
25102691
* a C function are automatically unwrapped if they are wrapped. This function is also called

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyNumberCheckNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static boolean doLong(Long object) {
9191

9292
@Specialization
9393
static boolean doBoolean(Boolean object) {
94-
return false;
94+
return true;
9595
}
9696

9797
@Specialization

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public abstract class ErrorMessages {
105105
public static final String BASE_OUT_OF_RANGE_FOR_INT = "base is out of range for int()";
106106
public static final String BASES_MUST_BE_TYPES = "bases must be types";
107107
public static final String BASES_ITEM_CAUSES_INHERITANCE_CYCLE = "a __bases__ item causes an inheritance cycle";
108+
public static final String BASE_MUST_BE = "PyNumber_ToBase: base must be 2, 8, 10 or 16";
108109
public static final String BOOL_SHOULD_RETURN_BOOL = "__bool__ should return bool, returned %p";
109110
public static final String BOTH_POINTS_MUST_HAVE_THE_SAME_NUMBER_OF_DIMENSIONS = "both points must have the same number of dimensions";
110111
public static final String BUFFER_INDICES_MUST_BE_INTS = "buffer indices must be integers, not %p";

0 commit comments

Comments
 (0)