2025-05-20 19:20:16 -05:00

93 lines
1.6 KiB
Go

package main
import (
"flag"
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
"strings"
)
var (
outputFilepath *string = flag.String("o", "out.zig", "Zig output filename")
)
func init() {
flag.Parse()
}
func main() {
inputFilepaths := flag.Args()
if len(inputFilepaths) > 1 {
panic("Only support one file!")
} else if len(inputFilepaths) < 1 {
panic("Must supply one input file")
}
inputFilepath := inputFilepaths[0]
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, inputFilepath, nil, parser.AllErrors)
if err != nil {
panic(err)
}
output, err := generate(f)
if err != nil {
panic(err)
}
outputFile, err := os.Create(*outputFilepath)
if err != nil {
panic(err)
}
_, err = outputFile.WriteString(output)
if err != nil {
panic(err)
}
fmt.Printf("%v:\n", *outputFilepath)
fmt.Println("--------------------")
fmt.Println(output)
}
func generate(f *ast.File) (string, error) {
sb := new(strings.Builder)
def := f.Decls[0].(*ast.FuncDecl)
if def.Name.Name != "main" {
return "", fmt.Errorf("must have main")
}
sb.WriteString(`const std = @import("std");`)
sb.WriteString("\npub fn main() void {\n")
stmt := def.Body.List[0].(*ast.ExprStmt)
call := stmt.X.(*ast.CallExpr)
fn := call.Fun.(*ast.Ident)
if fn.Name == "print" {
sb.WriteString(fmt.Sprintf(`std.debug.print(`))
args := call.Args
for _, arg := range args {
if s, ok := arg.(*ast.BasicLit); ok {
sb.WriteString(fmt.Sprintf("%s", s.Value))
} else {
panic("WTF")
}
}
sb.WriteString(", .{});\n")
} else {
return "", fmt.Errorf("expected printf")
}
sb.WriteString("}\n")
return sb.String(), nil
}