# HG changeset patch # User Jaroslav Tulach # Date 1447684889 -3600 # Node ID 78594d34222804c973a4712d69947c0213d3e6f0 # Parent 05f812bce8cc0e3b508d18750d9e81f8441298fa Give Truffle languages access to evaluation functions of other languages. diff -r 05f812bce8cc -r 78594d342228 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 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 languageClass, String mimeType) { + return super.findLanguageImpl(known, languageClass, mimeType); + } + + @Override protected Object languageGlobal(TruffleLanguage.Env env) { return env.langCtx.getLanguageGlobal(); } diff -r 05f812bce8cc -r 78594d342228 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 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 // diff -r 05f812bce8cc -r 78594d342228 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 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 builtin : builtins) { context.installBuiltin(builtin, true); } diff -r 05f812bce8cc -r 78594d342228 truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLEvalBuiltin.java --- /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, "").withMimeType(mimeType); + try { + return getContext().evalAny(source); + } catch (IOException ex) { + throw new IllegalArgumentException(ex); + } + } +} diff -r 05f812bce8cc -r 78594d342228 truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java --- 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 factory, boolean registerRootNodes) { @@ -227,4 +233,8 @@ } return a; } + + public Object evalAny(Source source) throws IOException { + return env.eval(source); + } } diff -r 05f812bce8cc -r 78594d342228 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 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 1, 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!";