Skip to content

Commit 54fbc31

Browse files
committed
[GR-11787] extensible builtins
PullRequest: graalpython/200
2 parents 485066a + 150fb94 commit 54fbc31

File tree

5 files changed

+238
-94
lines changed

5 files changed

+238
-94
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
com.oracle.graal.python.test.advance.CustomModule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2018, 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.test.advance;
42+
43+
import org.junit.Test;
44+
45+
import com.oracle.graal.python.test.PythonTests;
46+
47+
public class CustomBuiltinsTest extends PythonTests {
48+
@Test
49+
public void testCustomBuiltinModule() {
50+
assertPrints("success\n", "import CustomModule; print(CustomModule.success)");
51+
}
52+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2018, 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.test.advance;
42+
43+
import java.util.ArrayList;
44+
import java.util.List;
45+
46+
import com.oracle.graal.python.builtins.CoreFunctions;
47+
import com.oracle.graal.python.builtins.PythonBuiltins;
48+
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
49+
import com.oracle.graal.python.runtime.PythonCore;
50+
import com.oracle.truffle.api.dsl.NodeFactory;
51+
52+
@CoreFunctions(defineModule = "CustomModule")
53+
public class CustomModule extends PythonBuiltins {
54+
55+
@Override
56+
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
57+
return new ArrayList<>();
58+
}
59+
60+
@Override
61+
public void initialize(PythonCore core) {
62+
super.initialize(core);
63+
this.builtinConstants.put("success", "success");
64+
}
65+
}

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

Lines changed: 101 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,13 @@
3333
import java.math.BigInteger;
3434
import java.net.MalformedURLException;
3535
import java.net.URL;
36+
import java.util.ArrayList;
3637
import java.util.Arrays;
3738
import java.util.HashMap;
39+
import java.util.List;
3840
import java.util.Map;
3941
import java.util.Map.Entry;
42+
import java.util.ServiceLoader;
4043

4144
import com.oracle.graal.python.PythonLanguage;
4245
import com.oracle.graal.python.builtins.modules.ArrayModuleBuiltins;
@@ -138,6 +141,7 @@
138141
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
139142
import com.oracle.truffle.api.TruffleFile;
140143
import com.oracle.truffle.api.TruffleLanguage.Env;
144+
import com.oracle.truffle.api.TruffleOptions;
141145
import com.oracle.truffle.api.nodes.Node;
142146
import com.oracle.truffle.api.source.Source;
143147
import com.oracle.truffle.api.source.SourceSection;
@@ -185,86 +189,96 @@ public final class Python3Core implements PythonCore {
185189
"_sre",
186190
};
187191

