about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--pkg/lang/vm/exec.go54
-rw-r--r--pkg/lang/vm/value/data.go73
-rw-r--r--pkg/lang/vm/value/value.go6
3 files changed, 106 insertions, 27 deletions
diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go
index c145acf..54f43db 100644
--- a/pkg/lang/vm/exec.go
+++ b/pkg/lang/vm/exec.go
@@ -72,13 +72,13 @@ func (vm *VM) execAdd() error {
 
 	switch x.Type().Kind {
 	case value.IntType:
-		xv := int64(x.Data().(value.IntData))
+		xv := x.Data().(value.IntData).Get()
 		switch y.Type().Kind {
 		case value.IntType:
-			yv := int64(y.Data().(value.IntData))
+			yv := y.Data().(value.IntData).Get()
 			res = value.NewInt(xv + yv)
 		case value.FloatType:
-			yv := float64(y.Data().(value.FloatData))
+			yv := y.Data().(value.FloatData).Get()
 			res = value.NewFloat(float64(xv) + yv)
 		default:
 			return ErrInvalidOperandTypes{
@@ -88,13 +88,13 @@ func (vm *VM) execAdd() error {
 			}
 		}
 	case value.FloatType:
-		xv := float64(x.Data().(value.FloatData))
+		xv := x.Data().(value.FloatData).Get()
 		switch y.Type().Kind {
 		case value.IntType:
-			yv := float64(y.Data().(value.IntData))
-			res = value.NewFloat(xv + yv)
+			yv := y.Data().(value.IntData).Get()
+			res = value.NewFloat(xv + float64(yv))
 		case value.FloatType:
-			yv := float64(y.Data().(value.FloatData))
+			yv := y.Data().(value.FloatData).Get()
 			res = value.NewFloat(xv + yv)
 		default:
 			return ErrInvalidOperandTypes{
@@ -106,7 +106,7 @@ func (vm *VM) execAdd() error {
 	case value.StringType:
 		switch y.Type().Kind {
 		case value.StringType:
-			res = value.NewString(string(x.Data().(value.StringData)) + string(y.Data().(value.StringData)))
+			res = value.NewString(x.Data().(value.StringData).Get() + y.Data().(value.StringData).Get())
 		default:
 			return ErrInvalidOperandTypes{
 				Op: code.OpAdd,
@@ -142,13 +142,13 @@ func (vm *VM) execSub() error {
 
 	switch x.Type().Kind {
 	case value.IntType:
-		xv := int64(x.Data().(value.IntData))
+		xv := x.Data().(value.IntData).Get()
 		switch y.Type().Kind {
 		case value.IntType:
-			yv := int64(y.Data().(value.IntData))
+			yv := y.Data().(value.IntData).Get()
 			res = value.NewInt(xv - yv)
 		case value.FloatType:
-			yv := float64(y.Data().(value.FloatData))
+			yv := y.Data().(value.FloatData).Get()
 			res = value.NewFloat(float64(xv) - yv)
 		default:
 			return ErrInvalidOperandTypes{
@@ -158,13 +158,13 @@ func (vm *VM) execSub() error {
 			}
 		}
 	case value.FloatType:
-		xv := float64(x.Data().(value.FloatData))
+		xv := x.Data().(value.FloatData).Get()
 		switch y.Type().Kind {
 		case value.IntType:
-			yv := float64(y.Data().(value.IntData))
-			res = value.NewFloat(xv - yv)
+			yv := y.Data().(value.IntData).Get()
+			res = value.NewFloat(xv - float64(yv))
 		case value.FloatType:
-			yv := float64(y.Data().(value.FloatData))
+			yv := y.Data().(value.FloatData).Get()
 			res = value.NewFloat(xv - yv)
 		default:
 			return ErrInvalidOperandTypes{
@@ -199,16 +199,24 @@ func (vm *VM) execIndex() error {
 
 	switch v.Type().Kind {
 	case value.ArrayType:
-		arr := v.Data().([]value.Value)
-		idx := i.Data().(int64)
-		if idx < 0 || idx >= int64(len(arr)) {
-			return ErrArrayIndexOutOfBounds{
-				Index: int(idx),
-				Len:   len(arr),
+		arr := v.Data().(value.ArrayData)
+		switch i.Type().Kind {
+		case value.IntType:
+			idx := i.Data().(value.IntData).Get()
+			if idx < 0 || idx >= int64(arr.Len()) {
+				return ErrArrayIndexOutOfBounds{
+					Index: int(idx),
+					Len:   arr.Len(),
+				}
+			}
+			top.Push(arr.At(int(idx)))
+		default:
+			return ErrInvalidOperandTypes{
+				Op: code.OpIndex,
+				X:  i.Type(),
+				Y:  v.Type(),
 			}
 		}
-
-		top.Push(arr[idx])
 	default:
 		return ErrInvalidOperandTypes{
 			Op: code.OpIndex,
diff --git a/pkg/lang/vm/value/data.go b/pkg/lang/vm/value/data.go
index 1d63d32..6365f45 100644
--- a/pkg/lang/vm/value/data.go
+++ b/pkg/lang/vm/value/data.go
@@ -1,14 +1,85 @@
 package value
 
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+type Data fmt.Stringer
+
 type IntData int64
 
+func (i IntData) Get() int64 {
+	return int64(i)
+}
+
+func (i IntData) String() string {
+	return strconv.FormatInt(int64(i), 10)
+}
+
 type FloatData float64
 
+func (f FloatData) Get() float64 {
+	return float64(f)
+}
+
+func (f FloatData) String() string {
+	return strconv.FormatFloat(float64(f), 'f', -1, 64)
+}
+
 type StringData string
 
+func (s StringData) Get() string {
+	return string(s)
+}
+
+func (s StringData) String() string {
+	return "\"" + string(s) + "\""
+}
+
 type BoolData bool
 
-type ArrayData []Value
+func (b BoolData) Get() bool {
+	return bool(b)
+}
+
+func (b BoolData) String() string {
+	return strconv.FormatBool(bool(b))
+}
+
+type ArrayData struct {
+	arr *[]Value
+}
+
+func (a ArrayData) Get() *[]Value {
+	return a.arr
+}
+
+func (a ArrayData) String() string {
+	builder := strings.Builder{}
+	builder.WriteString("[")
+	for i, v := range *a.arr {
+		if i > 0 {
+			builder.WriteString(", ")
+		}
+		builder.WriteString(v.Data().String())
+	}
+	builder.WriteString("]")
+	return builder.String()
+}
+
+func (a ArrayData) Len() int {
+	return len(*a.arr)
+}
+
+func (a ArrayData) At(i int) Value {
+	return (*a.arr)[i]
+}
+
+func (a ArrayData) Push(v Value) {
+	*a.arr = append(*a.arr, v)
+}
 
 type NullData struct{}
 
diff --git a/pkg/lang/vm/value/value.go b/pkg/lang/vm/value/value.go
index e932ed3..daa17dd 100644
--- a/pkg/lang/vm/value/value.go
+++ b/pkg/lang/vm/value/value.go
@@ -2,7 +2,7 @@ package value
 
 type Value struct {
 	t Type
-	d any
+	d Data
 }
 
 func NewInt(x int64) Value {
@@ -27,7 +27,7 @@ func NewBool(b bool) Value {
 
 func NewArray(arr []Value) Value {
 	t := Type{Kind: ArrayType}
-	return Value{t: t, d: ArrayData(arr)}
+	return Value{t: t, d: ArrayData{arr: &arr}}
 }
 
 func NewNull() Value {
@@ -47,6 +47,6 @@ func (v Value) Type() Type {
 	return v.t
 }
 
-func (v Value) Data() any {
+func (v Value) Data() Data {
 	return v.d
 }