changeset 22375:78594d342228

Give Truffle languages access to evaluation functions of other languages.
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Mon, 16 Nov 2015 15:41:29 +0100
parents 05f812bce8cc
children 72545ac338eb
files truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLEvalBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java
diffstat 6 files changed, 139 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Mon Nov 16 07:00:50 2015 +0100
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Mon Nov 16 15:41:29 2015 +0100
@@ -385,6 +385,22 @@
         }
 
         /**
+         * Evaluates source of (potentially different) language. The {@link Source#getMimeType()
+         * MIME type) is used to identify the {@link TruffleLanguage} to use to perform the
+         * {@link #parse(com.oracle.truffle.api.source.Source, com.oracle.truffle.api.nodes.Node, java.lang.String...)}
+         * .
+         * 
+         * @param source the source to evaluate
+         * @return the result of the evaluation
+         * @throws IOException if the parsing or evaluation fails for some reason
+         */
+        public Object eval(Source source) throws IOException {
+            TruffleLanguage<?> language = API.findLanguageImpl(vm, null, source.getMimeType());
+            CallTarget call = language.parse(source, null);
+            return call.call();
+        }
+
+        /**
          * Input associated with {@link com.oracle.truffle.api.vm.PolyglotEngine} this language is
          * being executed in.
          *
@@ -484,6 +500,11 @@
         }
 
         @Override
+        protected TruffleLanguage<?> findLanguageImpl(Object known, Class<? extends TruffleLanguage> languageClass, String mimeType) {
+            return super.findLanguageImpl(known, languageClass, mimeType);
+        }
+
+        @Override
         protected Object languageGlobal(TruffleLanguage.Env env) {
             return env.langCtx.getLanguageGlobal();
         }
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Mon Nov 16 07:00:50 2015 +0100
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Mon Nov 16 15:41:29 2015 +0100
@@ -170,6 +170,11 @@
         return null;
     }
 
+    @Override
+    protected String evaluateSource() {
+        return "interopEval";
+    }
+
     //
     // Ignore tests working on floats and double
     //
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Mon Nov 16 07:00:50 2015 +0100
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Mon Nov 16 15:41:29 2015 +0100
@@ -210,7 +210,7 @@
     protected SLContext createContext(Env env) {
         final BufferedReader in = new BufferedReader(new InputStreamReader(env.in()));
         final PrintWriter out = new PrintWriter(env.out(), true);
-        SLContext context = new SLContext(this, in, out);
+        SLContext context = new SLContext(this, env, in, out);
         for (NodeFactory<? extends SLBuiltinNode> builtin : builtins) {
             context.installBuiltin(builtin, true);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLEvalBuiltin.java	Mon Nov 16 15:41:29 2015 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * The Universal Permissive License (UPL), Version 1.0
+ *
+ * Subject to the condition set forth below, permission is hereby granted to any
+ * person obtaining a copy of this software, associated documentation and/or
+ * data (collectively the "Software"), free of charge and under any and all
+ * copyright rights in the Software, and any and all patent rights owned or
+ * freely licensable by each licensor hereunder covering either (i) the
+ * unmodified Software as contributed to or provided by such licensor, or (ii)
+ * the Larger Works (as defined below), to deal in both
+ *
+ * (a) the Software, and
+ *
+ * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ * one is included with the Software each a "Larger Work" to which the Software
+ * is contributed by such licensors),
+ *
+ * without restriction, including without limitation the rights to copy, create
+ * derivative works of, display, perform, and distribute the Software and make,
+ * use, sell, offer for sale, import, export, have made, and have sold the
+ * Software and the Larger Work(s), and to sublicense the foregoing rights on
+ * either these or other terms.
+ *
+ * This license is subject to the following condition:
+ *
+ * The above copyright notice and either this complete permission notice or at a
+ * minimum a reference to the UPL must be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.sl.SLLanguage;
+import java.io.IOException;
+
+/**
+ * Builtin function to parse a text in other language.
+ */
+@NodeInfo(shortName = "interopEval")
+public abstract class SLEvalBuiltin extends SLBuiltinNode {
+
+    public SLEvalBuiltin() {
+        super(SourceSection.createUnavailable(SLLanguage.builtinKind, "interopEval"));
+    }
+
+    @Specialization
+    public Object interopEval(String mimeType, String code) {
+        Source source = Source.fromText(code, "<unknown>").withMimeType(mimeType);
+        try {
+            return getContext().evalAny(source);
+        } catch (IOException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+    }
+}
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Mon Nov 16 07:00:50 2015 +0100
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Mon Nov 16 15:41:29 2015 +0100
@@ -41,6 +41,7 @@
 package com.oracle.truffle.sl.runtime;
 
 import com.oracle.truffle.api.ExecutionContext;
+import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.dsl.NodeFactory;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.nodes.NodeInfo;
@@ -54,6 +55,7 @@
 import com.oracle.truffle.sl.builtins.SLAssertTrueBuiltinFactory;
 import com.oracle.truffle.sl.builtins.SLBuiltinNode;
 import com.oracle.truffle.sl.builtins.SLDefineFunctionBuiltinFactory;
+import com.oracle.truffle.sl.builtins.SLEvalBuiltinFactory;
 import com.oracle.truffle.sl.builtins.SLHelloEqualsWorldBuiltinFactory;
 import com.oracle.truffle.sl.builtins.SLNanoTimeBuiltinFactory;
 import com.oracle.truffle.sl.builtins.SLNewObjectBuiltinFactory;
@@ -69,6 +71,7 @@
 import com.oracle.truffle.sl.parser.SLNodeFactory;
 
 import java.io.BufferedReader;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.math.BigInteger;
 
@@ -90,19 +93,21 @@
     private final PrintWriter output;
     private final SLFunctionRegistry functionRegistry;
     private final Shape emptyShape;
+    private final TruffleLanguage.Env env;
 
-    public SLContext(SLLanguage language, BufferedReader input, PrintWriter output) {
-        this(language, input, output, true);
+    public SLContext(SLLanguage language, TruffleLanguage.Env env, BufferedReader input, PrintWriter output) {
+        this(language, env, input, output, true);
     }
 
     public SLContext(SLLanguage language) {
-        this(language, null, null, false);
+        this(language, null, null, null, false);
     }
 
-    private SLContext(SLLanguage language, BufferedReader input, PrintWriter output, boolean installBuiltins) {
+    private SLContext(SLLanguage language, TruffleLanguage.Env env, BufferedReader input, PrintWriter output, boolean installBuiltins) {
         this.language = language;
         this.input = input;
         this.output = output;
+        this.env = env;
         this.functionRegistry = new SLFunctionRegistry();
         installBuiltins(installBuiltins);
 
@@ -150,6 +155,7 @@
         installBuiltin(SLAssertTrueBuiltinFactory.getInstance(), registerRootNodes);
         installBuiltin(SLAssertFalseBuiltinFactory.getInstance(), registerRootNodes);
         installBuiltin(SLNewObjectBuiltinFactory.getInstance(), registerRootNodes);
+        installBuiltin(SLEvalBuiltinFactory.getInstance(), registerRootNodes);
     }
 
     public void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory, boolean registerRootNodes) {
@@ -227,4 +233,8 @@
         }
         return a;
     }
+
+    public Object evalAny(Source source) throws IOException {
+        return env.eval(source);
+    }
 }
--- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Mon Nov 16 07:00:50 2015 +0100
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Mon Nov 16 15:41:29 2015 +0100
@@ -38,6 +38,7 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import org.junit.Test;
 
@@ -157,6 +158,18 @@
     }
 
     /**
+     * Name of a function to parse source written in some other language. When the function is
+     * executed, it expects two arguments. First one is MIME type identifying
+     * {@link TruffleLanguage} and the second one is the source code to parse in that language and
+     * execute it. The result of the execution is then returned back to the caller.
+     *
+     * @return name of globally exported symbol to invoke when one wants to execute some code
+     */
+    protected String evaluateSource() {
+        throw new UnsupportedOperationException("evaluateSource() method not implemented");
+    }
+
+    /**
      * 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 <code>1</code>, the second
@@ -594,6 +607,22 @@
         assertEquals("Global from the language same with Java obtained one", language.getGlobalObject().get(), global);
     }
 
+    @Test
+    public void testEvaluateSource() throws Exception {
+        Language language = vm().getLanguages().get(mimeType());
+        assertNotNull("Langugage for " + mimeType() + " found", language);
+
+        PolyglotEngine.Value function = vm().findGlobalSymbol(evaluateSource());
+        assertNotNull(evaluateSource() + " found", function);
+
+        Random r = new Random();
+        double expect = Math.floor(r.nextDouble() * 100000.0) / 10.0;
+        Object parsed = function.invoke(null, "x-application/tck", "" + expect).get();
+        assertTrue("Expecting numeric result, was:" + expect, parsed instanceof Number);
+        double value = ((Number)parsed).doubleValue();
+        assertEquals("Gets the double", expect, value, 0.01);
+    }
+
     private PolyglotEngine.Value findGlobalSymbol(String name) throws Exception {
         PolyglotEngine.Value s = vm().findGlobalSymbol(name);
         assert s != null : "Symbol " + name + " is not found!";