diff options
| author | Mel <einebeere@gmail.com> | 2022-07-06 01:52:04 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-07-06 14:05:28 +0200 |
| commit | 7ab4e6290d7131e4a401d36d8480b3c2fec9ae41 (patch) | |
| tree | 380351f1dd080d4cfe2e6ecc9c5ce25a7cd20ed5 /cmd | |
| parent | 5d00068f228322a95895e7f92dd48e6cbb206832 (diff) | |
| download | jinx-7ab4e6290d7131e4a401d36d8480b3c2fec9ae41.tar.zst jinx-7ab4e6290d7131e4a401d36d8480b3c2fec9ae41.zip | |
Add lang binary and decompiler to VM
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/lang/main.go | 86 | ||||
| -rw-r--r-- | cmd/vm/main.go | 26 |
2 files changed, 109 insertions, 3 deletions
diff --git a/cmd/lang/main.go b/cmd/lang/main.go new file mode 100644 index 0000000..042a84e --- /dev/null +++ b/cmd/lang/main.go @@ -0,0 +1,86 @@ +package main + +import ( + "flag" + "fmt" + "jinx/pkg/lang/compiler" + "jinx/pkg/lang/parser" + "jinx/pkg/lang/scanner" + "jinx/pkg/lang/vm" + "jinx/pkg/lang/vm/code" + "os" +) + +func main() { + compile := flag.String("c", "", "compile to file") + run := flag.Bool("r", false, "run") + + flag.Parse() + + if *compile == "" && !*run { + exit("nothing to do, either -c or -r is required") + } + + path := flag.Arg(0) + if path == "" { + exit("no file specified") + } + + file, err := os.Open(path) + if err != nil { + exit("could not open file: %v", err) + } + defer file.Close() + + var bc code.Code + + scanner := scanner.New(file) + 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(program) + bc, err = comp.Compile() + if err != nil { + exit("compilation failed: %v", err) + } + + if *compile != "" { + output, err := os.Create(*compile) + if err != nil { + exit("could not create file: %v", err) + } + defer output.Close() + + if _, err := output.Write(bc.Code()); err != nil { + exit("could not write to file: %v", err) + } + } + + if *run { + vm := vm.New(&bc) + if err := vm.Run(); err != nil { + exit("execution failed: %v", err) + } + + res, err := vm.GetResult() + if err != nil { + exit("could not get result: %v", err) + } + + fmt.Println(res) + } +} + +func exit(format string, args ...any) { + message := fmt.Sprintf(format, args...) + fmt.Printf("error: %s\n", message) + os.Exit(1) +} diff --git a/cmd/vm/main.go b/cmd/vm/main.go index 19ba160..013899a 100644 --- a/cmd/vm/main.go +++ b/cmd/vm/main.go @@ -13,6 +13,7 @@ import ( func main() { // Take the first argument as the path to the file to be parsed. compile := flag.String("c", "", "compile to file (if not bytecode)") + decompile := flag.String("d", "", "decompile bytecode to file") run := flag.Bool("r", false, "run") bytecode := flag.Bool("b", false, "interpret bytecode, without this flag the program will be interpreted in Lang VM text format.") @@ -22,12 +23,16 @@ func main() { exit("-c and -b are mutually exclusive") } + if *compile != "" && *decompile != "" { + exit("-c and -d are mutually exclusive") + } + if *bytecode && !*run { exit("-b requires -r") } - if *compile == "" && !*run { - exit("nothing to do, either -c or -r is required") + if *compile == "" && *decompile == "" && !*run { + exit("nothing to do, either -c, -d or -r is required") } path := flag.Arg(0) @@ -42,7 +47,7 @@ func main() { defer file.Close() var bc code.Code - if !*bytecode { + if !*bytecode && *decompile == "" { comp := text.NewCompiler(file) bc, err = comp.Compile() if err != nil { @@ -67,6 +72,21 @@ func main() { } bc = code.New(content, code.NewDebugInfo(path)) + + if *decompile != "" { + decomp := text.NewDecompiler(bc) + result := decomp.Decompile() + + output, err := os.Create(*decompile) + if err != nil { + exit("could not create file: %v", err) + } + defer output.Close() + + if _, err := output.Write([]byte(result)); err != nil { + exit("could not write to file: %v", err) + } + } } if *run { |
