summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.go2
-rw-r--r--parser/compiler.go17
-rw-r--r--parser/interpreter_test.go2
-rw-r--r--vm/vm_test.go104
4 files changed, 110 insertions, 15 deletions
diff --git a/main.go b/main.go
index f9f125b..276f732 100644
--- a/main.go
+++ b/main.go
@@ -46,7 +46,7 @@ func repl(interp Interpreter, in io.Reader) (err error) {
res, err := interp.Eval(text + "\n")
switch {
case err == nil:
- if !res.IsNil() {
+ if res.IsValid() {
fmt.Println(": ", res)
}
text, prompt = "", "> "
diff --git a/parser/compiler.go b/parser/compiler.go
index 3b9a32d..aa16888 100644
--- a/parser/compiler.go
+++ b/parser/compiler.go
@@ -61,13 +61,14 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
case lang.String:
s := t.Block()
+ v := vm.Value{Data: reflect.ValueOf(s), Type: vm.TypeOf(s)}
i, ok := c.strings[s]
if !ok {
i = len(c.Data)
- c.Data = append(c.Data, vm.ValueOf(s))
+ c.Data = append(c.Data, v)
c.strings[s] = i
}
- push(&symbol{kind: symConst, value: vm.ValueOf(s)})
+ push(&symbol{kind: symConst, value: v})
emit(int64(t.Pos), vm.Dup, int64(i))
case lang.Add:
@@ -144,7 +145,11 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
// TODO: support assignment to local, composite objects.
st := tokens[i-1]
l := len(c.Data)
- typ := pop().Type
+ d := pop()
+ typ := d.Type
+ if typ == nil {
+ typ = d.value.Type
+ }
v := vm.NewValue(typ)
c.addSym(l, st.Str, v, symVar, typ, false)
c.Data = append(c.Data, v)
@@ -160,7 +165,11 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
if !ok {
return fmt.Errorf("symbol not found: %s", st.Str)
}
- typ := pop().Type
+ d := pop()
+ typ := d.Type
+ if typ == nil {
+ typ = d.value.Type
+ }
if s.Type == nil {
s.Type = typ
s.value = vm.NewValue(typ)
diff --git a/parser/interpreter_test.go b/parser/interpreter_test.go
index a6ad246..314f35b 100644
--- a/parser/interpreter_test.go
+++ b/parser/interpreter_test.go
@@ -69,6 +69,7 @@ func TestExpr(t *testing.T) {
{src: "-2 + 5", res: "3"},
{src: "5 + -2", res: "3"},
{src: "!false", res: "true"},
+ {src: `a := "hello"`, res: "hello"},
})
}
@@ -233,6 +234,7 @@ func TestVar(t *testing.T) {
{src: "var a, b int = 2, 5; a+b", res: "7"},
{src: "var x = 5; x", res: "5"},
{src: "var a = 1; func f() int { var a, b int = 3, 4; return a+b}; a+f()", res: "8"},
+ {src: `var a = "hello"; a`, res: "hello"},
{src: `var (
a, b int = 4+1, 3
c = 8
diff --git a/vm/vm_test.go b/vm/vm_test.go
index 8fa8e71..43333ad 100644
--- a/vm/vm_test.go
+++ b/vm/vm_test.go
@@ -3,6 +3,7 @@ package vm
import (
"fmt"
"log"
+ "reflect"
"testing"
)
@@ -61,7 +62,90 @@ var tests = []struct {
{0, Exit},
},
start: 0, end: 1, mem: "[3]",
-}, { // #01 -- Calling a function defined outside the VM.
+}, { // #01 -- A simple subtraction.
+ code: [][]int64{
+ {0, Push, 2},
+ {0, Push, 3},
+ {0, Sub},
+ {0, Exit},
+ },
+ start: 0, end: 1, mem: "[1]",
+}, { // #02 -- A simple multiplication.
+ code: [][]int64{
+ {0, Push, 3},
+ {0, Push, 2},
+ {0, Mul},
+ {0, Exit},
+ },
+ start: 0, end: 1, mem: "[6]",
+}, { // #03 -- lower.
+ code: [][]int64{
+ {0, Push, 3},
+ {0, Push, 2},
+ {0, Lower},
+ {0, Exit},
+ },
+ start: 0, end: 1, mem: "[true]",
+}, { // #04 -- greater.
+ code: [][]int64{
+ {0, Push, 2},
+ {0, Push, 3},
+ {0, Greater},
+ {0, Exit},
+ },
+ start: 0, end: 1, mem: "[true]",
+}, { // #05 -- equal.
+ code: [][]int64{
+ {0, Push, 2},
+ {0, Push, 3},
+ {0, Equal},
+ {0, Exit},
+ },
+ start: 0, end: 1, mem: "[false]",
+}, { // #06 -- equalSet.
+ code: [][]int64{
+ {0, Push, 2},
+ {0, Push, 3},
+ {0, EqualSet},
+ {0, Exit},
+ },
+ start: 0, end: 2, mem: "[2 false]",
+}, { // #07 -- equalSet.
+ code: [][]int64{
+ {0, Push, 3},
+ {0, Push, 3},
+ {0, EqualSet},
+ {0, Exit},
+ },
+ start: 0, end: 1, mem: "[true]",
+}, { // #08 not.
+ code: [][]int64{
+ {0, Push, 3},
+ {0, Push, 3},
+ {0, Equal},
+ {0, Not},
+ {0, Exit},
+ },
+ start: 0, end: 1, mem: "[false]",
+}, { // #09 pop.
+ code: [][]int64{
+ {0, Push, 3},
+ {0, Push, 2},
+ {0, Pop, 1},
+ {0, Exit},
+ },
+ start: 0, end: 1, mem: "[3]",
+}, { // #10 -- Assign a variable.
+ sym: []Value{{Type: TypeOf(0), Data: reflect.ValueOf(0)}},
+ code: [][]int64{
+ {0, Grow, 1},
+ {0, New, 2, 0},
+ {0, Push, 2},
+ {0, Assign, 1},
+ {0, Exit},
+ },
+ start: 1, end: 2, mem: "[2]",
+}, { // #11 -- Calling a function defined outside the VM.
sym: []Value{ValueOf(fmt.Println), ValueOf("Hello")},
code: [][]int64{
{0, Dup, 0},
@@ -69,7 +153,7 @@ var tests = []struct {
{0, Exit},
},
start: 1, end: 3, mem: "[6 <nil>]",
-}, { // #02 -- Defining and calling a function in VM.
+}, { // #12 -- Defining and calling a function in VM.
code: [][]int64{
{0, Jump, 3}, // 0
{0, Push, 3}, // 1
@@ -79,7 +163,7 @@ var tests = []struct {
{0, Exit}, // 5
},
start: 0, end: 1, mem: "[3]",
-}, { // #03 -- Defining and calling a function in VM.
+}, { // #13 -- Defining and calling a function in VM.
code: [][]int64{
{0, Jump, 3}, // 0
{0, Push, 3}, // 1
@@ -90,7 +174,7 @@ var tests = []struct {
{0, Exit}, // 6
},
start: 0, end: 1, mem: "[3]",
-}, { // #04 -- Defining and calling a function in VM.
+}, { // #14 -- Defining and calling a function in VM.
code: [][]int64{
{0, Jump, 5}, // 0
{0, Push, 3}, // 1
@@ -103,20 +187,20 @@ var tests = []struct {
{0, Exit}, // 8
},
start: 0, end: 1, mem: "[3]",
-}, { // #05 -- Fibonacci numbers, hand written. Showcase recursivity.
+}, { // #15 -- Fibonacci numbers, hand written. Showcase recursivity.
code: [][]int64{
{0, Jump, 19}, // 0
{0, Push, 2}, // 2 [2]
{0, Fdup, -2}, // 1 [2 i]
{0, Lower}, // 3 [true/false]
{0, JumpTrue, 13}, // 4 [], goto 17
- {0, Push, 2}, // 6 [i 2]
- {0, Fdup, -2}, // 5 [i]
+ {0, Push, 2}, // 5 [i 2]
+ {0, Fdup, -2}, // 6 [i]
{0, Sub}, // 7 [(i-2)]
{0, Push, 1}, // 8
{0, Call}, // 9 [fib(i-2)]
- {0, Push, 1}, // 11 [(i-2) i 1]
- {0, Fdup, -2}, // 10 [fib(i-2) i]
+ {0, Push, 1}, // 10 [(i-2) i 1]
+ {0, Fdup, -2}, // 11 [fib(i-2) i]
{0, Sub}, // 12 [(i-2) (i-1)]
{0, Push, 1}, // 13
{0, Call}, // 14 [fib(i-2) fib(i-1)]
@@ -130,7 +214,7 @@ var tests = []struct {
{0, Exit}, // 22
},
start: 0, end: 1, mem: "[8]",
-}, { // #06 -- Fibonacci with some immediate instructions.
+}, { // #16 -- Fibonacci with some immediate instructions.
code: [][]int64{
{0, Jump, 14}, // 0
{0, Fdup, -2}, // 1 [i]