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:
parent
258b3c8e9b
commit
2af696078d
@ -2,9 +2,10 @@
|
|||||||
package zig
|
package zig
|
||||||
|
|
||||||
// Root is the top-level node of a Zig source file.
|
// Root is the top-level node of a Zig source file.
|
||||||
|
// It represents the entire compilation unit.
|
||||||
type Root struct {
|
type Root struct {
|
||||||
ContainerDocComment DocComment // //! Doc Comment (optional)
|
ContainerDocComment DocComment // Module-level doc comment using //!
|
||||||
ContainerMembers []*ContainerMember
|
ContainerMembers []*ContainerMember // Top-level declarations and fields
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContainerMember struct {
|
type ContainerMember struct {
|
||||||
@ -111,11 +112,21 @@ type ParamDecl struct {
|
|||||||
Type TypeExpr // 'anytype' if 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.
|
// ContainerDecl represents a struct, enum, union, or opaque declaration.
|
||||||
type ContainerDecl struct {
|
type ContainerDecl struct {
|
||||||
Extern bool
|
Extern bool
|
||||||
Packed bool
|
Packed bool
|
||||||
Kind string // "struct", "enum", "union", "opaque"
|
Kind ContainerKind
|
||||||
TagType TypeExpr // Optional (for enum/union)
|
TagType TypeExpr // Optional (for enum/union)
|
||||||
Fields []*ContainerMember
|
Fields []*ContainerMember
|
||||||
DocComment DocComment
|
DocComment DocComment
|
||||||
@ -226,10 +237,18 @@ type ContinueStmt struct {
|
|||||||
|
|
||||||
func (*ContinueStmt) isStmt() {}
|
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.
|
// LoopStmt represents a for/while loop statement.
|
||||||
type LoopStmt struct {
|
type LoopStmt struct {
|
||||||
Inline bool // True if 'inline' is present
|
Inline bool // True if 'inline' is present
|
||||||
Kind string // "for" or "while"
|
Kind LoopKind // For or While
|
||||||
Prefix LoopPrefix // ForPrefix or WhilePrefix
|
Prefix LoopPrefix // ForPrefix or WhilePrefix
|
||||||
Body Stmt // Loop body
|
Body Stmt // Loop body
|
||||||
Else Stmt // Optional else branch
|
Else Stmt // Optional else branch
|
||||||
@ -331,9 +350,19 @@ type Identifier struct {
|
|||||||
Name string // The identifier name
|
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).
|
// Literal represents a literal value (int, float, string, char).
|
||||||
type Literal struct {
|
type Literal struct {
|
||||||
Kind string // "int", "float", "string", "char"
|
Kind LiteralKind
|
||||||
Value string // The literal value as a string
|
Value string // The literal value as a string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,15 +420,14 @@ type NosuspendExpr struct {
|
|||||||
Expr Expr // The expression to evaluate with nosuspend
|
Expr Expr // The expression to evaluate with nosuspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContinueExpr represents a 'continue' expression.
|
|
||||||
type ContinueExpr struct {
|
|
||||||
Label string // Optional label
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expr is any expression.
|
// Expr is any expression.
|
||||||
|
// This is an empty interface to allow maximum flexibility.
|
||||||
|
// Consider using type switches when working with expressions.
|
||||||
type Expr interface{}
|
type Expr interface{}
|
||||||
|
|
||||||
// TypeExpr is any type expression.
|
// 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{}
|
type TypeExpr interface{}
|
||||||
|
|
||||||
// PrefixTypeExpr represents a type with a string prefix. Examples include optionals and pointers.
|
// PrefixTypeExpr represents a type with a string prefix. Examples include optionals and pointers.
|
||||||
@ -500,43 +528,14 @@ type AwaitExpr struct {
|
|||||||
// UnreachableExpr represents the 'unreachable' keyword.
|
// UnreachableExpr represents the 'unreachable' keyword.
|
||||||
type UnreachableExpr struct{}
|
type UnreachableExpr struct{}
|
||||||
|
|
||||||
// EmptyInitListExpr represents an empty initializer list '{}'.
|
// Note: The following types were removed as they were duplicates:
|
||||||
type EmptyInitListExpr struct{}
|
// - EmptyInitListExpr (use InitListExpr with Empty=true)
|
||||||
|
// - PositionalInitListExpr (use InitListExpr with Values)
|
||||||
// PositionalInitListExpr represents a positional initializer list '{expr, ...}'.
|
// - FieldInitListExpr (use InitListExpr with Fields)
|
||||||
type PositionalInitListExpr struct {
|
// - SwitchProngPayload (use Payload)
|
||||||
Values []Expr // Expressions in order
|
// - SwitchProngCase (use SwitchCase)
|
||||||
}
|
// - SwitchProngFull (use SwitchProng)
|
||||||
|
// - SwitchElseProng (use SwitchProng with SwitchCase.IsElse=true)
|
||||||
// FieldInitListExpr represents a field initializer list '{.field = expr, ...}'.
|
|
||||||
type FieldInitListExpr struct {
|
|
||||||
Fields []*FieldInit // Field initializers
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwitchProngPayload represents a switch prong payload (|*x, y|).
|
|
||||||
type SwitchProngPayload struct {
|
|
||||||
Pointer bool
|
|
||||||
Names []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwitchProngCase represents a single case in a switch prong.
|
|
||||||
type SwitchProngCase struct {
|
|
||||||
Expr Expr // The case expression
|
|
||||||
To Expr // Optional, for ranges
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwitchProngFull represents a full switch prong with cases and payload.
|
|
||||||
type SwitchProngFull struct {
|
|
||||||
Inline bool
|
|
||||||
Cases []*SwitchProngCase // One or more cases
|
|
||||||
Payload *SwitchProngPayload // Optional
|
|
||||||
Expr Expr // The result expression
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwitchElseProng represents an 'else' prong in a switch.
|
|
||||||
type SwitchElseProng struct {
|
|
||||||
Expr Expr // The result expression
|
|
||||||
}
|
|
||||||
|
|
||||||
// VarPattern represents a variable pattern for destructuring or multiple variable declarations.
|
// VarPattern represents a variable pattern for destructuring or multiple variable declarations.
|
||||||
type VarPattern struct {
|
type VarPattern struct {
|
||||||
|
@ -5,9 +5,24 @@ func Id(name string) *Identifier {
|
|||||||
return &Identifier{Name: name}
|
return &Identifier{Name: name}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lit creates a literal expression.
|
// IntLit creates an integer literal.
|
||||||
func Lit(kind, value string) *Literal {
|
func IntLit(value string) *Literal {
|
||||||
return &Literal{Kind: kind, Value: value}
|
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.
|
// 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.
|
// StructDecl creates a struct declaration with the given fields/members.
|
||||||
func StructDecl(fields ...*ContainerMember) *ContainerDecl {
|
func StructDecl(fields ...*ContainerMember) *ContainerDecl {
|
||||||
return &ContainerDecl{
|
return &ContainerDecl{
|
||||||
Kind: "struct",
|
Kind: ContainerStruct,
|
||||||
Fields: fields,
|
Fields: fields,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,13 +178,27 @@ func Defer(stmt Stmt) *DeferStmt {
|
|||||||
// ForLoop creates a for loop statement.
|
// ForLoop creates a for loop statement.
|
||||||
func ForLoop(args []ForArg, payload *Payload, body Stmt, els Stmt) *LoopStmt {
|
func ForLoop(args []ForArg, payload *Payload, body Stmt, els Stmt) *LoopStmt {
|
||||||
return &LoopStmt{
|
return &LoopStmt{
|
||||||
Kind: "for",
|
Kind: LoopFor,
|
||||||
Prefix: &ForPrefix{Args: args, Payload: payload},
|
Prefix: &ForPrefix{Args: args, Payload: payload},
|
||||||
Body: body,
|
Body: body,
|
||||||
Else: els,
|
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.
|
// ForArg creates a for loop argument.
|
||||||
func ForArgExpr(expr Expr) ForArg {
|
func ForArgExpr(expr Expr) ForArg {
|
||||||
return ForArg{Expr: expr}
|
return ForArg{Expr: expr}
|
||||||
@ -229,3 +258,113 @@ func Unreachable() *UnreachableExpr {
|
|||||||
func Test(name string, block *Block) *TestDecl {
|
func Test(name string, block *Block) *TestDecl {
|
||||||
return &TestDecl{Name: name, Block: block}
|
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}
|
||||||
|
}
|
||||||
|
@ -119,6 +119,14 @@ func writeDecl(f *formatter, decl Decl) {
|
|||||||
}
|
}
|
||||||
writeBlock(f, d.Block)
|
writeBlock(f, d.Block)
|
||||||
f.writef("\n")
|
f.writef("\n")
|
||||||
|
case *UsingNamespaceDecl:
|
||||||
|
f.writef("usingnamespace ")
|
||||||
|
writeExpr(f, d.Expr)
|
||||||
|
f.writef(";\n")
|
||||||
|
case *ComptimeDecl:
|
||||||
|
f.writef("comptime")
|
||||||
|
writeBlock(f, d.Block)
|
||||||
|
f.writef("\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +156,9 @@ func writeTypeExpr(f *formatter, typ TypeExpr) {
|
|||||||
writeExpr(f, t.Size)
|
writeExpr(f, t.Size)
|
||||||
f.writef("]")
|
f.writef("]")
|
||||||
writeTypeExpr(f, t.Elem)
|
writeTypeExpr(f, t.Elem)
|
||||||
|
case *SliceTypeExpr:
|
||||||
|
f.writef("[]")
|
||||||
|
writeTypeExpr(f, t.Elem)
|
||||||
case *ErrorUnionTypeExpr:
|
case *ErrorUnionTypeExpr:
|
||||||
writeTypeExpr(f, t.ErrSet)
|
writeTypeExpr(f, t.ErrSet)
|
||||||
f.writef("!")
|
f.writef("!")
|
||||||
@ -217,7 +228,7 @@ func writeStmt(f *formatter, stmt Stmt) {
|
|||||||
f.writef("if (")
|
f.writef("if (")
|
||||||
writeExpr(f, s.Cond)
|
writeExpr(f, s.Cond)
|
||||||
f.writef(")")
|
f.writef(")")
|
||||||
|
|
||||||
// Handle payload if present
|
// Handle payload if present
|
||||||
if s.Payload != nil {
|
if s.Payload != nil {
|
||||||
f.writef(" ")
|
f.writef(" ")
|
||||||
@ -241,7 +252,7 @@ func writeStmt(f *formatter, stmt Stmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *LoopStmt:
|
case *LoopStmt:
|
||||||
if s.Kind == "while" {
|
if s.Kind == LoopWhile {
|
||||||
f.writef("while (")
|
f.writef("while (")
|
||||||
if wp, ok := s.Prefix.(*WhilePrefix); ok {
|
if wp, ok := s.Prefix.(*WhilePrefix); ok {
|
||||||
writeExpr(f, wp.Cond)
|
writeExpr(f, wp.Cond)
|
||||||
@ -258,7 +269,7 @@ func writeStmt(f *formatter, stmt Stmt) {
|
|||||||
f.writef(" ")
|
f.writef(" ")
|
||||||
writeStmt(f, s.Body)
|
writeStmt(f, s.Body)
|
||||||
}
|
}
|
||||||
} else if s.Kind == "for" {
|
} else if s.Kind == LoopFor {
|
||||||
f.writef("for (")
|
f.writef("for (")
|
||||||
if fp, ok := s.Prefix.(*ForPrefix); ok {
|
if fp, ok := s.Prefix.(*ForPrefix); ok {
|
||||||
for i, arg := range fp.Args {
|
for i, arg := range fp.Args {
|
||||||
@ -289,45 +300,45 @@ func writeStmt(f *formatter, stmt Stmt) {
|
|||||||
writeStmt(f, s.Body)
|
writeStmt(f, s.Body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *DeferStmt:
|
case *DeferStmt:
|
||||||
if s.ErrDefer {
|
if s.ErrDefer {
|
||||||
f.writef("errdefer")
|
f.writef("errdefer")
|
||||||
} else {
|
} else {
|
||||||
f.writef("defer")
|
f.writef("defer")
|
||||||
}
|
|
||||||
f.writef(" ")
|
|
||||||
writeStmt(f, s.Stmt)
|
|
||||||
case *BreakStmt:
|
|
||||||
f.writef("break")
|
|
||||||
if s.Label != "" {
|
|
||||||
f.writef(" :%s", s.Label)
|
|
||||||
}
|
|
||||||
if s.Value != nil {
|
|
||||||
f.writef(" ")
|
|
||||||
writeExpr(f, s.Value)
|
|
||||||
}
|
|
||||||
f.writef(";")
|
|
||||||
case *ContinueStmt:
|
|
||||||
f.writef("continue")
|
|
||||||
if s.Label != "" {
|
|
||||||
f.writef(" :%s", s.Label)
|
|
||||||
}
|
|
||||||
f.writef(";")
|
|
||||||
case *SwitchStmt:
|
|
||||||
f.writef("switch (")
|
|
||||||
writeExpr(f, s.Cond)
|
|
||||||
f.writef(") {\n")
|
|
||||||
f.indent++
|
|
||||||
for _, prong := range s.Prongs {
|
|
||||||
f.writeIndent()
|
|
||||||
writeSwitchProng(f, prong)
|
|
||||||
f.writef("\n")
|
|
||||||
}
|
|
||||||
f.indent--
|
|
||||||
f.writeIndent()
|
|
||||||
f.writef("}")
|
|
||||||
}
|
}
|
||||||
|
f.writef(" ")
|
||||||
|
writeStmt(f, s.Stmt)
|
||||||
|
case *BreakStmt:
|
||||||
|
f.writef("break")
|
||||||
|
if s.Label != "" {
|
||||||
|
f.writef(" :%s", s.Label)
|
||||||
|
}
|
||||||
|
if s.Value != nil {
|
||||||
|
f.writef(" ")
|
||||||
|
writeExpr(f, s.Value)
|
||||||
|
}
|
||||||
|
f.writef(";")
|
||||||
|
case *ContinueStmt:
|
||||||
|
f.writef("continue")
|
||||||
|
if s.Label != "" {
|
||||||
|
f.writef(" :%s", s.Label)
|
||||||
|
}
|
||||||
|
f.writef(";")
|
||||||
|
case *SwitchStmt:
|
||||||
|
f.writef("switch (")
|
||||||
|
writeExpr(f, s.Cond)
|
||||||
|
f.writef(") {\n")
|
||||||
|
f.indent++
|
||||||
|
for _, prong := range s.Prongs {
|
||||||
|
f.writeIndent()
|
||||||
|
writeSwitchProng(f, prong)
|
||||||
|
f.writef("\n")
|
||||||
|
}
|
||||||
|
f.indent--
|
||||||
|
f.writeIndent()
|
||||||
|
f.writef("}")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// writePayload emits a payload (|x|, |*x|, |*x, y|, etc).
|
// writePayload emits a payload (|x|, |*x|, |*x, y|, etc).
|
||||||
func writePayload(f *formatter, payload *Payload) {
|
func writePayload(f *formatter, payload *Payload) {
|
||||||
@ -431,7 +442,7 @@ func writeExpr(f *formatter, expr Expr) {
|
|||||||
f.writef(".%s", e.Field)
|
f.writef(".%s", e.Field)
|
||||||
case *Literal:
|
case *Literal:
|
||||||
switch e.Kind {
|
switch e.Kind {
|
||||||
case "string":
|
case LiteralString:
|
||||||
f.writef(`"%v"`, e.Value)
|
f.writef(`"%v"`, e.Value)
|
||||||
default:
|
default:
|
||||||
f.writef("%v", e.Value)
|
f.writef("%v", e.Value)
|
||||||
@ -456,11 +467,21 @@ func writeExpr(f *formatter, expr Expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ContainerDecl:
|
case *ContainerDecl:
|
||||||
if e.Kind == "struct" {
|
switch e.Kind {
|
||||||
|
case ContainerStruct:
|
||||||
f.writef("struct ")
|
f.writef("struct ")
|
||||||
writeStructBody(f, e)
|
writeStructBody(f, e)
|
||||||
} else {
|
case ContainerEnum:
|
||||||
panic("not implemented: " + e.Kind)
|
f.writef("enum ")
|
||||||
|
writeStructBody(f, e)
|
||||||
|
case ContainerUnion:
|
||||||
|
f.writef("union ")
|
||||||
|
writeStructBody(f, e)
|
||||||
|
case ContainerOpaque:
|
||||||
|
f.writef("opaque ")
|
||||||
|
writeStructBody(f, e)
|
||||||
|
default:
|
||||||
|
panic("unknown container kind")
|
||||||
}
|
}
|
||||||
case *TryExpr:
|
case *TryExpr:
|
||||||
f.writef("try ")
|
f.writef("try ")
|
||||||
@ -489,6 +510,58 @@ func writeExpr(f *formatter, expr Expr) {
|
|||||||
f.indent--
|
f.indent--
|
||||||
f.writeIndent()
|
f.writeIndent()
|
||||||
f.writef("}")
|
f.writef("}")
|
||||||
|
case *GroupedExpr:
|
||||||
|
f.writef("(")
|
||||||
|
writeExpr(f, e.Expr)
|
||||||
|
f.writef(")")
|
||||||
|
case *ComptimeExpr:
|
||||||
|
f.writef("comptime ")
|
||||||
|
writeExpr(f, e.Expr)
|
||||||
|
case *NosuspendExpr:
|
||||||
|
f.writef("nosuspend ")
|
||||||
|
writeExpr(f, e.Expr)
|
||||||
|
case *AsyncExpr:
|
||||||
|
f.writef("async ")
|
||||||
|
writeExpr(f, e.Expr)
|
||||||
|
case *AwaitExpr:
|
||||||
|
f.writef("await ")
|
||||||
|
writeExpr(f, e.Expr)
|
||||||
|
case *ResumeExpr:
|
||||||
|
f.writef("resume ")
|
||||||
|
writeExpr(f, e.Expr)
|
||||||
|
case *DotAsteriskExpr:
|
||||||
|
writeExpr(f, e.Receiver)
|
||||||
|
f.writef(".*")
|
||||||
|
case *DotQuestionExpr:
|
||||||
|
writeExpr(f, e.Receiver)
|
||||||
|
f.writef(".?")
|
||||||
|
case *IfExpr:
|
||||||
|
f.writef("if (")
|
||||||
|
writeExpr(f, e.Cond)
|
||||||
|
f.writef(")")
|
||||||
|
if e.Payload != nil {
|
||||||
|
f.writef(" ")
|
||||||
|
writePayload(f, e.Payload)
|
||||||
|
}
|
||||||
|
f.writef(" ")
|
||||||
|
writeExpr(f, e.Then)
|
||||||
|
if e.Else != nil {
|
||||||
|
f.writef(" else ")
|
||||||
|
writeExpr(f, e.Else)
|
||||||
|
}
|
||||||
|
case *SwitchExpr:
|
||||||
|
f.writef("switch (")
|
||||||
|
writeExpr(f, e.Cond)
|
||||||
|
f.writef(") {\n")
|
||||||
|
f.indent++
|
||||||
|
for _, prong := range e.Prongs {
|
||||||
|
f.writeIndent()
|
||||||
|
writeSwitchProng(f, prong)
|
||||||
|
f.writef("\n")
|
||||||
|
}
|
||||||
|
f.indent--
|
||||||
|
f.writeIndent()
|
||||||
|
f.writef("}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ fn main() void {
|
|||||||
{
|
{
|
||||||
Decl: zig.DeclareGlobalVar("std", zig.Call(
|
Decl: zig.DeclareGlobalVar("std", zig.Call(
|
||||||
zig.Id("@import"),
|
zig.Id("@import"),
|
||||||
zig.Lit("string", "std"),
|
zig.StringLit("std"),
|
||||||
), zig.GlobalVarConst),
|
), zig.GlobalVarConst),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -77,7 +77,7 @@ fn main() void {
|
|||||||
zig.FieldAccess(zig.Id("std"), "debug"),
|
zig.FieldAccess(zig.Id("std"), "debug"),
|
||||||
"print",
|
"print",
|
||||||
),
|
),
|
||||||
zig.Lit("string", `Hello, world!\n`),
|
zig.StringLit(`Hello, world!\n`),
|
||||||
zig.InitList(),
|
zig.InitList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -144,7 +144,7 @@ test "processData" {
|
|||||||
zig.ErrorUnionType(zig.Id("ProcessError"), zig.Id("i32")),
|
zig.ErrorUnionType(zig.Id("ProcessError"), zig.Id("i32")),
|
||||||
zig.NewBlock(
|
zig.NewBlock(
|
||||||
// var result: i32 = 0;
|
// var result: i32 = 0;
|
||||||
zig.DeclareVarStmt(false, []string{"result"}, zig.Id("i32"), zig.Lit("int", "0")),
|
zig.DeclareVarStmt(false, []string{"result"}, zig.Id("i32"), zig.IntLit("0")),
|
||||||
// defer std.debug.print("Cleanup\n", .{});
|
// defer std.debug.print("Cleanup\n", .{});
|
||||||
zig.Defer(
|
zig.Defer(
|
||||||
zig.NewExprStmt(
|
zig.NewExprStmt(
|
||||||
@ -153,7 +153,7 @@ test "processData" {
|
|||||||
zig.FieldAccess(zig.Id("std"), "debug"),
|
zig.FieldAccess(zig.Id("std"), "debug"),
|
||||||
"print",
|
"print",
|
||||||
),
|
),
|
||||||
zig.Lit("string", `Cleanup\n`),
|
zig.StringLit(`Cleanup\n`),
|
||||||
zig.InitList(),
|
zig.InitList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -162,7 +162,7 @@ test "processData" {
|
|||||||
zig.ForLoop(
|
zig.ForLoop(
|
||||||
[]zig.ForArg{
|
[]zig.ForArg{
|
||||||
zig.ForArgExpr(zig.Id("values")),
|
zig.ForArgExpr(zig.Id("values")),
|
||||||
{Expr: zig.Lit("int", "0"), From: zig.Lit("", "")},
|
{Expr: zig.IntLit("0"), From: zig.IntLit("")},
|
||||||
},
|
},
|
||||||
zig.PayloadNames([]string{"opt_val", "idx"}, []bool{false, false}),
|
zig.PayloadNames([]string{"opt_val", "idx"}, []bool{false, false}),
|
||||||
zig.NewBlockStmt(
|
zig.NewBlockStmt(
|
||||||
@ -178,8 +178,8 @@ test "processData" {
|
|||||||
zig.Prong(
|
zig.Prong(
|
||||||
[]*zig.SwitchCase{
|
[]*zig.SwitchCase{
|
||||||
zig.Case(
|
zig.Case(
|
||||||
zig.Unary("-", zig.Lit("int", "10")),
|
zig.Unary("-", zig.IntLit("10")),
|
||||||
zig.Unary("-", zig.Lit("int", "1")),
|
zig.Unary("-", zig.IntLit("1")),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
@ -193,7 +193,7 @@ test "processData" {
|
|||||||
// 0 => continue,
|
// 0 => continue,
|
||||||
zig.Prong(
|
zig.Prong(
|
||||||
[]*zig.SwitchCase{
|
[]*zig.SwitchCase{
|
||||||
zig.Case(zig.Lit("int", "0"), nil),
|
zig.Case(zig.IntLit("0"), nil),
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
zig.Continue(""),
|
zig.Continue(""),
|
||||||
@ -201,12 +201,12 @@ test "processData" {
|
|||||||
// 1...10 => { ... }
|
// 1...10 => { ... }
|
||||||
zig.Prong(
|
zig.Prong(
|
||||||
[]*zig.SwitchCase{
|
[]*zig.SwitchCase{
|
||||||
zig.Case(zig.Lit("int", "1"), zig.Lit("int", "10")),
|
zig.Case(zig.IntLit("1"), zig.IntLit("10")),
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
zig.NewBlockStmt(
|
zig.NewBlockStmt(
|
||||||
zig.If(
|
zig.If(
|
||||||
zig.Binary(">", zig.Id("idx"), zig.Lit("int", "3")),
|
zig.Binary(">", zig.Id("idx"), zig.IntLit("3")),
|
||||||
zig.Break("", nil),
|
zig.Break("", nil),
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -228,7 +228,7 @@ test "processData" {
|
|||||||
// else block
|
// else block
|
||||||
zig.NewBlockStmt(
|
zig.NewBlockStmt(
|
||||||
zig.If(
|
zig.If(
|
||||||
zig.Binary("==", zig.Id("idx"), zig.Lit("int", "0")),
|
zig.Binary("==", zig.Id("idx"), zig.IntLit("0")),
|
||||||
zig.Return(zig.FieldAccess(zig.Id("ProcessError"), "InvalidInput")),
|
zig.Return(zig.FieldAccess(zig.Id("ProcessError"), "InvalidInput")),
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -241,7 +241,7 @@ test "processData" {
|
|||||||
// if (values[0] == null) { unreachable; }
|
// if (values[0] == null) { unreachable; }
|
||||||
zig.If(
|
zig.If(
|
||||||
zig.Binary("==",
|
zig.Binary("==",
|
||||||
zig.Index(zig.Id("values"), zig.Lit("int", "0")),
|
zig.Index(zig.Id("values"), zig.IntLit("0")),
|
||||||
zig.Id("null"),
|
zig.Id("null"),
|
||||||
),
|
),
|
||||||
zig.NewBlockStmt(
|
zig.NewBlockStmt(
|
||||||
@ -253,7 +253,7 @@ test "processData" {
|
|||||||
zig.Return(zig.Id("result")),
|
zig.Return(zig.Id("result")),
|
||||||
),
|
),
|
||||||
[]*zig.ParamDecl{
|
[]*zig.ParamDecl{
|
||||||
zig.Param("values", zig.ArrayType(zig.Lit("int", "5"), zig.OptionalType(zig.Id("i32")))),
|
zig.Param("values", zig.ArrayType(zig.IntLit("5"), zig.OptionalType(zig.Id("i32")))),
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
),
|
),
|
||||||
@ -265,11 +265,11 @@ test "processData" {
|
|||||||
zig.DeclareVarStmt(true, []string{"data"}, nil,
|
zig.DeclareVarStmt(true, []string{"data"}, nil,
|
||||||
&zig.InitListExpr{
|
&zig.InitListExpr{
|
||||||
Values: []zig.Expr{
|
Values: []zig.Expr{
|
||||||
zig.Lit("int", "5"),
|
zig.IntLit("5"),
|
||||||
zig.Unary("-", zig.Lit("int", "3")),
|
zig.Unary("-", zig.IntLit("3")),
|
||||||
zig.Lit("int", "0"),
|
zig.IntLit("0"),
|
||||||
zig.Id("null"),
|
zig.Id("null"),
|
||||||
zig.Lit("int", "10"),
|
zig.IntLit("10"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -288,7 +288,7 @@ test "processData" {
|
|||||||
zig.Call(
|
zig.Call(
|
||||||
zig.Id("@as"),
|
zig.Id("@as"),
|
||||||
zig.Id("i32"),
|
zig.Id("i32"),
|
||||||
zig.Lit("int", "8"),
|
zig.IntLit("8"),
|
||||||
),
|
),
|
||||||
zig.Id("result"),
|
zig.Id("result"),
|
||||||
),
|
),
|
||||||
@ -328,7 +328,7 @@ pub fn main() !void {
|
|||||||
Decl: zig.DeclareGlobalVar("std",
|
Decl: zig.DeclareGlobalVar("std",
|
||||||
zig.Call(
|
zig.Call(
|
||||||
zig.Id("@import"),
|
zig.Id("@import"),
|
||||||
zig.Lit("string", "std"),
|
zig.StringLit("std"),
|
||||||
),
|
),
|
||||||
zig.GlobalVarConst,
|
zig.GlobalVarConst,
|
||||||
),
|
),
|
||||||
@ -353,26 +353,24 @@ pub fn main() !void {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
// var i: i32 = 1;
|
// var i: i32 = 1;
|
||||||
zig.DeclareVarStmt(false, []string{"i"}, zig.Id("i32"), zig.Lit("int", "1")),
|
zig.DeclareVarStmt(false, []string{"i"}, zig.Id("i32"), zig.IntLit("1")),
|
||||||
// while (i <= 5) : (i += 1) { ... }
|
// while (i <= 5) : (i += 1) { ... }
|
||||||
&zig.LoopStmt{
|
zig.WhileLoop(
|
||||||
Kind: "while",
|
zig.Binary("<=", zig.Id("i"), zig.IntLit("5")),
|
||||||
Prefix: &zig.WhilePrefix{
|
zig.Binary("+=", zig.Id("i"), zig.IntLit("1")),
|
||||||
Cond: zig.Binary("<=", zig.Id("i"), zig.Lit("int", "5")),
|
nil,
|
||||||
Continue: zig.Binary("+=", zig.Id("i"), zig.Lit("int", "1")),
|
zig.NewBlockStmt(
|
||||||
},
|
|
||||||
Body: zig.NewBlockStmt(
|
|
||||||
&zig.IfStmt{
|
&zig.IfStmt{
|
||||||
Cond: zig.Binary("==",
|
Cond: zig.Binary("==",
|
||||||
zig.Binary("%", zig.Id("i"), zig.Lit("int", "2")),
|
zig.Binary("%", zig.Id("i"), zig.IntLit("2")),
|
||||||
zig.Lit("int", "0"),
|
zig.IntLit("0"),
|
||||||
),
|
),
|
||||||
Then: zig.NewBlockStmt(
|
Then: zig.NewBlockStmt(
|
||||||
zig.NewExprStmt(
|
zig.NewExprStmt(
|
||||||
zig.Try(
|
zig.Try(
|
||||||
zig.Call(
|
zig.Call(
|
||||||
zig.FieldAccess(zig.Id("stdout"), "writeAll"),
|
zig.FieldAccess(zig.Id("stdout"), "writeAll"),
|
||||||
zig.Lit("string", `even: {d}\n`),
|
zig.StringLit(`even: {d}\n`),
|
||||||
zig.InitList(zig.Id("i")),
|
zig.InitList(zig.Id("i")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -383,7 +381,7 @@ pub fn main() !void {
|
|||||||
zig.Try(
|
zig.Try(
|
||||||
zig.Call(
|
zig.Call(
|
||||||
zig.FieldAccess(zig.Id("stdout"), "writeAll"),
|
zig.FieldAccess(zig.Id("stdout"), "writeAll"),
|
||||||
zig.Lit("string", `odd: {d}\n`),
|
zig.StringLit(`odd: {d}\n`),
|
||||||
zig.InitList(zig.Id("i")),
|
zig.InitList(zig.Id("i")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -391,7 +389,8 @@ pub fn main() !void {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
},
|
nil,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
nil,
|
nil,
|
||||||
zig.FnExport,
|
zig.FnExport,
|
||||||
@ -430,7 +429,7 @@ func TestStructWithFieldsAndMethod(t *testing.T) {
|
|||||||
zig.NewExprStmt(
|
zig.NewExprStmt(
|
||||||
zig.Binary("=",
|
zig.Binary("=",
|
||||||
zig.FieldAccess(zig.Id("self"), "count"),
|
zig.FieldAccess(zig.Id("self"), "count"),
|
||||||
zig.Lit("int", "0"),
|
zig.IntLit("0"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user