package vm import ( "jinx/pkg/lang/vm/code" "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() (code.Pos, error) { envPtr := vm.stack.CurrentCallEnv() vm.memory.Release(envPtr) for !vm.stack.ReachedBaseOfCall() { _, err := vm.popAndDrop() if err != nil { return code.Pos{}, 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, ErrNullPtrDereference{At: ptr} } 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) case mem.CellKindType: _, ok = cell.(value.TypeCell) case mem.CellKindObject: _, ok = cell.(value.ObjectCell) case mem.CellKindGlobal: _, ok = cell.(value.GlobalCell) } if !ok { return nil, ErrCorruptedMemCell{Ptr: ptr} } return cell, nil } func (vm *VM) module() int { return vm.pos.Module } func (vm *VM) pc() int { return vm.pos.PC } func (vm *VM) setPC(pc int) { vm.pos.PC = pc } func (vm *VM) advancePC(by int) { vm.pos.PC += by } func (vm *VM) setPos(pos code.Pos) { vm.pos = pos }