85 lines
1.6 KiB
Go
85 lines
1.6 KiB
Go
//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))
|
|
}
|