From e4d68d39ce7f990895686139cd5cba20d2b2ef89 Mon Sep 17 00:00:00 2001 From: Mel Date: Wed, 18 May 2022 19:37:47 +0200 Subject: Handle errors gracefully in VM --- pkg/lang/vm/vm.go | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'pkg/lang/vm/vm.go') 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 } -- cgit 1.4.1