aboutsummaryrefslogtreecommitdiff
path: root/cmd/lang
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/lang')
-rw-r--r--cmd/lang/main.go86
1 files changed, 86 insertions, 0 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)
+}