diff options
Diffstat (limited to 'pkg/lang/vm/exec.go')
| -rw-r--r-- | pkg/lang/vm/exec.go | 124 |
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 } |
