The community edition of the Truffle runtime providing execution engine and optimization support for dynamic programming languages built with the Truffle framework
—
Service Provider Interface (SPI) for implementing programming languages on the Truffle framework, including language registration, context management, and environment setup.
Main SPI class that language implementers extend to create new programming languages for GraalVM.
/**
* Base class for implementing programming languages on Truffle
* Extend this class and use @Registration to create a new language
*/
public abstract class TruffleLanguage<C> {
/**
* Creates a new context for language execution
* @param env The language environment
* @return New language context
*/
protected abstract C createContext(Env env);
/**
* Parses source code and returns an executable call target
* @param request Parse request containing source and parsing options
* @return Executable call target
* @throws Exception if parsing fails
*/
protected abstract CallTarget parse(ParsingRequest request) throws Exception;
/**
* Executes inline source code within an existing context
* @param request Inline execution request
* @return Execution result
* @throws Exception if execution fails
*/
protected Object executeInline(InlineParsingRequest request) throws Exception {
throw new UnsupportedOperationException("Inline execution not supported");
}
/**
* Finds meta-object for a given value (optional)
* @param context Language context
* @param value Value to find meta-object for
* @return Meta-object or null if not supported
*/
protected Object findMetaObject(C context, Object value) {
return null;
}
/**
* Returns display string for a value (optional)
* @param context Language context
* @param value Value to display
* @return Display string
*/
protected String toString(C context, Object value) {
return Objects.toString(value);
}
/**
* Finds source location for a value (optional)
* @param context Language context
* @param value Value to find location for
* @return Source section or null if not available
*/
protected SourceSection findSourceLocation(C context, Object value) {
return null;
}
/**
* Checks if a value is an object of this language
* @param context Language context
* @param value Value to check
* @return True if value belongs to this language
*/
protected boolean isObjectOfLanguage(C context, Object value) {
return false;
}
/**
* Returns the language home directory (optional)
* @return Language home path or null
*/
protected String getLanguageHome() {
return null;
}
/**
* Initializes the language (called once per language)
* @param context Language context
*/
protected void initializeContext(C context) throws Exception {
// Default implementation does nothing
}
/**
* Finalizes context before disposal
* @param context Language context
*/
protected void finalizeContext(C context) {
// Default implementation does nothing
}
/**
* Disposes the language context
* @param context Language context to dispose
*/
protected void disposeContext(C context) {
// Default implementation does nothing
}
}Usage Examples:
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.TruffleLanguage.Registration;
@Registration(
id = "mylang",
name = "My Language",
version = "1.0",
defaultMimeType = "application/x-mylang",
characterMimeTypes = {"application/x-mylang"},
fileTypeDetectors = MyLanguageFileDetector.class
)
public class MyLanguage extends TruffleLanguage<MyLanguageContext> {
@Override
protected MyLanguageContext createContext(Env env) {
return new MyLanguageContext(env);
}
@Override
protected CallTarget parse(ParsingRequest request) throws Exception {
Source source = request.getSource();
MyLanguageParser parser = new MyLanguageParser(source);
RootNode rootNode = parser.parse();
return rootNode.getCallTarget();
}
@Override
protected Object findMetaObject(MyLanguageContext context, Object value) {
if (value instanceof MyLanguageNumber) {
return context.getNumberMetaObject();
} else if (value instanceof MyLanguageString) {
return context.getStringMetaObject();
}
return null;
}
@Override
protected String toString(MyLanguageContext context, Object value) {
if (value instanceof MyLanguageObject) {
return ((MyLanguageObject) value).toDisplayString();
}
return super.toString(context, value);
}
}Annotation for registering languages with the Truffle language registry.
/**
* Annotation for registering Truffle languages
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Registration {
/** Unique language identifier */
String id();
/** Human-readable language name */
String name();
/** Language implementation version */
String version() default "";
/** Default MIME type for the language */
String defaultMimeType() default "";
/** All supported MIME types */
String[] mimeType() default {};
/** Character-based MIME types */
String[] characterMimeTypes() default {};
/** Binary MIME types */
String[] byteMimeTypes() default {};
/** Dependency on other languages */
String[] dependentLanguages() default {};
/** File type detectors */
Class<?>[] fileTypeDetectors() default {};
/** Whether language is interactive (REPL-capable) */
boolean interactive() default false;
/** Whether language is internal (not directly accessible) */
boolean internal() default false;
/** Language website URL */
String website() default "";
}Environment object providing access to language configuration and polyglot services.
/**
* Environment for language execution providing access to configuration and services
*/
public final class Env {
/** Returns the language options */
public OptionValues getOptions();
/** Returns command line arguments */
public String[] getApplicationArguments();
/** Checks if a MIME type is supported */
public boolean isMimeTypeSupported(String mimeType);
/** Parses source in another language */
public CallTarget parsePublic(Source source, String... argumentNames);
/** Parses inline source */
public CallTarget parseInline(Source source, Node location, MaterializedFrame frame);
/** Creates a new TruffleFile for file system access */
public TruffleFile getTruffleFile(String path);
/** Creates a new TruffleFile with URI */
public TruffleFile getTruffleFile(URI uri);
/** Returns the temporary directory */
public TruffleFile getTempDirectory();
/** Returns the current working directory */
public TruffleFile getCurrentWorkingDirectory();
/** Checks if native access is allowed */
public boolean isNativeAccessAllowed();
/** Checks if host access is allowed */
public boolean isHostLookupAllowed();
/** Looks up a host symbol */
public Object lookupHostSymbol(String symbolName);
/** Converts a host value to guest */
public Object asGuestValue(Object hostValue);
/** Converts a guest value to host */
public Object asHostValue(Object guestValue);
/** Checks if a value is host object */
public boolean isHostObject(Object guestValue);
/** Returns polyglot bindings */
public Object getPolyglotBindings();
/** Imports a polyglot symbol */
public Object importSymbol(String symbolName);
/** Exports a polyglot symbol */
public void exportSymbol(String symbolName, Object value);
/** Registers service provider */
public <T> T lookup(InstrumentInfo instrumentInfo, Class<T> serviceClass);
}Request objects for parsing source code.
/**
* Request for parsing source code
*/
public final class ParsingRequest {
/** Returns the source to parse */
public Source getSource();
/** Returns argument names for the executable */
public List<String> getArgumentNames();
/** Checks if parsing is for inline execution */
public boolean isInline();
/** Returns the frame for inline parsing */
public MaterializedFrame getFrame();
/** Returns the location node for inline parsing */
public Node getLocation();
}
/**
* Request for inline parsing and execution
*/
public final class InlineParsingRequest {
/** Returns the source to parse */
public Source getSource();
/** Returns the frame for execution */
public MaterializedFrame getFrame();
/** Returns the location node */
public Node getLocation();
}Information about registered languages and access to language instances.
/**
* Information about a registered language
*/
public final class LanguageInfo {
/** Returns the language ID */
public String getId();
/** Returns the language name */
public String getName();
/** Returns the language version */
public String getVersion();
/** Returns the default MIME type */
public String getDefaultMimeType();
/** Returns all MIME types */
public Set<String> getMimeTypes();
/** Checks if language is interactive */
public boolean isInteractive();
/** Checks if language is internal */
public boolean isInternal();
}
/**
* Utility for accessing language information and instances
*/
public final class LanguageAccess {
/** Gets current language instance */
public static <T extends TruffleLanguage<?>> T getCurrentLanguage(Class<T> languageClass);
/** Gets current language context */
public static <C> C getCurrentContext(Class<? extends TruffleLanguage<C>> languageClass);
/** Gets language info for current language */
public static LanguageInfo getCurrentLanguageInfo();
}Usage Examples:
public class MyLanguageContext {
private final Env env;
private final TruffleFile homeDirectory;
private final Map<String, Object> globals;
public MyLanguageContext(Env env) {
this.env = env;
this.homeDirectory = env.getCurrentWorkingDirectory();
this.globals = new HashMap<>();
// Initialize built-in functions
globals.put("print", new MyLanguagePrintFunction());
globals.put("import", new MyLanguageImportFunction());
}
public Object getGlobal(String name) {
// Check local globals first
Object value = globals.get(name);
if (value != null) {
return value;
}
// Try polyglot bindings
InteropLibrary interop = InteropLibrary.getUncached();
Object bindings = env.getPolyglotBindings();
try {
if (interop.isMemberReadable(bindings, name)) {
return interop.readMember(bindings, name);
}
} catch (Exception e) {
// Ignore and continue
}
// Try host lookup if allowed
if (env.isHostLookupAllowed()) {
try {
return env.lookupHostSymbol(name);
} catch (Exception e) {
// Symbol not found
}
}
return null;
}
}public final class OptionValues {
/** Gets the value of an option */
public <T> T get(OptionKey<T> optionKey);
/** Checks if an option has been set */
public boolean hasBeenSet(OptionKey<?> optionKey);
/** Returns all set options */
public Set<OptionKey<?>> getKeys();
}
public final class OptionKey<T> {
/** Creates a new option key with default value */
public OptionKey(T defaultValue);
/** Creates a new option key with default value and validator */
public OptionKey(T defaultValue, OptionType<T> type);
/** Returns the default value */
public T getDefaultValue();
/** Returns the option type */
public OptionType<T> getType();
}
public interface InstrumentInfo {
/** Returns the instrument ID */
String getId();
/** Returns the instrument name */
String getName();
/** Returns the instrument version */
String getVersion();
}Install with Tessl CLI
npx tessl i tessl/maven-org-graalvm-truffle--truffle-runtime