# HG changeset patch # User Jaroslav Tulach # Date 1442913746 -7200 # Node ID 0bcfe8c6088febc331ecb36462e1930e7e05c9bb # Parent 0480c4873a4a8a71250c9570b702cea98ab1c7bc# Parent dcb70d90c11d2a8d2666601e2eca53f2b1a65cf3 The central API to invoke various programs is now PolyglotEngine - a polyglot-ready enhancement of JDK's ScriptEngine diff -r 0480c4873a4a -r 0bcfe8c6088f CHANGELOG.md --- a/CHANGELOG.md Mon Sep 21 13:11:41 2015 +0200 +++ b/CHANGELOG.md Tue Sep 22 11:22:26 2015 +0200 @@ -11,8 +11,8 @@ 17-Jul-2015, [Repository Revision](http://lafo.ssw.uni-linz.ac.at/hg/truffle/shortlog/graal-0.8) ### Truffle * The Truffle repository no longer contains Graal -* TruffleVM is an entrypoint for creating, building and running multi language Truffle systems -* Implement TruffleLanguage and use @Registration to register your language into the TruffleVM system +* PolyglotEngine is an entrypoint for creating, building and running multi language Truffle systems +* Implement TruffleLanguage and use @Registration to register your language into the Truffle polyglot system * Include Truffle TCK (test compatibility kit) into your test cases to verify your language implementation is compliant enough * Interoperability API polished * Cleanup of Source related API diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java Tue Sep 22 11:22:26 2015 +0200 @@ -27,7 +27,7 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.test.vm.ImplicitExplicitExportTest.ExportImportLanguage1; import static com.oracle.truffle.api.test.vm.ImplicitExplicitExportTest.L1; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -50,8 +50,8 @@ @Test public void canGetAccessToOwnLanguageInstance() throws Exception { - TruffleVM vm = TruffleVM.newVM().executor(Executors.newSingleThreadExecutor()).build(); - TruffleVM.Language language = vm.getLanguages().get(L1); + PolyglotEngine vm = PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()).build(); + PolyglotEngine.Language language = vm.getLanguages().get(L1); assertNotNull("L1 language is defined", language); Source s = Source.fromText("return nothing", "nothing").withMimeType(L1); @@ -63,7 +63,7 @@ assertTrue("Right instance: " + afterInitialization, afterInitialization instanceof ExportImportLanguage1); } - Object findLanguageByClass(TruffleVM vm) throws IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { + Object findLanguageByClass(PolyglotEngine vm) throws IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { Method find = Accessor.class.getDeclaredMethod("findLanguage", Object.class, Class.class); find.setAccessible(true); TruffleLanguage.Env env = (TruffleLanguage.Env) find.invoke(API, vm, ExportImportLanguage1.class); diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineSingleThreadedTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineSingleThreadedTest.java Tue Sep 22 11:22:26 2015 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.test.vm; + +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.vm.PolyglotEngine; +import java.io.IOException; +import java.io.StringReader; +import java.net.URI; +import java.net.URISyntaxException; +import org.junit.Before; +import org.junit.Test; + +public class EngineSingleThreadedTest { + PolyglotEngine tvm; + + @Before + public void initInDifferentThread() throws InterruptedException { + final PolyglotEngine.Builder b = PolyglotEngine.buildNew(); + Thread t = new Thread("Initializer") { + @Override + public void run() { + tvm = b.build(); + } + }; + t.start(); + t.join(); + } + + @SuppressWarnings("deprecation") + @Test(expected = IllegalStateException.class) + public void evalURI() throws IOException, URISyntaxException { + tvm.eval(new URI("http://unknown.js")); + } + + @SuppressWarnings("deprecation") + @Test(expected = IllegalStateException.class) + public void evalString() throws IOException { + tvm.eval("text/javascript", "1 + 1"); + } + + @SuppressWarnings("deprecation") + @Test(expected = IllegalStateException.class) + public void evalReader() throws IOException { + try (StringReader sr = new StringReader("1 + 1")) { + tvm.eval("text/javascript", sr); + } + } + + @Test(expected = IllegalStateException.class) + public void evalSource() throws IOException { + tvm.eval(Source.fromText("", "Empty")); + } + + @Test(expected = IllegalStateException.class) + public void findGlobalSymbol() { + tvm.findGlobalSymbol("doesNotExists"); + } +} diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java Tue Sep 22 11:22:26 2015 +0200 @@ -25,7 +25,7 @@ import com.oracle.truffle.api.impl.Accessor; import com.oracle.truffle.api.source.Source; import static com.oracle.truffle.api.test.vm.ImplicitExplicitExportTest.L1; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import java.io.IOException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -37,8 +37,8 @@ @Test public void canGetAccessToOwnLanguageInstance() throws Exception { - TruffleVM vm = TruffleVM.newVM().build(); - TruffleVM.Language language = vm.getLanguages().get(L1); + PolyglotEngine vm = PolyglotEngine.buildNew().build(); + PolyglotEngine.Language language = vm.getLanguages().get(L1); assertNotNull("L1 language is defined", language); try { diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java Tue Sep 22 11:22:26 2015 +0200 @@ -24,7 +24,7 @@ import com.oracle.truffle.api.source.Source; import static com.oracle.truffle.api.test.vm.ImplicitExplicitExportTest.L3; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import java.io.IOException; import java.util.concurrent.Executors; import static org.junit.Assert.assertEquals; @@ -34,7 +34,7 @@ public class GlobalSymbolTest { @Test public void globalSymbolFoundByLanguage() throws IOException { - TruffleVM vm = TruffleVM.newVM().globalSymbol("ahoj", "42").executor(Executors.newSingleThreadExecutor()).build(); + PolyglotEngine vm = PolyglotEngine.buildNew().globalSymbol("ahoj", "42").executor(Executors.newSingleThreadExecutor()).build(); // @formatter:off Object ret = vm.eval( Source.fromText("return=ahoj", "Return").withMimeType(L3) @@ -45,8 +45,8 @@ @Test public void globalSymbolFoundByVMUser() throws IOException { - TruffleVM vm = TruffleVM.newVM().globalSymbol("ahoj", "42").build(); - TruffleVM.Symbol ret = vm.findGlobalSymbol("ahoj"); + PolyglotEngine vm = PolyglotEngine.buildNew().globalSymbol("ahoj", "42").build(); + PolyglotEngine.Value ret = vm.findGlobalSymbol("ahoj"); assertNotNull("Symbol found", ret); assertEquals("42", ret.get()); } diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java Tue Sep 22 11:22:26 2015 +0200 @@ -31,7 +31,7 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import java.io.IOException; import java.io.Reader; import java.util.Enumeration; @@ -48,12 +48,12 @@ public class ImplicitExplicitExportTest { private static Thread mainThread; - private TruffleVM vm; + private PolyglotEngine vm; @Before public void initializeVM() { mainThread = Thread.currentThread(); - vm = TruffleVM.newVM().executor(Executors.newSingleThreadExecutor()).build(); + vm = PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()).build(); assertTrue("Found " + L1 + " language", vm.getLanguages().containsKey(L1)); assertTrue("Found " + L2 + " language", vm.getLanguages().containsKey(L2)); assertTrue("Found " + L3 + " language", vm.getLanguages().containsKey(L3)); diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java Tue Sep 22 11:22:26 2015 +0200 @@ -46,7 +46,7 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.vm.EventConsumer; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import java.io.IOException; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -68,7 +68,7 @@ @Test public void accessProbeForAbstractLanguage() throws IOException { final Debugger[] arr = {null}; - TruffleVM vm = TruffleVM.newVM().onEvent(new EventConsumer(ExecutionEvent.class) { + PolyglotEngine vm = PolyglotEngine.buildNew().onEvent(new EventConsumer(ExecutionEvent.class) { @Override protected void on(ExecutionEvent event) { arr[0] = event.getDebugger(); diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleVMSingleThreadedTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleVMSingleThreadedTest.java Mon Sep 21 13:11:41 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.test.vm; - -import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.vm.TruffleVM; -import java.io.IOException; -import java.io.StringReader; -import java.net.URI; -import java.net.URISyntaxException; -import org.junit.Before; -import org.junit.Test; - -public class TruffleVMSingleThreadedTest { - TruffleVM tvm; - - @Before - public void initInDifferentThread() throws InterruptedException { - final TruffleVM.Builder b = TruffleVM.newVM(); - Thread t = new Thread("Initializer") { - @Override - public void run() { - tvm = b.build(); - } - }; - t.start(); - t.join(); - } - - @SuppressWarnings("deprecation") - @Test(expected = IllegalStateException.class) - public void evalURI() throws IOException, URISyntaxException { - tvm.eval(new URI("http://unknown.js")); - } - - @SuppressWarnings("deprecation") - @Test(expected = IllegalStateException.class) - public void evalString() throws IOException { - tvm.eval("text/javascript", "1 + 1"); - } - - @SuppressWarnings("deprecation") - @Test(expected = IllegalStateException.class) - public void evalReader() throws IOException { - try (StringReader sr = new StringReader("1 + 1")) { - tvm.eval("text/javascript", sr); - } - } - - @Test(expected = IllegalStateException.class) - public void evalSource() throws IOException { - tvm.eval(Source.fromText("", "Empty")); - } - - @Test(expected = IllegalStateException.class) - public void findGlobalSymbol() { - tvm.findGlobalSymbol("doesNotExists"); - } -} diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/EventConsumer.java --- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/EventConsumer.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/EventConsumer.java Tue Sep 22 11:22:26 2015 +0200 @@ -29,9 +29,9 @@ import com.oracle.truffle.api.debug.SuspendedEvent; /** - * {@link TruffleVM} generates various events and delivers them to - * {@link TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) registered} handlers. - * Each handler is registered for a particular type of event. Examples of events include + * {@link PolyglotEngine} generates various events and delivers them to + * {@link PolyglotEngine.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) registered} + * handlers. Each handler is registered for a particular type of event. Examples of events include * {@link ExecutionEvent} or {@link SuspendedEvent} useful when debugging {@link TruffleLanguage * Truffle language}s. * @@ -50,7 +50,7 @@ } /** - * Called by the {@link TruffleVM} when event of requested type appears. + * Called by the {@link PolyglotEngine} when event of requested type appears. * * @param event the instance of an event of the request type */ diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/JavaWrapper.java --- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/JavaWrapper.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/JavaWrapper.java Tue Sep 22 11:22:26 2015 +0200 @@ -29,17 +29,17 @@ import java.lang.reflect.Proxy; final class JavaWrapper implements InvocationHandler { - private final TruffleVM.Symbol value; + private final PolyglotEngine.Value value; private final Object wrapper; private final InvocationHandler chain; - public JavaWrapper(TruffleVM.Symbol value, Object wrapper, InvocationHandler chain) { + public JavaWrapper(PolyglotEngine.Value value, Object wrapper, InvocationHandler chain) { this.value = value; this.chain = chain; this.wrapper = wrapper; } - static T create(Class representation, Object wrapper, TruffleVM.Symbol value) { + static T create(Class representation, Object wrapper, PolyglotEngine.Value value) { InvocationHandler chain = Proxy.getInvocationHandler(wrapper); Object instance = Proxy.newProxyInstance(representation.getClassLoader(), new Class[]{representation}, new JavaWrapper(value, wrapper, chain)); return representation.cast(instance); @@ -50,7 +50,7 @@ if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } - TruffleVM.Symbol retValue = value.invokeProxy(chain, wrapper, method, args); + PolyglotEngine.Value retValue = value.invokeProxy(chain, wrapper, method, args); if (method.getReturnType() == void.class) { return null; } else { diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/LanguageCache.java --- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/LanguageCache.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/LanguageCache.java Tue Sep 22 11:22:26 2015 +0200 @@ -25,7 +25,7 @@ package com.oracle.truffle.api.vm; import com.oracle.truffle.api.TruffleLanguage; -import static com.oracle.truffle.api.vm.TruffleVM.LOG; +import static com.oracle.truffle.api.vm.PolyglotEngine.LOG; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -80,7 +80,7 @@ } private static ClassLoader loader() { - ClassLoader l = TruffleVM.class.getClassLoader(); + ClassLoader l = PolyglotEngine.class.getClassLoader(); if (l == null) { l = ClassLoader.getSystemClassLoader(); } diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java Tue Sep 22 11:22:26 2015 +0200 @@ -0,0 +1,954 @@ +/* + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.vm; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.TruffleLanguage.Env; +import com.oracle.truffle.api.TruffleLanguage.Registration; +import com.oracle.truffle.api.debug.DebugSupportProvider; +import com.oracle.truffle.api.debug.Debugger; +import com.oracle.truffle.api.debug.ExecutionEvent; +import com.oracle.truffle.api.debug.SuspendedEvent; +import com.oracle.truffle.api.impl.Accessor; +import com.oracle.truffle.api.instrument.Probe; +import com.oracle.truffle.api.instrument.ToolSupportProvider; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.source.Source; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Gate way into the world of {@link TruffleLanguage Truffle languages}. {@link #buildNew() + * Instantiate} your own portal into the isolated, multi language system with all the registered + * languages ready for your use. A {@link PolyglotEngine} runs inside of a JVM, there can + * however be multiple instances (some would say tenants) of {@link PolyglotEngine} running next to + * each other in a single JVM with a complete mutual isolation. There is 1:N mapping + * between JVM and {@link PolyglotEngine}. + *

