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:
@@ -119,6 +119,14 @@ func writeDecl(f *formatter, decl Decl) {
|
||||
}
|
||||
writeBlock(f, d.Block)
|
||||
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)
|
||||
f.writef("]")
|
||||
writeTypeExpr(f, t.Elem)
|
||||
case *SliceTypeExpr:
|
||||
f.writef("[]")
|
||||
writeTypeExpr(f, t.Elem)
|
||||
case *ErrorUnionTypeExpr:
|
||||
writeTypeExpr(f, t.ErrSet)
|
||||
f.writef("!")
|
||||
@@ -217,7 +228,7 @@ func writeStmt(f *formatter, stmt Stmt) {
|
||||
f.writef("if (")
|
||||
writeExpr(f, s.Cond)
|
||||
f.writef(")")
|
||||
|
||||
|
||||
// Handle payload if present
|
||||
if s.Payload != nil {
|
||||
f.writef(" ")
|
||||
@@ -241,7 +252,7 @@ func writeStmt(f *formatter, stmt Stmt) {
|
||||
}
|
||||
}
|
||||
case *LoopStmt:
|
||||
if s.Kind == "while" {
|
||||
if s.Kind == LoopWhile {
|
||||
f.writef("while (")
|
||||
if wp, ok := s.Prefix.(*WhilePrefix); ok {
|
||||
writeExpr(f, wp.Cond)
|
||||
@@ -258,7 +269,7 @@ func writeStmt(f *formatter, stmt Stmt) {
|
||||
f.writef(" ")
|
||||
writeStmt(f, s.Body)
|
||||
}
|
||||
} else if s.Kind == "for" {
|
||||
} else if s.Kind == LoopFor {
|
||||
f.writef("for (")
|
||||
if fp, ok := s.Prefix.(*ForPrefix); ok {
|
||||
for i, arg := range fp.Args {
|
||||
@@ -289,45 +300,45 @@ func writeStmt(f *formatter, stmt Stmt) {
|
||||
writeStmt(f, s.Body)
|
||||
}
|
||||
}
|
||||
case *DeferStmt:
|
||||
if s.ErrDefer {
|
||||
f.writef("errdefer")
|
||||
} else {
|
||||
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("}")
|
||||
case *DeferStmt:
|
||||
if s.ErrDefer {
|
||||
f.writef("errdefer")
|
||||
} else {
|
||||
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("}")
|
||||
}
|
||||
}
|
||||
|
||||
// writePayload emits a payload (|x|, |*x|, |*x, y|, etc).
|
||||
func writePayload(f *formatter, payload *Payload) {
|
||||
@@ -431,7 +442,7 @@ func writeExpr(f *formatter, expr Expr) {
|
||||
f.writef(".%s", e.Field)
|
||||
case *Literal:
|
||||
switch e.Kind {
|
||||
case "string":
|
||||
case LiteralString:
|
||||
f.writef(`"%v"`, e.Value)
|
||||
default:
|
||||
f.writef("%v", e.Value)
|
||||
@@ -456,11 +467,21 @@ func writeExpr(f *formatter, expr Expr) {
|
||||
}
|
||||
}
|
||||
case *ContainerDecl:
|
||||
if e.Kind == "struct" {
|
||||
switch e.Kind {
|
||||
case ContainerStruct:
|
||||
f.writef("struct ")
|
||||
writeStructBody(f, e)
|
||||
} else {
|
||||
panic("not implemented: " + e.Kind)
|
||||
case ContainerEnum:
|
||||
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:
|
||||
f.writef("try ")
|
||||
@@ -489,6 +510,58 @@ func writeExpr(f *formatter, expr Expr) {
|
||||
f.indent--
|
||||
f.writeIndent()
|
||||
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("}")
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user