summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2023-09-04 16:58:15 +0200
committerMarc Vertes <mvertes@free.fr>2023-09-04 16:58:15 +0200
commit4241593b42bffac2f8fcb63f1e88621fe025e360 (patch)
tree48680879982947524e1b028e179608bb5cbcda23 /main.go
parent8feddd9b3eefb920c4a0c7a5b4c3b8ae160f3c71 (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.go71
1 files changed, 71 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..037614c
--- /dev/null
+++ b/main.go
@@ -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
+}