From d002309e93984253b604feb74a08fdf4ac2a4101 Mon Sep 17 00:00:00 2001 From: Luke Wilson Date: Sat, 24 May 2025 15:46:45 -0500 Subject: [PATCH] Refactored code generator, tracks indentation, no error checking --- internal/zig/zig.go | 150 ++++++++++++++++++++------------------- internal/zig/zig_test.go | 2 +- 2 files changed, 78 insertions(+), 74 deletions(-) diff --git a/internal/zig/zig.go b/internal/zig/zig.go index e27e33e..22cd4ac 100644 --- a/internal/zig/zig.go +++ b/internal/zig/zig.go @@ -6,123 +6,127 @@ import ( ) type formatter struct { - io.Writer + w io.Writer + line int // 1-based + col int // 1-based, reset to 1 after newline + indent int // indentation level } -func (f *formatter) WriteString(s string) (n int, err error) { - return f.Write([]byte(s)) +const indentStr = " " // 4 spaces per indent + +func (f *formatter) Writef(format string, a ...any) { + s := fmt.Sprintf(format, a...) + for i, r := range s { + if r == '\n' { + f.line++ + f.col = 1 + // If next character is not a newline and not end, and not a closing brace, write indentation + if i+1 < len(s) && s[i+1] != '\n' && s[i+1] != '}' { + f.writeIndent() + } + } else { + if f.col == 0 { + f.col = 1 + } else { + f.col++ + } + } + } + if _, err := f.w.Write([]byte(s)); err != nil { + panic(err) + } } -func (f *formatter) Writef(format string, a ...any) (err error) { - _, err = fmt.Fprintf(f, format, a...) - return err +func (f *formatter) writeIndent() { + for i := 0; i < f.indent; i++ { + if _, err := f.w.Write([]byte(indentStr)); err != nil { + panic(err) + } + f.col += len(indentStr) + } } -func Write(w io.Writer, root *Root) error { - f := &formatter{Writer: w} +func Write(w io.Writer, root *Root) (err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(error); ok { + err = e + } else { + panic(r) + } + } + }() + f := &formatter{w: w, line: 1, col: 1, indent: 0} if root.ContainerDocComment != "" { - if err := f.Writef("//! %s\n\n", root.ContainerDocComment); err != nil { - return err - } + f.Writef("//! %s\n\n", root.ContainerDocComment) } for _, member := range root.ContainerMembers { // Only handle Decl for now (fields not needed for hello world) if member.Decl != nil { - if err := writeDecl(f, member.Decl); err != nil { - return err - } + writeDecl(f, member.Decl) } } return nil } -func writeDecl(f *formatter, decl Decl) error { +func writeDecl(f *formatter, decl Decl) { switch fn := decl.(type) { case *FnDecl: - if err := f.Writef("fn %s(", fn.Name); err != nil { - return err - } - if err := writeParams(f, fn.Params); err != nil { - return err - } - if _, err := f.WriteString(") "); err != nil { - return err - } - if err := writeTypeExpr(f, fn.ReturnType); err != nil { - return err - } - if err := writeBlock(f, fn.Body); err != nil { - return err - } + f.Writef("fn %s(", fn.Name) + writeParams(f, fn.Params) + f.Writef(") ") + writeTypeExpr(f, fn.ReturnType) + writeBlock(f, fn.Body) } - return nil } -func writeParams(f *formatter, params []*ParamDecl) error { +func writeParams(f *formatter, params []*ParamDecl) { for i, param := range params { if i > 0 { - if _, err := f.WriteString(", "); err != nil { - return err - } + f.Writef(", ") } if param.Name != "" { - if _, err := f.WriteString(param.Name); err != nil { - return err - } - if _, err := f.WriteString(": "); err != nil { - return err - } - } - if err := writeTypeExpr(f, param.Type); err != nil { - return err + f.Writef("%s: ", param.Name) } + writeTypeExpr(f, param.Type) } - return nil } -func writeTypeExpr(f *formatter, typ TypeExpr) error { +func writeTypeExpr(f *formatter, typ TypeExpr) { switch t := typ.(type) { case *Identifier: - _, err := f.WriteString(t.Name) - return err + f.Writef("%s", t.Name) case nil: - return nil + // nothing default: - // fallback: print as string - _, err := f.WriteString(fmt.Sprintf("%v", t)) - return err + f.Writef("%v", t) } } -func writeBlock(f *formatter, block *Block) error { +func writeBlock(f *formatter, block *Block) { if block == nil { - _, err := f.WriteString(";") - return err + f.Writef(";") + return } - if _, err := f.WriteString(" {\n"); err != nil { - return err - } - for _, stmt := range block.Stmts { - if err := writeStmt(f, stmt); err != nil { - return err - } - if _, err := f.WriteString("\n"); err != nil { - return err + f.Writef(" {\n") + f.indent++ + for i, stmt := range block.Stmts { + f.writeIndent() + writeStmt(f, stmt) + if i < len(block.Stmts)-1 { + f.Writef("\n") } } - if _, err := f.WriteString("}\n"); err != nil { - return err - } - return nil + f.indent-- + f.Writef("\n") + f.writeIndent() + f.Writef("}\n") } -func writeStmt(f *formatter, stmt Stmt) error { +func writeStmt(f *formatter, stmt Stmt) { switch stmt.(type) { case *ReturnStmt: - if _, err := f.WriteString("return;"); err != nil { - return err - } + f.Writef("return;") } - return nil } diff --git a/internal/zig/zig_test.go b/internal/zig/zig_test.go index 83d8875..e582c47 100644 --- a/internal/zig/zig_test.go +++ b/internal/zig/zig_test.go @@ -20,7 +20,7 @@ func TestHelloWorld(t *testing.T) { expected := `//! Hello, world! fn main() void { -return; + return; } `