//go:build ignore package main import ( "fmt" "go/ast" "go/parser" "go/token" "os" "sort" "strings" "text/template" ) const outputTemplate = `// Code generated by gen/main.go; DO NOT EDIT. package opcodes // initializeNameMappings populates nameToEmu from constants func (om *OpcodeManager) initializeNameMappings() { {{- range . }} om.nameToEmu["{{ .Name }}"] = {{ .Name }} {{- end }} } ` type OpcodeInfo struct { Name string } func main() { opcodes := []OpcodeInfo{} // Parse each source file for OP_ constants files := []string{"login.go", "emu.go"} for _, filename := range files { fset := token.NewFileSet() node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments) if err != nil { fmt.Fprintf(os.Stderr, "Failed to parse %s: %v\n", filename, err) continue } // Find all OP_ and LS_ constants ast.Inspect(node, func(n ast.Node) bool { spec, ok := n.(*ast.ValueSpec) if !ok { return true } for _, name := range spec.Names { if strings.HasPrefix(name.Name, "OP_") || strings.HasPrefix(name.Name, "LS_") { opcodes = append(opcodes, OpcodeInfo{Name: name.Name}) } } return true }) } // Sort for consistent output sort.Slice(opcodes, func(i, j int) bool { return opcodes[i].Name < opcodes[j].Name }) // Generate output tmpl, err := template.New("opcodes").Parse(outputTemplate) if err != nil { panic(err) } file, err := os.Create("generated.go") if err != nil { panic(err) } defer file.Close() if err := tmpl.Execute(file, opcodes); err != nil { panic(err) } fmt.Printf("Generated %d opcode mappings\n", len(opcodes)) }