diff options
| author | Mel <einebeere@gmail.com> | 2022-08-11 01:26:09 +0000 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-08-11 01:26:09 +0000 |
| commit | 8193e5c590177b91b51acd818e8a365ab6845988 (patch) | |
| tree | 24716cf6ff5fbc9b34dca416350f93da90a6ed21 /cmd/compmod/main.go | |
| parent | 86f31acf6789be116dcc54ed85b069a37c0f7aa8 (diff) | |
| download | jinx-8193e5c590177b91b51acd818e8a365ab6845988.tar.zst jinx-8193e5c590177b91b51acd818e8a365ab6845988.zip | |
Add compmod tool to compile built-in modules
Diffstat (limited to 'cmd/compmod/main.go')
| -rw-r--r-- | cmd/compmod/main.go | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/cmd/compmod/main.go b/cmd/compmod/main.go new file mode 100644 index 0000000..7cea8ce --- /dev/null +++ b/cmd/compmod/main.go @@ -0,0 +1,94 @@ +package main + +import ( + _ "embed" + "flag" + "fmt" + "html/template" + "jinx/pkg/lang/compiler" + "jinx/pkg/lang/parser" + "jinx/pkg/lang/scanner" + "jinx/pkg/lang/vm/code" + "os" +) + +//go:embed compiled.tmpl +var compiledTemplateString string + +type compiledTemplateInfo struct { + Module string + Globals []string + Bytes string +} + +func main() { + flag.Parse() + + moduleName := flag.Arg(0) + if moduleName == "" { + exit("no module specified") + } + + moduleSourcePath := fmt.Sprintf("pkg/lang/modules/%s/%s.lang", moduleName, moduleName) + moduleOutputPath := fmt.Sprintf("pkg/lang/modules/%s/compiled.go", moduleName) + + sourceFile, err := os.Open(moduleSourcePath) + if err != nil { + exit("could not open file: %v", err) + } + defer sourceFile.Close() + + scanner := scanner.New(sourceFile) + tokens, err := scanner.Scan() + if err != nil { + exit("error during scanning: %v", err) + } + + parser := parser.New(tokens) + program, err := parser.Parse() + if err != nil { + exit("error during parsing: %v", err) + } + + comp := compiler.New(moduleName, "", program) + module, err := comp.Compile() + if err != nil { + exit("compilation failed: %v", err) + } + + code := turnCodeIntoBytes(module.Code().Code()) + + info := compiledTemplateInfo{ + Module: module.Name(), + Globals: module.Globals(), + Bytes: code, + } + + compiledTemplate, err := template.New("compiled").Parse(compiledTemplateString) + if err != nil { + exit("could not parse template: %v", err) + } + + outputFile, err := os.Create(moduleOutputPath) + if err != nil { + exit("could not create file: %v", err) + } + + if err := compiledTemplate.Execute(outputFile, info); err != nil { + exit("could not write to file: %v", err) + } +} + +func turnCodeIntoBytes(code code.Raw) string { + var result string + for _, b := range []byte(code) { + result += fmt.Sprintf("0x%x, ", b) + } + return result +} + +func exit(format string, args ...any) { + message := fmt.Sprintf(format, args...) + fmt.Printf("error: %s\n", message) + os.Exit(1) +} |
