A multi-language framework for executing dynamic languages that achieves high performance when combined with Graal.
—
Truffle's interoperability system enables seamless integration between different languages through a standardized message-based protocol. It provides polyglot object access, cross-language method calls, and unified data type handling across the Truffle ecosystem.
Core library providing standardized messages for cross-language object interaction.
/**
* Main library for polyglot interoperability operations
*/
public abstract class InteropLibrary extends Library {
/**
* Get uncached interop library instance
* @return Uncached InteropLibrary
*/
public static InteropLibrary getUncached();
/**
* Get interop library for specific receiver
* @param receiver Object to get library for
* @return InteropLibrary instance
*/
public static InteropLibrary getUncached(Object receiver);
// ===== Array Operations =====
/**
* Check if object has array elements
* @param receiver Object to check
* @return true if has array elements
*/
public abstract boolean hasArrayElements(Object receiver);
/**
* Get array size
* @param receiver Array object
* @return Array size
* @throws UnsupportedMessageException if not an array
*/
public abstract long getArraySize(Object receiver) throws UnsupportedMessageException;
/**
* Check if array index is readable
* @param receiver Array object
* @param index Array index
* @return true if readable
*/
public abstract boolean isArrayElementReadable(Object receiver, long index);
/**
* Check if array index is writable
* @param receiver Array object
* @param index Array index
* @return true if writable
*/
public abstract boolean isArrayElementWritable(Object receiver, long index);
/**
* Check if array index is insertable
* @param receiver Array object
* @param index Array index
* @return true if insertable
*/
public abstract boolean isArrayElementInsertable(Object receiver, long index);
/**
* Check if array index is removable
* @param receiver Array object
* @param index Array index
* @return true if removable
*/
public abstract boolean isArrayElementRemovable(Object receiver, long index);
/**
* Read array element
* @param receiver Array object
* @param index Array index
* @return Element value
* @throws UnsupportedMessageException if not supported
* @throws InvalidArrayIndexException if invalid index
*/
public abstract Object readArrayElement(Object receiver, long index)
throws UnsupportedMessageException, InvalidArrayIndexException;
/**
* Write array element
* @param receiver Array object
* @param index Array index
* @param value New value
* @throws UnsupportedMessageException if not supported
* @throws UnsupportedTypeException if incompatible type
* @throws InvalidArrayIndexException if invalid index
*/
public abstract void writeArrayElement(Object receiver, long index, Object value)
throws UnsupportedMessageException, UnsupportedTypeException, InvalidArrayIndexException;
/**
* Remove array element
* @param receiver Array object
* @param index Array index
* @throws UnsupportedMessageException if not supported
* @throws InvalidArrayIndexException if invalid index
*/
public abstract void removeArrayElement(Object receiver, long index)
throws UnsupportedMessageException, InvalidArrayIndexException;
// ===== Object Member Operations =====
/**
* Check if object has members
* @param receiver Object to check
* @return true if has members
*/
public abstract boolean hasMembers(Object receiver);
/**
* Get object members
* @param receiver Object to inspect
* @param includeInternal Whether to include internal members
* @return Object with member names
* @throws UnsupportedMessageException if not supported
*/
public abstract Object getMembers(Object receiver, boolean includeInternal)
throws UnsupportedMessageException;
/**
* Check if member is readable
* @param receiver Object to check
* @param member Member name
* @return true if readable
*/
public abstract boolean isMemberReadable(Object receiver, String member);
/**
* Check if member is writable
* @param receiver Object to check
* @param member Member name
* @return true if writable
*/
public abstract boolean isMemberWritable(Object receiver, String member);
/**
* Check if member is insertable
* @param receiver Object to check
* @param member Member name
* @return true if insertable
*/
public abstract boolean isMemberInsertable(Object receiver, String member);
/**
* Check if member is removable
* @param receiver Object to check
* @param member Member name
* @return true if removable
*/
public abstract boolean isMemberRemovable(Object receiver, String member);
/**
* Check if member is invocable
* @param receiver Object to check
* @param member Member name
* @return true if invocable
*/
public abstract boolean isMemberInvocable(Object receiver, String member);
/**
* Read object member
* @param receiver Object to read from
* @param member Member name
* @return Member value
* @throws UnsupportedMessageException if not supported
* @throws UnknownIdentifierException if member not found
*/
public abstract Object readMember(Object receiver, String member)
throws UnsupportedMessageException, UnknownIdentifierException;
/**
* Write object member
* @param receiver Object to write to
* @param member Member name
* @param value New value
* @throws UnsupportedMessageException if not supported
* @throws UnknownIdentifierException if member not found
* @throws UnsupportedTypeException if incompatible type
*/
public abstract void writeMember(Object receiver, String member, Object value)
throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException;
/**
* Remove object member
* @param receiver Object to modify
* @param member Member name
* @throws UnsupportedMessageException if not supported
* @throws UnknownIdentifierException if member not found
*/
public abstract void removeMember(Object receiver, String member)
throws UnsupportedMessageException, UnknownIdentifierException;
/**
* Invoke object member
* @param receiver Object containing member
* @param member Member name
* @param arguments Invocation arguments
* @return Invocation result
* @throws UnsupportedMessageException if not supported
* @throws UnknownIdentifierException if member not found
* @throws ArityException if wrong number of arguments
* @throws UnsupportedTypeException if incompatible argument types
*/
public abstract Object invokeMember(Object receiver, String member, Object... arguments)
throws UnsupportedMessageException, UnknownIdentifierException, ArityException, UnsupportedTypeException;
// ===== Executable Operations =====
/**
* Check if object is executable
* @param receiver Object to check
* @return true if executable
*/
public abstract boolean isExecutable(Object receiver);
/**
* Execute object
* @param receiver Executable object
* @param arguments Execution arguments
* @return Execution result
* @throws UnsupportedMessageException if not executable
* @throws ArityException if wrong number of arguments
* @throws UnsupportedTypeException if incompatible argument types
*/
public abstract Object execute(Object receiver, Object... arguments)
throws UnsupportedMessageException, ArityException, UnsupportedTypeException;
// ===== Instantiation Operations =====
/**
* Check if object is instantiable
* @param receiver Object to check
* @return true if instantiable
*/
public abstract boolean isInstantiable(Object receiver);
/**
* Instantiate object
* @param receiver Constructor object
* @param arguments Constructor arguments
* @return New instance
* @throws UnsupportedMessageException if not instantiable
* @throws ArityException if wrong number of arguments
* @throws UnsupportedTypeException if incompatible argument types
*/
public abstract Object instantiate(Object receiver, Object... arguments)
throws UnsupportedMessageException, ArityException, UnsupportedTypeException;
// ===== Pointer Operations =====
/**
* Check if object is a pointer
* @param receiver Object to check
* @return true if pointer
*/
public abstract boolean isPointer(Object receiver);
/**
* Get pointer address
* @param receiver Pointer object
* @return Pointer address
* @throws UnsupportedMessageException if not a pointer
*/
public abstract long asPointer(Object receiver)
throws UnsupportedMessageException;
/**
* Convert to native pointer
* @param receiver Object to convert
* @return Native pointer
* @throws UnsupportedMessageException if not convertible
*/
public abstract void toNative(Object receiver)
throws UnsupportedMessageException;
// ===== Type Checking Operations =====
/**
* Check if object is null
* @param receiver Object to check
* @return true if null
*/
public abstract boolean isNull(Object receiver);
/**
* Check if object is boolean
* @param receiver Object to check
* @return true if boolean
*/
public abstract boolean isBoolean(Object receiver);
/**
* Convert to boolean
* @param receiver Object to convert
* @return boolean value
* @throws UnsupportedMessageException if not convertible
*/
public abstract boolean asBoolean(Object receiver)
throws UnsupportedMessageException;
/**
* Check if object is string
* @param receiver Object to check
* @return true if string
*/
public abstract boolean isString(Object receiver);
/**
* Convert to string
* @param receiver Object to convert
* @return String value
* @throws UnsupportedMessageException if not convertible
*/
public abstract String asString(Object receiver)
throws UnsupportedMessageException;
/**
* Check if object is number
* @param receiver Object to check
* @return true if number
*/
public abstract boolean isNumber(Object receiver);
/**
* Check if number fits in int
* @param receiver Number object
* @return true if fits in int
*/
public abstract boolean fitsInInt(Object receiver);
/**
* Convert to int
* @param receiver Number object
* @return int value
* @throws UnsupportedMessageException if not convertible
*/
public abstract int asInt(Object receiver)
throws UnsupportedMessageException;
/**
* Check if number fits in long
* @param receiver Number object
* @return true if fits in long
*/
public abstract boolean fitsInLong(Object receiver);
/**
* Convert to long
* @param receiver Number object
* @return long value
* @throws UnsupportedMessageException if not convertible
*/
public abstract long asLong(Object receiver)
throws UnsupportedMessageException;
/**
* Check if number fits in double
* @param receiver Number object
* @return true if fits in double
*/
public abstract boolean fitsInDouble(Object receiver);
/**
* Convert to double
* @param receiver Number object
* @return double value
* @throws UnsupportedMessageException if not convertible
*/
public abstract double asDouble(Object receiver)
throws UnsupportedMessageException;
}Base interface for objects that participate in cross-language interoperability.
/**
* Marker interface for objects that can be used across language boundaries
*/
public interface TruffleObject {
// Marker interface - no methods
}Annotations for exporting interop capabilities to other languages.
/**
* Exports library implementation for a class
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
@Repeatable(ExportLibrary.List.class)
public @interface ExportLibrary {
/**
* Library class to export
* @return Library class
*/
Class<? extends Library> value();
/**
* Receiver type for library
* @return Receiver class
*/
Class<?> receiverType() default Object.class;
/**
* Priority for library resolution
* @return Priority value
*/
int priority() default 0;
/**
* Container for multiple ExportLibrary annotations
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
@interface List {
ExportLibrary[] value();
}
}
/**
* Exports message implementation
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface ExportMessage {
/**
* Message name (defaults to method name)
* @return Message name
*/
String name() default "";
/**
* Library class containing message
* @return Library class
*/
Class<? extends Library> library() default Library.class;
}Usage Example:
@ExportLibrary(InteropLibrary.class)
public class MyInteropObject implements TruffleObject {
private final Map<String, Object> members = new HashMap<>();
@ExportMessage
boolean hasMembers() {
return true;
}
@ExportMessage
Object getMembers(boolean includeInternal) {
return new MemberKeys(members.keySet());
}
@ExportMessage
boolean isMemberReadable(String member) {
return members.containsKey(member);
}
@ExportMessage
Object readMember(String member) throws UnknownIdentifierException {
Object value = members.get(member);
if (value == null) {
throw UnknownIdentifierException.create(member);
}
return value;
}
@ExportMessage
boolean isMemberWritable(String member) {
return true;
}
@ExportMessage
void writeMember(String member, Object value) {
members.put(member, value);
}
}Library for operations on AST nodes in interop contexts.
/**
* Library for interop operations on nodes
*/
public abstract class NodeLibrary extends Library {
/**
* Get uncached node library
* @return Uncached NodeLibrary
*/
public static NodeLibrary getUncached();
/**
* Check if receiver accepts language and frame
* @param receiver Node to check
* @param frame Execution frame
* @param language Target language
* @return true if accepts
*/
public boolean accepts(Object receiver, VirtualFrame frame, Class<? extends TruffleLanguage<?>> language) {
return false;
}
/**
* Get view of node for specific language
* @param receiver Node to get view for
* @param frame Execution frame
* @param language Target language
* @return Language-specific view
* @throws UnsupportedMessageException if not supported
*/
public Object getView(Object receiver, VirtualFrame frame, Class<? extends TruffleLanguage<?>> language)
throws UnsupportedMessageException {
throw UnsupportedMessageException.create();
}
}Comprehensive exception hierarchy for interop error handling.
/**
* Base class for all interop exceptions
*/
public abstract class InteropException extends AbstractTruffleException {
/**
* Protected constructor
* @param message Exception message
*/
protected InteropException(String message) {
super(message);
}
/**
* Protected constructor
* @param message Exception message
* @param cause Exception cause
*/
protected InteropException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* Exception for unsupported interop messages
*/
public final class UnsupportedMessageException extends InteropException {
/**
* Create exception
* @return New exception instance
*/
public static UnsupportedMessageException create() {
return new UnsupportedMessageException();
}
private UnsupportedMessageException() {
super("Message not supported");
}
}
/**
* Exception for incorrect number of arguments
*/
public final class ArityException extends InteropException {
/**
* Create exception
* @param expectedArity Expected number of arguments
* @param actualArity Actual number of arguments
* @return New exception instance
*/
public static ArityException create(int expectedArity, int actualArity) {
return new ArityException(expectedArity, actualArity);
}
private final int expectedArity;
private final int actualArity;
private ArityException(int expectedArity, int actualArity) {
super("Expected " + expectedArity + " arguments but got " + actualArity);
this.expectedArity = expectedArity;
this.actualArity = actualArity;
}
/**
* Get expected arity
* @return Expected number of arguments
*/
public int getExpectedArity() {
return expectedArity;
}
/**
* Get actual arity
* @return Actual number of arguments
*/
public int getActualArity() {
return actualArity;
}
}
/**
* Exception for unsupported type conversions
*/
public final class UnsupportedTypeException extends InteropException {
/**
* Create exception
* @param suppliedValues Values that caused the error
* @return New exception instance
*/
public static UnsupportedTypeException create(Object[] suppliedValues) {
return new UnsupportedTypeException(suppliedValues);
}
/**
* Create exception with message
* @param suppliedValues Values that caused the error
* @param message Error message
* @return New exception instance
*/
public static UnsupportedTypeException create(Object[] suppliedValues, String message) {
return new UnsupportedTypeException(suppliedValues, message);
}
private final Object[] suppliedValues;
private UnsupportedTypeException(Object[] suppliedValues) {
super("Unsupported type");
this.suppliedValues = suppliedValues;
}
private UnsupportedTypeException(Object[] suppliedValues, String message) {
super(message);
this.suppliedValues = suppliedValues;
}
/**
* Get supplied values
* @return Array of supplied values
*/
public Object[] getSuppliedValues() {
return suppliedValues;
}
}
/**
* Exception for unknown identifiers/members
*/
public final class UnknownIdentifierException extends InteropException {
/**
* Create exception
* @param unknownIdentifier Unknown identifier
* @return New exception instance
*/
public static UnknownIdentifierException create(String unknownIdentifier) {
return new UnknownIdentifierException(unknownIdentifier);
}
private final String unknownIdentifier;
private UnknownIdentifierException(String unknownIdentifier) {
super("Unknown identifier: " + unknownIdentifier);
this.unknownIdentifier = unknownIdentifier;
}
/**
* Get unknown identifier
* @return Unknown identifier string
*/
public String getUnknownIdentifier() {
return unknownIdentifier;
}
}
/**
* Exception for invalid array indices
*/
public final class InvalidArrayIndexException extends InteropException {
/**
* Create exception
* @param invalidIndex Invalid index value
* @return New exception instance
*/
public static InvalidArrayIndexException create(long invalidIndex) {
return new InvalidArrayIndexException(invalidIndex);
}
private final long invalidIndex;
private InvalidArrayIndexException(long invalidIndex) {
super("Invalid array index: " + invalidIndex);
this.invalidIndex = invalidIndex;
}
/**
* Get invalid index
* @return Invalid index value
*/
public long getInvalidIndex() {
return invalidIndex;
}
}
/**
* Exception for iterator exhaustion
*/
public final class StopIterationException extends InteropException {
/**
* Create exception
* @return New exception instance
*/
public static StopIterationException create() {
return new StopIterationException();
}
private StopIterationException() {
super("Iterator exhausted");
}
}Enumeration for categorizing interop exceptions.
/**
* Categories of interop exceptions
*/
public enum ExceptionType {
/**
* Runtime error in guest language
*/
RUNTIME_ERROR,
/**
* Parsing error in guest language
*/
PARSE_ERROR,
/**
* Exit request from guest language
*/
EXIT,
/**
* Interrupt signal
*/
INTERRUPT
}Classes for cross-language iteration support.
/**
* Iterator for arrays in interop contexts
*/
public final class ArrayIterator implements TruffleObject {
/**
* Create array iterator
* @param array Array to iterate
* @return ArrayIterator instance
*/
public static ArrayIterator create(Object array) {
return new ArrayIterator(array);
}
private ArrayIterator(Object array) {
// Implementation details
}
}
/**
* Iterator for hash-like objects in interop contexts
*/
public final class HashIterator implements TruffleObject {
/**
* Create hash iterator
* @param hash Hash object to iterate
* @return HashIterator instance
*/
public static HashIterator create(Object hash) {
return new HashIterator(hash);
}
private HashIterator(Object hash) {
// Implementation details
}
}/**
* Base class for all Truffle libraries
*/
public abstract class Library extends Node {
/**
* Check if library accepts receiver
* @param receiver Object to check
* @return true if accepts
*/
public boolean accepts(Object receiver) {
return true;
}
}
/**
* Factory for library instances
*/
public abstract class LibraryFactory<T extends Library> {
/**
* Get uncached library instance
* @return Uncached library
*/
public abstract T getUncached();
/**
* Get uncached library for specific receiver
* @param receiver Target receiver
* @return Uncached library
*/
public abstract T getUncached(Object receiver);
/**
* Create cached library
* @param receiver Target receiver
* @return Cached library
*/
public abstract T create(Object receiver);
}
/**
* Message representation for library operations
*/
public abstract class Message {
/**
* Get message name
* @return Message name
*/
public abstract String getSimpleName();
/**
* Get qualified message name
* @return Qualified name
*/
public abstract String getQualifiedName();
}Install with Tessl CLI
npx tessl i tessl/maven-org-graalvm-truffle--truffle-api