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 }