- 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.
544 lines
14 KiB
Go
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)
|
|
}
|