From 8193e5c590177b91b51acd818e8a365ab6845988 Mon Sep 17 00:00:00 2001 From: Mel Date: Thu, 11 Aug 2022 01:26:09 +0000 Subject: Add compmod tool to compile built-in modules --- cmd/compmod/main.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 cmd/compmod/main.go (limited to 'cmd/compmod/main.go') 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) +} -- cgit 1.4.1