Luke Wilson 2af696078d Improve Zig AST developer experience
- Convert string-based type discrimination to type-safe enums
  - ContainerKind (struct, enum, union, opaque)
  - LiteralKind (int, float, string, char)
  - LoopKind (for, while)
- Remove duplicate AST nodes (consolidated init lists, removed unused types)
- Add comprehensive helper functions for all AST constructions
- Implement formatters for all AST nodes (expressions, statements, types)
- Add typed literal constructors: IntLit, FloatLit, StringLit, CharLit
- Improve documentation and add deprecation notices

This makes the AST more intuitive and type-safe for developers.
2025-06-05 21:10:50 -05:00

544 lines
14 KiB
Go

// Abstract Syntax Tree (AST) definitions for Zig, closely following the grammar in zig-grammar.peg
package zig
// Root is the top-level node of a Zig source file.
// It represents the entire compilation unit.
type Root struct {
ContainerDocComment DocComment // Module-level doc comment using //!
ContainerMembers []*ContainerMember // Top-level declarations and fields
}
type ContainerMember struct {
DocComment DocComment // /// Doc Comment (optional)
Comptime bool // 'comptime' field (optional)
Field *ContainerField
Decl Decl // Can be nil if this is a field
}
// ContainerField represents a field in a struct/enum/union container.
type ContainerField struct {
Name string // May be empty for anonymous fields
Type TypeExpr
ByteAlign *Expr // Optional
Value Expr // Optional initializer
}
// Decl is any top-level declaration (function, variable, usingnamespace, etc).
type Decl interface {
isDecl()
}
// FnFlags is a bitfield for function declaration options.
type FnFlags uint8
const (
FnExport FnFlags = 1 << iota
FnExtern
FnInline
FnNoInline
FnThreadLocal
)
// FnDecl represents a function declaration.
type FnDecl struct {
Flags FnFlags
ExternName string // Optional string for extern
Name string // May be empty (anonymous)
Params []*ParamDecl
ByteAlign *Expr
AddrSpace *Expr
LinkSection *Expr
CallConv *Expr
ReturnType TypeExpr
Body *Block // nil means semicolon
}
func (*FnDecl) isDecl() {}
// GlobalVarFlags is a bitfield for global variable declaration options.
type GlobalVarFlags uint8
const (
GlobalVarConst GlobalVarFlags = 1 << iota
GlobalVarExport
GlobalVarExtern
GlobalVarThreadLocal
)
// GlobalVarDecl represents a top-level (global) variable or constant declaration.
// These are only allowed at the container/module scope and use a restricted syntax:
// no destructuring or multi-var declarations, just a single name and optional type/initializer.
type GlobalVarDecl struct {
Flags GlobalVarFlags
ExternName string // Optional string for extern
Name string
Type TypeExpr // Optional
ByteAlign *Expr
AddrSpace *Expr
LinkSection *Expr
Value Expr // Optional initializer
}
func (*GlobalVarDecl) isDecl() {}
// UsingNamespaceDecl represents a 'usingnamespace' declaration.
type UsingNamespaceDecl struct {
Expr Expr
}
func (*UsingNamespaceDecl) isDecl() {}
// ComptimeDecl represents a 'comptime' block at the container level.
type ComptimeDecl struct {
Block *Block
}
func (*ComptimeDecl) isDecl() {}
// TestDecl represents a 'test' declaration.
type TestDecl struct {
Name string // Optional
Block *Block
}
func (*TestDecl) isDecl() {}
// ParamDecl represents a function parameter.
type ParamDecl struct {
DocComment DocComment // /// Doc Comment (optional)
NoAlias bool
Comptime bool
Name string // May be empty
Type TypeExpr // 'anytype' if empty
}
// ContainerKind represents the kind of container (struct, enum, union, opaque).
type ContainerKind int
const (
ContainerStruct ContainerKind = iota
ContainerEnum
ContainerUnion
ContainerOpaque
)
// ContainerDecl represents a struct, enum, union, or opaque declaration.
type ContainerDecl struct {
Extern bool
Packed bool
Kind ContainerKind
TagType TypeExpr // Optional (for enum/union)
Fields []*ContainerMember
DocComment DocComment
}
func (*ContainerDecl) isDecl() {}
// ErrorSetDecl represents an error set declaration.
type ErrorSetDecl struct {
Names []string
}
func (*ErrorSetDecl) isDecl() {}
// Block represents a block of statements.
type Block struct {
Label string // Optional
Stmts []Stmt
}
// Stmt is any statement.
type Stmt interface {
isStmt()
}
// ExprStmt represents an expression statement (e.g. a function call as a statement).
type ExprStmt struct {
Expr Expr
}
func (*ExprStmt) isStmt() {}
// VarDeclStmt represents a local variable or constant declaration statement inside a function or block.
// These support destructuring and multi-var declarations, and are only valid at statement/block scope.
type VarDeclStmt struct {
Const bool
Pattern VarPattern // Destructuring or multiple variable names
Type TypeExpr // Optional
Value Expr // Optional initializer
ByteAlign Expr // Optional
AddrSpace Expr // Optional
LinkSection Expr // Optional
}
func (*VarDeclStmt) isStmt() {}
// ReturnStmt represents a 'return' statement.
type ReturnStmt struct {
Value Expr // Optional
}
func (*ReturnStmt) isStmt() {}
// IfStmt represents an if statement (with optional else branch and payload).
type IfStmt struct {
Cond Expr // Condition expression
Then Stmt // Then branch
Else Stmt // Optional else branch
Payload *Payload // Optional payload (for |x|, |*x|, |*x, y|, etc.)
}
func (*IfStmt) isStmt() {}
// IfExpr represents an if expression (with optional else branch and payload).
type IfExpr struct {
Cond Expr // Condition expression
Then Expr // Then branch
Else Expr // Optional else branch
Payload *Payload // Optional payload (for |x|, |*x|, |*x, y|, etc.)
}
// DeferStmt represents a 'defer' or 'errdefer' statement.
type DeferStmt struct {
ErrDefer bool // True for 'errdefer', false for 'defer'
Payload *Payload // Optional payload (for |x|, |*x|, etc.)
Stmt Stmt // Statement to defer
}
func (*DeferStmt) isStmt() {}
// SuspendStmt represents a 'suspend' or 'nosuspend' statement.
type SuspendStmt struct {
NoSuspend bool
Stmt Stmt
}
func (*SuspendStmt) isStmt() {}
// BlockStmt allows a block to be used as a statement.
type BlockStmt struct {
Block *Block
}
func (*BlockStmt) isStmt() {}
// BreakStmt represents a 'break' statement.
type BreakStmt struct {
Label string // Optional
Value Expr // Optional
}
func (*BreakStmt) isStmt() {}
// ContinueStmt represents a 'continue' statement.
type ContinueStmt struct {
Label string // Optional
}
func (*ContinueStmt) isStmt() {}
// LoopKind represents the kind of loop (for or while).
type LoopKind int
const (
LoopFor LoopKind = iota
LoopWhile
)
// LoopStmt represents a for/while loop statement.
type LoopStmt struct {
Inline bool // True if 'inline' is present
Kind LoopKind // For or While
Prefix LoopPrefix // ForPrefix or WhilePrefix
Body Stmt // Loop body
Else Stmt // Optional else branch
Payload *Payload // Optional payload (for |x|, |*x|, |*x, y|, etc.)
}
func (*LoopStmt) isStmt() {}
// LoopPrefix is the prefix of a for/while loop.
type LoopPrefix interface{}
// ForPrefix represents the prefix of a for loop.
type ForPrefix struct {
Args []ForArg // For loop arguments
Payload *Payload // Payload (|*x, y|, etc.)
}
// ForArg represents an argument in a for loop.
type ForArg struct {
Expr Expr // Argument expression
From Expr // Optional (for .. or ..<)
}
// WhilePrefix represents the prefix of a while loop.
type WhilePrefix struct {
Cond Expr // Condition expression
Payload *Payload // Optional payload (for |x|, |*x|, etc.)
Continue Expr // Optional (while continue expression)
}
// SwitchStmt represents a switch statement.
type SwitchStmt struct {
Cond Expr
Prongs []*SwitchProng
}
func (*SwitchStmt) isStmt() {}
// SwitchExpr represents a switch expression.
type SwitchExpr struct {
Cond Expr
Prongs []*SwitchProng
}
// SwitchProng represents a prong in a switch.
type SwitchProng struct {
Inline bool // True if 'inline' is present
Cases []*SwitchCase // List of cases for this prong
Payload *Payload // Optional payload (for |*x, y|, etc.)
Expr Expr // Result expression for this prong
}
// SwitchCase represents a case in a switch.
type SwitchCase struct {
Expr Expr
To Expr // Optional (for ..)
IsElse bool
}
// AsmExpr represents an inline assembly expression.
type AsmExpr struct {
Volatile bool
Template Expr
Outputs []*AsmOutputItem
Inputs []*AsmInputItem
Clobbers []string
}
// AsmOutputItem represents an output operand in asm.
type AsmOutputItem struct {
Name string
Constraint string
Type TypeExpr
}
// AsmInputItem represents an input operand in asm.
type AsmInputItem struct {
Name string
Constraint string
Expr Expr
}
// InitListExpr represents an initializer list.
// Exactly one of Fields, Values, or Empty must be set (non-nil/non-empty or true).
type InitListExpr struct {
Fields []*FieldInit // Field initializers (for {.foo = 1, .bar = 2}), mutually exclusive with Values/Empty
Values []Expr // Positional initializers (for {1, 2, 3}), mutually exclusive with Fields/Empty
Empty bool // True if '{}', mutually exclusive with Fields/Values
}
// FieldInit represents a field initializer in an init list.
type FieldInit struct {
Name string
Value Expr
}
// Identifier represents an identifier expression (variable, field, etc).
type Identifier struct {
Name string // The identifier name
}
// LiteralKind represents the kind of literal.
type LiteralKind int
const (
LiteralInt LiteralKind = iota
LiteralFloat
LiteralString
LiteralChar
)
// Literal represents a literal value (int, float, string, char).
type Literal struct {
Kind LiteralKind
Value string // The literal value as a string
}
// BinaryExpr represents a binary operation (e.g. +, -, *, /, etc).
type BinaryExpr struct {
Op string // Operator, e.g. "+", "-", "*", etc.
Left Expr // Left operand
Right Expr // Right operand
}
// UnaryExpr represents a unary operation (e.g. !, -, ~, etc).
type UnaryExpr struct {
Op string // Operator, e.g. "-", "!", "~"
Expr Expr // Operand
}
// GroupedExpr represents a parenthesized expression.
type GroupedExpr struct {
Expr Expr // The grouped expression
}
// CallExpr represents a function call.
type CallExpr struct {
Fun Expr // Function being called
Args []Expr // Arguments to the function
}
// FieldAccessExpr represents a field/member access as a suffix operation (e.g. foo.bar).
//
// Note: in order to call a function on an object, use a CallExpr with a Fun of a FieldAccessExpr.
// See TestHelloWorld for example.
type FieldAccessExpr struct {
Receiver Expr // The object being accessed
Field string // The field name
}
// IndexExpr represents an indexing operation as a suffix (e.g. arr[0]).
type IndexExpr struct {
Receiver Expr // The object being indexed
Index Expr // The index expression
}
// ResumeExpr represents a 'resume' expression.
type ResumeExpr struct {
Expr Expr // The expression to resume
}
// ComptimeExpr represents a 'comptime' expression.
type ComptimeExpr struct {
Expr Expr // The expression to evaluate at comptime
}
// NosuspendExpr represents a 'nosuspend' expression.
type NosuspendExpr struct {
Expr Expr // The expression to evaluate with nosuspend
}
// Expr is any expression.
// This is an empty interface to allow maximum flexibility.
// Consider using type switches when working with expressions.
type Expr interface{}
// TypeExpr is any type expression.
// This is an empty interface to allow maximum flexibility.
// Consider using type switches when working with type expressions.
type TypeExpr interface{}
// PrefixTypeExpr represents a type with a string prefix. Examples include optionals and pointers.
type PrefixTypeExpr struct {
Op string
Base TypeExpr
}
// ArrayTypeExpr represents an array type ([N]T).
type ArrayTypeExpr struct {
Size Expr
Elem TypeExpr
}
// SliceTypeExpr represents a slice type ([]T).
type SliceTypeExpr struct {
Elem TypeExpr
}
// ErrorUnionTypeExpr represents an error union type (E!T).
type ErrorUnionTypeExpr struct {
ErrSet TypeExpr
Type TypeExpr
}
// DocComment represents a doc comment (/// or //! lines).
// Newlines in the string automatically add more comments in the output.
type DocComment string
// Payload represents a control flow payload (|x|, |*x|, |*x, y|, etc).
// Each entry in Names corresponds to a variable name; the same index in Pointers is true if that name is a pointer (|*x|).
type Payload struct {
Names []string // Names in the payload, in order
Pointers []bool // True if the corresponding name is a pointer (|*x|, |*x, y|, |*x, *y|, etc.)
}
// LabeledBlock represents a labeled block or loop (label: {...}).
type LabeledBlock struct {
Label string // The label name
Block *Block // The labeled block
}
// LabeledTypeExpr represents a labeled type block (label: type).
type LabeledTypeExpr struct {
Label string // The label name
Type TypeExpr // The labeled type
}
// IfTypeExpr represents an if expression at the type level.
type IfTypeExpr struct {
Cond Expr
Then TypeExpr
Else TypeExpr // Optional
Payload *Payload // Optional
}
// ForTypeExpr represents a for expression at the type level.
type ForTypeExpr struct {
Prefix *ForPrefix
Body TypeExpr
Else TypeExpr // Optional
Payload *Payload // Optional
}
// WhileTypeExpr represents a while expression at the type level.
type WhileTypeExpr struct {
Prefix *WhilePrefix
Body TypeExpr
Else TypeExpr // Optional
Payload *Payload // Optional
}
// DotAsteriskExpr represents a .*
type DotAsteriskExpr struct {
Receiver Expr // The expression being dereferenced
}
// DotQuestionExpr represents a .?
type DotQuestionExpr struct {
Receiver Expr // The expression being checked for optional
}
// AsyncExpr represents an 'async' expression.
type AsyncExpr struct {
Expr Expr // The expression to be awaited asynchronously
}
// TryExpr represents a 'try' expression.
type TryExpr struct {
Expr Expr // The expression to try
}
// AwaitExpr represents an 'await' expression.
type AwaitExpr struct {
Expr Expr // The expression to await
}
// UnreachableExpr represents the 'unreachable' keyword.
type UnreachableExpr struct{}
// Note: The following types were removed as they were duplicates:
// - EmptyInitListExpr (use InitListExpr with Empty=true)
// - PositionalInitListExpr (use InitListExpr with Values)
// - FieldInitListExpr (use InitListExpr with Fields)
// - SwitchProngPayload (use Payload)
// - SwitchProngCase (use SwitchCase)
// - SwitchProngFull (use SwitchProng)
// - SwitchElseProng (use SwitchProng with SwitchCase.IsElse=true)
// VarPattern represents a variable pattern for destructuring or multiple variable declarations.
type VarPattern struct {
Names []string // Variable names (single or multiple for destructuring)
}