changeset 21468:99942eac9c6d

Introducing TruffleVM - a central place to invoke code in any registered TruffleLanguage.
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Fri, 22 May 2015 13:41:10 +0200
parents d4db9d812c8d
children 286aef83a9a7
files graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleTCK.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleVMSingleThreadedTest.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/SymbolInvoker.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java graal/com.oracle.truffle.dsl.processor/src/META-INF/services/javax.annotation.processing.Processor graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java graal/com.oracle.truffle.interop/src/META-INF/services/com.oracle.truffle.api.impl.SymbolInvoker graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/SymbolInvokerImpl.java graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/TruffleGlobalScope.java graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/TruffleLanguage.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java
diffstat 14 files changed, 1090 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleTCK.java	Fri May 22 13:41:10 2015 +0200
@@ -0,0 +1,113 @@
+/*
+ * 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.vm.TruffleVM;
+import java.util.Random;
+
+/**
+ * A collection of tests that can certify language implementaiton to be complient with most recent
+ * requirements of the Truffle infrastructure and tooling. Subclass, implement abstract methods and
+ * include in your test suite.
+ */
+public abstract class TruffleTCK {
+    private TruffleVM vm;
+
+    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(java.lang.String, java.lang.String) Execute} any scripts you need, and
+     * prepare global symbols with proper names. The symbols will then be looked up by the
+     * infastructure (using the names provided by you from methods like {@link #plusInt()}) and used
+     * for internal testing.
+     *
+     * @return initialized Truffle virtual machine
+     */
+    protected abstract TruffleVM prepareVM() throws Exception;
+
+    /**
+     * Name of function which will return value 42 as a number. The return value of the method
+     * should be instance of {@link Number} and its {@link Number#intValue()} should return
+     * <code>42</code>.
+     *
+     * @return name of globally exported symbol
+     */
+    protected abstract String fourtyTwo();
+
+    /**
+     * Name of function to add two integer values together. The symbol will be invoked with two
+     * parameters of type {@link Integer} and expects result of type {@link Number} which's
+     * {@link Number#intValue()} is equivalent of <code>param1 + param2</code>.
+     *
+     * @return name of globally exported symbol
+     */
+    protected abstract String plusInt();
+
+    private TruffleVM vm() throws Exception {
+        if (vm == null) {
+            vm = prepareVM();
+        }
+        return vm;
+    }
+
+    //
+    // The tests
+    //
+
+    public void testFortyTwo() throws Exception {
+        TruffleVM.Symbol fourtyTwo = findGlobalSymbol(fourtyTwo());
+
+        Object res = fourtyTwo.invoke(null);
+
+        assert res instanceof Number : "should yield a number, but was: " + res;
+
+        Number n = (Number) res;
+
+        assert 42 == n.intValue() : "The value is 42 =  " + n.intValue();
+    }
+
+    public void testPlusWithInts() throws Exception {
+        Random r = new Random();
+        int a = r.nextInt(100);
+        int b = r.nextInt(100);
+
+        TruffleVM.Symbol plus = findGlobalSymbol(plusInt());
+
+        Object res = plus.invoke(null, a, b);
+
+        assert res instanceof Number : "+ on two ints should yield a number, but was: " + res;
+
+        Number n = (Number) res;
+
+        assert a + b == n.intValue() : "The value is correct: (" + a + " + " + b + ") =  " + n.intValue();
+    }
+
+    private TruffleVM.Symbol findGlobalSymbol(String name) throws Exception {
+        TruffleVM.Symbol s = vm().findGlobalSymbol(name);
+        assert s != null : "Symbol " + name + " is not found!";
+        return s;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleVMSingleThreadedTest.java	Fri May 22 13:41:10 2015 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.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 {
+        Thread t = new Thread("Initializer") {
+            @Override
+            public void run() {
+                tvm = TruffleVM.create();
+            }
+        };
+        t.start();
+        t.join();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void evalURI() throws IOException, URISyntaxException {
+        tvm.eval(new URI("http://unknown.js"));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void evalString() throws IOException {
+        tvm.eval("text/javascript", "1 + 1");
+    }
+
+    @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 findGlobalSymbol() {
+        tvm.findGlobalSymbol("doesNotExists");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Fri May 22 13:41:10 2015 +0200
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2014, 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;
+
+import com.oracle.truffle.api.impl.Accessor;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.TruffleVM;
+import com.oracle.truffle.api.vm.TruffleVM.Language;
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An entry point for everyone who wants to implement a Truffle based language. By providing
+ * implementation of this type and registering it using {@link Registration} annotation, your
+ * language becomes accessible to users of the {@link 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, multi tennat hosting, debugging, etc.) will be made available to them.
+ */
+public abstract class TruffleLanguage {
+    private Env env;
+
+    /**
+     * The annotation to use to register your language to the {@link TruffleVM Truffle} system. By
+     * annotating your implementation of {@link TruffleLanguage} by this annotation you are just a
+     * <em>one JAR drop to the classpath</em> away from your users. Once they include your JAR in
+     * their application, your language will be available to the {@link TruffleVM Truffle virtual
+     * machine}.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @Target(ElementType.TYPE)
+    public @interface Registration {
+        /**
+         * Unique name of your language. This name will be exposed to users via the
+         * {@link Language#getName()} getter.
+         *
+         * @return identifier of your language
+         */
+        String name();
+
+        /**
+         * List of mimetypes associated with your language. Users will use them (directly or
+         * inderectly) when {@link TruffleVM#eval(java.lang.String, java.lang.String) executing}
+         * their code snippets or their {@link TruffleVM#eval(java.net.URI) files}.
+         *
+         * @return array of mime types assigned to your language files
+         */
+        String[] mimeType();
+    }
+
+    @SuppressWarnings("all")
+    void attachEnv(Env env) {
+        this.env = env;
+    }
+
+    protected final Env env() {
+        if (this.env == null) {
+            throw new NullPointerException("Accessing env before initialization is finished");
+        }
+        return this.env;
+    }
+
+    protected abstract Object eval(Source code) throws IOException;
+
+    /**
+     * Called when some other language is seeking for a global symbol. This method is supposed to do
+     * lazy binding, e.g. there is no need to export symbols in advance, it is fine to wait until
+     * somebody asks for it (by calling this method).
+     * <p>
+     * The exported object can either be <code>TruffleObject</code> (e.g. a native object from the
+     * other language) to support interoperability between languages or one of Java primitive
+     * wrappers ( {@link Integer}, {@link Double}, {@link Short}, etc.).
+     *
+     * @param globalName the name of the global symbol to find
+     * @return an exported object or <code>null</code>, if the symbol does not represent anything
+     *         meaningful in this language
+     */
+    protected abstract Object findExportedSymbol(String globalName);
+
+    /**
+     * Returns global object for the language.
+     * <p>
+     * The object is expected to be <code>TruffleObject</code> (e.g. a native object from the other
+     * language) but technically it can be one of Java primitive wrappers ({@link Integer},
+     * {@link Double}, {@link Short}, etc.).
+     *
+     * @return the global object or <code>null</code> if the language does not support such concept
+     */
+    protected abstract Object getLanguageGlobal();
+
+    /**
+     * Checks whether the object is provided by this language.
+     *
+     * @param object the object to check
+     * @return <code>true</code> if this language can deal with such object in native way
+     */
+    protected abstract boolean isObjectOfLanguage(Object object);
+
+    /**
+     * Represents execution environment of the {@link TruffleLanguage}. Each active
+     * {@link TruffleLanguage} receives instance of the environment before any code is executed upon
+     * it. The environment has knowledge of all active languages and can exchange symbols between
+     * them.
+     */
+    public static final class Env {
+        private final TruffleVM vm;
+        private final TruffleLanguage lang;
+
+        Env(TruffleVM vm, TruffleLanguage lang) {
+            this.vm = vm;
+            this.lang = lang;
+        }
+
+        /**
+         * Asks the environment to go through other registered languages and find whether they
+         * export global symbol of specified name. The expected return type is either
+         * <code>TruffleObject</code>, or one of wrappers of Java primitive types ({@link Integer},
+         * {@link Double}).
+         *
+         * @param globalName the name of the symbol to search for
+         * @return object representing the symbol or <code>null</code>
+         */
+        public Object importSymbol(String globalName) {
+            return API.importSymbol(vm, lang, globalName);
+        }
+    }
+
+    private static final AccessAPI API = new AccessAPI();
+
+    private static final class AccessAPI extends Accessor {
+
+        @Override
+        protected Env attachEnv(TruffleVM vm, TruffleLanguage l) {
+            Env env = new Env(vm, l);
+            l.attachEnv(env);
+            return env;
+        }
+
+        @Override
+        public Object importSymbol(TruffleVM vm, TruffleLanguage queryingLang, String globalName) {
+            return super.importSymbol(vm, queryingLang, globalName);
+        }
+
+        @Override
+        protected Object eval(TruffleLanguage l, Source s) throws IOException {
+            return l.eval(s);
+        }
+
+        @Override
+        protected Object findExportedSymbol(TruffleLanguage l, String globalName) {
+            return l.findExportedSymbol(globalName);
+        }
+
+        @Override
+        protected Object languageGlobal(TruffleLanguage l) {
+            return l.getLanguageGlobal();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Fri May 22 13:41:10 2015 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, 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.impl;
+
+import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.api.TruffleLanguage.Env;
+import com.oracle.truffle.api.vm.TruffleVM;
+import com.oracle.truffle.api.source.Source;
+import java.io.IOException;
+import java.util.ServiceLoader;
+
+/**
+ * Communication between TruffleVM and TruffleLanguage API/SPI.
+ */
+public abstract class Accessor {
+    private static Accessor API;
+    private static Accessor SPI;
+    static {
+        TruffleLanguage lng = new TruffleLanguage() {
+            @Override
+            protected Object eval(Source code) throws IOException {
+                return null;
+            }
+
+            @Override
+            protected Object findExportedSymbol(String globalName) {
+                return null;
+            }
+
+            @Override
+            protected Object getLanguageGlobal() {
+                return null;
+            }
+
+            @Override
+            protected boolean isObjectOfLanguage(Object object) {
+                return false;
+            }
+        };
+        lng.hashCode();
+    }
+
+    protected Accessor() {
+        if (this.getClass().getSimpleName().endsWith("API")) {
+            if (API != null) {
+                throw new IllegalStateException();
+            }
+            API = this;
+        } else {
+            if (SPI != null) {
+                throw new IllegalStateException();
+            }
+            SPI = this;
+        }
+    }
+
+    protected Env attachEnv(TruffleVM vm, TruffleLanguage l) {
+        return API.attachEnv(vm, l);
+    }
+
+    protected Object eval(TruffleLanguage l, Source s) throws IOException {
+        return API.eval(l, s);
+    }
+
+    protected Object importSymbol(TruffleVM vm, TruffleLanguage queryingLang, String globalName) {
+        return SPI.importSymbol(vm, queryingLang, globalName);
+    }
+
+    protected Object findExportedSymbol(TruffleLanguage l, String globalName) {
+        return API.findExportedSymbol(l, globalName);
+    }
+
+    protected Object languageGlobal(TruffleLanguage l) {
+        return API.languageGlobal(l);
+    }
+
+    protected Object invoke(Object obj, Object[] args) throws IOException {
+        for (SymbolInvoker si : ServiceLoader.load(SymbolInvoker.class)) {
+            return si.invoke(obj, args);
+        }
+        throw new IOException("No symbol invoker found!");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/SymbolInvoker.java	Fri May 22 13:41:10 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 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.impl;
+
+import java.io.IOException;
+
+/**
+ * XXX: Temporary class to make unit tests pass without messing with Message implementations and
+ * associated nodes too much.
+ */
+public abstract class SymbolInvoker {
+    protected abstract Object invoke(Object symbol, Object... args) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java	Fri May 22 13:41:10 2015 +0200
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2014, 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.TruffleLanguage;
+import com.oracle.truffle.api.TruffleLanguage.Registration;
+import com.oracle.truffle.api.TruffleLanguage.Env;
+import com.oracle.truffle.api.impl.Accessor;
+import com.oracle.truffle.api.source.Source;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+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.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Virtual machine for Truffle based languages. Use {@link #create()} to instantiate 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 co-operate. Use {@link #create()} multiple
+ * times to create different, isolated virtual machines completely separated from each other.
+ * <p>
+ * 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.
+ * <p>
+ * The <code>TruffleVM</code> is single-threaded and tries to enforce that. It records the thread it
+ * has been {@link #create() created} by and checks that all subsequent calls are coming from the
+ * same thread.
+ */
+public final class TruffleVM {
+    private static final Logger LOG = Logger.getLogger(TruffleVM.class.getName());
+    private static final SPIAccessor SPI = new SPIAccessor();
+    private final Thread initThread;
+    private final Map<String, Language> langs;
+
+    private TruffleVM() {
+        initThread = Thread.currentThread();
+        this.langs = new HashMap<>();
+        Enumeration<URL> en;
+        try {
+            en = loader().getResources("META-INF/truffle/language");
+        } catch (IOException ex) {
+            throw new IllegalStateException("Cannot read list of Truffle languages", ex);
+        }
+        while (en.hasMoreElements()) {
+            URL u = en.nextElement();
+            Properties p;
+            try {
+                p = new Properties();
+                try (InputStream is = u.openStream()) {
+                    p.load(is);
+                }
+            } catch (IOException ex) {
+                LOG.log(Level.CONFIG, "Cannot process " + u + " as language definition", ex);
+                continue;
+            }
+            Language l = new Language(p);
+            for (String mimeType : l.getMimeTypes()) {
+                langs.put(mimeType, l);
+            }
+        }
+    }
+
+    static ClassLoader loader() {
+        ClassLoader l = TruffleVM.class.getClassLoader();
+        if (l == null) {
+            l = ClassLoader.getSystemClassLoader();
+        }
+        return l;
+    }
+
+    /**
+     * Creates new Truffle virtual machine. 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 TruffleVM create() {
+        return new TruffleVM();
+    }
+
+    /**
+     * Descriptions of languages supported in this Truffle virtual machine.
+     *
+     * @return an immutable map with keys being mimetypes and values the {@link Language
+     *         descriptions} of associated languages
+     */
+    public Map<String, Language> 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 <code>null</code>
+     * @throws IOException exception to signal I/O problems or problems with processing the file's
+     *             content
+     */
+    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);
+            mimeType = file.getName().endsWith(".c") ? "text/x-c" : Files.probeContentType(file.toPath());
+        } else {
+            URL url = location.toURL();
+            s = Source.fromURL(url, location.toString());
+            URLConnection conn = url.openConnection();
+            mimeType = conn.getContentType();
+        }
+        TruffleLanguage l = getTruffleLang(mimeType);
+        if (l == null) {
+            throw new IOException("No language for " + location + " with mime type " + mimeType + " found. Supported types: " + langs.keySet());
+        }
+        return SPI.eval(l, s);
+    }
+
+    /**
+     * 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 exceution, possibly <code>null</code>
+     * @throws IOException thrown to signal errors while processing the code
+     */
+    public Object eval(String mimeType, Reader reader) throws IOException {
+        checkThread();
+        TruffleLanguage l = getTruffleLang(mimeType);
+        if (l == null) {
+            throw new IOException("No language for mime type " + mimeType + " found. Supported types: " + langs.keySet());
+        }
+        return SPI.eval(l, Source.fromReader(reader, mimeType));
+    }
+
+    /**
+     * 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 exceution, possibly <code>null</code>
+     * @throws IOException thrown to signal errors while processing the code
+     */
+    public Object eval(String mimeType, String code) throws IOException {
+        checkThread();
+        TruffleLanguage l = getTruffleLang(mimeType);
+        if (l == null) {
+            throw new IOException("No language for mime type " + mimeType + " found. Supported types: " + langs.keySet());
+        }
+        return SPI.eval(l, Source.fromText(code, mimeType));
+    }
+
+    /**
+     * 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.
+     * <p>
+     * The names of the symbols are language dependant, but for example the Java language bindings
+     * follow the specification for method references:
+     * <ul>
+     * <li>"java.lang.Exception::new" is a reference to constructor of {@link Exception}
+     * <li>"java.lang.Integer::valueOf" is a reference to static method in {@link Integer} class
+     * </ul>
+     * Once an symbol is obtained, it remembers values for fast acces and is ready for being
+     * invoked.
+     *
+     * @param globalName the name of the symbol to find
+     * @return found symbol or <code>null</code> if it has not been found
+     */
+    public Symbol findGlobalSymbol(String globalName) {
+        checkThread();
+        Object obj = null;
+        Object global = null;
+        for (Language dl : langs.values()) {
+            TruffleLanguage l = dl.getImpl();
+            obj = SPI.findExportedSymbol(l, globalName);
+            if (obj != null) {
+                global = SPI.languageGlobal(l);
+                break;
+            }
+        }
+        return obj == null ? null : new Symbol(obj, global);
+    }
+
+    private void checkThread() {
+        if (initThread != Thread.currentThread()) {
+            throw new IllegalStateException("TruffleVM created on " + initThread.getName() + " but used on " + Thread.currentThread().getName());
+        }
+    }
+
+    private TruffleLanguage getTruffleLang(String mimeType) {
+        checkThread();
+        Language l = langs.get(mimeType);
+        return l == null ? null : l.getImpl();
+    }
+
+    /**
+     * 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 Object obj;
+        private final Object global;
+
+        Symbol(Object obj, Object global) {
+            this.obj = obj;
+            this.global = global;
+        }
+
+        /**
+         * 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 <code>invoke</code> method returns.
+         *
+         * @param thiz this/self in language that support such concept; use <code>null</code> to let
+         *            the language use default this/self or ignore the value
+         * @param args arguments to pass when invoking the symbol
+         * @return the value returned by invoking the symbol
+         * @throws IOException signals problem during execution
+         */
+        public Object invoke(Object thiz, Object... args) throws IOException {
+            List<Object> arr = new ArrayList<>();
+            if (thiz == null) {
+                if (global != null) {
+                    arr.add(global);
+                }
+            } else {
+                arr.add(thiz);
+            }
+            arr.addAll(Arrays.asList(args));
+            return SPI.invoke(obj, arr.toArray());
+        }
+    }
+
+    /**
+     * 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 descritors and creates {@link Language} objects to represent them. One
+     * can obtain a {@link #getName() name} or list of supported {@link #getMimeTypes() mimetypes}
+     * 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 Properties props;
+        private TruffleLanguage impl;
+
+        Language(Properties props) {
+            this.props = props;
+        }
+
+        /**
+         * Mimetypes recognized by the language.
+         *
+         * @return returns immutable set of recognized mimetypes
+         */
+        public Set<String> getMimeTypes() {
+            TreeSet<String> ts = new TreeSet<>();
+            for (int i = 0;; i++) {
+                String mt = props.getProperty("mimeType." + i);
+                if (mt == null) {
+                    break;
+                }
+                ts.add(mt);
+            }
+            return Collections.unmodifiableSet(ts);
+        }
+
+        /**
+         * Human readable name of the language. Think of C, Ruby, JS, etc.
+         *
+         * @return string giving the language a name
+         */
+        public String getName() {
+            return props.getProperty("name");
+        }
+
+        TruffleLanguage getImpl() {
+            if (impl == null) {
+                String n = props.getProperty("className");
+                try {
+                    TruffleLanguage lang = (TruffleLanguage) Class.forName(n, true, loader()).newInstance();
+                    SPI.attachEnv(TruffleVM.this, lang);
+                    impl = lang;
+                } catch (Exception ex) {
+                    throw new IllegalStateException("Cannot initialize " + getName() + " language with implementation " + n, ex);
+                }
+            }
+            return impl;
+        }
+
+        @Override
+        public String toString() {
+            return "[" + getName() + " for " + getMimeTypes() + "]";
+        }
+    } // end of Language
+
+    private static class SPIAccessor extends Accessor {
+        @Override
+        public Object importSymbol(TruffleVM vm, TruffleLanguage ownLang, String globalName) {
+            Set<Language> uniqueLang = new LinkedHashSet<>(vm.langs.values());
+            for (Language dl : uniqueLang) {
+                TruffleLanguage l = dl.getImpl();
+                if (l == ownLang) {
+                    continue;
+                }
+                Object obj = SPI.findExportedSymbol(l, globalName);
+                if (obj != null) {
+                    return obj;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public Env attachEnv(TruffleVM vm, TruffleLanguage l) {
+            return super.attachEnv(vm, l);
+        }
+
+        @Override
+        public Object eval(TruffleLanguage l, Source s) throws IOException {
+            return super.eval(l, s);
+        }
+
+        @Override
+        public Object findExportedSymbol(TruffleLanguage l, String globalName) {
+            return super.findExportedSymbol(l, globalName);
+        }
+
+        @Override
+        public Object languageGlobal(TruffleLanguage l) {
+            return super.languageGlobal(l);
+        }
+
+        @Override
+        public Object invoke(Object obj, Object[] args) throws IOException {
+            return super.invoke(obj, args);
+        }
+    } // end of SPIAccessor
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/META-INF/services/javax.annotation.processing.Processor	Fri May 22 10:50:43 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/META-INF/services/javax.annotation.processing.Processor	Fri May 22 13:41:10 2015 +0200
@@ -1,2 +1,3 @@
 com.oracle.truffle.dsl.processor.TruffleProcessor
 com.oracle.truffle.dsl.processor.verify.VerifyTruffleProcessor
+com.oracle.truffle.dsl.processor.LanguageRegistrationProcessor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java	Fri May 22 13:41:10 2015 +0200
@@ -0,0 +1,83 @@
+/*
+ * 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.dsl.processor;
+
+import com.oracle.truffle.api.TruffleLanguage.Registration;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Properties;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+
+@SupportedAnnotationTypes("com.oracle.truffle.api.*")
+public final class LanguageRegistrationProcessor extends AbstractProcessor {
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    private void createProviderFile(TypeElement language, Registration annotation) {
+        String filename = "META-INF/truffle/language";
+        try {
+            FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, language);
+            Properties p = new Properties();
+            String className = processingEnv.getElementUtils().getBinaryName(language).toString();
+            p.setProperty("name", annotation.name());
+            p.setProperty("className", className);
+            String[] mimes = annotation.mimeType();
+            for (int i = 0; i < mimes.length; i++) {
+                p.setProperty("mimeType." + i, mimes[i]);
+            }
+            try (OutputStream os = file.openOutputStream()) {
+                p.store(os, "Generated by " + LanguageRegistrationProcessor.class.getName());
+            }
+        } catch (IOException e) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), language);
+        }
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        for (Element e : roundEnv.getElementsAnnotatedWith(Registration.class)) {
+            Registration annotation = e.getAnnotation(Registration.class);
+            if (annotation != null && e.getKind() == ElementKind.CLASS) {
+                if (!e.getModifiers().contains(Modifier.PUBLIC)) {
+                    processingEnv.getMessager().printMessage(Kind.ERROR, "Registered language class must be public", e);
+                }
+                createProviderFile((TypeElement) e, annotation);
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.interop/src/META-INF/services/com.oracle.truffle.api.impl.SymbolInvoker	Fri May 22 13:41:10 2015 +0200
@@ -0,0 +1,1 @@
+com.oracle.truffle.interop.SymbolInvokerImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/SymbolInvokerImpl.java	Fri May 22 13:41:10 2015 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 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.interop;
+
+import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.impl.SymbolInvoker;
+import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.interop.messages.Execute;
+import com.oracle.truffle.interop.messages.Receiver;
+import com.oracle.truffle.interop.node.ForeignObjectAccessNode;
+import java.io.IOException;
+
+public final class SymbolInvokerImpl extends SymbolInvoker {
+    static final FrameDescriptor UNUSED_FRAMEDESCRIPTOR = new FrameDescriptor();
+
+    @Override
+    protected Object invoke(Object symbol, Object... arr) throws IOException {
+        ForeignObjectAccessNode executeMain = ForeignObjectAccessNode.getAccess(Execute.create(Receiver.create(), arr.length));
+        CallTarget callTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(executeMain, (TruffleObject) symbol, arr));
+        VirtualFrame frame = Truffle.getRuntime().createVirtualFrame(arr, UNUSED_FRAMEDESCRIPTOR);
+        return callTarget.call(frame);
+    }
+
+    private static class TemporaryRoot extends RootNode {
+        @Child private ForeignObjectAccessNode foreignAccess;
+        private final TruffleObject function;
+        private final Object[] args;
+
+        public TemporaryRoot(ForeignObjectAccessNode foreignAccess, TruffleObject function, Object... args) {
+            this.foreignAccess = foreignAccess;
+            this.function = function;
+            this.args = args;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return foreignAccess.executeForeign(frame, function, args);
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/TruffleGlobalScope.java	Fri May 22 10:50:43 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 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.interop;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.interop.*;
-
-public interface TruffleGlobalScope {
-    void exportTruffleObject(Object identifier, TruffleObject object);
-
-    FrameSlot getFrameSlot(Object identifier);
-
-    TruffleObject getTruffleObject(FrameSlot slot);
-
-    boolean contains(Object identifier);
-}
--- a/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/TruffleLanguage.java	Fri May 22 10:50:43 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014, 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.interop;
-
-import com.oracle.truffle.api.interop.*;
-
-public interface TruffleLanguage {
-    String getLanguageName();
-
-    Object run(String[] arguments);
-
-    void setTruffleGlobalScope(TruffleGlobalScope globalScope);
-
-    TruffleObject getLanguageGlobal();
-
-    boolean isObjectOfLanguage(TruffleObject object);
-
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Fri May 22 10:50:43 2015 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Fri May 22 13:41:10 2015 +0200
@@ -37,8 +37,8 @@
 import org.junit.runners.model.*;
 
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.*;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.sl.SLMain;
 import com.oracle.truffle.sl.builtins.*;
 import com.oracle.truffle.sl.factory.*;
 import com.oracle.truffle.sl.runtime.*;
@@ -171,6 +171,10 @@
             for (NodeFactory<? extends SLBuiltinNode> builtin : builtins) {
                 context.installBuiltin(builtin);
             }
+            /*
+             * TruffleVM vm = TruffleVM.create(); String script = readAllLines(testCase.path); for
+             * (int i = 0; i < repeats; i++) { vm.eval("application/x-sl", script); }
+             */
             final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName);
             SLMain.run(context, source, null, repeats);
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Fri May 22 10:50:43 2015 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Fri May 22 13:41:10 2015 +0200
@@ -32,6 +32,7 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.tools.*;
+import com.oracle.truffle.api.vm.TruffleVM;
 import com.oracle.truffle.sl.builtins.*;
 import com.oracle.truffle.sl.factory.*;
 import com.oracle.truffle.sl.nodes.*;
@@ -129,7 +130,13 @@
  * <em>default printer</em>.
  *
  */
-public class SLMain {
+@TruffleLanguage.Registration(name = "sl", mimeType = "application/x-sl")
+public class SLMain extends TruffleLanguage {
+    private final SLContext context;
+
+    public SLMain() {
+        this.context = SLContextFactory.create(new BufferedReader(new InputStreamReader(System.in)), System.out);
+    }
 
     /* Demonstrate per-type tabulation of node execution counts */
     private static boolean nodeExecCounts = false;
@@ -142,22 +149,21 @@
      * 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 {
-
-        SLContext context = SLContextFactory.create(new BufferedReader(new InputStreamReader(System.in)), System.out);
-
-        Source source;
-        if (args.length == 0) {
-            source = Source.fromReader(new InputStreamReader(System.in), "stdin");
-        } else {
-            source = Source.fromFileName(args[0]);
-        }
+        TruffleVM vm = TruffleVM.create();
+        assert vm.getLanguages().containsKey("application/x-sl");
 
         int repeats = 1;
         if (args.length >= 2) {
             repeats = Integer.parseInt(args[1]);
         }
 
-        run(context, source, System.out, repeats);
+        while (repeats-- > 0) {
+            if (args.length == 0) {
+                vm.eval("application/x-sl", new InputStreamReader(System.in));
+            } else {
+                vm.eval(new File(args[0]).toURI());
+            }
+        }
     }
 
     /**
@@ -341,4 +347,25 @@
         return result.toString();
     }
 
+    @Override
+    protected Object eval(Source code) throws IOException {
+        context.executeMain(code);
+        return null;
+    }
+
+    @Override
+    protected Object findExportedSymbol(String globalName) {
+        return null;
+    }
+
+    @Override
+    protected Object getLanguageGlobal() {
+        return null;
+    }
+
+    @Override
+    protected boolean isObjectOfLanguage(Object object) {
+        return false;
+    }
+
 }