about summary refs log tree commit diff
path: root/pkg/lang/vm/exec.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/exec.go')
-rw-r--r--pkg/lang/vm/exec.go124
1 files changed, 101 insertions, 23 deletions
diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go
index f50d60b..c145acf 100644
--- a/pkg/lang/vm/exec.go
+++ b/pkg/lang/vm/exec.go
@@ -1,6 +1,9 @@
 package vm
 
-import "jinx/pkg/lang/vm/value"
+import (
+	"jinx/pkg/lang/vm/code"
+	"jinx/pkg/lang/vm/value"
+)
 
 func (vm *VM) execPushInt(x int64) {
 	vm.stack.Top().Push(value.NewInt(x))
@@ -26,20 +29,44 @@ func (vm *VM) execPushArray() {
 	vm.stack.Top().Push(value.NewArray([]value.Value{}))
 }
 
-func (vm *VM) execGetLocal(offset int) {
+func (vm *VM) execGetLocal(offset int) error {
 	top := vm.stack.Top()
-	top.Push(top.At(int(offset)))
+
+	local, err := top.At(int(offset))
+	if err != nil {
+		return err
+	}
+
+	top.Push(local)
+	return nil
 }
 
-func (vm *VM) execGetArg() {
-	vm.stack.Top().Push(vm.stack.Prev().Pop())
+func (vm *VM) execGetArg() error {
+	prev, err := vm.stack.Prev()
+	if err != nil {
+		return err
+	}
+
+	arg, err := prev.Pop()
+	if err != nil {
+		return err
+	}
+
+	vm.stack.Top().Push(arg)
+	return nil
 }
 
-func (vm *VM) execAdd() {
+func (vm *VM) execAdd() error {
 	top := vm.stack.Top()
 
-	x := top.Pop()
-	y := top.Pop()
+	x, err := top.Pop()
+	if err != nil {
+		return err
+	}
+	y, err := top.Pop()
+	if err != nil {
+		return err
+	}
 
 	var res value.Value
 
@@ -54,7 +81,11 @@ func (vm *VM) execAdd() {
 			yv := float64(y.Data().(value.FloatData))
 			res = value.NewFloat(float64(xv) + yv)
 		default:
-			panic("invalid operand types")
+			return ErrInvalidOperandTypes{
+				Op: code.OpAdd,
+				X:  x.Type(),
+				Y:  y.Type(),
+			}
 		}
 	case value.FloatType:
 		xv := float64(x.Data().(value.FloatData))
@@ -66,27 +97,46 @@ func (vm *VM) execAdd() {
 			yv := float64(y.Data().(value.FloatData))
 			res = value.NewFloat(xv + yv)
 		default:
-			panic("invalid operand types")
+			return ErrInvalidOperandTypes{
+				Op: code.OpAdd,
+				X:  x.Type(),
+				Y:  y.Type(),
+			}
 		}
 	case value.StringType:
 		switch y.Type().Kind {
 		case value.StringType:
 			res = value.NewString(string(x.Data().(value.StringData)) + string(y.Data().(value.StringData)))
 		default:
-			panic("invalid operand types")
+			return ErrInvalidOperandTypes{
+				Op: code.OpAdd,
+				X:  x.Type(),
+				Y:  y.Type(),
+			}
 		}
 	default:
-		panic("invalid operand types")
+		return ErrInvalidOperandTypes{
+			Op: code.OpAdd,
+			X:  x.Type(),
+			Y:  y.Type(),
+		}
 	}
 
 	top.Push(res)
+	return nil
 }
 
-func (vm *VM) execSub() {
+func (vm *VM) execSub() error {
 	top := vm.stack.Top()
 
-	x := top.Pop()
-	y := top.Pop()
+	x, err := top.Pop()
+	if err != nil {
+		return err
+	}
+	y, err := top.Pop()
+	if err != nil {
+		return err
+	}
 
 	var res value.Value
 
@@ -101,7 +151,11 @@ func (vm *VM) execSub() {
 			yv := float64(y.Data().(value.FloatData))
 			res = value.NewFloat(float64(xv) - yv)
 		default:
-			panic("invalid operand types")
+			return ErrInvalidOperandTypes{
+				Op: code.OpSub,
+				X:  x.Type(),
+				Y:  y.Type(),
+			}
 		}
 	case value.FloatType:
 		xv := float64(x.Data().(value.FloatData))
@@ -113,31 +167,55 @@ func (vm *VM) execSub() {
 			yv := float64(y.Data().(value.FloatData))
 			res = value.NewFloat(xv - yv)
 		default:
-			panic("invalid operand types")
+			return ErrInvalidOperandTypes{
+				Op: code.OpSub,
+				X:  x.Type(),
+				Y:  y.Type(),
+			}
 		}
 	default:
-		panic("invalid operand types")
+		return ErrInvalidOperandTypes{
+			Op: code.OpSub,
+			X:  x.Type(),
+			Y:  y.Type(),
+		}
 	}
 
 	top.Push(res)
+	return nil
 }
 
-func (vm *VM) execIndex() {
+func (vm *VM) execIndex() error {
 	top := vm.stack.Top()
 
-	v := top.Pop()
-	i := top.Pop()
+	v, err := top.Pop()
+	if err != nil {
+		return err
+	}
+	i, err := top.Pop()
+	if err != nil {
+		return err
+	}
 
 	switch v.Type().Kind {
 	case value.ArrayType:
 		arr := v.Data().([]value.Value)
 		idx := i.Data().(int64)
 		if idx < 0 || idx >= int64(len(arr)) {
-			panic("index out of bounds")
+			return ErrArrayIndexOutOfBounds{
+				Index: int(idx),
+				Len:   len(arr),
+			}
 		}
 
 		top.Push(arr[idx])
 	default:
-		panic("invalid operand types")
+		return ErrInvalidOperandTypes{
+			Op: code.OpIndex,
+			X:  v.Type(),
+			Y:  i.Type(),
+		}
 	}
+
+	return nil
 }