188-
private final PythonBuiltins[] BUILTINS = new PythonBuiltins[]{
189-
new BuiltinConstructors(),
190-
new BuiltinFunctions(),
191-
new InteropModuleBuiltins(),
192-
new ObjectBuiltins(),
193-
new CellBuiltins(),
194-
new BoolBuiltins(),
195-
new FloatBuiltins(),
196-
new BytesBuiltins(),
197-
new ComplexBuiltins(),
198-
new ByteArrayBuiltins(),
199-
new TypeBuiltins(),
200-
new IntBuiltins(),
201-
new TruffleObjectBuiltins(),
202-
new ListBuiltins(),
203-
new DictBuiltins(),
204-
new DictViewBuiltins(),
205-
new DictValuesBuiltins(),
206-
new DictKeysIteratorBuiltins(),
207-
new DictValuesIteratorBuiltins(),
208-
new DictItemsIteratorBuiltins(),
209-
new RangeBuiltins(),
210-
new SliceBuiltins(),
211-
new TupleBuiltins(),
212-
new StringBuiltins(),
213-
new SetBuiltins(),
214-
new FrozenSetBuiltins(),
215-
new IteratorBuiltins(),
216-
new ReversedBuiltins(),
217-
new PZipBuiltins(),
218-
new EnumerateBuiltins(),
219-
new SentinelIteratorBuiltins(),
220-
new ForeignIteratorBuiltins(),
221-
new GeneratorBuiltins(),
222-
new AbstractFunctionBuiltins(),
223-
new FunctionBuiltins(),
224-
new BuiltinFunctionBuiltins(),
225-
new AbstractMethodBuiltins(),
226-
new MethodBuiltins(),
227-
new BuiltinMethodBuiltins(),
228-
new CodeBuiltins(),
229-
new FrameBuiltins(),
230-
new MappingproxyBuiltins(),
231-
new GetSetDescriptorTypeBuiltins(),
232-
new BaseExceptionBuiltins(),
233-
new PosixModuleBuiltins(),
234-
new ImpModuleBuiltins(),
235-
new ArrayModuleBuiltins(),
236-
new ArrayBuiltins(),
237-
new TimeModuleBuiltins(),
238-
new MathModuleBuiltins(),
239-
new MarshalModuleBuiltins(),
240-
new RandomModuleBuiltins(),
241-
new RandomBuiltins(),
242-
new TruffleCextBuiltins(),
243-
new WeakRefModuleBuiltins(),
244-
new ReferenceTypeBuiltins(),
245-
new IOModuleBuiltins(),
246-
new StringModuleBuiltins(),
247-
new ItertoolsModuleBuiltins(),
248-
new FunctoolsModuleBuiltins(),
249-
new ErrnoModuleBuiltins(),
250-
new CodecsModuleBuiltins(),
251-
new CollectionsModuleBuiltins(),
252-
new JavaModuleBuiltins(),
253-
new SREModuleBuiltins(),
254-
new AstModuleBuiltins(),
255-
new SelectModuleBuiltins(),
256-
new SignalModuleBuiltins(),
257-
new TracebackBuiltins(),
258-
new GcModuleBuiltins(),
259-
new AtexitModuleBuiltins(),
260-
new FaulthandlerModuleBuiltins(),
261-
new UnicodeDataModuleBuiltins(),
262-
new LocaleModuleBuiltins(),
263-
new SysModuleBuiltins(),
264-
new BufferBuiltins(),
265-
new MemoryviewBuiltins(),
266-
new SuperBuiltins(),
267-
};
192+
private final PythonBuiltins[] builtins;
193+
194+
private static final PythonBuiltins[] initializeBuiltins() {
195+
List<PythonBuiltins> builtins = new ArrayList<>(Arrays.asList(
196+
new BuiltinConstructors(),
197+
new BuiltinFunctions(),
198+
new InteropModuleBuiltins(),
199+
new ObjectBuiltins(),
200+
new CellBuiltins(),
201+
new BoolBuiltins(),
202+
new FloatBuiltins(),
203+
new BytesBuiltins(),
204+
new ComplexBuiltins(),
205+
new ByteArrayBuiltins(),
206+
new TypeBuiltins(),
207+
new IntBuiltins(),
208+
new TruffleObjectBuiltins(),
209+
new ListBuiltins(),
210+
new DictBuiltins(),
211+
new DictViewBuiltins(),
212+
new DictValuesBuiltins(),
213+
new DictKeysIteratorBuiltins(),
214+
new DictValuesIteratorBuiltins(),
215+
new DictItemsIteratorBuiltins(),
216+
new RangeBuiltins(),
217+
new SliceBuiltins(),
218+
new TupleBuiltins(),
219+
new StringBuiltins(),
220+
new SetBuiltins(),
221+
new FrozenSetBuiltins(),
222+
new IteratorBuiltins(),
223+
new ReversedBuiltins(),
224+
new PZipBuiltins(),
225+
new EnumerateBuiltins(),
226+
new SentinelIteratorBuiltins(),
227+
new ForeignIteratorBuiltins(),
228+
new GeneratorBuiltins(),
229+
new AbstractFunctionBuiltins(),
230+
new FunctionBuiltins(),
231+
new BuiltinFunctionBuiltins(),
232+
new AbstractMethodBuiltins(),
233+
new MethodBuiltins(),
234+
new BuiltinMethodBuiltins(),
235+
new CodeBuiltins(),
236+
new FrameBuiltins(),
237+
new MappingproxyBuiltins(),
238+
new GetSetDescriptorTypeBuiltins(),
239+
new BaseExceptionBuiltins(),
240+
new PosixModuleBuiltins(),
241+
new ImpModuleBuiltins(),
242+
new ArrayModuleBuiltins(),
243+
new ArrayBuiltins(),
244+
new TimeModuleBuiltins(),
245+
new MathModuleBuiltins(),
246+
new MarshalModuleBuiltins(),
247+
new RandomModuleBuiltins(),
248+
new RandomBuiltins(),
249+
new TruffleCextBuiltins(),
250+
new WeakRefModuleBuiltins(),
251+
new ReferenceTypeBuiltins(),
252+
new IOModuleBuiltins(),
253+
new StringModuleBuiltins(),
254+
new ItertoolsModuleBuiltins(),
255+
new FunctoolsModuleBuiltins(),
256+
new ErrnoModuleBuiltins(),
257+
new CodecsModuleBuiltins(),
258+
new CollectionsModuleBuiltins(),
259+
new JavaModuleBuiltins(),
260+
new SREModuleBuiltins(),
261+
new AstModuleBuiltins(),
262+
new SelectModuleBuiltins(),
263+
new SignalModuleBuiltins(),
264+
new TracebackBuiltins(),
265+
new GcModuleBuiltins(),
266+
new AtexitModuleBuiltins(),
267+
new FaulthandlerModuleBuiltins(),
268+
new UnicodeDataModuleBuiltins(),
269+
new LocaleModuleBuiltins(),
270+
new SysModuleBuiltins(),
271+
new BufferBuiltins(),
272+
new MemoryviewBuiltins(),
273+
new SuperBuiltins()));
274+
if (!TruffleOptions.AOT) {
275+
ServiceLoader<PythonBuiltins> providers = ServiceLoader.load(PythonBuiltins.class);
276+
for (PythonBuiltins builtin : providers) {
277+
builtins.add(builtin);
278+
}
279+
}
280+
return builtins.toArray(new PythonBuiltins[builtins.size()]);
281+
}
268282

