Skip to content

Commit 6c90027

Browse files
committed
Implement jarray module
1 parent 0118930 commit 6c90027

File tree

2 files changed

+226
-2
lines changed

2 files changed

+226
-2
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@
4444
import java.util.regex.Matcher;
4545
import java.util.regex.Pattern;
4646

47-
import com.oracle.graal.python.builtins.objects.NotImplementedBuiltins;
48-
import com.oracle.graal.python.builtins.objects.ellipsis.EllipsisBuiltins;
4947
import org.graalvm.nativeimage.ImageInfo;
5048

5149
import com.oracle.graal.python.PythonLanguage;
@@ -70,6 +68,7 @@
7068
import com.oracle.graal.python.builtins.modules.IOModuleBuiltins;
7169
import com.oracle.graal.python.builtins.modules.ImpModuleBuiltins;
7270
import com.oracle.graal.python.builtins.modules.ItertoolsModuleBuiltins;
71+
import com.oracle.graal.python.builtins.modules.JArrayModuleBuiltins;
7372
import com.oracle.graal.python.builtins.modules.JavaModuleBuiltins;
7473
import com.oracle.graal.python.builtins.modules.LZMAModuleBuiltins;
7574
import com.oracle.graal.python.builtins.modules.LocaleModuleBuiltins;
@@ -104,6 +103,7 @@
104103
import com.oracle.graal.python.builtins.modules.WeakRefModuleBuiltins;
105104
import com.oracle.graal.python.builtins.modules.ZLibModuleBuiltins;
106105
import com.oracle.graal.python.builtins.modules.ZipImportModuleBuiltins;
106+
import com.oracle.graal.python.builtins.objects.NotImplementedBuiltins;
107107
import com.oracle.graal.python.builtins.objects.PNone;
108108
import com.oracle.graal.python.builtins.objects.array.ArrayBuiltins;
109109
import com.oracle.graal.python.builtins.objects.bool.BoolBuiltins;
@@ -117,6 +117,7 @@
117117
import com.oracle.graal.python.builtins.objects.dict.DictValuesBuiltins;
118118
import com.oracle.graal.python.builtins.objects.dict.DictViewBuiltins;
119119
import com.oracle.graal.python.builtins.objects.dict.PDict;
120+
import com.oracle.graal.python.builtins.objects.ellipsis.EllipsisBuiltins;
120121
import com.oracle.graal.python.builtins.objects.enumerate.EnumerateBuiltins;
121122
import com.oracle.graal.python.builtins.objects.exception.BaseExceptionBuiltins;
122123
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
@@ -384,6 +385,7 @@ private static PythonBuiltins[] initializeBuiltins() {
384385
new CodecsTruffleModuleBuiltins(),
385386
new CollectionsModuleBuiltins(),
386387
new JavaModuleBuiltins(),
388+
new JArrayModuleBuiltins(),
387389
new SREModuleBuiltins(),
388390
new AstModuleBuiltins(),
389391
new SelectModuleBuiltins(),
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.builtins.modules;
42+
43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
44+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError;
45+
46+
import java.lang.reflect.Array;
47+
import java.util.List;
48+
49+
import com.oracle.graal.python.annotations.ArgumentClinic;
50+
import com.oracle.graal.python.builtins.Builtin;
51+
import com.oracle.graal.python.builtins.CoreFunctions;
52+
import com.oracle.graal.python.builtins.PythonBuiltins;
53+
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
54+
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
55+
import com.oracle.graal.python.builtins.objects.list.PList;
56+
import com.oracle.graal.python.nodes.ErrorMessages;
57+
import com.oracle.graal.python.nodes.PNodeWithRaise;
58+
import com.oracle.graal.python.nodes.builtins.ListNodes;
59+
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
60+
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
61+
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode;
62+
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
63+
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
64+
import com.oracle.graal.python.runtime.sequence.PSequence;
65+
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
66+
import com.oracle.truffle.api.CompilerDirectives;
67+
import com.oracle.truffle.api.TruffleLanguage;
68+
import com.oracle.truffle.api.dsl.Cached;
69+
import com.oracle.truffle.api.dsl.Fallback;
70+
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
71+
import com.oracle.truffle.api.dsl.NodeFactory;
72+
import com.oracle.truffle.api.dsl.Specialization;
73+
import com.oracle.truffle.api.interop.InteropLibrary;
74+
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
75+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
76+
import com.oracle.truffle.api.interop.UnsupportedTypeException;
77+
import com.oracle.truffle.api.library.CachedLibrary;
78+
79+
@CoreFunctions(defineModule = "jarray")
80+
public class JArrayModuleBuiltins extends PythonBuiltins {
81+
82+
@Override
83+
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
84+
return JArrayModuleBuiltinsFactory.getFactories();
85+
}
86+
87+
abstract static class ArrayFromTypeCode extends PNodeWithRaise {
88+
public abstract Object execute(int length, String typeCode);
89+
90+
protected static final String Z = "z";
91+
protected static final String C = "c";
92+
protected static final String B = "b";
93+
protected static final String H = "h";
94+
protected static final String I = "i";
95+
protected static final String L = "l";
96+
protected static final String F = "f";
97+
protected static final String D = "d";
98+
99+
@Specialization(guards = "eq(typeCode, Z)")
100+
static Object z(int length, @SuppressWarnings("unused") String typeCode) {
101+
return new boolean[length];
102+
}
103+
104+
@Specialization(guards = "eq(typeCode, C)")
105+
static Object c(int length, @SuppressWarnings("unused") String typeCode) {
106+
return new char[length];
107+
}
108+
109+
@Specialization(guards = "eq(typeCode, B)")
110+
static Object b(int length, @SuppressWarnings("unused") String typeCode) {
111+
return new byte[length];
112+
}
113+
114+
@Specialization(guards = "eq(typeCode, H)")
115+
static Object h(int length, @SuppressWarnings("unused") String typeCode) {
116+
return new short[length];
117+
}
118+
119+
@Specialization(guards = "eq(typeCode, I)")
120+
static Object i(int length, @SuppressWarnings("unused") String typeCode) {
121+
return new int[length];
122+
}
123+
124+
@Specialization(guards = "eq(typeCode, L)")
125+
static Object l(int length, @SuppressWarnings("unused") String typeCode) {
126+
return new long[length];
127+
}
128+
129+
@Specialization(guards = "eq(typeCode, F)")
130+
static Object f(int length, @SuppressWarnings("unused") String typeCode) {
131+
return new float[length];
132+
}
133+
134+
@Specialization(guards = "eq(typeCode, D)")
135+
static Object d(int length, @SuppressWarnings("unused") String typeCode) {
136+
return new double[length];
137+
}
138+
139+
@Fallback
140+
@SuppressWarnings("unused")
141+
Object error(int length, String typeCode) {
142+
throw raise(ValueError, "Invalid type code '%s'", typeCode);
143+
}
144+
145+
protected static boolean eq(String a, String b) {
146+
return b.equals(a);
147+
}
148+
}
149+
150+
@Builtin(name = "zeros", minNumOfPositionalArgs = 2, parameterNames = {"length", "type"})
151+
@ArgumentClinic(name = "length", conversion = ArgumentClinic.ClinicConversion.Index, defaultValue = "0")
152+
@GenerateNodeFactory
153+
abstract static class ZerosNode extends PythonBinaryClinicBuiltinNode {
154+
public abstract Object execute(int length, Object type);
155+
156+
@Specialization(guards = "isString(typeCodeObj)")
157+
Object fromTypeCode(int length, Object typeCodeObj,
158+
@Cached CastToJavaStringNode cast,
159+
@Cached ArrayFromTypeCode fromTypeCodeNode) {
160+
String typeCode = cast.execute(typeCodeObj);
161+
Object array = fromTypeCodeNode.execute(length, typeCode);
162+
return getContext().getEnv().asGuestValue(array);
163+
}
164+
165+
@Specialization(guards = "!isString(classObj)")
166+
Object fromClass(int length, Object classObj) {
167+
TruffleLanguage.Env env = getContext().getEnv();
168+
if (env.isHostObject(classObj)) {
169+
Object clazz = env.asHostObject(classObj);
170+
if (clazz instanceof Class) {
171+
Object array = Array.newInstance((Class<?>) clazz, length);
172+
return env.asGuestValue(array);
173+
}
174+
}
175+
throw raise(TypeError, "Second argument must be a string type code or a java.lang.Class object, not %p", classObj);
176+
}
177+
178+
@Override
179+
protected ArgumentClinicProvider getArgumentClinic() {
180+
return JArrayModuleBuiltinsClinicProviders.ZerosNodeClinicProviderGen.INSTANCE;
181+
}
182+
}
183+
184+
@Builtin(name = "array", minNumOfPositionalArgs = 2, parameterNames = {"sequence", "type"})
185+
@GenerateNodeFactory
186+
abstract static class ArrayNode extends PythonBinaryBuiltinNode {
187+
@Specialization
188+
Object fromSequence(PSequence sequence, Object type,
189+
@CachedLibrary(limit = "5") InteropLibrary lib,
190+
@Cached SequenceNodes.GetSequenceStorageNode getSequenceStorageNode,
191+
@Cached SequenceStorageNodes.LenNode lenNode,
192+
@Cached SequenceStorageNodes.GetItemScalarNode getItemScalarNode,
193+
@Cached ZerosNode zerosNode) {
194+
SequenceStorage storage = getSequenceStorageNode.execute(sequence);
195+
int length = lenNode.execute(storage);
196+
Object array = zerosNode.execute(length, type);
197+
for (int i = 0; i < length; i++) {
198+
Object value = getItemScalarNode.execute(storage, i);
199+
try {
200+
lib.writeArrayElement(array, i, value);
201+
} catch (UnsupportedTypeException e) {
202+
throw raise(TypeError, ErrorMessages.TYPE_P_NOT_SUPPORTED_BY_FOREIGN_OBJ, value);
203+
} catch (UnsupportedMessageException | InvalidArrayIndexException e) {
204+
throw CompilerDirectives.shouldNotReachHere("failed to set array item");
205+
}
206+
}
207+
return array;
208+
}
209+
210+
@Specialization(guards = "!isPSequence(sequence)")
211+
Object fromIterable(Object sequence, Object type,
212+
@Cached ListNodes.ConstructListNode constructListNode,
213+
@CachedLibrary(limit = "5") InteropLibrary lib,
214+
@Cached SequenceNodes.GetSequenceStorageNode getSequenceStorageNode,
215+
@Cached SequenceStorageNodes.LenNode lenNode,
216+
@Cached SequenceStorageNodes.GetItemScalarNode getItemScalarNode,
217+
@Cached ZerosNode zerosNode) {
218+
PList list = constructListNode.execute(sequence);
219+
return fromSequence(list, type, lib, getSequenceStorageNode, lenNode, getItemScalarNode, zerosNode);
220+
}
221+
}
222+
}

0 commit comments

Comments
 (0)