about summary refs log tree commit diff
path: root/pkg/lang/vm/vm.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/vm.go')
-rw-r--r--pkg/lang/vm/vm.go36
1 files changed, 23 insertions, 13 deletions
diff --git a/pkg/lang/vm/vm.go b/pkg/lang/vm/vm.go
index 6746e64..c538841 100644
--- a/pkg/lang/vm/vm.go
+++ b/pkg/lang/vm/vm.go
@@ -19,19 +19,28 @@ func New(code *code.Code) *VM {
 	}
 }
 
-func (vm *VM) GetResult() string {
-	return fmt.Sprintf("%v", vm.stack.Top().Pop().Data())
+func (vm *VM) GetResult() (string, error) {
+	res, err := vm.stack.Top().Pop()
+	if err != nil {
+		return "", err
+	}
+
+	return fmt.Sprintf("%v", res.Data()), nil
 }
 
-func (vm *VM) Run() {
+func (vm *VM) Run() error {
 	for vm.pc < vm.code.Len() {
 		op, advance := vm.code.GetOp(vm.pc)
 		vm.pc += advance
 
-		if vm.step(op) == stepDecisionHalt {
-			return
+		if decision, err := vm.step(op); err != nil {
+			return err
+		} else if decision == stepDecisionHalt {
+			return nil
 		}
 	}
+
+	return nil
 }
 
 type stepDecision int
@@ -41,12 +50,13 @@ const (
 	stepDecisionHalt
 )
 
-func (vm *VM) step(op code.Op) stepDecision {
+func (vm *VM) step(op code.Op) (stepDecision, error) {
+	var err error
 	switch op {
 	case code.OpNop:
 		// do nothing
 	case code.OpHalt:
-		return stepDecisionHalt
+		return stepDecisionHalt, nil
 
 	case code.OpPushInt:
 		x, advance := vm.code.GetInt(vm.pc)
@@ -82,7 +92,7 @@ func (vm *VM) step(op code.Op) stepDecision {
 		offset, advance := vm.code.GetInt(vm.pc)
 		vm.pc += advance
 
-		vm.execGetLocal(int(offset))
+		err = vm.execGetLocal(int(offset))
 	case code.OpGetMember:
 		panic("not implemented")
 	case code.OpGetArg:
@@ -91,11 +101,11 @@ func (vm *VM) step(op code.Op) stepDecision {
 		panic("not implemented")
 
 	case code.OpAdd:
-		vm.execAdd()
+		err = vm.execAdd()
 	case code.OpSub:
-		vm.execSub()
+		err = vm.execSub()
 	case code.OpIndex:
-		vm.execIndex()
+		err = vm.execIndex()
 	case code.OpCall:
 		panic("not implemented")
 
@@ -109,8 +119,8 @@ func (vm *VM) step(op code.Op) stepDecision {
 		panic("not implemented")
 
 	default:
-		panic(fmt.Errorf("unimplemented op: %v", op))
+		err = ErrInvalidOp{Op: uint8(op)}
 	}
 
-	return stepDecisionContinue
+	return stepDecisionContinue, err
 }