Skip to content

Commit 0232729

Browse files
committed
Extract foreign number behavior from ForeignObjectBuiltins to ForeignNumberBuiltins
1 parent 24be2b9 commit 0232729

File tree

9 files changed

+902
-495
lines changed

9 files changed

+902
-495
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_interop.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,46 @@ def foo(a, b):
10321032
assert list(h.keys()) == ['b', 'a']
10331033
assert foo(**h) == [1, 2]
10341034

1035+
def test_foreign_number_list(self):
1036+
from java.util import ArrayList
1037+
# Like c(42) in R
1038+
n = __graalpython__.foreign_number_list(42)
1039+
1040+
assert isinstance(n, list)
1041+
assert list in type(n).mro()
1042+
self.assertEqual(['ForeignNumberList', 'ForeignNumberType', 'list', 'foreign', 'object'], [t.__name__ for t in type(n).mro()])
1043+
assert repr(n) == '42', repr(n)
1044+
assert str(n) == '42', str(n)
1045+
assert n
1046+
1047+
a = __graalpython__.foreign_number_list(2)
1048+
b = __graalpython__.foreign_number_list(3)
1049+
assert a + b == 5
1050+
assert a - b == -1
1051+
assert a * b == 6
1052+
assert a / b == (2 / 3)
1053+
assert a // b == 0
1054+
1055+
l = ArrayList()
1056+
l.extend([1, 2, 3])
1057+
1058+
with self.assertRaisesRegex(TypeError, "'<' not supported between instances of 'ForeignList' and 'int'"):
1059+
assert l < 4
1060+
1061+
assert l < n
1062+
1063+
# does not work because > resolves to ForeignNumberType.__gt__ which doesn't handle foreign list on LHS
1064+
with self.assertRaisesRegex(TypeError, "'>' not supported between instances of 'int' and 'ForeignList'"):
1065+
assert n > l
1066+
1067+
l[0] = 100
1068+
assert not l < n
1069+
with self.assertRaisesRegex(TypeError, "'>' not supported between instances of 'int' and 'ForeignList'"):
1070+
assert not n > l
1071+
assert l > n
1072+
with self.assertRaisesRegex(TypeError, "'<' not supported between instances of 'int' and 'ForeignList'"):
1073+
assert n < l
1074+
10351075
def test_foreign_repl(self):
10361076
from java.util.logging import LogRecord
10371077
from java.util.logging import Level

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import java.util.ServiceLoader;
6060
import java.util.logging.Level;
6161

