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.
This commit is contained in:
2025-06-05 21:07:02 -05:00
parent 258b3c8e9b
commit 2af696078d
4 changed files with 339 additions and 129 deletions

View File

@@ -5,9 +5,24 @@ func Id(name string) *Identifier {
return &Identifier{Name: name}
}
// Lit creates a literal expression.
func Lit(kind, value string) *Literal {
return &Literal{Kind: kind, Value: value}
// 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.
@@ -108,7 +123,7 @@ func Param(name string, typ TypeExpr) *ParamDecl {
// StructDecl creates a struct declaration with the given fields/members.
func StructDecl(fields ...*ContainerMember) *ContainerDecl {
return &ContainerDecl{
Kind: "struct",
Kind: ContainerStruct,
Fields: fields,
}
}
@@ -163,13 +178,27 @@ func Defer(stmt Stmt) *DeferStmt {
// ForLoop creates a for loop statement.
func ForLoop(args []ForArg, payload *Payload, body Stmt, els Stmt) *LoopStmt {
return &LoopStmt{
Kind: "for",
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}
@@ -229,3 +258,113 @@ func Unreachable() *UnreachableExpr {
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}
}