+ * It would not be correct to think of a {@link PolyglotEngine} as a runtime for a single + * {@link TruffleLanguage Truffle language} (Ruby, Python, R, C, JavaScript, etc.) either. + * {@link PolyglotEngine} can host as many of Truffle languages as {@link Registration registered on + * a class path} of your JVM application. {@link PolyglotEngine} orchestrates these + * languages, manages exchange of objects and calls among them. While it may happen that there is + * just one activated language inside of a {@link PolyglotEngine}, the greatest strength of + * {@link PolyglotEngine} is in inter-operability between all Truffle languages. There is 1:N + * mapping between {@link PolyglotEngine} and {@link TruffleLanguage Truffle language + * implementations}. + *

+ * Use {@link #buildNew()} to create new isolated portal ready for execution of various languages. + * All the languages in a single portal see each other exported global symbols and can cooperate. + * Use {@link #buildNew()} multiple times to create different, isolated portal environment + * completely separated from each other. + *

+ * Once instantiated use {@link #eval(java.net.URI)} with a reference to a file or URL or directly + * pass code snippet into the virtual machine via {@link #eval(java.lang.String, java.lang.String)}. + * Support for individual languages is initialized on demand - e.g. once a file of certain MIME type + * is about to be processed, its appropriate engine (if found), is initialized. Once an engine gets + * initialized, it remains so, until the virtual machine isn't garbage collected. + *

+ * The engine is single-threaded and tries to enforce that. It records the thread it has been + * {@link Builder#build() created} by and checks that all subsequent calls are coming from the same + * thread. There is 1:1 mapping between {@link PolyglotEngine} and a thread that can tell it what to + * do. + */ +@SuppressWarnings("rawtypes") +public class PolyglotEngine { + static final Logger LOG = Logger.getLogger(PolyglotEngine.class.getName()); + private static final SPIAccessor SPI = new SPIAccessor(); + private final Thread initThread; + private final Executor executor; + private final Map langs; + private final InputStream in; + private final OutputStream err; + private final OutputStream out; + private final EventConsumer[] handlers; + private final Map globals; + private Debugger debugger; + + /** + * Private & temporary only constructor. + */ + PolyglotEngine() { + this.initThread = null; + this.in = null; + this.err = null; + this.out = null; + this.langs = null; + this.handlers = null; + this.globals = null; + this.executor = null; + } + + /** + * Real constructor used from the builder. + */ + PolyglotEngine(Executor executor, Map globals, OutputStream out, OutputStream err, InputStream in, EventConsumer[] handlers) { + this.executor = executor; + this.out = out; + this.err = err; + this.in = in; + this.handlers = handlers; + this.initThread = Thread.currentThread(); + this.globals = new HashMap<>(globals); + Map map = new HashMap<>(); + for (Map.Entry en : LanguageCache.languages().entrySet()) { + map.put(en.getKey(), createLanguage(en)); + } + this.langs = map; + } + + /** + * Creation of new Truffle virtual machine. Use the {@link Builder} methods to configure your + * virtual machine and then create one using {@link Builder#build()}: + * + *

+     * {@link PolyglotEngine} vm = {@link PolyglotEngine}.{@link PolyglotEngine#buildNew() buildNew()}
+     *     .{@link Builder#setOut(java.io.OutputStream) setOut}({@link OutputStream yourOutput})
+     *     .{@link Builder#setErr(java.io.OutputStream) setrr}({@link OutputStream yourOutput})
+     *     .{@link Builder#setIn(java.io.InputStream) setIn}({@link InputStream yourInput})
+     *     .{@link Builder#build() build()};
+     * 
+ * + * It searches for {@link Registration languages registered} in the system class loader and + * makes them available for later evaluation via + * {@link #eval(java.lang.String, java.lang.String)} methods. + * + * @return new, isolated virtual machine with pre-registered languages + */ + public static PolyglotEngine.Builder buildNew() { + // making Builder non-static inner class is a + // nasty trick to avoid the Builder class to appear + // in Javadoc next to PolyglotEngine class + PolyglotEngine vm = new PolyglotEngine(); + return vm.new Builder(); + } + + /** + * Builder for a new {@link PolyglotEngine}. Call various configuration methods in a chain and + * at the end create new {@link PolyglotEngine virtual machine}: + * + *
+     * {@link PolyglotEngine} vm = {@link PolyglotEngine}.{@link PolyglotEngine#buildNew() buildNew()}
+     *     .{@link Builder#setOut(java.io.OutputStream) setOut}({@link OutputStream yourOutput})
+     *     .{@link Builder#setErr(java.io.OutputStream) setrr}({@link OutputStream yourOutput})
+     *     .{@link Builder#setIn(java.io.InputStream) setIn}({@link InputStream yourInput})
+     *     .{@link Builder#build() build()};
+     * 
+ */ + public class Builder { + private OutputStream out; + private OutputStream err; + private InputStream in; + private final List> handlers = new ArrayList<>(); + private final Map globals = new HashMap<>(); + private Executor executor; + + Builder() { + } + + /** + * Changes the default output for languages running in to be created + * {@link PolyglotEngine virtual machine}. The default is to use {@link System#out}. + * + * @param os the stream to use as output + * @return instance of this builder + */ + public Builder setOut(OutputStream os) { + out = os; + return this; + } + + /** + * @deprecated does nothing + */ + @Deprecated + @SuppressWarnings("unused") + public Builder stdOut(Writer w) { + return this; + } + + /** + * Changes the error output for languages running in to be created + * {@link PolyglotEngine virtual machine}. The default is to use {@link System#err}. + * + * @param os the stream to use as output + * @return instance of this builder + */ + public Builder setErr(OutputStream os) { + err = os; + return this; + } + + /** + * @deprecated does nothing + */ + @Deprecated + @SuppressWarnings("unused") + public Builder stdErr(Writer w) { + return this; + } + + /** + * Changes the default input for languages running in to be created + * {@link PolyglotEngine virtual machine}. The default is to use {@link System#in}. + * + * @param is the stream to use as input + * @return instance of this builder + */ + public Builder setIn(InputStream is) { + in = is; + return this; + } + + /** + * @deprecated does nothing + */ + @Deprecated + @SuppressWarnings("unused") + public Builder stdIn(Reader r) { + return this; + } + + /** + * Registers another instance of {@link EventConsumer} into the to be created + * {@link PolyglotEngine}. + * + * @param handler the handler to register + * @return instance of this builder + */ + public Builder onEvent(EventConsumer handler) { + handler.getClass(); + handlers.add(handler); + return this; + } + + /** + * Adds global named symbol into the configuration of to-be-built {@link PolyglotEngine}. + * This symbol will be accessible to all languages via + * {@link Env#importSymbol(java.lang.String)} and will take precedence over + * {@link TruffleLanguage#findExportedSymbol symbols exported by languages itself}. Repeated + * use of globalSymbol is possible; later definition of the same name overrides + * the previous one. + * + * @param name name of the symbol to register + * @param obj value of the object - expected to be primitive wrapper, {@link String} or + * TruffleObject for mutual inter-operability + * @return instance of this builder + * @see PolyglotEngine#findGlobalSymbol(java.lang.String) + */ + public Builder globalSymbol(String name, Object obj) { + globals.put(name, obj); + return this; + } + + /** + * Provides own executor for running {@link PolyglotEngine} scripts. By default + * {@link PolyglotEngine#eval(com.oracle.truffle.api.source.Source)} and + * {@link Value#invoke(java.lang.Object, java.lang.Object[])} are executed synchronously in + * the calling thread. Sometimes, however it is more beneficial to run them asynchronously - + * the easiest way to do so is to provide own executor when configuring the { + * {@link #executor(java.util.concurrent.Executor) the builder}. The executor is expected to + * execute all {@link Runnable runnables} passed into its + * {@link Executor#execute(java.lang.Runnable)} method in the order they arrive and in a + * single (yet arbitrary) thread. + * + * @param executor the executor to use for internal execution inside the {@link #build() to + * be created} {@link PolyglotEngine} + * @return instance of this builder + */ + @SuppressWarnings("hiding") + public Builder executor(Executor executor) { + this.executor = executor; + return this; + } + + /** + * Creates the {@link PolyglotEngine Truffle virtual machine}. The configuration is taken + * from values passed into configuration methods in this class. + * + * @return new, isolated virtual machine with pre-registered languages + */ + @SuppressWarnings("deprecation") + public PolyglotEngine build() { + if (out == null) { + out = System.out; + } + if (err == null) { + err = System.err; + } + if (in == null) { + in = System.in; + } + Executor nonNullExecutor = executor != null ? executor : new Executor() { + @Override + public void execute(Runnable command) { + command.run(); + } + }; + return new TruffleVM(nonNullExecutor, globals, out, err, in, handlers.toArray(new EventConsumer[0])); + } + } + + /** + * Descriptions of languages supported in this Truffle virtual machine. + * + * @return an immutable map with keys being MIME types and values the {@link Language + * descriptions} of associated languages + */ + public Map getLanguages() { + return Collections.unmodifiableMap(langs); + } + + /** + * Evaluates file located on a given URL. Is equivalent to loading the content of a file and + * executing it via {@link #eval(java.lang.String, java.lang.String)} with a MIME type guess + * based on the file's extension and/or content. + * + * @param location the location of a file to execute + * @return result of a processing the file, possibly null + * @throws IOException exception to signal I/O problems or problems with processing the file's + * content + * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)} + */ + @Deprecated + public Object eval(URI location) throws IOException { + checkThread(); + Source s; + String mimeType; + if (location.getScheme().equals("file")) { + File file = new File(location); + s = Source.fromFileName(file.getPath(), true); + if (file.getName().endsWith(".c")) { + mimeType = "text/x-c"; + } else if (file.getName().endsWith(".sl")) { + mimeType = "application/x-sl"; + } else if (file.getName().endsWith(".R") || file.getName().endsWith(".r")) { + mimeType = "application/x-r"; + } else { + mimeType = Files.probeContentType(file.toPath()); + } + } else { + URL url = location.toURL(); + s = Source.fromURL(url, location.toString()); + URLConnection conn = url.openConnection(); + mimeType = conn.getContentType(); + } + Language l = langs.get(mimeType); + if (l == null) { + throw new IOException("No language for " + location + " with MIME type " + mimeType + " found. Supported types: " + langs.keySet()); + } + return eval(l, s).get(); + } + + /** + * Evaluates code snippet. Chooses a language registered for a given MIME type (throws + * {@link IOException} if there is none). And passes the specified code to it for execution. + * + * @param mimeType MIME type of the code snippet - chooses the right language + * @param reader the source of code snippet to execute + * @return result of an execution, possibly null + * @throws IOException thrown to signal errors while processing the code + * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)} + */ + @Deprecated + public Object eval(String mimeType, Reader reader) throws IOException { + checkThread(); + Language l = langs.get(mimeType); + if (l == null) { + throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet()); + } + return eval(l, Source.fromReader(reader, mimeType)).get(); + } + + /** + * Evaluates code snippet. Chooses a language registered for a given MIME type (throws + * {@link IOException} if there is none). And passes the specified code to it for execution. + * + * @param mimeType MIME type of the code snippet - chooses the right language + * @param code the code snippet to execute + * @return result of an execution, possibly null + * @throws IOException thrown to signal errors while processing the code + * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)} + */ + @Deprecated + public Object eval(String mimeType, String code) throws IOException { + checkThread(); + Language l = langs.get(mimeType); + if (l == null) { + throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet()); + } + return eval(l, Source.fromText(code, mimeType)).get(); + } + + /** + * Evaluates provided source. Chooses language registered for a particular + * {@link Source#getMimeType() MIME type} (throws {@link IOException} if there is none). The + * language is then allowed to parse and execute the source. + * + * @param source code snippet to execute + * @return a {@link Value} object that holds result of an execution, never null + * @throws IOException thrown to signal errors while processing the code + */ + public Value eval(Source source) throws IOException { + String mimeType = source.getMimeType(); + checkThread(); + Language l = langs.get(mimeType); + if (l == null) { + throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet()); + } + return eval(l, source); + } + + private Value eval(final Language l, final Source s) throws IOException { + final Debugger[] fillIn = {debugger}; + final Object[] result = {null, null}; + final CountDownLatch ready = new CountDownLatch(1); + final TruffleLanguage[] lang = {null}; + executor.execute(new Runnable() { + @Override + public void run() { + evalImpl(fillIn, lang, s, result, l, ready); + } + }); + exceptionCheck(result); + return createValue(lang[0], result, ready); + } + + Value createValue(TruffleLanguage lang, Object[] result, CountDownLatch ready) { + return new Value(lang, result, ready); + } + + Language createLanguage(Map.Entry en) { + return new Language(en.getValue()); + } + + @SuppressWarnings("try") + private void evalImpl(Debugger[] fillIn, TruffleLanguage[] fillLang, Source s, Object[] result, Language l, CountDownLatch ready) { + try (Closeable d = SPI.executionStart(this, fillIn, s)) { + TruffleLanguage langImpl = l.getImpl(true); + fillLang[0] = langImpl; + PolyglotEngine.findDebuggerSupport(langImpl); + if (debugger == null) { + debugger = fillIn[0]; + } + result[0] = SPI.eval(langImpl, s); + } catch (IOException ex) { + result[1] = ex; + } finally { + ready.countDown(); + } + } + + /** + * Looks global symbol provided by one of initialized languages up. First of all execute your + * program via one of your {@link #eval(java.lang.String, java.lang.String)} and then look + * expected symbol up using this method. + *

+ * The names of the symbols are language dependent, but for example the Java language bindings + * follow the specification for method references: + *

    + *
  • "java.lang.Exception::new" is a reference to constructor of {@link Exception} + *
  • "java.lang.Integer::valueOf" is a reference to static method in {@link Integer} class + *
+ * Once an symbol is obtained, it remembers values for fast access and is ready for being + * invoked. + * + * @param globalName the name of the symbol to find + * @return found symbol or null if it has not been found + */ + public Value findGlobalSymbol(final String globalName) { + checkThread(); + final TruffleLanguage[] lang = {null}; + final Object[] obj = {globals.get(globalName), null}; + final CountDownLatch ready = new CountDownLatch(1); + if (obj[0] == null) { + executor.execute(new Runnable() { + @Override + public void run() { + findGlobalSymbolImpl(obj, globalName, lang, ready); + } + }); + try { + ready.await(); + } catch (InterruptedException ex) { + LOG.log(Level.SEVERE, null, ex); + } + } else { + ready.countDown(); + } + return obj[0] == null ? null : createValue(lang[0], obj, ready); + } + + private void findGlobalSymbolImpl(Object[] obj, String globalName, TruffleLanguage[] lang, CountDownLatch ready) { + if (obj[0] == null) { + for (Language dl : langs.values()) { + TruffleLanguage.Env env = dl.getEnv(false); + if (env == null) { + continue; + } + obj[0] = SPI.findExportedSymbol(env, globalName, true); + if (obj[0] != null) { + lang[0] = dl.getImpl(true); + break; + } + } + } + if (obj[0] == null) { + for (Language dl : langs.values()) { + TruffleLanguage.Env env = dl.getEnv(false); + if (env == null) { + continue; + } + obj[0] = SPI.findExportedSymbol(env, globalName, true); + if (obj[0] != null) { + lang[0] = dl.getImpl(true); + break; + } + } + } + ready.countDown(); + } + + private void checkThread() { + if (initThread != Thread.currentThread()) { + throw new IllegalStateException("PolyglotEngine created on " + initThread.getName() + " but used on " + Thread.currentThread().getName()); + } + } + + @SuppressWarnings("unchecked") + void dispatch(Object ev) { + Class type = ev.getClass(); + if (type == SuspendedEvent.class) { + dispatchSuspendedEvent((SuspendedEvent) ev); + } + if (type == ExecutionEvent.class) { + dispatchExecutionEvent((ExecutionEvent) ev); + } + dispatch(type, ev); + } + + @SuppressWarnings("unused") + void dispatchSuspendedEvent(SuspendedEvent event) { + } + + @SuppressWarnings("unused") + void dispatchExecutionEvent(ExecutionEvent event) { + } + + @SuppressWarnings("unchecked") + void dispatch(Class type, Event event) { + for (EventConsumer handler : handlers) { + if (handler.type == type) { + handler.on(event); + } + } + } + + static void exceptionCheck(Object[] result) throws RuntimeException, IOException { + if (result[1] instanceof IOException) { + throw (IOException) result[1]; + } + if (result[1] instanceof RuntimeException) { + throw (RuntimeException) result[1]; + } + } + + /** + * A future value wrapper. A user level wrapper around values returned by evaluation of various + * {@link PolyglotEngine} functions like + * {@link PolyglotEngine#findGlobalSymbol(java.lang.String)} and + * {@link PolyglotEngine#eval(com.oracle.truffle.api.source.Source)} or value returned by + * {@link #invoke(java.lang.Object, java.lang.Object...) sbbsequent of execution}. In case the + * {@link PolyglotEngine} has been initialized for + * {@link Builder#executor(java.util.concurrent.Executor) asynchronous excution}, the + * {@link Value} represents a future - e.g. it is returned immediately, leaving the execution + * running on behind. + */ + public class Value { + private final TruffleLanguage language; + private final Object[] result; + private final CountDownLatch ready; + private CallTarget target; + + Value(TruffleLanguage language, Object[] result, CountDownLatch ready) { + this.language = language; + this.result = result; + this.ready = ready; + } + + /** + * Obtains the object represented by this symbol. The raw object can either be a + * wrapper about primitive type (e.g. {@link Number}, {@link String}, {@link Character}, + * {@link Boolean}) or a TruffleObject representing more complex object from a + * language. The method can return null. + * + * @return the object or null + * @throws IOException in case it is not possible to obtain the value of the object + */ + public Object get() throws IOException { + waitForSymbol(); + exceptionCheck(result); + return result[0]; + } + + /** + * Obtains Java view of the object represented by this symbol. The method basically + * delegates to + * {@link JavaInterop#asJavaObject(java.lang.Class, com.oracle.truffle.api.interop.TruffleObject)} + * just handles primitive types as well. + * + * @param the type of the view one wants to obtain + * @param representation the class of the view interface (it has to be an interface) + * @return instance of the view wrapping the object of this symbol + * @throws IOException in case it is not possible to obtain the value of the object + * @throws ClassCastException if the value cannot be converted to desired view + */ + public T as(Class representation) throws IOException { + Object obj = get(); + if (representation.isInstance(obj)) { + return representation.cast(obj); + } + T wrapper = JavaInterop.asJavaObject(representation, (TruffleObject) obj); + return JavaWrapper.create(representation, wrapper, this); + } + + /** + * Invokes the symbol. If the symbol represents a function, then it should be invoked with + * provided arguments. If the symbol represents a field, then first argument (if provided) + * should set the value to the field; the return value should be the actual value of the + * field when the invoke method returns. + * + * @param thiz this/self in language that support such concept; use null to let + * the language use default this/self or ignore the value + * @param args arguments to pass when invoking the symbol + * @return symbol wrapper around the value returned by invoking the symbol, never + * null + * @throws IOException signals problem during execution + */ + public Value invoke(final Object thiz, final Object... args) throws IOException { + get(); + final Debugger[] fillIn = {debugger}; + final CountDownLatch done = new CountDownLatch(1); + final Object[] res = {null, null}; + executor.execute(new Runnable() { + @Override + public void run() { + invokeImpl(fillIn, thiz, args, res, done); + } + }); + exceptionCheck(res); + return createValue(language, res, done); + } + + @SuppressWarnings("try") + final Value invokeProxy(final InvocationHandler chain, final Object wrapper, final Method method, final Object[] args) throws IOException { + final Debugger[] fillIn = {debugger}; + final CountDownLatch done = new CountDownLatch(1); + final Object[] res = {null, null}; + executor.execute(new Runnable() { + @Override + public void run() { + try (final Closeable c = SPI.executionStart(PolyglotEngine.this, fillIn, null)) { + if (debugger == null) { + debugger = fillIn[0]; + } + res[0] = chain.invoke(wrapper, method, args); + } catch (IOException ex) { + res[1] = ex; + } catch (Throwable ex) { + res[1] = ex; + } finally { + done.countDown(); + } + } + }); + exceptionCheck(res); + return new Value(language, res, done); + } + + @SuppressWarnings("try") + private void invokeImpl(Debugger[] fillIn, Object thiz, Object[] args, Object[] res, CountDownLatch done) { + try (final Closeable c = SPI.executionStart(PolyglotEngine.this, fillIn, null)) { + if (debugger == null) { + debugger = fillIn[0]; + } + List arr = new ArrayList<>(); + if (thiz == null && language != null) { + Object global = SPI.languageGlobal(SPI.findLanguage(PolyglotEngine.this, language.getClass())); + if (global != null) { + arr.add(global); + } + } else { + arr.add(thiz); + } + arr.addAll(Arrays.asList(args)); + for (;;) { + try { + if (target == null) { + target = SymbolInvokerImpl.createCallTarget(language, result[0], arr.toArray()); + } + res[0] = target.call(arr.toArray()); + break; + } catch (ArgumentsMishmashException ex) { + target = null; + } + } + } catch (IOException ex) { + res[1] = ex; + } catch (RuntimeException ex) { + res[1] = ex; + } finally { + done.countDown(); + } + } + + private void waitForSymbol() throws InterruptedIOException { + checkThread(); + try { + ready.await(); + } catch (InterruptedException ex) { + throw (InterruptedIOException) new InterruptedIOException(ex.getMessage()).initCause(ex); + } + } + } + + /** + * Description of a language registered in {@link PolyglotEngine Truffle virtual machine}. + * Languages are registered by {@link Registration} annotation which stores necessary + * information into a descriptor inside of the language's JAR file. When a new + * {@link PolyglotEngine} is created, it reads all available descriptors and creates + * {@link Language} objects to represent them. One can obtain a {@link #getName() name} or list + * of supported {@link #getMimeTypes() MIME types} for each language. The actual language + * implementation is not initialized until + * {@link PolyglotEngine#eval(java.lang.String, java.lang.String) a code is evaluated} in it. + */ + public class Language { + private final LanguageCache info; + private TruffleLanguage.Env env; + + Language(LanguageCache info) { + this.info = info; + } + + /** + * MIME types recognized by the language. + * + * @return returns immutable set of recognized MIME types + */ + public Set getMimeTypes() { + return info.getMimeTypes(); + } + + /** + * Human readable name of the language. Think of C, Ruby, JS, etc. + * + * @return string giving the language a name + */ + public String getName() { + return info.getName(); + } + + /** + * Name of the language version. + * + * @return string specifying the language version + */ + public String getVersion() { + return info.getVersion(); + } + + /** + * Human readable string that identifies the language and version. + * + * @return string describing the specific language version + */ + public String getShortName() { + return getName() + "(" + getVersion() + ")"; + } + + TruffleLanguage getImpl(boolean create) { + getEnv(create); + return info.getImpl(false); + } + + TruffleLanguage.Env getEnv(boolean create) { + if (env == null && create) { + env = SPI.attachEnv(PolyglotEngine.this, info.getImpl(true), out, err, in); + } + return env; + } + + @Override + public String toString() { + return "[" + getShortName() + " for " + getMimeTypes() + "]"; + } + } // end of Language + + // + // Accessor helper methods + // + + TruffleLanguage findLanguage(Probe probe) { + Class languageClazz = SPI.findLanguage(probe); + for (Map.Entry entrySet : langs.entrySet()) { + Language languageDescription = entrySet.getValue(); + final TruffleLanguage impl = languageDescription.getImpl(false); + if (languageClazz.isInstance(impl)) { + return impl; + } + } + throw new IllegalStateException("Cannot find language " + languageClazz + " among " + langs); + } + + Env findEnv(Class languageClazz) { + for (Map.Entry entrySet : langs.entrySet()) { + Language languageDescription = entrySet.getValue(); + Env env = languageDescription.getEnv(false); + if (env != null && languageClazz.isInstance(languageDescription.getImpl(false))) { + return env; + } + } + throw new IllegalStateException("Cannot find language " + languageClazz + " among " + langs); + } + + static DebugSupportProvider findDebuggerSupport(TruffleLanguage l) { + return SPI.getDebugSupport(l); + } + + private static class SPIAccessor extends Accessor { + @Override + public Object importSymbol(Object vmObj, TruffleLanguage ownLang, String globalName) { + PolyglotEngine vm = (PolyglotEngine) vmObj; + Object g = vm.globals.get(globalName); + if (g != null) { + return g; + } + Set uniqueLang = new LinkedHashSet<>(vm.langs.values()); + for (Language dl : uniqueLang) { + TruffleLanguage l = dl.getImpl(false); + TruffleLanguage.Env env = dl.getEnv(false); + if (l == ownLang || l == null || env == null) { + continue; + } + Object obj = SPI.findExportedSymbol(env, globalName, true); + if (obj != null) { + return obj; + } + } + for (Language dl : uniqueLang) { + TruffleLanguage l = dl.getImpl(false); + TruffleLanguage.Env env = dl.getEnv(false); + if (l == ownLang || l == null || env == null) { + continue; + } + Object obj = SPI.findExportedSymbol(env, globalName, false); + if (obj != null) { + return obj; + } + } + return null; + } + + @Override + protected Env attachEnv(Object obj, TruffleLanguage language, OutputStream stdOut, OutputStream stdErr, InputStream stdIn) { + PolyglotEngine vm = (PolyglotEngine) obj; + return super.attachEnv(vm, language, stdOut, stdErr, stdIn); + } + + @Override + public Object eval(TruffleLanguage l, Source s) throws IOException { + return super.eval(l, s); + } + + @Override + public Object findExportedSymbol(TruffleLanguage.Env env, String globalName, boolean onlyExplicit) { + return super.findExportedSymbol(env, globalName, onlyExplicit); + } + + @Override + protected Object languageGlobal(TruffleLanguage.Env env) { + return super.languageGlobal(env); + } + + @Override + public ToolSupportProvider getToolSupport(TruffleLanguage l) { + return super.getToolSupport(l); + } + + @Override + public DebugSupportProvider getDebugSupport(TruffleLanguage l) { + return super.getDebugSupport(l); + } + + @Override + protected Class findLanguage(Probe probe) { + return super.findLanguage(probe); + } + + @Override + protected Env findLanguage(Object obj, Class languageClass) { + PolyglotEngine vm = (PolyglotEngine) obj; + return vm.findEnv(languageClass); + } + + @Override + protected Closeable executionStart(Object obj, Debugger[] fillIn, Source s) { + PolyglotEngine vm = (PolyglotEngine) obj; + return super.executionStart(vm, fillIn, s); + } + + @Override + protected void dispatchEvent(Object obj, Object event) { + PolyglotEngine vm = (PolyglotEngine) obj; + vm.dispatch(event); + } + } // end of SPIAccessor +} diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java --- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java Tue Sep 22 11:22:26 2015 +0200 @@ -24,143 +24,37 @@ */ package com.oracle.truffle.api.vm; -import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.TruffleLanguage.Env; -import com.oracle.truffle.api.TruffleLanguage.Registration; -import com.oracle.truffle.api.debug.DebugSupportProvider; -import com.oracle.truffle.api.debug.Debugger; import com.oracle.truffle.api.debug.ExecutionEvent; import com.oracle.truffle.api.debug.SuspendedEvent; -import com.oracle.truffle.api.impl.Accessor; -import com.oracle.truffle.api.instrument.Probe; -import com.oracle.truffle.api.instrument.ToolSupportProvider; -import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.source.Source; -import java.io.Closeable; -import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.InterruptedIOException; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.net.URI; -import java.net.URL; -import java.net.URLConnection; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; -import java.util.logging.Level; -import java.util.logging.Logger; /** - * Virtual machine for Truffle based languages. Term virtual machine is a bit overloaded, - * so don't think of Java virtual machine here - while we are running and using - * {@link TruffleVM} inside of a JVM there can be multiple instances (some would say - * tenants) of {@link TruffleVM} running next to each other in a single JVM with a complete - * mutual isolation. There is 1:N mapping between JVM and {@link TruffleVM}. - *

- * It would not be correct to think of a {@link TruffleVM} as a runtime for a single Truffle - * language (Ruby, Python, R, C, JavaScript, etc.) either. {@link TruffleVM} can host as many of - * Truffle languages as {@link Registration registered on a class path} of your JVM - * application. {@link TruffleVM} orchestrates these languages, manages exchange of objects and - * calls among them. While it may happen that there is just one activated language inside of a - * {@link TruffleVM}, the greatest strength of {@link TruffleVM} is in interoperability between all - * Truffle languages. There is 1:N mapping between {@link TruffleVM} and {@link TruffleLanguage - * Truffle language implementations}. - *

- * Use {@link #newVM()} to create new isolated virtual machine ready for execution of various - * languages. All the languages in a single virtual machine see each other exported global symbols - * and can cooperate. Use {@link #newVM()} multiple times to create different, isolated virtual - * machines completely separated from each other. - *

- * Once instantiated use {@link #eval(java.net.URI)} with a reference to a file or URL or directly - * pass code snippet into the virtual machine via {@link #eval(java.lang.String, java.lang.String)}. - * Support for individual languages is initialized on demand - e.g. once a file of certain MIME type - * is about to be processed, its appropriate engine (if found), is initialized. Once an engine gets - * initialized, it remains so, until the virtual machine isn't garbage collected. - *

- * The TruffleVM is single-threaded and tries to enforce that. It records the thread it - * has been {@link Builder#build() created} by and checks that all subsequent calls are coming from - * the same thread. There is 1:1 mapping between {@link TruffleVM} and a thread that can tell it - * what to do. + * @deprecated */ -@SuppressWarnings("rawtypes") -public final class TruffleVM { - static final Logger LOG = Logger.getLogger(TruffleVM.class.getName()); - private static final SPIAccessor SPI = new SPIAccessor(); - private final Thread initThread; - private final Executor executor; - private final Map langs; - private final InputStream in; - private final OutputStream err; - private final OutputStream out; - private final EventConsumer[] handlers; - private final Map globals; - private Debugger debugger; - - /** - * Private & temporary only constructor. - */ +@Deprecated +@SuppressWarnings({"rawtypes", "deprecated"}) +public final class TruffleVM extends PolyglotEngine { private TruffleVM() { - this.initThread = null; - this.in = null; - this.err = null; - this.out = null; - this.langs = null; - this.handlers = null; - this.globals = null; - this.executor = null; + super(); } /** * Real constructor used from the builder. */ - private TruffleVM(Executor executor, Map globals, OutputStream out, OutputStream err, InputStream in, EventConsumer[] handlers) { - this.executor = executor; - this.out = out; - this.err = err; - this.in = in; - this.handlers = handlers; - this.initThread = Thread.currentThread(); - this.globals = new HashMap<>(globals); - Map map = new HashMap<>(); - for (Map.Entry en : LanguageCache.languages().entrySet()) { - map.put(en.getKey(), new Language(en.getValue())); - } - this.langs = map; + TruffleVM(Executor executor, Map globals, OutputStream out, OutputStream err, InputStream in, EventConsumer[] handlers) { + super(executor, globals, out, err, in, handlers); } - /** - * Creation of new Truffle virtual machine. Use the {@link Builder} methods to configure your - * virtual machine and then create one using {@link Builder#build()}: - * - *

-     * {@link TruffleVM} vm = {@link TruffleVM}.{@link TruffleVM#newVM() newVM()}
-     *     .{@link Builder#setOut(java.io.OutputStream) setOut}({@link OutputStream yourOutput})
-     *     .{@link Builder#setErr(java.io.OutputStream) setrr}({@link OutputStream yourOutput})
-     *     .{@link Builder#setIn(java.io.InputStream) setIn}({@link InputStream yourInput})
-     *     .{@link Builder#build() build()};
-     * 
- * - * It searches for {@link Registration languages registered} in the system class loader and - * makes them available for later evaluation via - * {@link #eval(java.lang.String, java.lang.String)} methods. - * - * @return new, isolated virtual machine with pre-registered languages - */ + @Deprecated public static TruffleVM.Builder newVM() { // making Builder non-static inner class is a // nasty trick to avoid the Builder class to appear @@ -169,766 +63,126 @@ return vm.new Builder(); } - /** - * Builder for a new {@link TruffleVM}. Call various configuration methods in a chain and at the - * end create new {@link TruffleVM virtual machine}: - * - *
-     * {@link TruffleVM} vm = {@link TruffleVM}.{@link TruffleVM#newVM() newVM()}
-     *     .{@link Builder#setOut(java.io.OutputStream) setOut}({@link OutputStream yourOutput})
-     *     .{@link Builder#setErr(java.io.OutputStream) setrr}({@link OutputStream yourOutput})
-     *     .{@link Builder#setIn(java.io.InputStream) setIn}({@link InputStream yourInput})
-     *     .{@link Builder#build() build()};
-     * 
- */ - public final class Builder { - private OutputStream out; - private OutputStream err; - private InputStream in; - private final List> handlers = new ArrayList<>(); - private final Map globals = new HashMap<>(); - private Executor executor; - + @SuppressWarnings("deprecation") + @Deprecated + public final class Builder extends PolyglotEngine.Builder { Builder() { } - /** - * Changes the default output for languages running in to be created - * {@link TruffleVM virtual machine}. The default is to use {@link System#out}. - * - * @param os the stream to use as output - * @return instance of this builder - */ + @Deprecated + @Override public Builder setOut(OutputStream os) { - out = os; - return this; - } - - /** - * @deprecated does nothing - */ - @Deprecated - @SuppressWarnings("unused") - public Builder stdOut(Writer w) { - return this; - } - - /** - * Changes the error output for languages running in to be created - * {@link TruffleVM virtual machine}. The default is to use {@link System#err}. - * - * @param os the stream to use as output - * @return instance of this builder - */ - public Builder setErr(OutputStream os) { - err = os; - return this; - } - - /** - * @deprecated does nothing - */ - @Deprecated - @SuppressWarnings("unused") - public Builder stdErr(Writer w) { + super.setOut(os); return this; } - /** - * Changes the default input for languages running in to be created - * {@link TruffleVM virtual machine}. The default is to use {@link System#in}. - * - * @param is the stream to use as input - * @return instance of this builder - */ - public Builder setIn(InputStream is) { - in = is; - return this; - } - - /** - * @deprecated does nothing - */ @Deprecated - @SuppressWarnings("unused") - public Builder stdIn(Reader r) { - return this; - } - - /** - * Registers another instance of {@link EventConsumer} into the to be created - * {@link TruffleVM}. - * - * @param handler the handler to register - * @return instance of this builder - */ - public Builder onEvent(EventConsumer handler) { - handler.getClass(); - handlers.add(handler); - return this; + @Override + public Builder executor(Executor executor) { + return (Builder) super.executor(executor); } - /** - * Adds global named symbol into the configuration of to-be-built {@link TruffleVM}. This - * symbol will be accessible to all languages via {@link Env#importSymbol(java.lang.String)} - * and will take precedence over {@link TruffleLanguage#findExportedSymbol symbols exported - * by languages itself}. Repeated use of globalSymbol is possible; later - * definition of the same name overrides the previous one. - * - * @param name name of the symbol to register - * @param obj value of the object - expected to be primitive wrapper, {@link String} or - * TruffleObject for mutual inter-operability - * @return instance of this builder - * @see TruffleVM#findGlobalSymbol(java.lang.String) - */ - public Builder globalSymbol(String name, Object obj) { - globals.put(name, obj); - return this; - } - - /** - * Provides own executor for running {@link TruffleVM} scripts. By default - * {@link TruffleVM#eval(com.oracle.truffle.api.source.Source)} and - * {@link Symbol#invoke(java.lang.Object, java.lang.Object...)} are executed synchronously - * in the calling thread. Sometimes, however it is more beneficial to run them - * asynchronously - the easiest way to do so is to provide own executor when configuring the - * { {@link #executor(java.util.concurrent.Executor) the builder}. The executor is expected - * to execute all {@link Runnable runnables} passed into its - * {@link Executor#execute(java.lang.Runnable)} method in the order they arrive and in a - * single (yet arbitrary) thread. - * - * @param executor the executor to use for internal execution inside the {@link #build() to - * be created} {@link TruffleVM} - * @return instance of this builder - */ - @SuppressWarnings("hiding") - public Builder executor(Executor executor) { - this.executor = executor; + @Deprecated + @Override + public Builder setErr(OutputStream os) { + super.setErr(os); return this; } - /** - * Creates the {@link TruffleVM Truffle virtual machine}. The configuration is taken from - * values passed into configuration methods in this class. - * - * @return new, isolated virtual machine with pre-registered languages - */ - public TruffleVM build() { - if (out == null) { - out = System.out; - } - if (err == null) { - err = System.err; - } - if (in == null) { - in = System.in; - } - Executor nonNullExecutor = executor != null ? executor : new Executor() { - @Override - public void execute(Runnable command) { - command.run(); - } - }; - return new TruffleVM(nonNullExecutor, globals, out, err, in, handlers.toArray(new EventConsumer[0])); + @Deprecated + @Override + public Builder globalSymbol(String name, Object obj) { + return (Builder) super.globalSymbol(name, obj); } - } - - /** - * Descriptions of languages supported in this Truffle virtual machine. - * - * @return an immutable map with keys being MIME types and values the {@link Language - * descriptions} of associated languages - */ - public Map getLanguages() { - return Collections.unmodifiableMap(langs); - } - /** - * Evaluates file located on a given URL. Is equivalent to loading the content of a file and - * executing it via {@link #eval(java.lang.String, java.lang.String)} with a MIME type guess - * based on the file's extension and/or content. - * - * @param location the location of a file to execute - * @return result of a processing the file, possibly null - * @throws IOException exception to signal I/O problems or problems with processing the file's - * content - * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)} - */ - @Deprecated - public Object eval(URI location) throws IOException { - checkThread(); - Source s; - String mimeType; - if (location.getScheme().equals("file")) { - File file = new File(location); - s = Source.fromFileName(file.getPath(), true); - if (file.getName().endsWith(".c")) { - mimeType = "text/x-c"; - } else if (file.getName().endsWith(".sl")) { - mimeType = "application/x-sl"; - } else if (file.getName().endsWith(".R") || file.getName().endsWith(".r")) { - mimeType = "application/x-r"; - } else { - mimeType = Files.probeContentType(file.toPath()); - } - } else { - URL url = location.toURL(); - s = Source.fromURL(url, location.toString()); - URLConnection conn = url.openConnection(); - mimeType = conn.getContentType(); - } - Language l = langs.get(mimeType); - if (l == null) { - throw new IOException("No language for " + location + " with MIME type " + mimeType + " found. Supported types: " + langs.keySet()); + @Deprecated + @Override + public Builder setIn(InputStream is) { + super.setIn(is); + return this; } - return eval(l, s).get(); - } - /** - * Evaluates code snippet. Chooses a language registered for a given MIME type (throws - * {@link IOException} if there is none). And passes the specified code to it for execution. - * - * @param mimeType MIME type of the code snippet - chooses the right language - * @param reader the source of code snippet to execute - * @return result of an execution, possibly null - * @throws IOException thrown to signal errors while processing the code - * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)} - */ - @Deprecated - public Object eval(String mimeType, Reader reader) throws IOException { - checkThread(); - Language l = langs.get(mimeType); - if (l == null) { - throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet()); + @Deprecated + @Override + public Builder onEvent(EventConsumer handler) { + return (Builder) super.onEvent(handler); } - return eval(l, Source.fromReader(reader, mimeType)).get(); - } - - /** - * Evaluates code snippet. Chooses a language registered for a given MIME type (throws - * {@link IOException} if there is none). And passes the specified code to it for execution. - * - * @param mimeType MIME type of the code snippet - chooses the right language - * @param code the code snippet to execute - * @return result of an execution, possibly null - * @throws IOException thrown to signal errors while processing the code - * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)} - */ - @Deprecated - public Object eval(String mimeType, String code) throws IOException { - checkThread(); - Language l = langs.get(mimeType); - if (l == null) { - throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet()); - } - return eval(l, Source.fromText(code, mimeType)).get(); - } - /** - * Evaluates provided source. Chooses language registered for a particular - * {@link Source#getMimeType() MIME type} (throws {@link IOException} if there is none). The - * language is then allowed to parse and execute the source. - * - * @param source code snippet to execute - * @return a {@link Symbol} object that holds result of an execution, never null - * @throws IOException thrown to signal errors while processing the code - */ - public Symbol eval(Source source) throws IOException { - String mimeType = source.getMimeType(); - checkThread(); - Language l = langs.get(mimeType); - if (l == null) { - throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet()); + @Deprecated + @Override + public Builder stdIn(Reader r) { + return (Builder) super.stdIn(r); } - return eval(l, source); - } - - private Symbol eval(final Language l, final Source s) throws IOException { - final Debugger[] fillIn = {debugger}; - final Object[] result = {null, null}; - final CountDownLatch ready = new CountDownLatch(1); - final TruffleLanguage[] lang = {null}; - executor.execute(new Runnable() { - @Override - public void run() { - evalImpl(fillIn, lang, s, result, l, ready); - } - }); - exceptionCheck(result); - return new Symbol(lang[0], result, ready); - } - - @SuppressWarnings("try") - private void evalImpl(Debugger[] fillIn, TruffleLanguage[] fillLang, Source s, Object[] result, Language l, CountDownLatch ready) { - try (Closeable d = SPI.executionStart(this, fillIn, s)) { - TruffleLanguage langImpl = l.getImpl(true); - fillLang[0] = langImpl; - TruffleVM.findDebuggerSupport(langImpl); - if (debugger == null) { - debugger = fillIn[0]; - } - result[0] = SPI.eval(langImpl, s); - } catch (IOException ex) { - result[1] = ex; - } finally { - ready.countDown(); - } - } - /** - * Looks global symbol provided by one of initialized languages up. First of all execute your - * program via one of your {@link #eval(java.lang.String, java.lang.String)} and then look - * expected symbol up using this method. - *

- * The names of the symbols are language dependent, but for example the Java language bindings - * follow the specification for method references: - *

    - *
  • "java.lang.Exception::new" is a reference to constructor of {@link Exception} - *
  • "java.lang.Integer::valueOf" is a reference to static method in {@link Integer} class - *
- * Once an symbol is obtained, it remembers values for fast access and is ready for being - * invoked. - * - * @param globalName the name of the symbol to find - * @return found symbol or null if it has not been found - */ - public Symbol findGlobalSymbol(final String globalName) { - checkThread(); - final TruffleLanguage[] lang = {null}; - final Object[] obj = {globals.get(globalName), null}; - final CountDownLatch ready = new CountDownLatch(1); - if (obj[0] == null) { - executor.execute(new Runnable() { - @Override - public void run() { - findGlobalSymbolImpl(obj, globalName, lang, ready); - } - }); - try { - ready.await(); - } catch (InterruptedException ex) { - LOG.log(Level.SEVERE, null, ex); - } - } else { - ready.countDown(); + @Deprecated + @Override + public Builder stdErr(Writer w) { + return (Builder) super.stdErr(w); } - return obj[0] == null ? null : new Symbol(lang[0], obj, ready); - } - private void findGlobalSymbolImpl(Object[] obj, String globalName, TruffleLanguage[] lang, CountDownLatch ready) { - if (obj[0] == null) { - for (Language dl : langs.values()) { - TruffleLanguage.Env env = dl.getEnv(false); - if (env == null) { - continue; - } - obj[0] = SPI.findExportedSymbol(env, globalName, true); - if (obj[0] != null) { - lang[0] = dl.getImpl(true); - break; - } - } + @Deprecated + @Override + public Builder stdOut(Writer w) { + return (Builder) super.stdOut(w); } - if (obj[0] == null) { - for (Language dl : langs.values()) { - TruffleLanguage.Env env = dl.getEnv(false); - if (env == null) { - continue; - } - obj[0] = SPI.findExportedSymbol(env, globalName, true); - if (obj[0] != null) { - lang[0] = dl.getImpl(true); - break; - } - } - } - ready.countDown(); - } - private void checkThread() { - if (initThread != Thread.currentThread()) { - throw new IllegalStateException("TruffleVM created on " + initThread.getName() + " but used on " + Thread.currentThread().getName()); + @Deprecated + @Override + public TruffleVM build() { + return (TruffleVM) super.build(); } } - @SuppressWarnings("unchecked") - void dispatch(Object ev) { - Class type = ev.getClass(); - if (type == SuspendedEvent.class) { - dispatchSuspendedEvent((SuspendedEvent) ev); - } - if (type == ExecutionEvent.class) { - dispatchExecutionEvent((ExecutionEvent) ev); - } - dispatch(type, ev); + @Override + Value createValue(TruffleLanguage lang, Object[] result, CountDownLatch ready) { + return new Symbol(lang, result, ready); + } + + @Override + Language createLanguage(Map.Entry en) { + return new Language(en.getValue()); } - @SuppressWarnings("unused") + @Override + @SuppressWarnings("unchecked") + public Map getLanguages() { + return (Map) super.getLanguages(); + } + + @Override + public Symbol eval(Source source) throws IOException { + return (Symbol) super.eval(source); + } + + @Override + public Symbol findGlobalSymbol(final String globalName) { + return (Symbol) super.findGlobalSymbol(globalName); + } + + @Override void dispatchSuspendedEvent(SuspendedEvent event) { } - @SuppressWarnings("unused") + @Override void dispatchExecutionEvent(ExecutionEvent event) { } - @SuppressWarnings("unchecked") - void dispatch(Class type, Event event) { - for (EventConsumer handler : handlers) { - if (handler.type == type) { - handler.on(event); - } - } - } - - static void exceptionCheck(Object[] result) throws RuntimeException, IOException { - if (result[1] instanceof IOException) { - throw (IOException) result[1]; - } - if (result[1] instanceof RuntimeException) { - throw (RuntimeException) result[1]; - } - } - - /** - * Represents {@link TruffleVM#findGlobalSymbol(java.lang.String) global symbol} provided by one - * of the initialized languages in {@link TruffleVM Truffle virtual machine}. - */ - public class Symbol { - private final TruffleLanguage language; - private final Object[] result; - private final CountDownLatch ready; - private CallTarget target; - + @Deprecated + public class Symbol extends Value { Symbol(TruffleLanguage language, Object[] result, CountDownLatch ready) { - this.language = language; - this.result = result; - this.ready = ready; - } - - /** - * Obtains the object represented by this symbol. The raw object can either be a - * wrapper about primitive type (e.g. {@link Number}, {@link String}, {@link Character}, - * {@link Boolean}) or a TruffleObject representing more complex object from a - * language. The method can return null. - * - * @return the object or null - * @throws IOException in case it is not possible to obtain the value of the object - */ - public Object get() throws IOException { - waitForSymbol(); - exceptionCheck(result); - return result[0]; - } - - /** - * Obtains Java view of the object represented by this symbol. The method basically - * delegates to - * {@link JavaInterop#asJavaObject(java.lang.Class, com.oracle.truffle.api.interop.TruffleObject)} - * just handles primitive types as well. - * - * @param the type of the view one wants to obtain - * @param representation the class of the view interface (it has to be an interface) - * @return instance of the view wrapping the object of this symbol - * @throws IOException in case it is not possible to obtain the value of the object - * @throws ClassCastException if the value cannot be converted to desired view - */ - public T as(Class representation) throws IOException { - Object obj = get(); - if (representation.isInstance(obj)) { - return representation.cast(obj); - } - T wrapper = JavaInterop.asJavaObject(representation, (TruffleObject) obj); - return JavaWrapper.create(representation, wrapper, this); + super(language, result, ready); } - /** - * Invokes the symbol. If the symbol represents a function, then it should be invoked with - * provided arguments. If the symbol represents a field, then first argument (if provided) - * should set the value to the field; the return value should be the actual value of the - * field when the invoke method returns. - * - * @param thiz this/self in language that support such concept; use null to let - * the language use default this/self or ignore the value - * @param args arguments to pass when invoking the symbol - * @return symbol wrapper around the value returned by invoking the symbol, never - * null - * @throws IOException signals problem during execution - */ + @Override public Symbol invoke(final Object thiz, final Object... args) throws IOException { - get(); - final Debugger[] fillIn = {debugger}; - final CountDownLatch done = new CountDownLatch(1); - final Object[] res = {null, null}; - executor.execute(new Runnable() { - @Override - public void run() { - invokeImpl(fillIn, thiz, args, res, done); - } - }); - exceptionCheck(res); - return new Symbol(language, res, done); - } - - @SuppressWarnings("try") - final Symbol invokeProxy(final InvocationHandler chain, final Object wrapper, final Method method, final Object[] args) throws IOException { - final Debugger[] fillIn = {debugger}; - final CountDownLatch done = new CountDownLatch(1); - final Object[] res = {null, null}; - executor.execute(new Runnable() { - @Override - public void run() { - try (final Closeable c = SPI.executionStart(TruffleVM.this, fillIn, null)) { - if (debugger == null) { - debugger = fillIn[0]; - } - res[0] = chain.invoke(wrapper, method, args); - } catch (IOException ex) { - res[1] = ex; - } catch (Throwable ex) { - res[1] = ex; - } finally { - done.countDown(); - } - } - }); - exceptionCheck(res); - return new Symbol(language, res, done); - } - - @SuppressWarnings("try") - private void invokeImpl(Debugger[] fillIn, Object thiz, Object[] args, Object[] res, CountDownLatch done) { - try (final Closeable c = SPI.executionStart(TruffleVM.this, fillIn, null)) { - if (debugger == null) { - debugger = fillIn[0]; - } - List arr = new ArrayList<>(); - if (thiz == null && language != null) { - Object global = SPI.languageGlobal(SPI.findLanguage(TruffleVM.this, language.getClass())); - if (global != null) { - arr.add(global); - } - } else { - arr.add(thiz); - } - arr.addAll(Arrays.asList(args)); - for (;;) { - try { - if (target == null) { - target = SymbolInvokerImpl.createCallTarget(language, result[0], arr.toArray()); - } - res[0] = target.call(arr.toArray()); - break; - } catch (ArgumentsMishmashException ex) { - target = null; - } - } - } catch (IOException ex) { - res[1] = ex; - } catch (RuntimeException ex) { - res[1] = ex; - } finally { - done.countDown(); - } - } - - private void waitForSymbol() throws InterruptedIOException { - checkThread(); - try { - ready.await(); - } catch (InterruptedException ex) { - throw (InterruptedIOException) new InterruptedIOException(ex.getMessage()).initCause(ex); - } + return (Symbol) super.invoke(thiz, args); } } - /** - * Description of a language registered in {@link TruffleVM Truffle virtual machine}. Languages - * are registered by {@link Registration} annotation which stores necessary information into a - * descriptor inside of the language's JAR file. When a new {@link TruffleVM} is created, it - * reads all available descriptors and creates {@link Language} objects to represent them. One - * can obtain a {@link #getName() name} or list of supported {@link #getMimeTypes() MIME types} - * for each language. The actual language implementation is not initialized until - * {@link TruffleVM#eval(java.lang.String, java.lang.String) a code is evaluated} in it. - */ - public final class Language { - private final LanguageCache info; - private TruffleLanguage.Env env; - + @Deprecated + public final class Language extends PolyglotEngine.Language { Language(LanguageCache info) { - this.info = info; - } - - /** - * MIME types recognized by the language. - * - * @return returns immutable set of recognized MIME types - */ - public Set getMimeTypes() { - return info.getMimeTypes(); - } - - /** - * Human readable name of the language. Think of C, Ruby, JS, etc. - * - * @return string giving the language a name - */ - public String getName() { - return info.getName(); - } - - /** - * Name of the language version. - * - * @return string specifying the language version - */ - public String getVersion() { - return info.getVersion(); - } - - /** - * Human readable string that identifies the language and version. - * - * @return string describing the specific language version - */ - public String getShortName() { - return getName() + "(" + getVersion() + ")"; - } - - TruffleLanguage getImpl(boolean create) { - getEnv(create); - return info.getImpl(false); - } - - TruffleLanguage.Env getEnv(boolean create) { - if (env == null && create) { - env = SPI.attachEnv(TruffleVM.this, info.getImpl(true), out, err, in); - } - return env; - } - - @Override - public String toString() { - return "[" + getShortName() + " for " + getMimeTypes() + "]"; + super(info); } } // end of Language - - // - // Accessor helper methods - // - - TruffleLanguage findLanguage(Probe probe) { - Class languageClazz = SPI.findLanguage(probe); - for (Map.Entry entrySet : langs.entrySet()) { - Language languageDescription = entrySet.getValue(); - final TruffleLanguage impl = languageDescription.getImpl(false); - if (languageClazz.isInstance(impl)) { - return impl; - } - } - throw new IllegalStateException("Cannot find language " + languageClazz + " among " + langs); - } - - Env findEnv(Class languageClazz) { - for (Map.Entry entrySet : langs.entrySet()) { - Language languageDescription = entrySet.getValue(); - Env env = languageDescription.getEnv(false); - if (env != null && languageClazz.isInstance(languageDescription.getImpl(false))) { - return env; - } - } - throw new IllegalStateException("Cannot find language " + languageClazz + " among " + langs); - } - - static DebugSupportProvider findDebuggerSupport(TruffleLanguage l) { - return SPI.getDebugSupport(l); - } - - private static class SPIAccessor extends Accessor { - @Override - public Object importSymbol(Object vmObj, TruffleLanguage ownLang, String globalName) { - TruffleVM vm = (TruffleVM) vmObj; - Object g = vm.globals.get(globalName); - if (g != null) { - return g; - } - Set uniqueLang = new LinkedHashSet<>(vm.langs.values()); - for (Language dl : uniqueLang) { - TruffleLanguage l = dl.getImpl(false); - TruffleLanguage.Env env = dl.getEnv(false); - if (l == ownLang || l == null || env == null) { - continue; - } - Object obj = SPI.findExportedSymbol(env, globalName, true); - if (obj != null) { - return obj; - } - } - for (Language dl : uniqueLang) { - TruffleLanguage l = dl.getImpl(false); - TruffleLanguage.Env env = dl.getEnv(false); - if (l == ownLang || l == null || env == null) { - continue; - } - Object obj = SPI.findExportedSymbol(env, globalName, false); - if (obj != null) { - return obj; - } - } - return null; - } - - @Override - protected Env attachEnv(Object obj, TruffleLanguage language, OutputStream stdOut, OutputStream stdErr, InputStream stdIn) { - TruffleVM vm = (TruffleVM) obj; - return super.attachEnv(vm, language, stdOut, stdErr, stdIn); - } - - @Override - public Object eval(TruffleLanguage l, Source s) throws IOException { - return super.eval(l, s); - } - - @Override - public Object findExportedSymbol(TruffleLanguage.Env env, String globalName, boolean onlyExplicit) { - return super.findExportedSymbol(env, globalName, onlyExplicit); - } - - @Override - protected Object languageGlobal(TruffleLanguage.Env env) { - return super.languageGlobal(env); - } - - @Override - public ToolSupportProvider getToolSupport(TruffleLanguage l) { - return super.getToolSupport(l); - } - - @Override - public DebugSupportProvider getDebugSupport(TruffleLanguage l) { - return super.getDebugSupport(l); - } - - @Override - protected Class findLanguage(Probe probe) { - return super.findLanguage(probe); - } - - @Override - protected Env findLanguage(Object obj, Class languageClass) { - TruffleVM vm = (TruffleVM) obj; - return vm.findEnv(languageClass); - } - - @Override - protected Closeable executionStart(Object obj, Debugger[] fillIn, Source s) { - TruffleVM vm = (TruffleVM) obj; - return super.executionStart(vm, fillIn, s); - } - - @Override - protected void dispatchEvent(Object obj, Object event) { - TruffleVM vm = (TruffleVM) obj; - vm.dispatch(event); - } - } // end of SPIAccessor } diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/package-info.java --- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/package-info.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/package-info.java Tue Sep 22 11:22:26 2015 +0200 @@ -30,8 +30,8 @@ */ /** - * Central place to create and control {@link com.oracle.truffle.api.vm.TruffleVM Truffle Virtual - * Machine} and all languages hosted in it. + * Central place to create and control {@link com.oracle.truffle.api.vm.PolyglotEngine polyglot + * execution engine} and all languages hosted in it. */ package com.oracle.truffle.api.vm; diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Tue Sep 22 11:22:26 2015 +0200 @@ -48,10 +48,10 @@ /** * An entry point for everyone who wants to implement a Truffle based language. By providing an * implementation of this type and registering it using {@link Registration} annotation, your - * language becomes accessible to users of the {@link com.oracle.truffle.api.vm.TruffleVM Truffle - * virtual machine} - all they will need to do is to include your JAR into their application and all - * the Truffle goodies (multi-language support, multitenant hosting, debugging, etc.) will be made - * available to them. + * language becomes accessible to users of the {@link com.oracle.truffle.api.vm.PolyglotEngine + * polyglot execution engine} - all they will need to do is to include your JAR into their + * application and all the Truffle goodies (multi-language support, multitenant hosting, debugging, + * etc.) will be made available to them. * * @param internal state of the language associated with every thread that is executing program * {@link #parse(com.oracle.truffle.api.source.Source, com.oracle.truffle.api.nodes.Node, java.lang.String...) diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Breakpoint.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Breakpoint.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Breakpoint.java Tue Sep 22 11:22:26 2015 +0200 @@ -30,7 +30,7 @@ import java.io.IOException; /** - * Breakpoint in a {@link com.oracle.truffle.api.vm.TruffleVM} with + * Breakpoint in a {@link com.oracle.truffle.api.vm.PolyglotEngine} with * {@link com.oracle.truffle.api.debug debugging turned on}. You can ask * {@link Debugger#setLineBreakpoint(int, com.oracle.truffle.api.source.LineLocation, boolean)} or * {@link Debugger#setTagBreakpoint(int, com.oracle.truffle.api.instrument.SyntaxTag, boolean)} to diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java Tue Sep 22 11:22:26 2015 +0200 @@ -51,8 +51,8 @@ import java.util.List; /** - * Represents debugging related state of a {@link com.oracle.truffle.api.vm.TruffleVM}. Instance of - * this class is delivered via {@link SuspendedEvent#getDebugger()} and + * Represents debugging related state of a {@link com.oracle.truffle.api.vm.PolyglotEngine}. + * Instance of this class is delivered via {@link SuspendedEvent#getDebugger()} and * {@link ExecutionEvent#getDebugger()} events, once {@link com.oracle.truffle.api.debug debugging * is turned on}. */ diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ExecutionEvent.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ExecutionEvent.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ExecutionEvent.java Tue Sep 22 11:22:26 2015 +0200 @@ -26,7 +26,7 @@ /** * This event is delivered to all - * {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) + * {@link com.oracle.truffle.api.vm.PolyglotEngine.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) * registered event handlers} when an execution is about to be started. The event is the intended * place to initialize debugger - e.g. set * {@link Debugger#setLineBreakpoint(int, com.oracle.truffle.api.source.LineLocation, boolean) @@ -35,7 +35,7 @@ * the state of the event becomes invalid and subsequent calls to the event methods yield * {@link IllegalStateException}. One can however obtain reference to {@link Debugger} instance and * keep it to further manipulate with debugging capabilities of the - * {@link com.oracle.truffle.api.vm.TruffleVM} when it is running. + * {@link com.oracle.truffle.api.vm.PolyglotEngine} when it is running. */ @SuppressWarnings("javadoc") public final class ExecutionEvent { @@ -48,10 +48,10 @@ /** * Debugger associated with the execution. This debugger remains valid after the event is * processed, it is possible and suggested to keep a reference to it and use it any time later - * when evaluating sources in the {@link com.oracle.truffle.api.vm.TruffleVM}. + * when evaluating sources in the {@link com.oracle.truffle.api.vm.PolyglotEngine}. * * @return instance of debugger associated with the just starting execution and any subsequent - * ones in the same {@link com.oracle.truffle.api.vm.TruffleVM}. + * ones in the same {@link com.oracle.truffle.api.vm.PolyglotEngine}. */ public Debugger getDebugger() { return debugger; diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java Tue Sep 22 11:22:26 2015 +0200 @@ -37,7 +37,7 @@ /** * This event is delivered to all - * {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) + * {@link com.oracle.truffle.api.vm.PolyglotEngine.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) * registered event handlers} when an execution is suspended on a * {@link Debugger#setLineBreakpoint(int, com.oracle.truffle.api.source.LineLocation, boolean) * breakpoint} or during {@link #prepareStepInto(int) stepping}. Methods in this event can only be @@ -82,10 +82,10 @@ /** * Debugger associated with the just suspended execution. This debugger remains valid after the * event is processed, it is possible and suggested to keep a reference to it and use it any - * time later when evaluating sources in the {@link com.oracle.truffle.api.vm.TruffleVM}. + * time later when evaluating sources in the {@link com.oracle.truffle.api.vm.PolyglotEngine}. * * @return instance of debugger associated with the just suspended execution and any subsequent - * ones in the same {@link com.oracle.truffle.api.vm.TruffleVM}. + * ones in the same {@link com.oracle.truffle.api.vm.PolyglotEngine}. */ public Debugger getDebugger() { return debugger; @@ -104,8 +104,8 @@ } /** - * Gets the stack frames from the currently halted {@link com.oracle.truffle.api.vm.TruffleVM} - * execution. + * Gets the stack frames from the currently halted + * {@link com.oracle.truffle.api.vm.PolyglotEngine} execution. * * @return list of stack frames */ diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/package-info.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/package-info.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/package-info.java Tue Sep 22 11:22:26 2015 +0200 @@ -30,28 +30,28 @@ */ /** - * Control over {@link com.oracle.truffle.api.debug.Debugger debugging} of your {@link com.oracle.truffle.api.vm.TruffleVM}. Each {@link com.oracle.truffle.api.vm.TruffleVM} + * Control over {@link com.oracle.truffle.api.debug.Debugger debugging} of your {@link com.oracle.truffle.api.vm.PolyglotEngine}. Each {@link com.oracle.truffle.api.vm.PolyglotEngine} * is inherently capable to run in debugging mode - there is just one thing - * to do - the {@link com.oracle.truffle.api.vm.TruffleVM.Builder creator of the virtual machine} - * needs to turn debugging on when constructing its Truffle virtual machine: + * to do - the {@link com.oracle.truffle.api.vm.PolyglotEngine.Builder creator of the virtual machine} + * needs to turn debugging on when constructing its polyglot execution engine: *
- * vm = {@link com.oracle.truffle.api.vm.TruffleVM#newVM()}.
- *     {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(new {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}
+ * vm = {@link com.oracle.truffle.api.vm.PolyglotEngine#buildNew()}.
+ *     {@link com.oracle.truffle.api.vm.PolyglotEngine.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(new {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}
  *     {@code <}{@link com.oracle.truffle.api.debug.ExecutionEvent}{@code >}() {
  *         public void handle({@link com.oracle.truffle.api.debug.ExecutionEvent} ev) {
- *             // configure the virtual machine as {@link com.oracle.truffle.api.vm.TruffleVM#eval(com.oracle.truffle.api.source.Source) new execution} is starting
+ *             // configure the virtual machine as {@link com.oracle.truffle.api.vm.PolyglotEngine#eval(com.oracle.truffle.api.source.Source) new execution} is starting
  *         }
  *     }).
- *     {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(new {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}{@code <}
+ *     {@link com.oracle.truffle.api.vm.PolyglotEngine.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(new {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}{@code <}
  *     {@link com.oracle.truffle.api.debug.SuspendedEvent}{@code >}() {
  *         public void handle({@link com.oracle.truffle.api.debug.SuspendedEvent} ev) {
  *             // execution is suspended on a breakpoint or on a step - decide what next
  *         }
- *     }).{@link com.oracle.truffle.api.vm.TruffleVM.Builder#build() build()};
+ *     }).{@link com.oracle.truffle.api.vm.PolyglotEngine.Builder#build() build()};
  * 
* The debugging is controlled by events emitted by the Truffle virtual machine * at important moments. The {@link com.oracle.truffle.api.debug.ExecutionEvent} - * is sent when a call to {@link com.oracle.truffle.api.vm.TruffleVM#eval(com.oracle.truffle.api.source.Source)} + * is sent when a call to {@link com.oracle.truffle.api.vm.PolyglotEngine#eval(com.oracle.truffle.api.source.Source)} * is made and allows one to configure {@link com.oracle.truffle.api.debug.Breakpoint breakpoints} and/or decide whether the * program should {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareStepInto() step-into} or * {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareContinue() just run}. Once the execution is suspended a @@ -63,7 +63,7 @@ * The events methods are only available when the event is being delivered and * shouldn't be used anytime later. Both events however provide access to * {@link com.oracle.truffle.api.debug.Debugger} which can be kept and used - * during whole existence of the {@link com.oracle.truffle.api.vm.TruffleVM}. + * during whole existence of the {@link com.oracle.truffle.api.vm.PolyglotEngine}. * {@link com.oracle.truffle.api.debug.Debugger} is the central class that * keeps information about {@link com.oracle.truffle.api.debug.Debugger#getBreakpoints() registered breakpoints} * and allows one create new {@link com.oracle.truffle.api.debug.Breakpoint ones}. diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Tue Sep 22 11:22:26 2015 +0200 @@ -44,7 +44,7 @@ import java.lang.ref.WeakReference; /** - * Communication between TruffleVM and TruffleLanguage API/SPI. + * Communication between PolyglotEngine and TruffleLanguage API/SPI. */ @SuppressWarnings("rawtypes") public abstract class Accessor { diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java Tue Sep 22 11:22:26 2015 +0200 @@ -41,7 +41,7 @@ package com.oracle.truffle.sl.test; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.tck.TruffleTCK; import static org.junit.Assert.assertTrue; import org.junit.Test; @@ -53,13 +53,13 @@ public class SLTckTest extends TruffleTCK { @Test public void testVerifyPresence() { - TruffleVM vm = TruffleVM.newVM().build(); + PolyglotEngine vm = PolyglotEngine.buildNew().build(); assertTrue("Our language is present", vm.getLanguages().containsKey("application/x-sl")); } @Override - protected TruffleVM prepareVM() throws Exception { - TruffleVM vm = TruffleVM.newVM().build(); + protected PolyglotEngine prepareVM() throws Exception { + PolyglotEngine vm = PolyglotEngine.buildNew().build(); // @formatter:off vm.eval( Source.fromText( diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java Tue Sep 22 11:22:26 2015 +0200 @@ -41,7 +41,7 @@ package com.oracle.truffle.sl.test; import com.oracle.truffle.api.dsl.NodeFactory; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.sl.SLLanguage; import com.oracle.truffle.sl.builtins.SLBuiltinNode; import com.oracle.truffle.sl.test.SLTestRunner.TestCase; @@ -229,7 +229,7 @@ ByteArrayOutputStream out = new ByteArrayOutputStream(); try { - TruffleVM vm = TruffleVM.newVM().setIn(new ByteArrayInputStream(repeat(testCase.testInput, repeats).getBytes("UTF-8"))).setOut(out).build(); + PolyglotEngine vm = PolyglotEngine.buildNew().setIn(new ByteArrayInputStream(repeat(testCase.testInput, repeats).getBytes("UTF-8"))).setOut(out).build(); String script = readAllLines(testCase.path); diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Tue Sep 22 11:22:26 2015 +0200 @@ -46,7 +46,7 @@ import com.oracle.truffle.api.instrument.StandardSyntaxTag; import com.oracle.truffle.api.instrument.impl.DefaultSimpleInstrumentListener; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.sl.nodes.instrument.SLStandardASTProber; import com.oracle.truffle.sl.nodes.local.SLWriteLocalVariableNode; import com.oracle.truffle.sl.test.SLTestRunner; @@ -241,7 +241,7 @@ // We use the name of the file to determine what visitor to attach to it. if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) { // Set up the execution context for Simple and register our two listeners - TruffleVM vm = TruffleVM.newVM().setIn(new ByteArrayInputStream(testCase.testInput.getBytes("UTF-8"))).setOut(out).build(); + PolyglotEngine vm = PolyglotEngine.buildNew().setIn(new ByteArrayInputStream(testCase.testInput.getBytes("UTF-8"))).setOut(out).build(); final String src = readAllLines(testCase.path); vm.eval(Source.fromText(src, testCase.path.toString()).withMimeType("application/x-sl")); @@ -252,7 +252,7 @@ probe.attach(Instrument.create(slPrintAssigmentValueListener, "SL print assignment value")); } - TruffleVM.Symbol main = vm.findGlobalSymbol("main"); + PolyglotEngine.Value main = vm.findGlobalSymbol("main"); main.invoke(null); } else { notifier.fireTestFailure(new Failure(testCase.name, new UnsupportedOperationException("No instrumentation found."))); diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLHandler.java --- a/truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLHandler.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLHandler.java Tue Sep 22 11:22:26 2015 +0200 @@ -43,7 +43,7 @@ import com.oracle.truffle.api.instrument.KillException; import com.oracle.truffle.api.instrument.QuitException; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.tools.debug.shell.REPLMessage; import com.oracle.truffle.tools.debug.shell.client.SimpleREPLClient; import com.oracle.truffle.tools.debug.shell.server.REPLHandler; @@ -128,9 +128,9 @@ if (!file.canRead()) { return finishReplyFailed(reply, "can't find file \"" + fileName + "\""); } - final TruffleVM vm = serverContext.vm(); + final PolyglotEngine vm = serverContext.vm(); vm.eval(Source.fromFileName(file.getPath())); - TruffleVM.Symbol main = vm.findGlobalSymbol("main"); + PolyglotEngine.Value main = vm.findGlobalSymbol("main"); if (main != null) { main.invoke(null); } diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java --- a/truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java Tue Sep 22 11:22:26 2015 +0200 @@ -49,8 +49,8 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.vm.EventConsumer; -import com.oracle.truffle.api.vm.TruffleVM; -import com.oracle.truffle.api.vm.TruffleVM.Language; +import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.api.vm.PolyglotEngine.Language; import com.oracle.truffle.sl.SLLanguage; import com.oracle.truffle.sl.nodes.instrument.SLDefaultVisualizer; import com.oracle.truffle.tools.debug.shell.REPLMessage; @@ -90,7 +90,7 @@ } private final Language language; - private final TruffleVM vm; + private final PolyglotEngine vm; private Debugger db; private final String statusPrefix; private final Map handlerMap = new HashMap<>(); @@ -140,7 +140,7 @@ } }; - TruffleVM newVM = TruffleVM.newVM().onEvent(onHalted).onEvent(onExec).build(); + PolyglotEngine newVM = PolyglotEngine.buildNew().onEvent(onHalted).onEvent(onExec).build(); this.language = newVM.getLanguages().get("application/x-sl"); assert language != null; @@ -215,7 +215,7 @@ } @Override - public TruffleVM vm() { + public PolyglotEngine vm() { return vm; } diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java Tue Sep 22 11:22:26 2015 +0200 @@ -61,8 +61,8 @@ import com.oracle.truffle.api.nodes.NodeUtil; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.api.vm.TruffleVM; -import com.oracle.truffle.api.vm.TruffleVM.Symbol; +import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.api.vm.PolyglotEngine.Value; import com.oracle.truffle.sl.builtins.SLBuiltinNode; import com.oracle.truffle.sl.builtins.SLDefineFunctionBuiltin; import com.oracle.truffle.sl.builtins.SLNanoTimeBuiltin; @@ -226,7 +226,7 @@ * The main entry point. Use the mx command "mx sl" to run it with the correct class path setup. */ public static void main(String[] args) throws IOException { - TruffleVM vm = TruffleVM.newVM().build(); + PolyglotEngine vm = PolyglotEngine.buildNew().build(); assert vm.getLanguages().containsKey("application/x-sl"); setupToolDemos(); @@ -243,7 +243,7 @@ source = Source.fromFileName(args[0]); } vm.eval(source); - Symbol main = vm.findGlobalSymbol("main"); + Value main = vm.findGlobalSymbol("main"); if (main == null) { throw new SLException("No function main() defined in SL source file."); } @@ -257,10 +257,10 @@ * Temporary method during API evolution, supports debugger integration. */ public static void run(Source source) throws IOException { - TruffleVM vm = TruffleVM.newVM().build(); + PolyglotEngine vm = PolyglotEngine.buildNew().build(); assert vm.getLanguages().containsKey("application/x-sl"); vm.eval(source); - Symbol main = vm.findGlobalSymbol("main"); + Value main = vm.findGlobalSymbol("main"); if (main == null) { throw new SLException("No function main() defined in SL source file."); } @@ -271,7 +271,7 @@ * Parse and run the specified SL source. Factored out in a separate method so that it can also * be used by the unit test harness. */ - public static long run(TruffleVM context, Path path, PrintWriter logOutput, PrintWriter out, int repeats, List> currentBuiltins) throws IOException { + public static long run(PolyglotEngine context, Path path, PrintWriter logOutput, PrintWriter out, int repeats, List> currentBuiltins) throws IOException { builtins = currentBuiltins; if (logOutput != null) { @@ -287,7 +287,7 @@ } /* Lookup our main entry point, which is per definition always named "main". */ - Symbol main = context.findGlobalSymbol("main"); + Value main = context.findGlobalSymbol("main"); if (main == null) { throw new SLException("No function main() defined in SL source file."); } @@ -495,7 +495,7 @@ // if (statementCounts || coverage) { // if (registeredASTProber == null) { // final ASTProber newProber = new SLStandardASTProber(); - // // This should be registered on the TruffleVM + // // This should be registered on the PolyglotEngine // Probe.registerASTProber(newProber); // registeredASTProber = newProber; // } @@ -544,7 +544,7 @@ public SLDebugProvider() { if (registeredASTProber == null) { registeredASTProber = new SLStandardASTProber(); - // This should be registered on the TruffleVM + // This should be registered on the PolyglotEngine Probe.registerASTProber(registeredASTProber); } } @@ -558,7 +558,7 @@ public void enableASTProbing(ASTProber prober) { if (prober != null) { - // This should be registered on the TruffleVM + // This should be registered on the PolyglotEngine Probe.registerASTProber(prober); } } diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java --- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Tue Sep 22 11:22:26 2015 +0200 @@ -27,7 +27,7 @@ import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.vm.TruffleVM; +import com.oracle.truffle.api.vm.PolyglotEngine; import java.io.IOException; import java.util.Random; import static org.junit.Assert.assertEquals; @@ -45,28 +45,28 @@ */ public abstract class TruffleTCK { private static final Random RANDOM = new Random(); - private TruffleVM tckVM; + private PolyglotEngine tckVM; protected TruffleTCK() { } /** - * This methods is called before first test is executed. It's purpose is to set a TruffleVM with - * your language up, so it is ready for testing. - * {@link TruffleVM#eval(com.oracle.truffle.api.source.Source) Execute} any scripts you need, - * and prepare global symbols with proper names. The symbols will then be looked up by the + * This methods is called before first test is executed. It's purpose is to set a + * {@link PolyglotEngine} with your language up, so it is ready for testing. + * {@link PolyglotEngine#eval(com.oracle.truffle.api.source.Source) Execute} any scripts you + * need, and prepare global symbols with proper names. The symbols will then be looked up by the * infrastructure (using the names provided by you from methods like {@link #plusInt()}) and * used for internal testing. * * @return initialized Truffle virtual machine * @throws java.lang.Exception thrown when the VM preparation fails */ - protected abstract TruffleVM prepareVM() throws Exception; + protected abstract PolyglotEngine prepareVM() throws Exception; /** * MIME type associated with your language. The MIME type will be passed to - * {@link TruffleVM#eval(com.oracle.truffle.api.source.Source)} method of the - * {@link #prepareVM() created TruffleVM}. + * {@link PolyglotEngine#eval(com.oracle.truffle.api.source.Source)} method of the + * {@link #prepareVM() created engine}. * * @return mime type of the tested language */ @@ -84,8 +84,9 @@ /** * Name of a function that returns null. Truffle languages are encouraged to have * their own type representing null, but when such value is returned from - * {@link TruffleVM#eval}, it needs to be converted to real Java null by sending a - * foreign access isNull message. There is a test to verify it is really true. + * {@link PolyglotEngine#eval}, it needs to be converted to real Java null by + * sending a foreign access isNull message. There is a test to verify it is really + * true. * * @return name of globally exported symbol */ @@ -140,7 +141,7 @@ } /** - * Name of a function that counts number of its invocations in current {@link TruffleVM} + * Name of a function that counts number of its invocations in current {@link PolyglotEngine} * context. Your function should somehow keep a counter to remember number of its invocations * and always increment it. The first invocation should return 1, the second * 2 and so on. The returned values are expected to be instances of {@link Number}. @@ -154,8 +155,8 @@ /** * Return a code snippet that is invalid in your language. Its - * {@link TruffleVM#eval(com.oracle.truffle.api.source.Source) evaluation} should fail and yield - * an exception. + * {@link PolyglotEngine#eval(com.oracle.truffle.api.source.Source) evaluation} should fail and + * yield an exception. * * @return code snippet invalid in the tested language */ @@ -186,7 +187,7 @@ throw new UnsupportedOperationException("compoundObject() method not implemented"); } - private TruffleVM vm() throws Exception { + private PolyglotEngine vm() throws Exception { if (tckVM == null) { tckVM = prepareVM(); } @@ -199,7 +200,7 @@ @Test public void testFortyTwo() throws Exception { - TruffleVM.Symbol fourtyTwo = findGlobalSymbol(fourtyTwo()); + PolyglotEngine.Value fourtyTwo = findGlobalSymbol(fourtyTwo()); Object res = fourtyTwo.invoke(null).get(); @@ -222,7 +223,7 @@ @Test public void testNull() throws Exception { - TruffleVM.Symbol retNull = findGlobalSymbol(returnsNull()); + PolyglotEngine.Value retNull = findGlobalSymbol(returnsNull()); Object res = retNull.invoke(null).get(); @@ -244,7 +245,7 @@ int a = RANDOM.nextInt(100); int b = RANDOM.nextInt(100); - TruffleVM.Symbol plus = findGlobalSymbol(plus(int.class, int.class)); + PolyglotEngine.Value plus = findGlobalSymbol(plus(int.class, int.class)); Number n = plus.invoke(null, a, b).as(Number.class); assert a + b == n.intValue() : "The value is correct: (" + a + " + " + b + ") = " + n.intValue(); @@ -255,7 +256,7 @@ int a = RANDOM.nextInt(100); int b = RANDOM.nextInt(100); - TruffleVM.Symbol plus = findGlobalSymbol(plus(byte.class, byte.class)); + PolyglotEngine.Value plus = findGlobalSymbol(plus(byte.class, byte.class)); Number n = plus.invoke(null, (byte) a, (byte) b).as(Number.class); assert a + b == n.intValue() : "The value is correct: (" + a + " + " + b + ") = " + n.intValue(); @@ -266,7 +267,7 @@ int a = RANDOM.nextInt(100); int b = RANDOM.nextInt(100); - TruffleVM.Symbol plus = findGlobalSymbol(plus(short.class, short.class)); + PolyglotEngine.Value plus = findGlobalSymbol(plus(short.class, short.class)); Number n = plus.invoke(null, (short) a, (short) b).as(Number.class); assert a + b == n.intValue() : "The value is correct: (" + a + " + " + b + ") = " + n.intValue(); @@ -277,7 +278,7 @@ long a = RANDOM.nextInt(100); long b = RANDOM.nextInt(100); - TruffleVM.Symbol plus = findGlobalSymbol(plus(long.class, long.class)); + PolyglotEngine.Value plus = findGlobalSymbol(plus(long.class, long.class)); Number n = plus.invoke(null, a, b).as(Number.class); assert a + b == n.longValue() : "The value is correct: (" + a + " + " + b + ") = " + n.longValue(); @@ -288,7 +289,7 @@ float a = RANDOM.nextFloat(); float b = RANDOM.nextFloat(); - TruffleVM.Symbol plus = findGlobalSymbol(plus(float.class, float.class)); + PolyglotEngine.Value plus = findGlobalSymbol(plus(float.class, float.class)); Number n = plus.invoke(null, a, b).as(Number.class); assertEquals("Correct value computed", a + b, n.floatValue(), 0.01f); @@ -299,7 +300,7 @@ double a = RANDOM.nextDouble(); double b = RANDOM.nextDouble(); - TruffleVM.Symbol plus = findGlobalSymbol(plus(float.class, float.class)); + PolyglotEngine.Value plus = findGlobalSymbol(plus(float.class, float.class)); Number n = plus.invoke(null, a, b).as(Number.class); assertEquals("Correct value computed", a + b, n.doubleValue(), 0.01); @@ -329,7 +330,7 @@ @Test public void testMaxOrMinValue() throws Exception { - TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); + PolyglotEngine.Value apply = findGlobalSymbol(applyNumbers()); TruffleObject fn = JavaInterop.asTruffleFunction(LongBinaryOperation.class, new MaxMinObject(true)); Object res = apply.invoke(null, fn).get(); @@ -343,10 +344,10 @@ @Test public void testMaxOrMinValue2() throws Exception { - TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); + PolyglotEngine.Value apply = findGlobalSymbol(applyNumbers()); TruffleObject fn = JavaInterop.asTruffleFunction(LongBinaryOperation.class, new MaxMinObject(false)); - final TruffleVM.Symbol result = apply.invoke(null, fn); + final PolyglotEngine.Value result = apply.invoke(null, fn); try { String res = result.as(String.class); @@ -361,7 +362,7 @@ @Test public void testPrimitiveReturnTypeByte() throws Exception { - TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); + PolyglotEngine.Value apply = findGlobalSymbol(applyNumbers()); byte value = (byte) RANDOM.nextInt(100); @@ -372,7 +373,7 @@ @Test public void testPrimitiveReturnTypeShort() throws Exception { - TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); + PolyglotEngine.Value apply = findGlobalSymbol(applyNumbers()); short value = (short) RANDOM.nextInt(100); @@ -383,7 +384,7 @@ @Test public void testPrimitiveReturnTypeInt() throws Exception { - TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); + PolyglotEngine.Value apply = findGlobalSymbol(applyNumbers()); int value = RANDOM.nextInt(100); @@ -394,7 +395,7 @@ @Test public void testPrimitiveReturnTypeLong() throws Exception { - TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); + PolyglotEngine.Value apply = findGlobalSymbol(applyNumbers()); long value = RANDOM.nextInt(1000); @@ -405,7 +406,7 @@ @Test public void testPrimitiveReturnTypeFloat() throws Exception { - TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); + PolyglotEngine.Value apply = findGlobalSymbol(applyNumbers()); float value = RANDOM.nextInt(1000) + RANDOM.nextFloat(); @@ -416,7 +417,7 @@ @Test public void testPrimitiveReturnTypeDouble() throws Exception { - TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers()); + PolyglotEngine.Value apply = findGlobalSymbol(applyNumbers()); double value = RANDOM.nextInt(1000) + RANDOM.nextDouble(); @@ -431,7 +432,7 @@ if (id == null) { return; } - TruffleVM.Symbol apply = findGlobalSymbol(id); + PolyglotEngine.Value apply = findGlobalSymbol(id); byte value = (byte) RANDOM.nextInt(100); @@ -445,7 +446,7 @@ if (id == null) { return; } - TruffleVM.Symbol apply = findGlobalSymbol(id); + PolyglotEngine.Value apply = findGlobalSymbol(id); short value = (short) RANDOM.nextInt(100); Number n = (Number) apply.invoke(null, value).get(); @@ -458,7 +459,7 @@ if (id == null) { return; } - TruffleVM.Symbol apply = findGlobalSymbol(id); + PolyglotEngine.Value apply = findGlobalSymbol(id); int value = RANDOM.nextInt(100); @@ -472,7 +473,7 @@ if (id == null) { return; } - TruffleVM.Symbol apply = findGlobalSymbol(id); + PolyglotEngine.Value apply = findGlobalSymbol(id); long value = RANDOM.nextInt(1000); @@ -486,7 +487,7 @@ if (id == null) { return; } - TruffleVM.Symbol apply = findGlobalSymbol(id); + PolyglotEngine.Value apply = findGlobalSymbol(id); float value = RANDOM.nextInt(1000) + RANDOM.nextFloat(); @@ -500,7 +501,7 @@ if (id == null) { return; } - TruffleVM.Symbol apply = findGlobalSymbol(id); + PolyglotEngine.Value apply = findGlobalSymbol(id); double value = RANDOM.nextInt(1000) + RANDOM.nextDouble(); @@ -514,7 +515,7 @@ if (id == null) { return; } - TruffleVM.Symbol apply = findGlobalSymbol(id); + PolyglotEngine.Value apply = findGlobalSymbol(id); TruffleObject fn = JavaInterop.asTruffleFunction(LongBinaryOperation.class, new MaxMinObject(true)); @@ -525,11 +526,11 @@ @Test public void testCoExistanceOfMultipleLanguageInstances() throws Exception { final String countMethod = countInvocations(); - TruffleVM.Symbol count1 = findGlobalSymbol(countMethod); - TruffleVM vm1 = tckVM; + PolyglotEngine.Value count1 = findGlobalSymbol(countMethod); + PolyglotEngine vm1 = tckVM; tckVM = null; // clean-up - TruffleVM.Symbol count2 = findGlobalSymbol(countMethod); - TruffleVM vm2 = tckVM; + PolyglotEngine.Value count2 = findGlobalSymbol(countMethod); + PolyglotEngine vm2 = tckVM; assertNotSame("Two virtual machines allocated", vm1, vm2); @@ -554,17 +555,17 @@ } - private TruffleVM.Symbol findGlobalSymbol(String name) throws Exception { - TruffleVM.Symbol s = vm().findGlobalSymbol(name); + private PolyglotEngine.Value findGlobalSymbol(String name) throws Exception { + PolyglotEngine.Value s = vm().findGlobalSymbol(name); assert s != null : "Symbol " + name + " is not found!"; return s; } private CompoundObject findCompoundSymbol() throws Exception { final String compoundObjectName = compoundObject(); - TruffleVM.Symbol s = vm().findGlobalSymbol(compoundObjectName); + PolyglotEngine.Value s = vm().findGlobalSymbol(compoundObjectName); assert s != null : "Symbol " + compoundObjectName + " is not found!"; - final TruffleVM.Symbol value = s.invoke(null); + final PolyglotEngine.Value value = s.invoke(null); CompoundObject obj = value.as(CompoundObject.class); assertNotNull("Compound object for " + value + " found", obj); int traverse = RANDOM.nextInt(10); diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java Tue Sep 22 11:22:26 2015 +0200 @@ -32,8 +32,8 @@ import com.oracle.truffle.api.instrument.Visualizer; import com.oracle.truffle.api.instrument.impl.DefaultVisualizer; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.vm.TruffleVM; -import com.oracle.truffle.api.vm.TruffleVM.Language; +import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.api.vm.PolyglotEngine.Language; import com.oracle.truffle.tools.debug.shell.REPLMessage; import java.util.ArrayList; import java.util.Collections; @@ -76,7 +76,7 @@ return new DefaultVisualizer(); } - public abstract TruffleVM vm(); + public abstract PolyglotEngine vm(); protected abstract Debugger db(); diff -r 0480c4873a4a -r 0bcfe8c6088f truffle/overview.html --- a/truffle/overview.html Mon Sep 21 13:11:41 2015 +0200 +++ b/truffle/overview.html Tue Sep 22 11:22:26 2015 +0200 @@ -33,7 +33,7 @@

Truffle is a framework for writing and executing interpreters. In case you want to execute already written interpreters from your Java application, -start at {@link com.oracle.truffle.api.vm.TruffleVM}. In case you'd like +start at {@link com.oracle.truffle.api.vm.PolyglotEngine}. In case you'd like to write your own Truffle based language, start at {@link com.oracle.truffle.api.TruffleLanguage}.