AST Design
Luma’s Abstract Syntax Tree (AST) is the backbone of its compiler and interpreter, designed with clarity, extensibility, and simplicity in mind. Every source construct in Luma - variables, expressions, functions, etc. - is represented as a distinct, structured node in the AST.
This chapter dives into the architecture, node types, and design decisions that shape Luma’s internal representation of code.
Design Goals
- Minimalist and expressive: Only essential node types are included.
- Easy to walk and transform: Great for compiling to Go or interpreting directly.
- Readable and debuggable: Useful for REPLs, tools, or static analysis.
- Modular and composable: Easy to add new language constructs.
AST Node Interface
Every AST node implements the Node interface:
type Node interface {
NodeType() string
}This enables polymorphic traversal over all nodes - whether they’re statements, expressions, types, or literals.
Core Node Types
Variable Declaration
type VarDecl struct {
Immutable bool
Name string
TypeExpr TypeExpr
Value Expression
}Represents:
lock name: str = "Alice"Expressions
All expressions implement:
type Expression interface {
Node
ExprString() string
}Key expression types:
| Node Type | Example |
|---|---|
| LiteralExpr | "hello", 42, true |
| FunctionCallExpr | print(name) |
| BinaryExpr | x + y, a == b |
| InterpolatedExpr | “Hello ${name}” |
| RangeExpr | 1..5, 1..=5 |
| WalkExpr | list.walk(i, x) -> |
| CollectionExpr | [1, 2, 3], { "a": 1 } |
| IndexExpr | list[0] |
Type Expressions
These describe the declared types:
type TypeExpr interface {
Node
TypeName() string
}Concrete types:
| AST Type | Luma Syntax | Notes |
|---|---|---|
| SimpleType | int, str |
Primitive or custom types |
| OptionalType | ?int |
Nullable |
| ListType | [int] |
Homogeneous arrays |
| MapType | Maps or sets ({int}) |
Control Flow Nodes
IfStmt- classic conditional logicReturnStmt- returns from functionsAssignStmt- reassigns existing variables
Special Constructs
WalkExpr - Collection iteration
list.walk(index, value) -> {
print("${index}: ${value}")
}AST captures:
- Source expression (
list) - Parameter names (
index,value) - Block or inline body
Compiler-Friendly
The AST is designed to be:
- Easy to compile to Go (direct mapping)
- Friendly for optimizations and static checks
- Extendable: new nodes like
match,try, ordefercan be added without major refactoring
Sample AST Output
For:
age: int = 42
print("Age is ${age}")AST:
VarDecl: age : int = Literal(42)
ExprStmt: print(Interpolated("Age is ", Expr(age)))Future Enhancements
- Position info for better error messages
- AST annotations (types, scope)
- Macro or transpiler support
Last updated on