0
# Node Framework
1
2
Abstract Syntax Tree (AST) node framework providing the foundation for building executable language interpreters with support for optimization, specialization, and compilation.
3
4
## Capabilities
5
6
### Node
7
8
Base class for all AST nodes in Truffle, providing core functionality for tree structure, source attribution, and optimization support.
9
10
```java { .api }
11
/**
12
* Base class for all nodes in a Truffle AST
13
* Provides tree structure, source information, and optimization hooks
14
*/
15
public abstract class Node implements NodeInterface, Cloneable {
16
/** Returns the parent node or null for root */
17
public final Node getParent();
18
19
/** Returns all child nodes */
20
public final Iterable<Node> getChildren();
21
22
/** Replaces this node with another node */
23
public final <T extends Node> T replace(T newNode);
24
25
/** Replaces this node with another node and reason */
26
public final <T extends Node> T replace(T newNode, CharSequence reason);
27
28
/** Checks if this node can be replaced */
29
public boolean isReplaceable();
30
31
/** Returns a deep copy of this node */
32
public Node deepCopy();
33
34
/** Returns a copy of this node */
35
public Node copy();
36
37
/** Accepts a node visitor */
38
public void accept(NodeVisitor visitor);
39
40
/** Returns the source section for this node */
41
public SourceSection getSourceSection();
42
43
/** Checks if source section is available */
44
public final boolean hasSourceSection();
45
46
/** Returns a string representation of the source location */
47
public final String getSourceLocation();
48
49
/** Returns the root node of this AST */
50
public final RootNode getRootNode();
51
52
/** Returns the language info for this node's language */
53
public final LanguageInfo getLanguage();
54
55
/** Notifies that this node was adopted into an AST */
56
protected void onReplace(Node newNode, CharSequence reason) {
57
// Default implementation does nothing
58
}
59
60
/**
61
* Returns a cost estimate for this node
62
* Used by the runtime for compilation heuristics
63
*/
64
public NodeCost getCost() {
65
return NodeCost.MONOMORPHIC;
66
}
67
68
/**
69
* Returns debug information about this node
70
*/
71
protected Object getDebugProperties() {
72
return null;
73
}
74
}
75
```
76
77
### RootNode
78
79
Special node representing the root of an executable AST, serving as the entry point for method execution.
80
81
```java { .api }
82
/**
83
* Root node of a Truffle AST representing an executable unit
84
* Entry point for method/function execution
85
*/
86
public abstract class RootNode extends Node {
87
/**
88
* Executes this root node with the given frame
89
* @param frame Execution frame containing arguments and local variables
90
* @return Execution result
91
*/
92
public abstract Object execute(VirtualFrame frame);
93
94
/** Returns the language info for this root node */
95
public final LanguageInfo getLanguageInfo();
96
97
/** Returns the call target for this root node */
98
public final CallTarget getCallTarget();
99
100
/** Returns the frame descriptor for this root node */
101
public final FrameDescriptor getFrameDescriptor();
102
103
/**
104
* Returns the name of this executable unit
105
* Used for debugging and profiling
106
*/
107
public String getName() {
108
return "Unnamed";
109
}
110
111
/**
112
* Returns a qualified name including module/class information
113
*/
114
public String getQualifiedName() {
115
return getName();
116
}
117
118
/**
119
* Checks if this root node represents internal code
120
* Internal code is excluded from stack traces by default
121
*/
122
public boolean isInternal() {
123
return false;
124
}
125
126
/**
127
* Checks if this root node can be cloned for splitting
128
*/
129
public boolean isCloningAllowed() {
130
return true;
131
}
132
133
/**
134
* Creates a split version of this root node
135
*/
136
public RootNode split() {
137
return cloneUninitializedRootNode();
138
}
139
140
/**
141
* Checks if this root node represents a tail call position
142
*/
143
public boolean isTail() {
144
return true;
145
}
146
147
/**
148
* Returns debug information for this root node
149
*/
150
protected Object getDebugInfo() {
151
return null;
152
}
153
}
154
```
155
156
**Usage Examples:**
157
158
```java
159
import com.oracle.truffle.api.frame.VirtualFrame;
160
import com.oracle.truffle.api.nodes.RootNode;
161
162
public class MyLanguageFunctionRootNode extends RootNode {
163
@Child private MyLanguageStatementNode bodyNode;
164
private final String functionName;
165
166
public MyLanguageFunctionRootNode(LanguageInfo language, FrameDescriptor frameDescriptor,
167
MyLanguageStatementNode bodyNode, String functionName) {
168
super(language, frameDescriptor);
169
this.bodyNode = bodyNode;
170
this.functionName = functionName;
171
}
172
173
@Override
174
public Object execute(VirtualFrame frame) {
175
try {
176
return bodyNode.execute(frame);
177
} catch (MyLanguageReturnException returnEx) {
178
return returnEx.getReturnValue();
179
}
180
}
181
182
@Override
183
public String getName() {
184
return functionName;
185
}
186
187
@Override
188
public boolean isInternal() {
189
return functionName.startsWith("__");
190
}
191
}
192
```
193
194
### DirectCallNode
195
196
Optimized node for calling a known call target directly.
197
198
```java { .api }
199
/**
200
* Optimized call node for direct calls to a known call target
201
* Provides better performance than indirect calls when target is known
202
*/
203
public abstract class DirectCallNode extends Node {
204
/** Creates a direct call node for the given call target */
205
public static DirectCallNode create(CallTarget callTarget);
206
207
/** Calls the target with the given arguments */
208
public abstract Object call(Object... arguments);
209
210
/** Returns the call target */
211
public abstract CallTarget getCallTarget();
212
213
/**
214
* Checks if this call can be inlined
215
* Inlining provides better optimization opportunities
216
*/
217
public abstract boolean isInlinable();
218
219
/**
220
* Checks if calls should be inlined
221
* Returns true if inlining is beneficial
222
*/
223
public abstract boolean isInliningForced();
224
225
/**
226
* Forces or prevents inlining of this call
227
*/
228
public abstract void forceInlining();
229
230
/**
231
* Returns the current call target, accounting for splitting
232
*/
233
public abstract CallTarget getCurrentCallTarget();
234
235
/**
236
* Returns the original call target before any splitting
237
*/
238
public abstract CallTarget getClonedCallTarget();
239
}
240
```
241
242
### IndirectCallNode
243
244
Node for calling targets that are not known at compile time.
245
246
```java { .api }
247
/**
248
* Call node for indirect calls where target is determined at runtime
249
* Less optimized than direct calls but supports dynamic dispatch
250
*/
251
public abstract class IndirectCallNode extends Node {
252
/** Creates an indirect call node */
253
public static IndirectCallNode create();
254
255
/** Calls the given call target with arguments */
256
public abstract Object call(CallTarget callTarget, Object... arguments);
257
}
258
```
259
260
### Node Annotations and Metadata
261
262
Annotations for configuring node behavior and specialization.
263
264
```java { .api }
265
/**
266
* Marks a field as a child node
267
* Child nodes are automatically adopted and included in tree operations
268
*/
269
@Target(ElementType.FIELD)
270
@Retention(RetentionPolicy.RUNTIME)
271
public @interface Child {
272
}
273
274
/**
275
* Marks a field as containing child nodes
276
* Used for arrays or collections of child nodes
277
*/
278
@Target(ElementType.FIELD)
279
@Retention(RetentionPolicy.RUNTIME)
280
public @interface Children {
281
}
282
283
/**
284
* Node cost enumeration for optimization heuristics
285
*/
286
public enum NodeCost {
287
/** Uninitialized node - has not executed yet */
288
UNINITIALIZED,
289
290
/** Monomorphic node - handles one type efficiently */
291
MONOMORPHIC,
292
293
/** Polymorphic node - handles multiple types with some overhead */
294
POLYMORPHIC,
295
296
/** Megamorphic node - handles many types with significant overhead */
297
MEGAMORPHIC,
298
299
/** Invalid node - should be replaced */
300
INVALID
301
}
302
```
303
304
### Node Visitors and Introspection
305
306
Utilities for traversing and analyzing node trees.
307
308
```java { .api }
309
/**
310
* Visitor interface for traversing node trees
311
*/
312
public interface NodeVisitor {
313
/**
314
* Visits a node
315
* @param node The node being visited
316
* @return true to continue visiting children, false to skip
317
*/
318
boolean visit(Node node);
319
}
320
321
/**
322
* Utility class for node tree operations
323
*/
324
public final class NodeUtil {
325
/** Finds all nodes of a specific type in the tree */
326
public static <T> List<T> findAllNodeInstances(Node root, Class<T> clazz);
327
328
/** Finds the first node of a specific type */
329
public static <T> T findFirstNodeInstance(Node root, Class<T> clazz);
330
331
/** Counts nodes in the tree */
332
public static int countNodes(Node root);
333
334
/** Creates a tree representation string */
335
public static String printTreeToString(Node root);
336
337
/** Dumps the tree structure to output */
338
public static void printTree(Node root);
339
340
/** Verifies tree structure integrity */
341
public static boolean verify(Node root);
342
343
/** Returns all parent nodes up to root */
344
public static List<Node> collectParents(Node node);
345
}
346
```
347
348
### Loop Nodes
349
350
Specialized nodes for optimized loop execution.
351
352
```java { .api }
353
/**
354
* Interface for optimized loop execution
355
*/
356
public interface LoopNode extends Node.Child {
357
/** Executes the loop */
358
void execute(VirtualFrame frame);
359
360
/** Returns the repeating node executed in the loop */
361
RepeatingNode getRepeatingNode();
362
}
363
364
/**
365
* Interface for nodes that repeat in a loop
366
*/
367
public interface RepeatingNode extends Node.Child {
368
/**
369
* Executes one iteration of the loop
370
* @param frame Current execution frame
371
* @return true to continue looping, false to exit
372
*/
373
boolean executeRepeating(VirtualFrame frame);
374
}
375
376
/**
377
* Factory for creating loop nodes
378
*/
379
public final class Truffle {
380
/** Creates an optimized loop node */
381
public static LoopNode createLoopNode(RepeatingNode repeatingNode);
382
}
383
```
384
385
**Usage Examples:**
386
387
```java
388
// Creating a specialized node with child nodes
389
public abstract class MyLanguageBinaryOpNode extends MyLanguageExpressionNode {
390
@Child private MyLanguageExpressionNode leftNode;
391
@Child private MyLanguageExpressionNode rightNode;
392
393
public MyLanguageBinaryOpNode(MyLanguageExpressionNode left, MyLanguageExpressionNode right) {
394
this.leftNode = left;
395
this.rightNode = right;
396
}
397
398
@Override
399
public final Object execute(VirtualFrame frame) {
400
Object leftValue = leftNode.execute(frame);
401
Object rightValue = rightNode.execute(frame);
402
return execute(leftValue, rightValue);
403
}
404
405
protected abstract Object execute(Object left, Object right);
406
}
407
408
// Using loop nodes for optimized iteration
409
public class MyLanguageWhileNode extends MyLanguageStatementNode {
410
@Child private MyLanguageExpressionNode conditionNode;
411
@Child private LoopNode loopNode;
412
413
public MyLanguageWhileNode(MyLanguageExpressionNode condition, MyLanguageStatementNode body) {
414
this.conditionNode = condition;
415
this.loopNode = Truffle.createLoopNode(new MyLanguageWhileRepeatingNode(condition, body));
416
}
417
418
@Override
419
public Object execute(VirtualFrame frame) {
420
loopNode.execute(frame);
421
return MyLanguageNull.INSTANCE;
422
}
423
424
private static class MyLanguageWhileRepeatingNode extends Node implements RepeatingNode {
425
@Child private MyLanguageExpressionNode conditionNode;
426
@Child private MyLanguageStatementNode bodyNode;
427
428
@Override
429
public boolean executeRepeating(VirtualFrame frame) {
430
if (!isTruthy(conditionNode.execute(frame))) {
431
return false; // Exit loop
432
}
433
434
try {
435
bodyNode.execute(frame);
436
return true; // Continue loop
437
} catch (MyLanguageBreakException e) {
438
return false; // Break statement
439
}
440
}
441
}
442
}
443
```
444
445
## Common Types
446
447
```java { .api }
448
public interface NodeInterface {
449
/** Base interface implemented by all nodes */
450
}
451
452
public final class SourceSection {
453
/** Returns the source object */
454
public Source getSource();
455
456
/** Checks if this section is available */
457
public boolean isAvailable();
458
459
/** Returns the start line (1-based) */
460
public int getStartLine();
461
462
/** Returns the start column (1-based) */
463
public int getStartColumn();
464
465
/** Returns the end line (1-based) */
466
public int getEndLine();
467
468
/** Returns the end column (1-based) */
469
public int getEndColumn();
470
471
/** Returns the character index (0-based) */
472
public int getCharIndex();
473
474
/** Returns the character length */
475
public int getCharLength();
476
477
/** Returns the characters in this section */
478
public CharSequence getCharacters();
479
}
480
481
public abstract class CallTarget {
482
/** Calls this target with the given arguments */
483
public abstract Object call(Object... arguments);
484
}
485
```