about summary refs log tree commit diff
path: root/pkg/lang/vm/stack.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/stack.go')
-rw-r--r--pkg/lang/vm/stack.go45
1 files changed, 37 insertions, 8 deletions
diff --git a/pkg/lang/vm/stack.go b/pkg/lang/vm/stack.go
index 937be32..51e43c8 100644
--- a/pkg/lang/vm/stack.go
+++ b/pkg/lang/vm/stack.go
@@ -64,6 +64,39 @@ func (stack *Stack) Top() (value.Value, error) {
 	return stack.data[stack.Len()-1], nil
 }
 
+func (stack *Stack) Len() int {
+	return len(stack.data)
+}
+
+func (stack *Stack) IsEmpty() bool {
+	return len(stack.data) == 0
+}
+
+func (stack *Stack) PushCall(newPc, returnPc int) error {
+	if stack.CallDepth() == 1000 {
+		return ErrReachedMaxCallDepth
+	}
+
+	stack.calls = append(stack.calls, callFrame{
+		pc:       newPc,
+		returnPc: returnPc,
+		base:     stack.Len(),
+	})
+
+	return nil
+}
+
+func (stack *Stack) PopCall() (int, error) {
+	if stack.CallDepth() == 0 {
+		return 0, ErrReachedRootCallFrame
+	}
+
+	call := stack.TopCall()
+	stack.calls = stack.calls[:stack.CallDepth()-1]
+
+	return call.returnPc, nil
+}
+
 func (stack *Stack) ShiftTopCallBase(by int) error {
 	call := stack.TopCall()
 	newBase := call.base - by
@@ -76,18 +109,14 @@ func (stack *Stack) ShiftTopCallBase(by int) error {
 	return nil
 }
 
-func (stack *Stack) Len() int {
-	return len(stack.data)
-}
-
-func (stack *Stack) IsEmpty() bool {
-	return len(stack.data) == 0
-}
-
 func (stack *Stack) TopCall() *callFrame {
 	return &stack.calls[len(stack.calls)-1]
 }
 
+func (stack *Stack) CallDepth() int {
+	return len(stack.calls)
+}
+
 func (stack *Stack) ReachedBaseOfCall() bool {
 	return stack.TopCall().base == stack.Len()
 }