package main import ( "flag" "fmt" "io" "jinx/pkg/lang/modules" "jinx/pkg/lang/vm" "jinx/pkg/lang/vm/code" "jinx/pkg/lang/vm/text" "os" ) 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.") flag.Parse() if *compile != "" && *bytecode { 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 == "" && *decompile == "" && !*run { exit("nothing to do, either -c, -d 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 if !*bytecode && *decompile == "" { comp := text.NewCompiler(file) 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) } } } else { content, err := io.ReadAll(file) if err != nil { exit("could not read file: %v", err) } 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 { vm := vm.New(modules.NewUnknownModule(&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) }