summaryrefslogtreecommitdiff
path: root/interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'interpreter')
-rw-r--r--interpreter/dump_test.go5
-rw-r--r--interpreter/interpreter.go16
-rw-r--r--interpreter/interpreter_test.go7
-rw-r--r--interpreter/repl.go35
4 files changed, 48 insertions, 15 deletions
diff --git a/interpreter/dump_test.go b/interpreter/dump_test.go
index dd172b9..d8fcc55 100644
--- a/interpreter/dump_test.go
+++ b/interpreter/dump_test.go
@@ -4,11 +4,12 @@ import (
"testing"
"github.com/mvertes/parscan/interpreter"
+ "github.com/mvertes/parscan/lang/golang"
)
func TestDump(t *testing.T) {
initProgram := "var a int = 2+1; a"
- interp := interpreter.NewInterpreter(GoScanner)
+ interp := interpreter.NewInterpreter(golang.GoSpec)
r, e := interp.Eval(initProgram)
t.Log(r, e)
if e != nil {
@@ -24,7 +25,7 @@ func TestDump(t *testing.T) {
d := interp.Dump()
t.Log(d)
- interp = interpreter.NewInterpreter(GoScanner)
+ interp = interpreter.NewInterpreter(golang.GoSpec)
r, e = interp.Eval(initProgram)
t.Log(r, e)
if e != nil {
diff --git a/interpreter/interpreter.go b/interpreter/interpreter.go
index 06a4bc1..62b593b 100644
--- a/interpreter/interpreter.go
+++ b/interpreter/interpreter.go
@@ -4,25 +4,25 @@ import (
"reflect"
"github.com/mvertes/parscan/compiler"
- "github.com/mvertes/parscan/scanner"
+ "github.com/mvertes/parscan/lang"
"github.com/mvertes/parscan/vm"
)
const debug = true
-// Interpreter represents the state of an interpreter.
-type Interpreter struct {
+// Interp represents the state of an interpreter.
+type Interp struct {
*compiler.Compiler
*vm.Machine
}
-// NewInterpreter returns a new interpreter state.
-func NewInterpreter(s *scanner.Scanner) *Interpreter {
- return &Interpreter{compiler.NewCompiler(s), &vm.Machine{}}
+// NewInterpreter returns a new interpreter.
+func NewInterpreter(s *lang.Spec) *Interp {
+ return &Interp{compiler.NewCompiler(s), &vm.Machine{}}
}
-// Eval interprets a src program and return the last produced value if any, or an error.
-func (i *Interpreter) Eval(src string) (res reflect.Value, err error) {
+// Eval evaluates code string and return the last produced value if any, or an error.
+func (i *Interp) Eval(src string) (res reflect.Value, err error) {
codeOffset := len(i.Code)
dataOffset := 0
if codeOffset > 0 {
diff --git a/interpreter/interpreter_test.go b/interpreter/interpreter_test.go
index 800ace5..71c7dd1 100644
--- a/interpreter/interpreter_test.go
+++ b/interpreter/interpreter_test.go
@@ -7,7 +7,6 @@ import (
"github.com/mvertes/parscan/interpreter"
"github.com/mvertes/parscan/lang/golang"
- "github.com/mvertes/parscan/scanner"
)
type etest struct {
@@ -15,19 +14,17 @@ type etest struct {
skip bool
}
-var GoScanner *scanner.Scanner
-
func init() {
log.SetFlags(log.Lshortfile)
- GoScanner = scanner.NewScanner(golang.GoSpec)
}
func gen(test etest) func(*testing.T) {
return func(t *testing.T) {
+ t.Parallel()
if test.skip {
t.Skip()
}
- interp := interpreter.NewInterpreter(GoScanner)
+ interp := interpreter.NewInterpreter(golang.GoSpec)
errStr := ""
r, e := interp.Eval(test.src)
t.Log(r, e)
diff --git a/interpreter/repl.go b/interpreter/repl.go
new file mode 100644
index 0000000..73af8a7
--- /dev/null
+++ b/interpreter/repl.go
@@ -0,0 +1,35 @@
+package interpreter
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+
+ "github.com/mvertes/parscan/scanner"
+)
+
+// Repl executes an interactive line oriented Read Eval Print Loop (REPL).
+func (i *Interp) Repl(in io.Reader) (err error) {
+ liner := bufio.NewScanner(in)
+ text, prompt := "", "> "
+ fmt.Print(prompt)
+ for liner.Scan() {
+ text += liner.Text()
+ res, err := i.Eval(text + "\n")
+ switch {
+ case err == nil:
+ if res.IsValid() {
+ fmt.Println(": ", res)
+ }
+ text, prompt = "", "> "
+ case errors.Is(err, scanner.ErrBlock):
+ prompt = ">> "
+ default:
+ fmt.Println("Error:", err)
+ text, prompt = "", "> "
+ }
+ fmt.Print(prompt)
+ }
+ return err
+}