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/stack.go | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) (limited to 'pkg/lang/vm/stack.go') diff --git a/pkg/lang/vm/stack.go b/pkg/lang/vm/stack.go index 1d028e5..9cf7db8 100644 --- a/pkg/lang/vm/stack.go +++ b/pkg/lang/vm/stack.go @@ -1,6 +1,8 @@ package vm -import "jinx/pkg/lang/vm/value" +import ( + "jinx/pkg/lang/vm/value" +) type CallStack []*LocalStack @@ -8,34 +10,64 @@ func NewCallStack() CallStack { return []*LocalStack{{}} } -func (cs *CallStack) Push() { +func (cs *CallStack) Push() error { + if len(*cs) > 1000 { + return ErrCallStackOverflow + } + *cs = append(*cs, &LocalStack{}) + return nil } -func (cs *CallStack) Pop() { +func (cs *CallStack) Pop() error { + if len(*cs) <= 1 { + return ErrCantPopRootFrame + } + *cs = (*cs)[:len(*cs)-1] + return nil } func (cs *CallStack) Top() *LocalStack { return (*cs)[len(*cs)-1] } -func (cs *CallStack) Prev() *LocalStack { - return (*cs)[len(*cs)-2] +func (cs *CallStack) Prev() (*LocalStack, error) { + if len(*cs) <= 1 { + return nil, ErrNoPreviousCallFrame + } + + return (*cs)[len(*cs)-2], nil } type LocalStack []value.Value -func (ls *LocalStack) Push(v value.Value) { +func (ls *LocalStack) Push(v value.Value) error { + if len(*ls) > 1000 { + return ErrLocalStackOverflow + } + *ls = append(*ls, v) + return nil } -func (ls *LocalStack) Pop() value.Value { +func (ls *LocalStack) Pop() (value.Value, error) { + if len(*ls) == 0 { + return value.Value{}, ErrCallFrameEmpty + } + v := (*ls)[len(*ls)-1] *ls = (*ls)[:len(*ls)-1] - return v + return v, nil } -func (ls *LocalStack) At(at int) value.Value { - return (*ls)[at] +func (ls *LocalStack) At(at int) (value.Value, error) { + if at >= len(*ls) { + return value.Value{}, ErrLocalIndexOutOfBounds{ + Index: at, + Len: len(*ls), + } + } + + return (*ls)[at], nil } -- cgit 1.4.1