269283
// not using EnumMap, HashMap, etc. to allow this to fold away during partial evaluation
270284
@CompilationFinal(dimensions = 1) private final PythonBuiltinClass[] builtinTypes = new PythonBuiltinClass[PythonBuiltinClassType.VALUES.length];
@@ -289,6 +303,7 @@ public final class Python3Core implements PythonCore {
289303

290304
public Python3Core(PythonParser parser) {
291305
this.parser = parser;
306+
this.builtins = initializeBuiltins();
292307
}
293308

294309
@Override
@@ -482,7 +497,7 @@ private void initializeTypes() {
482497
// n.b.: the builtin modules and classes and their constructors are initialized first here,
483498
// so we have the mapping from java classes to python classes and builtin names to modules
484499
// available.
485-
for (PythonBuiltins builtin : BUILTINS) {
500+
for (PythonBuiltins builtin : builtins) {
486501
CoreFunctions annotation = builtin.getClass().getAnnotation(CoreFunctions.class);
487502
if (annotation.defineModule().length() > 0) {
488503
createModule(annotation.defineModule());
@@ -501,7 +516,7 @@ private void initializeTypes() {
501516
}
502517

503518
private void populateBuiltins() {
504-
for (PythonBuiltins builtin : BUILTINS) {
519+
for (PythonBuiltins builtin : builtins) {
505520
builtin.initialize(this);
506521
CoreFunctions annotation = builtin.getClass().getAnnotation(CoreFunctions.class);
507522
if (annotation.defineModule().length() > 0) {
@@ -532,14 +547,14 @@ private PythonModule createModule(String name) {
532547
return mod;
533548
}
534549

535-
private void addBuiltinsTo(PythonObject obj, PythonBuiltins builtins) {
536-
Map<String, Object> builtinConstants = builtins.getBuiltinConstants();
550+
private void addBuiltinsTo(PythonObject obj, PythonBuiltins builtinsForObj) {
551+
Map<String, Object> builtinConstants = builtinsForObj.getBuiltinConstants();
537552
for (Map.Entry<String, Object> entry : builtinConstants.entrySet()) {
538553
String constantName = entry.getKey();
539554
obj.setAttribute(constantName, entry.getValue());
540555
}
541556

542-
Map<String, BoundBuiltinCallable<?>> builtinFunctions = builtins.getBuiltinFunctions();
557+
Map<String, BoundBuiltinCallable<?>> builtinFunctions = builtinsForObj.getBuiltinFunctions();
543558
for (Entry<String, BoundBuiltinCallable<?>> entry : builtinFunctions.entrySet()) {
544559
String methodName = entry.getKey();
545560
Object value;
@@ -552,7 +567,7 @@ private void addBuiltinsTo(PythonObject obj, PythonBuiltins builtins) {
552567
obj.setAttribute(methodName, value);
553568
}
554569

555-
Map<PythonBuiltinClass, Entry<PythonBuiltinClassType[], Boolean>> builtinClasses = builtins.getBuiltinClasses();
570+
Map<PythonBuiltinClass, Entry<PythonBuiltinClassType[], Boolean>> builtinClasses = builtinsForObj.getBuiltinClasses();
556571
for (Entry<PythonBuiltinClass, Entry<PythonBuiltinClassType[], Boolean>> entry : builtinClasses.entrySet()) {
557572
boolean isPublic = entry.getValue().getValue();
558573
if (isPublic) {

0 commit comments

Comments
 (0)