diff options
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/compmod/compiled.tmpl | 22 | ||||
| -rw-r--r-- | cmd/compmod/main.go | 94 |
2 files changed, 116 insertions, 0 deletions
diff --git a/cmd/compmod/compiled.tmpl b/cmd/compmod/compiled.tmpl new file mode 100644 index 0000000..2070749 --- /dev/null +++ b/cmd/compmod/compiled.tmpl @@ -0,0 +1,22 @@ +package {{.Module}} + +import ( + "jinx/pkg/lang/modules" + "jinx/pkg/lang/vm/code" +) + +var moduleCompiled = []byte{ + {{.Bytes}} +} + +var moduleCode = code.New(code.Raw(moduleCompiled), code.NewDebugInfo("{{.Module}}")) + +var Module = modules.NewModule( + "", + "{{.Module}}", + &moduleCode, + []modules.ModuleRef{}, + []string{ + {{range .Globals}}"{{.}}", {{end}} + }, +) 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) +} |
