diff options
| author | Marc Vertes <mvertes@free.fr> | 2023-09-04 16:58:15 +0200 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2023-09-04 16:58:15 +0200 |
| commit | 4241593b42bffac2f8fcb63f1e88621fe025e360 (patch) | |
| tree | 48680879982947524e1b028e179608bb5cbcda23 /main.go | |
| parent | 8feddd9b3eefb920c4a0c7a5b4c3b8ae160f3c71 (diff) | |
codegen: add interpreter tests
Also simplify project structure. The executable is now produced in
the root directory. Work in progress.
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 71 |
1 files changed, 71 insertions, 0 deletions
@@ -0,0 +1,71 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "io" + "log" + "os" + + "github.com/gnolang/parscan/codegen" + "github.com/gnolang/parscan/lang/golang" + "github.com/gnolang/parscan/scanner" + "github.com/gnolang/parscan/vm0" +) + +type Interpreter interface { + Eval(string) (any, error) +} + +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 { + log.Fatal(err) + } +} + +// isatty returns true if the input stream is a tty (i.e. a character device). +func isatty(in io.Reader) bool { + s, ok := in.(interface{ Stat() (os.FileInfo, error) }) + if !ok { + return false + } + stat, err := s.Stat() + return err == nil && stat.Mode()&os.ModeCharDevice != 0 +} |
