about summary refs log tree commit diff
path: root/pkg/lang/vm/utils.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/utils.go')
-rw-r--r--pkg/lang/vm/utils.go69
1 files changed, 69 insertions, 0 deletions
diff --git a/pkg/lang/vm/utils.go b/pkg/lang/vm/utils.go
new file mode 100644
index 0000000..95c0298
--- /dev/null
+++ b/pkg/lang/vm/utils.go
@@ -0,0 +1,69 @@
+package vm
+
+import (
+	"jinx/pkg/lang/vm/mem"
+	"jinx/pkg/lang/vm/value"
+)
+
+func (vm *VM) popAndDrop() (value.Value, error) {
+	v, err := vm.stack.Pop()
+	if err != nil {
+		return value.Value{}, err
+	}
+	v.Drop(&vm.memory)
+	return v, nil
+}
+
+func (vm *VM) popCallAndDrop() (int, error) {
+	envPtr := vm.stack.CurrentCallEnv()
+	vm.memory.Release(envPtr)
+
+	for !vm.stack.ReachedBaseOfCall() {
+		_, err := vm.popAndDrop()
+		if err != nil {
+			return 0, err
+		}
+	}
+
+	return vm.stack.PopCall()
+}
+
+func (vm *VM) getMemCell(ptr mem.Ptr, kind mem.CellKind, allowNil bool) (mem.CellData, error) {
+	if ptr.IsNull() {
+		return nil, ErrEnvNotSet
+	}
+
+	if !vm.memory.Is(ptr, kind) {
+		return nil, ErrUnexpectedMemCell{Ptr: ptr, Expected: mem.CellKindEnv, Got: vm.memory.Kind(ptr)}
+	}
+
+	cell, err := vm.memory.Get(ptr)
+	if err != nil {
+		return nil, err
+	}
+
+	if cell == nil {
+		if allowNil {
+			return nil, nil
+		}
+		return nil, ErrMemNilCell{Ptr: ptr}
+	}
+
+	ok := false
+	switch kind {
+	case mem.CellKindString:
+		_, ok = cell.(value.StringCell)
+	case mem.CellKindArray:
+		_, ok = cell.(value.ArrayCell)
+	case mem.CellKindEnv:
+		_, ok = cell.(value.EnvCell)
+	case mem.CellKindOutlet:
+		_, ok = cell.(value.OutletCell)
+	}
+
+	if !ok {
+		return nil, ErrCorruptedMemCell{Ptr: ptr}
+	}
+
+	return cell, nil
+}