about summary refs log tree commit diff
path: root/pkg/lang/vm/stack.go
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-05-18 19:37:47 +0200
committerMel <einebeere@gmail.com>2022-05-18 19:37:47 +0200
commite4d68d39ce7f990895686139cd5cba20d2b2ef89 (patch)
tree8862118abb2181f3bb244daaec5ced0497bc07fd /pkg/lang/vm/stack.go
parent089fa82b8f83695cb17b8f41d0376c03303e7663 (diff)
downloadjinx-e4d68d39ce7f990895686139cd5cba20d2b2ef89.tar.zst
jinx-e4d68d39ce7f990895686139cd5cba20d2b2ef89.zip
Handle errors gracefully in VM
Diffstat (limited to 'pkg/lang/vm/stack.go')
-rw-r--r--pkg/lang/vm/stack.go52
1 files changed, 42 insertions, 10 deletions
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
 }