com.oracle.truffle.tutorial.embedding.package-info Maven / Gradle / Ivy
Show all versions of truffle-tck Show documentation
/*
* Copyright (c) 2017, 2017, 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.
*/
// @formatter:off
/*
@ApiInfo(
group="Tutorial"
)
*/
/**
* Truffle Tutorial: Embedding Truffle Languages in Java
*
* This tutorial shows how to embed the Truffle language
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine execution environment} in a
* Java application.
*
* The Truffle environment lets Java interoperate with Truffle-implemented
* guest languages via foreign objects and foreign functions.
* For example Java code
* can directly access guest language methods, objects, classes,
* and some complex data structures
* with Java-typed accessors. In the reverse direction, guest language code can access Java objects,
* classes, and constructors.
*
* This tutorial helps you get started, starting with setup instructions, followed by descriptions of
* different interoperation scenarios with (working) code examples.
*
*
Related information
*
* {@link com.oracle.truffle.api.vm.PolyglotEngine}: execution environment for Truffle-implemented languages.
* {@linkplain com.oracle.truffle.tutorial Other Truffle Tutorials}
*
*
* Contents
*
*
*
*
* Setup
*
* Download
* GraalVM,
* which contains all the necessary pre-built components.
* Truffle bits are
* uploaded to Maven central. You can use them from your pom.xml
* file as:
*
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-api</artifactId>
<version>0.23</version> <!-- or any later version -->
</dependency>
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-dsl-processor</artifactId>
<version>0.23</version> <!-- same version as above -->
<scope>provided</scope>
</dependency>
*
*
* Get started
*
* Guest language "Hello World!"
*
* Integrating Truffle into your Java application starts with building
* an instance of {@link com.oracle.truffle.api.vm.PolyglotEngine}, the
* execution environment for Truffle-implemented languages.
* You can then use the engine to
* {@link com.oracle.truffle.api.vm.PolyglotEngine#eval evaluate}
* guest language source code.
*
* The following example creates the (literal) JavaScript
* {@link com.oracle.truffle.api.source.Source} named hello.js
,
* evaluates it, and then "casts" the result to a Java string.
* You can also create a {@link com.oracle.truffle.api.source.Source} that
* wraps a file name or URL.
*
* {@codesnippet com.oracle.truffle.tutorial.HelloWorld#helloWorldInJavaScript}
*
*
It's a polyglot world
*
* How to list all available languages? (TBD)
*
* Add a language
*
* The set of supported languages is determined by putting their JAR files on a
* classpath of your application. Some languages are available in central
*
* Maven repository. To include them, modify your pom.xml
file (if
* using Maven) dependency section:
*
*
* <dependency>
* <groupId>com.oracle.truffle</groupId>
* <artifactId>truffle-sl</artifactId>
* <version>0.23</version>
* </dependency>
*
*
* In addition to languages found on classpath the
* GraalVM
* download comes with highly efficient implementations of JavaScript,
* Ruby and
* the R language.
*
* Hello World in Ruby and JavaScript
*
* Mixing languages (TBD)
*
* Call guest language functions from Java
*
* Tuffle interoperation lets Java call
* foreign functions that guest language code exports (details vary across languages).
* This section presents a few examples.
*
* Define and call a JavaScript function
*
* A function exported from a dynamic language becomes a callable foreign function
* by giving it a Java type, for example the Java interface {@code Multiplier} in the following code.
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithJavaScript#callJavaScriptFunctionFromJava}
*
* Notes:
*
* - Evaluating the JS source returns an anonymous JS function of two arguments wrapped
* in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value} that can be
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) "cast"}
* to a foreign function with a Java type.
* - Parentheses around the JS function definition keep it out of JavaScript's
* global scope, so the Java object holds the only reference to it.
*
*
* Define and call a Ruby function
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithRuby#callRubyFunctionFromJava}
*
* Notes:
*
* - Evaluating the Ruby source returns a Ruby Proc of two arguments wrapped
* in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value} that can be
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) "cast"}
* to a foreign function with a Java type.
*
*
* Call an existing R function
*
* In this sample we use a reference to existing R function {@code qbinom} from the built-in stats package.
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithR#callRFunctionFromJava}
*
* Call multiple guest language functions with shared state from Java
*
* Often it is necessary to export multiple dynamic language functions that work
* together, for example by sharing variables. This can be done by giving
* an exported group of functions a Java type with more than a single method,
* for example the Java interface {@code Counter} in the following code.
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithJavaScript#callJavaScriptFunctionsWithSharedStateFromJava}
*
* Notes:
*
* - Evaluating the JS source returns an anonymous JS function of no arguments wrapped
* in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value} (assigned
* to {@code jsFunction}) that can be
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#execute(Object...) executed}
* directly, without giving it a Java type.
* - Executing {@code jsFunction} returns a JS dynamic object (containing two methods
* and a shared variable) wrapped in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value}
* that can be {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) "cast"}
* to a foreign object with a Java type.
* - Parentheses around the JS function definition keep it out of JavaScript's
* global scope, so the Java object holds the only reference to it.
*
*
* Access guest language classes from Java
*
* Access a JavaScript class
*
* The ECMAScript 6 specification adds the concept of typeless classes to JavaScript.
* Truffle interoperation allows Java to access fields and functions of a JavaScript class,
* for example the foreign function factory and class given the Java type
* {@code Incrementor} in the following code.
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithJavaScript#callJavaScriptClassFactoryFromJava}
*
* Notes:
*
* - Evaluating the JS source returns an anonymous JS function of no arguments wrapped
* in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value} (assigned
* to {@code jsFunction}) that can be
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#execute(Object...) executed}
* directly, without giving it a Java type.
* - Executing {@code jsFunction} returns a JS factory method for class
* {@code JSIncrementor} that can also be executed directly.
* - Executing the JS factory returns a JS object
* wrapped in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value}
* that can be {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) "cast"}
* to a foreign object with the Java type {@code Incrementor}.
* - Parentheses around the JS function definition keep it out of JavaScript's
* global scope, so the Java object holds the only reference to it.
*
*
* Access guest language data structures from Java
*
* The method {@link com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) Value.as(Class)}
* plays an essential role supporting interoperation between Java and guest language data
* structures.
* This section presents a few examples.
*
* Access a JavaScript Array
*
* The following example demonstrates type-safe Java foreign access
* to members of a JavaScript array with members of a known type,
* accessed as a Java {@link java.util.List} of objects with type given by interface {@code Point}.
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithJavaScript#accessJavaScriptArrayWithTypedElementsFromJava}
*
* Notes:
*
* - Evaluating the JS source returns an anonymous JS function of no arguments wrapped
* in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value} (assigned
* to {@code jsFunction}) that can be
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) "cast"}
* to a foreign function with Java type {@code PointProvider}.
* - Invoking the foreign function (assigned to {@code pointProvider}) creates
* a JS array, which is returned as a foreign object
* with Java type {@code List
}.
* - Parentheses around the JS function definition keep it out of JavaScript's
* global scope, so the Java object holds the only reference to it.
*
*
* Access a JavaScript JSON structure
*
* This example demonstrates type-safe Java foreign access to a JavaScript JSON-like
* structure, based on JSON data returned by a GitHub API.
* The GitHub response contains a list of repository objects. Each repository has an id,
* name, list of URLs, and a nested structure describing its owner. Java interfaces
* {@code Repository} and {@code Owner} define the structure as Java types.
*
* The following Java code is able to inspect a JavaScript JSON data structure
* generated by "mock parser" in a type-safe way.
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithJavaScript#accessJavaScriptJSONObjectFromJava}
*
* Notes:
*
* - Evaluating the JS source returns an anonymous JS function of no arguments wrapped
* in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value} (assigned
* to {@code jsFunction}) that can be
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#execute(Object...) executed}
* directly, without giving it a Java type.
* - Executing {@code jsFunction} returns a JS mock JSON parser function
* (assigned to {@code jsMockParser}) wrapped in a
* {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value}, that can be
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) "cast"}
* to a foreign function with Java type {@code ParseJSON}.
* - Calling the Java-typed mock parser creates a JS data structure, which is
* returned as a foreign object with Java type {@code List
}.
* - Parentheses around the JS function definition keep it out of JavaScript's
* global scope, so the Java object holds the only reference to it.
*
*
* Access Java from guest languages
*
* Access Java fields and methods from JavaScript
*
* Public members of Java objects can be exposed to guest language code
* as foreign objects, for example Java objects of type {@code Moment} in
* the following example.
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithJavaScript#accessFieldsOfJavaObject}
*
* Notes:
*
* - Evaluating the JS source returns an anonymous JS function of one argument wrapped
* in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value} (assigned to
* {@code jsFunction}) that can be executed directly with one argument.
* - The Java argument {@code javaMoment} is seen by the JS function as a
* foreign object whose public fields are visible.
*
- Executing {@code jsFunction} returns a JS number
* that can be
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) "cast"}
* to a Java {@link java.lang.Number} and then to a Java {@code int}.
* - Parentheses around the JS function definition keep it out of JavaScript's
* global scope, so the Java object holds the only reference to it.
*
*
* The multiple steps needed to convert the result in the above example
* produces awkward code that can be simplified.
* Instead of invoking the JS function directly, and "casting" the wrapped JS result,
* we can instead
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) "cast"}
* the JS function to a Java foreign function (of type {@code MomentConverter}) that
* returns the desired Java type directly, as shown in the following variation.
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithJavaScript#accessFieldsOfJavaObjectWithConverter}
*
* Access Java constructors and static methods from JavaScript
*
* Dynamic languages can also access the public constructors and public static methods
* of any Java class for which they are provided a reference.
* The following example shows JavaScript access to the public constructor of a Java
* class.
*
* {@codesnippet com.oracle.truffle.tck.impl.PolyglotEngineWithJavaScript#createJavaScriptFactoryForJavaClass}
*
* Notes:
*
* - Evaluating the JS source returns an anonymous JS function of one argument wrapped
* in a {@link com.oracle.truffle.api.vm.PolyglotEngine.Value Value} (assigned to
* {@code jsFunction}) that can be executed directly with one argument.
* - The Java class argument {@code Moment.class} is seen by the JS function as a
* foreign class whose public constructor is visible.
*
- Executing {@code jsFunction} with the Java class argument returns
* a JS "factory" function (for the Java class) that can be
* {@linkplain com.oracle.truffle.api.vm.PolyglotEngine.Value#as(Class) "cast"}
* to the desired Java function type ({@code MomentFactory}).
* - Parentheses around the JS function definition keep it out of JavaScript's
* global scope, so the Java object holds the only reference to it.
*
*
*
*
*
* @since 0.25
*/
package com.oracle.truffle.tutorial.embedding;