go-zig-compiler/internal/zig/asthelpers.go
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

371 lines
9.7 KiB
Go

package zig
// Id creates an identifier expression.
func Id(name string) *Identifier {
return &Identifier{Name: name}
}
// IntLit creates an integer literal.
func IntLit(value string) *Literal {
return &Literal{Kind: LiteralInt, Value: value}
}
// FloatLit creates a float literal.
func FloatLit(value string) *Literal {
return &Literal{Kind: LiteralFloat, Value: value}
}
// StringLit creates a string literal.
func StringLit(value string) *Literal {
return &Literal{Kind: LiteralString, Value: value}
}
// CharLit creates a character literal.
func CharLit(value string) *Literal {
return &Literal{Kind: LiteralChar, Value: value}
}
// FieldAccess creates a field access expression.
func FieldAccess(recv Expr, field string) *FieldAccessExpr {
return &FieldAccessExpr{Receiver: recv, Field: field}
}
// Call creates a function call expression.
func Call(fun Expr, args ...Expr) *CallExpr {
return &CallExpr{Fun: fun, Args: args}
}
// InitList creates an initializer list expression.
func InitList(exprs ...Expr) *InitListExpr {
if len(exprs) == 0 {
return &InitListExpr{Empty: true}
}
return &InitListExpr{Values: exprs}
}
// DeclareFn creates a function declaration with flags.
func DeclareFn(name string, retType TypeExpr, body *Block, params []*ParamDecl, flags FnFlags) *FnDecl {
return &FnDecl{
Name: name,
ReturnType: retType,
Body: body,
Flags: flags,
Params: params,
}
}
// NewExprStmt creates an expression statement.
func NewExprStmt(expr Expr) *ExprStmt {
return &ExprStmt{Expr: expr}
}
// DeclareVarStmt creates a variable or const declaration statement.
func DeclareVarStmt(constant bool, names []string, typ TypeExpr, value Expr) *VarDeclStmt {
return &VarDeclStmt{
Const: constant,
Pattern: VarPattern{Names: names},
Type: typ,
Value: value,
}
}
// DeclareGlobalVar creates a global variable declaration with flags.
func DeclareGlobalVar(name string, value Expr, flags GlobalVarFlags) *GlobalVarDecl {
return &GlobalVarDecl{
Flags: flags,
Name: name,
Value: value,
}
}
// Return creates a return statement.
func Return(value Expr) *ReturnStmt {
return &ReturnStmt{Value: value}
}
// If creates an if statement.
func If(cond Expr, then, els Stmt) *IfStmt {
return &IfStmt{Cond: cond, Then: then, Else: els}
}
// IfWithPayload creates an if statement with a payload.
func IfWithPayload(cond Expr, payload *Payload, then, els Stmt) *IfStmt {
return &IfStmt{Cond: cond, Payload: payload, Then: then, Else: els}
}
// NewBlock creates a block of statements.
func NewBlock(stmts ...Stmt) *Block {
return &Block{Stmts: stmts}
}
// NewBlock creates a block statement containing a block of statements.
func NewBlockStmt(stmts ...Stmt) *BlockStmt {
return &BlockStmt{
Block: &Block{Stmts: stmts},
}
}
// Try creates a try expression.
func Try(expr Expr) *TryExpr {
return &TryExpr{Expr: expr}
}
// Binary creates a binary expression.
func Binary(op string, left, right Expr) *BinaryExpr {
return &BinaryExpr{Op: op, Left: left, Right: right}
}
// Param creates a function parameter declaration.
func Param(name string, typ TypeExpr) *ParamDecl {
return &ParamDecl{Name: name, Type: typ}
}
// StructDecl creates a struct declaration with the given fields/members.
func StructDecl(fields ...*ContainerMember) *ContainerDecl {
return &ContainerDecl{
Kind: ContainerStruct,
Fields: fields,
}
}
// Field creates a struct field (optionally with initializer).
func Field(name string, typ TypeExpr, byteAlign *Expr, value Expr) *ContainerMember {
return &ContainerMember{
Field: &ContainerField{
Name: name,
Type: typ,
ByteAlign: byteAlign,
Value: value,
},
}
}
// Method creates a method (function declaration) as a struct member.
func Method(fn *FnDecl) *ContainerMember {
return &ContainerMember{Decl: fn}
}
// OptionalType creates an optional type (?T).
func OptionalType(base TypeExpr) *PrefixTypeExpr {
return &PrefixTypeExpr{Op: "?", Base: base}
}
// PointerType creates a pointer type (*T).
func PointerType(base TypeExpr) *PrefixTypeExpr {
return &PrefixTypeExpr{Op: "*", Base: base}
}
// ArrayType creates an array type ([N]T).
func ArrayType(size Expr, elem TypeExpr) *ArrayTypeExpr {
return &ArrayTypeExpr{Size: size, Elem: elem}
}
// ErrorSet creates an error set declaration.
func ErrorSet(names ...string) *ErrorSetDecl {
return &ErrorSetDecl{Names: names}
}
// ErrorUnionType creates an error union type (E!T).
func ErrorUnionType(errSet, typ TypeExpr) *ErrorUnionTypeExpr {
return &ErrorUnionTypeExpr{ErrSet: errSet, Type: typ}
}
// DeferStmt creates a defer statement.
func Defer(stmt Stmt) *DeferStmt {
return &DeferStmt{Stmt: stmt}
}
// ForLoop creates a for loop statement.
func ForLoop(args []ForArg, payload *Payload, body Stmt, els Stmt) *LoopStmt {
return &LoopStmt{
Kind: LoopFor,
Prefix: &ForPrefix{Args: args, Payload: payload},
Body: body,
Else: els,
}
}
// WhileLoop creates a while loop statement.
func WhileLoop(cond Expr, continueExpr Expr, payload *Payload, body Stmt, els Stmt) *LoopStmt {
return &LoopStmt{
Kind: LoopWhile,
Prefix: &WhilePrefix{
Cond: cond,
Continue: continueExpr,
Payload: payload,
},
Body: body,
Else: els,
}
}
// ForArg creates a for loop argument.
func ForArgExpr(expr Expr) ForArg {
return ForArg{Expr: expr}
}
// Payload creates a payload for control flow.
func PayloadNames(names []string, pointers []bool) *Payload {
return &Payload{Names: names, Pointers: pointers}
}
// SwitchStmt creates a switch statement.
func Switch(cond Expr, prongs ...*SwitchProng) *SwitchStmt {
return &SwitchStmt{Cond: cond, Prongs: prongs}
}
// SwitchProng creates a switch prong.
func Prong(cases []*SwitchCase, payload *Payload, expr Expr) *SwitchProng {
return &SwitchProng{Cases: cases, Payload: payload, Expr: expr}
}
// SwitchCase creates a switch case.
func Case(expr Expr, to Expr) *SwitchCase {
return &SwitchCase{Expr: expr, To: to}
}
// ElseCase creates an else case for a switch.
func ElseCase() *SwitchCase {
return &SwitchCase{IsElse: true}
}
// BreakStmt creates a break statement.
func Break(label string, value Expr) *BreakStmt {
return &BreakStmt{Label: label, Value: value}
}
// ContinueStmt creates a continue statement.
func Continue(label string) *ContinueStmt {
return &ContinueStmt{Label: label}
}
// UnaryExpr creates a unary expression.
func Unary(op string, expr Expr) *UnaryExpr {
return &UnaryExpr{Op: op, Expr: expr}
}
// IndexExpr creates an index expression.
func Index(receiver, index Expr) *IndexExpr {
return &IndexExpr{Receiver: receiver, Index: index}
}
// UnreachableExpr creates an unreachable expression.
func Unreachable() *UnreachableExpr {
return &UnreachableExpr{}
}
// TestDecl creates a test declaration.
func Test(name string, block *Block) *TestDecl {
return &TestDecl{Name: name, Block: block}
}
// GroupedExpr creates a grouped (parenthesized) expression.
func Grouped(expr Expr) *GroupedExpr {
return &GroupedExpr{Expr: expr}
}
// ComptimeExpr creates a comptime expression.
func Comptime(expr Expr) *ComptimeExpr {
return &ComptimeExpr{Expr: expr}
}
// NosuspendExpr creates a nosuspend expression.
func Nosuspend(expr Expr) *NosuspendExpr {
return &NosuspendExpr{Expr: expr}
}
// SliceType creates a slice type ([]T).
func SliceType(elem TypeExpr) *SliceTypeExpr {
return &SliceTypeExpr{Elem: elem}
}
// IfExpression creates an if expression.
func IfExpression(cond Expr, then, els Expr) *IfExpr {
return &IfExpr{Cond: cond, Then: then, Else: els}
}
// IfExpressionWithPayload creates an if expression with a payload.
func IfExpressionWithPayload(cond Expr, payload *Payload, then, els Expr) *IfExpr {
return &IfExpr{Cond: cond, Payload: payload, Then: then, Else: els}
}
// SwitchExpression creates a switch expression.
func SwitchExpression(cond Expr, prongs ...*SwitchProng) *SwitchExpr {
return &SwitchExpr{Cond: cond, Prongs: prongs}
}
// EnumDecl creates an enum declaration.
func EnumDecl(tagType TypeExpr, fields ...*ContainerMember) *ContainerDecl {
return &ContainerDecl{
Kind: ContainerEnum,
TagType: tagType,
Fields: fields,
}
}
// UnionDecl creates a union declaration.
func UnionDecl(tagType TypeExpr, fields ...*ContainerMember) *ContainerDecl {
return &ContainerDecl{
Kind: ContainerUnion,
TagType: tagType,
Fields: fields,
}
}
// OpaqueDecl creates an opaque declaration.
func OpaqueDecl() *ContainerDecl {
return &ContainerDecl{
Kind: ContainerOpaque,
}
}
// AsyncExpr creates an async expression.
func Async(expr Expr) *AsyncExpr {
return &AsyncExpr{Expr: expr}
}
// AwaitExpr creates an await expression.
func Await(expr Expr) *AwaitExpr {
return &AwaitExpr{Expr: expr}
}
// ResumeExpr creates a resume expression.
func Resume(expr Expr) *ResumeExpr {
return &ResumeExpr{Expr: expr}
}
// DotAsterisk creates a .* expression (pointer dereference).
func DotAsterisk(receiver Expr) *DotAsteriskExpr {
return &DotAsteriskExpr{Receiver: receiver}
}
// DotQuestion creates a .? expression (optional unwrap).
func DotQuestion(receiver Expr) *DotQuestionExpr {
return &DotQuestionExpr{Receiver: receiver}
}
// ErrDefer creates an errdefer statement.
func ErrDefer(payload *Payload, stmt Stmt) *DeferStmt {
return &DeferStmt{ErrDefer: true, Payload: payload, Stmt: stmt}
}
// UsingNamespace creates a usingnamespace declaration.
func UsingNamespace(expr Expr) *UsingNamespaceDecl {
return &UsingNamespaceDecl{Expr: expr}
}
// ComptimeBlock creates a comptime block declaration.
func ComptimeBlock(block *Block) *ComptimeDecl {
return &ComptimeDecl{Block: block}
}
// InitListFields creates an init list with field initializers.
func InitListFields(fields ...*FieldInit) *InitListExpr {
return &InitListExpr{Fields: fields}
}
// FieldInitPair creates a field initializer.
func FieldInitPair(name string, value Expr) *FieldInit {
return &FieldInit{Name: name, Value: value}
}