62+
import com.oracle.graal.python.builtins.objects.foreign.ForeignNumberBuiltins;
6263
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
6364
import com.oracle.graal.python.nodes.object.GetForeignObjectClassNode;
6465
import org.graalvm.nativeimage.ImageInfo;
@@ -486,6 +487,7 @@ private static PythonBuiltins[] initializeBuiltins(boolean nativeAccessAllowed,
486487
new TypeBuiltins(),
487488
new IntBuiltins(),
488489
new ForeignObjectBuiltins(),
490+
new ForeignNumberBuiltins(),
489491
new ListBuiltins(),
490492
new DictBuiltins(),
491493
new DictReprBuiltin(),

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import static com.oracle.graal.python.builtins.objects.type.MethodsFlags.DICTVALUESVIEW_M_FLAGS;
4444
import static com.oracle.graal.python.builtins.objects.type.MethodsFlags.DICT_M_FLAGS;
4545
import static com.oracle.graal.python.builtins.objects.type.MethodsFlags.FLOAT_M_FLAGS;
46+
import static com.oracle.graal.python.builtins.objects.type.MethodsFlags.FOREIGNNUMBER_M_FLAGS;
4647
import static com.oracle.graal.python.builtins.objects.type.MethodsFlags.FOREIGNOBJECT_M_FLAGS;
4748
import static com.oracle.graal.python.builtins.objects.type.MethodsFlags.FROZENSET_M_FLAGS;
4849
import static com.oracle.graal.python.builtins.objects.type.MethodsFlags.GENERATOR_M_FLAGS;
@@ -135,6 +136,7 @@
135136
import com.oracle.graal.python.builtins.objects.dict.DictValuesBuiltins;
136137
import com.oracle.graal.python.builtins.objects.dict.DictViewBuiltins;
137138
import com.oracle.graal.python.builtins.objects.floats.FloatBuiltins;
139+
import com.oracle.graal.python.builtins.objects.foreign.ForeignNumberBuiltins;
138140
import com.oracle.graal.python.builtins.objects.foreign.ForeignObjectBuiltins;
139141
import com.oracle.graal.python.builtins.objects.function.BuiltinMethodDescriptor;
140142
import com.oracle.graal.python.builtins.objects.function.FunctionBuiltins;
@@ -185,7 +187,6 @@
185187
@ExportLibrary(ReflectionLibrary.class)
186188
public enum PythonBuiltinClassType implements TruffleObject {
187189

188-
ForeignObject(J_FOREIGN, Flags.PRIVATE_BASE_WDICT, FOREIGNOBJECT_M_FLAGS, ForeignObjectBuiltins.SLOTS),
189190
Boolean("bool", J_BUILTINS, Flags.PUBLIC_DERIVED_WODICT, BOOLEAN_M_FLAGS),
190191
PArray("array", "array", ARRAY_M_FLAGS, ArrayBuiltins.SLOTS),
191192
PArrayIterator("arrayiterator", Flags.PRIVATE_DERIVED_WODICT),
@@ -297,6 +298,10 @@ public enum PythonBuiltinClassType implements TruffleObject {
297298
Unpickler("Unpickler", "_pickle"),
298299
PickleBuffer("PickleBuffer", "_pickle"),
299300

301+
// Foreign
302+
ForeignObject(J_FOREIGN, Flags.PRIVATE_BASE_WDICT, FOREIGNOBJECT_M_FLAGS, ForeignObjectBuiltins.SLOTS),
303+
ForeignNumber("ForeignNumberType", Flags.PRIVATE_BASE_WDICT, FOREIGNNUMBER_M_FLAGS, ForeignNumberBuiltins.SLOTS),
304+
300305
// bz2
301306
BZ2Compressor("BZ2Compressor", "_bz2"),
302307
BZ2Decompressor("BZ2Decompressor", "_bz2"),

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@
7878
import java.util.List;
7979
import java.util.logging.Level;
8080

81+
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
82+
import com.oracle.truffle.api.interop.TruffleObject;
83+
import com.oracle.truffle.api.library.ExportLibrary;
84+
import com.oracle.truffle.api.library.ExportMessage;
8185
import org.graalvm.home.Version;
8286
import org.graalvm.nativeimage.ImageInfo;
8387

@@ -274,6 +278,7 @@ public void postInitialize(Python3Core core) {
274278
mod.setAttribute(tsLiteral("get_handle_table_id"), PNone.NO_VALUE);
275279
mod.setAttribute(tsLiteral("is_strong_handle_table_ref"), PNone.NO_VALUE);
276280
mod.setAttribute(tsLiteral("clear_interop_type_registry"), PNone.NO_VALUE);
281+
mod.setAttribute(tsLiteral("foreign_number_list"), PNone.NO_VALUE);
277282
}
278283
if (PythonImageBuildOptions.WITHOUT_PLATFORM_ACCESS || !context.getOption(PythonOptions.RunViaLauncher)) {
279284
mod.setAttribute(tsLiteral("list_files"), PNone.NO_VALUE);
@@ -1142,4 +1147,48 @@ Object currentRSS() {
11421147
return getContext().getCApiContext().getCurrentRSS();
11431148
}
11441149
}
1150+
1151+
@Builtin(name = "foreign_number_list", maxNumOfPositionalArgs = 1)
1152+
@GenerateNodeFactory
1153+
public abstract static class ForeignNumberListNode extends PythonBuiltinNode {
1154+
1155+
@Specialization
1156+
@TruffleBoundary
1157+
Object foreignNumberList(Object number) {
1158+
return new ForeignNumberList(number);
1159+
}
1160+
1161+
@ExportLibrary(value = InteropLibrary.class, delegateTo = "number")
1162+
static final class ForeignNumberList implements TruffleObject {
1163+
final Object number;
1164+
1165+
ForeignNumberList(Object number) {
1166+
this.number = number;
1167+
}
1168+
1169+
@ExportMessage
1170+
boolean hasArrayElements() {
1171+
return true;
1172+
}
1173+
1174+
@ExportMessage
1175+
boolean isArrayElementReadable(long index) {
1176+
return index == 0;
1177+
}
1178+
1179+
@TruffleBoundary
1180+
@ExportMessage
1181+
Object readArrayElement(long index) throws InvalidArrayIndexException {
1182+
if (!isArrayElementReadable(index)) {
1183+
throw InvalidArrayIndexException.create(index);
1184+
}
1185+
return number;
1186+
}
1187+
1188+
@ExportMessage
1189+
long getArraySize() {
1190+
return 1;
1191+
}
1192+
}
1193+
}
11451194
}

0 commit comments

Comments
 (0)