summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go109
1 files changed, 73 insertions, 36 deletions
diff --git a/main.go b/main.go
index 037614c..4ae57da 100644
--- a/main.go
+++ b/main.go
@@ -3,6 +3,7 @@ package main
import (
"bufio"
"errors"
+ "flag"
"fmt"
"io"
"log"
@@ -20,42 +21,7 @@ type Interpreter interface {
func main() {
log.SetFlags(log.Lshortfile)
- var interp Interpreter = vm0.New(golang.GoParser)
- if len(os.Args) > 1 && os.Args[1] == "1" {
- interp = codegen.NewInterpreter(golang.GoParser)
- interp.(*codegen.Interpreter).AddSym(fmt.Println, "println")
- }
- in := os.Stdin
-
- if isatty(in) {
- // Provide an interactive line oriented Read Eval Print Loop (REPL).
- liner := bufio.NewScanner(in)
- text, prompt := "", "> "
- fmt.Print(prompt)
- for liner.Scan() {
- text += liner.Text()
- res, err := interp.Eval(text + "\n")
- if err == nil {
- if res != nil {
- fmt.Println(": ", res)
- }
- text, prompt = "", "> "
- } else if errors.Is(err, scanner.ErrBlock) {
- prompt = ">> "
- } else {
- fmt.Println("Error:", err)
- text, prompt = "", "> "
- }
- fmt.Print(prompt)
- }
- return
- }
-
- buf, err := io.ReadAll(in)
- if err != nil {
- log.Fatal(err)
- }
- if _, err := interp.Eval(string(buf)); err != nil {
+ if err := run(os.Args[1:]); err != nil {
log.Fatal(err)
}
}
@@ -69,3 +35,74 @@ func isatty(in io.Reader) bool {
stat, err := s.Stat()
return err == nil && stat.Mode()&os.ModeCharDevice != 0
}
+
+// repl executes an interactive line oriented Read Eval Print Loop (REPL).
+func repl(interp Interpreter, in io.Reader) (err error) {
+ liner := bufio.NewScanner(in)
+ text, prompt := "", "> "
+ fmt.Print(prompt)
+ for liner.Scan() {
+ text += liner.Text()
+ res, err := interp.Eval(text + "\n")
+ if err == nil {
+ if res != nil {
+ fmt.Println(": ", res)
+ }
+ text, prompt = "", "> "
+ } else if errors.Is(err, scanner.ErrBlock) {
+ prompt = ">> "
+ } else {
+ fmt.Println("Error:", err)
+ text, prompt = "", "> "
+ }
+ fmt.Print(prompt)
+ }
+ return
+}
+
+func run(arg []string) (err error) {
+ var i int
+
+ rflag := flag.NewFlagSet("run", flag.ContinueOnError)
+ rflag.IntVar(&i, "i", 1, "set interpreter version for execution, possible values: 0, 1")
+ rflag.Usage = func() {
+ fmt.Println("Usage: parscan run [options] [path] [args]")
+ fmt.Println("Options:")
+ rflag.PrintDefaults()
+ }
+ if err = rflag.Parse(arg); err != nil {
+ return err
+ }
+ args := rflag.Args()
+
+ var interp Interpreter
+ switch i {
+ case 0:
+ interp = vm0.New(golang.GoParser)
+ case 1:
+ interp = codegen.NewInterpreter(golang.GoParser)
+ interp.(*codegen.Interpreter).AddSym(fmt.Println, "println")
+ default:
+ return fmt.Errorf("invalid interpreter version: %v", i)
+ }
+
+ log.Println("args:", args)
+ in := os.Stdin
+ if len(args) > 0 {
+ if in, err = os.Open(arg[0]); err != nil {
+ return err
+ }
+ defer in.Close()
+ }
+
+ if isatty(in) {
+ return repl(interp, in)
+ }
+
+ buf, err := io.ReadAll(in)
+ if err != nil {
+ return err
+ }
+ _, err = interp.Eval(string(buf))
+ return err
+}