diff options
Diffstat (limited to 'pkg/lang/vm/utils.go')
| -rw-r--r-- | pkg/lang/vm/utils.go | 69 |
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 +} |
