The community edition of the Truffle runtime providing execution engine and optimization support for dynamic programming languages built with the Truffle framework
—
Abstract Syntax Tree (AST) node framework providing the foundation for building executable language interpreters with support for optimization, specialization, and compilation.
Base class for all AST nodes in Truffle, providing core functionality for tree structure, source attribution, and optimization support.
/**
* Base class for all nodes in a Truffle AST
* Provides tree structure, source information, and optimization hooks
*/
public abstract class Node implements NodeInterface, Cloneable {
/** Returns the parent node or null for root */
public final Node getParent();
/** Returns all child nodes */
public final Iterable<Node> getChildren();
/** Replaces this node with another node */
public final <T extends Node> T replace(T newNode);
/** Replaces this node with another node and reason */
public final <T extends Node> T replace(T newNode, CharSequence reason);
/** Checks if this node can be replaced */
public boolean isReplaceable();
/** Returns a deep copy of this node */
public Node deepCopy();
/** Returns a copy of this node */
public Node copy();
/** Accepts a node visitor */
public void accept(NodeVisitor visitor);
/** Returns the source section for this node */
public SourceSection getSourceSection();
/** Checks if source section is available */
public final boolean hasSourceSection();
/** Returns a string representation of the source location */
public final String getSourceLocation();
/** Returns the root node of this AST */
public final RootNode getRootNode();
/** Returns the language info for this node's language */
public final LanguageInfo getLanguage();
/** Notifies that this node was adopted into an AST */
protected void onReplace(Node newNode, CharSequence reason) {
// Default implementation does nothing
}
/**
* Returns a cost estimate for this node
* Used by the runtime for compilation heuristics
*/
public NodeCost getCost() {
return NodeCost.MONOMORPHIC;
}
/**
* Returns debug information about this node
*/
protected Object getDebugProperties() {
return null;
}
}Special node representing the root of an executable AST, serving as the entry point for method execution.
/**
* Root node of a Truffle AST representing an executable unit
* Entry point for method/function execution
*/
public abstract class RootNode extends Node {
/**
* Executes this root node with the given frame
* @param frame Execution frame containing arguments and local variables
* @return Execution result
*/
public abstract Object execute(VirtualFrame frame);
/** Returns the language info for this root node */
public final LanguageInfo getLanguageInfo();
/** Returns the call target for this root node */
public final CallTarget getCallTarget();
/** Returns the frame descriptor for this root node */
public final FrameDescriptor getFrameDescriptor();
/**
* Returns the name of this executable unit
* Used for debugging and profiling
*/
public String getName() {
return "Unnamed";
}
/**
* Returns a qualified name including module/class information
*/
public String getQualifiedName() {
return getName();
}
/**
* Checks if this root node represents internal code
* Internal code is excluded from stack traces by default
*/
public boolean isInternal() {
return false;
}
/**
* Checks if this root node can be cloned for splitting
*/
public boolean isCloningAllowed() {
return true;
}
/**
* Creates a split version of this root node
*/
public RootNode split() {
return cloneUninitializedRootNode();
}
/**
* Checks if this root node represents a tail call position
*/
public boolean isTail() {
return true;
}
/**
* Returns debug information for this root node
*/
protected Object getDebugInfo() {
return null;
}
}Usage Examples:
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
public class MyLanguageFunctionRootNode extends RootNode {
@Child private MyLanguageStatementNode bodyNode;
private final String functionName;
public MyLanguageFunctionRootNode(LanguageInfo language, FrameDescriptor frameDescriptor,
MyLanguageStatementNode bodyNode, String functionName) {
super(language, frameDescriptor);
this.bodyNode = bodyNode;
this.functionName = functionName;
}
@Override
public Object execute(VirtualFrame frame) {
try {
return bodyNode.execute(frame);
} catch (MyLanguageReturnException returnEx) {
return returnEx.getReturnValue();
}
}
@Override
public String getName() {
return functionName;
}
@Override
public boolean isInternal() {
return functionName.startsWith("__");
}
}Optimized node for calling a known call target directly.
/**
* Optimized call node for direct calls to a known call target
* Provides better performance than indirect calls when target is known
*/
public abstract class DirectCallNode extends Node {
/** Creates a direct call node for the given call target */
public static DirectCallNode create(CallTarget callTarget);
/** Calls the target with the given arguments */
public abstract Object call(Object... arguments);
/** Returns the call target */
public abstract CallTarget getCallTarget();
/**
* Checks if this call can be inlined
* Inlining provides better optimization opportunities
*/
public abstract boolean isInlinable();
/**
* Checks if calls should be inlined
* Returns true if inlining is beneficial
*/
public abstract boolean isInliningForced();
/**
* Forces or prevents inlining of this call
*/
public abstract void forceInlining();
/**
* Returns the current call target, accounting for splitting
*/
public abstract CallTarget getCurrentCallTarget();
/**
* Returns the original call target before any splitting
*/
public abstract CallTarget getClonedCallTarget();
}Node for calling targets that are not known at compile time.
/**
* Call node for indirect calls where target is determined at runtime
* Less optimized than direct calls but supports dynamic dispatch
*/
public abstract class IndirectCallNode extends Node {
/** Creates an indirect call node */
public static IndirectCallNode create();
/** Calls the given call target with arguments */
public abstract Object call(CallTarget callTarget, Object... arguments);
}Annotations for configuring node behavior and specialization.
/**
* Marks a field as a child node
* Child nodes are automatically adopted and included in tree operations
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Child {
}
/**
* Marks a field as containing child nodes
* Used for arrays or collections of child nodes
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Children {
}
/**
* Node cost enumeration for optimization heuristics
*/
public enum NodeCost {
/** Uninitialized node - has not executed yet */
UNINITIALIZED,
/** Monomorphic node - handles one type efficiently */
MONOMORPHIC,
/** Polymorphic node - handles multiple types with some overhead */
POLYMORPHIC,
/** Megamorphic node - handles many types with significant overhead */
MEGAMORPHIC,
/** Invalid node - should be replaced */
INVALID
}Utilities for traversing and analyzing node trees.
/**
* Visitor interface for traversing node trees
*/
public interface NodeVisitor {
/**
* Visits a node
* @param node The node being visited
* @return true to continue visiting children, false to skip
*/
boolean visit(Node node);
}
/**
* Utility class for node tree operations
*/
public final class NodeUtil {
/** Finds all nodes of a specific type in the tree */
public static <T> List<T> findAllNodeInstances(Node root, Class<T> clazz);
/** Finds the first node of a specific type */
public static <T> T findFirstNodeInstance(Node root, Class<T> clazz);
/** Counts nodes in the tree */
public static int countNodes(Node root);
/** Creates a tree representation string */
public static String printTreeToString(Node root);
/** Dumps the tree structure to output */
public static void printTree(Node root);
/** Verifies tree structure integrity */
public static boolean verify(Node root);
/** Returns all parent nodes up to root */
public static List<Node> collectParents(Node node);
}Specialized nodes for optimized loop execution.
/**
* Interface for optimized loop execution
*/
public interface LoopNode extends Node.Child {
/** Executes the loop */
void execute(VirtualFrame frame);
/** Returns the repeating node executed in the loop */
RepeatingNode getRepeatingNode();
}
/**
* Interface for nodes that repeat in a loop
*/
public interface RepeatingNode extends Node.Child {
/**
* Executes one iteration of the loop
* @param frame Current execution frame
* @return true to continue looping, false to exit
*/
boolean executeRepeating(VirtualFrame frame);
}
/**
* Factory for creating loop nodes
*/
public final class Truffle {
/** Creates an optimized loop node */
public static LoopNode createLoopNode(RepeatingNode repeatingNode);
}Usage Examples:
// Creating a specialized node with child nodes
public abstract class MyLanguageBinaryOpNode extends MyLanguageExpressionNode {
@Child private MyLanguageExpressionNode leftNode;
@Child private MyLanguageExpressionNode rightNode;
public MyLanguageBinaryOpNode(MyLanguageExpressionNode left, MyLanguageExpressionNode right) {
this.leftNode = left;
this.rightNode = right;
}
@Override
public final Object execute(VirtualFrame frame) {
Object leftValue = leftNode.execute(frame);
Object rightValue = rightNode.execute(frame);
return execute(leftValue, rightValue);
}
protected abstract Object execute(Object left, Object right);
}
// Using loop nodes for optimized iteration
public class MyLanguageWhileNode extends MyLanguageStatementNode {
@Child private MyLanguageExpressionNode conditionNode;
@Child private LoopNode loopNode;
public MyLanguageWhileNode(MyLanguageExpressionNode condition, MyLanguageStatementNode body) {
this.conditionNode = condition;
this.loopNode = Truffle.createLoopNode(new MyLanguageWhileRepeatingNode(condition, body));
}
@Override
public Object execute(VirtualFrame frame) {
loopNode.execute(frame);
return MyLanguageNull.INSTANCE;
}
private static class MyLanguageWhileRepeatingNode extends Node implements RepeatingNode {
@Child private MyLanguageExpressionNode conditionNode;
@Child private MyLanguageStatementNode bodyNode;
@Override
public boolean executeRepeating(VirtualFrame frame) {
if (!isTruthy(conditionNode.execute(frame))) {
return false; // Exit loop
}
try {
bodyNode.execute(frame);
return true; // Continue loop
} catch (MyLanguageBreakException e) {
return false; // Break statement
}
}
}
}public interface NodeInterface {
/** Base interface implemented by all nodes */
}
public final class SourceSection {
/** Returns the source object */
public Source getSource();
/** Checks if this section is available */
public boolean isAvailable();
/** Returns the start line (1-based) */
public int getStartLine();
/** Returns the start column (1-based) */
public int getStartColumn();
/** Returns the end line (1-based) */
public int getEndLine();
/** Returns the end column (1-based) */
public int getEndColumn();
/** Returns the character index (0-based) */
public int getCharIndex();
/** Returns the character length */
public int getCharLength();
/** Returns the characters in this section */
public CharSequence getCharacters();
}
public abstract class CallTarget {
/** Calls this target with the given arguments */
public abstract Object call(Object... arguments);
}Install with Tessl CLI
npx tessl i tessl/maven-org-graalvm-truffle--truffle-runtime