From 2ddb215e3b0d3818b3fac8f315d97d8020eb699f Mon Sep 17 00:00:00 2001 From: Mel Date: Sat, 28 May 2022 14:28:46 +0000 Subject: Extract stack package and hide behind interface --- pkg/lang/vm/errors.go | 26 ------- pkg/lang/vm/exec.go | 24 +++--- pkg/lang/vm/mem/cell.go | 2 +- pkg/lang/vm/mem/mem.go | 32 +++++--- pkg/lang/vm/stack.go | 158 -------------------------------------- pkg/lang/vm/stack/errors.go | 34 +++++++++ pkg/lang/vm/stack/stack.go | 180 ++++++++++++++++++++++++++++++++++++++++++++ pkg/lang/vm/utils.go | 2 +- pkg/lang/vm/value/cells.go | 8 +- pkg/lang/vm/value/data.go | 20 ++--- pkg/lang/vm/value/value.go | 8 +- pkg/lang/vm/vm.go | 7 +- 12 files changed, 272 insertions(+), 229 deletions(-) delete mode 100644 pkg/lang/vm/stack.go create mode 100644 pkg/lang/vm/stack/errors.go create mode 100644 pkg/lang/vm/stack/stack.go (limited to 'pkg/lang/vm') diff --git a/pkg/lang/vm/errors.go b/pkg/lang/vm/errors.go index 2f5b56a..a717c09 100644 --- a/pkg/lang/vm/errors.go +++ b/pkg/lang/vm/errors.go @@ -25,35 +25,9 @@ func (e Error) Error() string { // Fatal errors var ( - ErrStackOverflow = errors.New("stack overflow (max depth: 1000)") - ErrStackUnderflow = errors.New("local stack underflow") - - ErrReachedMaxCallDepth = errors.New("reached max call depth (max depth: 1000)") - ErrReachedRootCallFrame = errors.New("reached root call frame") - - ErrCallBaseCantBeNegative = errors.New("call base cannot be negative") - ErrEnvNotSet = errors.New("env not set") ) -type ErrLocalIndexOutOfBounds struct { - Index int - Len int -} - -func (e ErrLocalIndexOutOfBounds) Error() string { - return fmt.Sprintf("local index out of bounds: %d (len: %d)", e.Index, e.Len) -} - -type ErrStackIndexOutOfBounds struct { - Index int - Len int -} - -func (e ErrStackIndexOutOfBounds) Error() string { - return fmt.Sprintf("stack index out of bounds: %d (len: %d)", e.Index, e.Len) -} - type ErrInvalidOp struct { Op uint8 } diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go index c9b8615..bd4cdf5 100644 --- a/pkg/lang/vm/exec.go +++ b/pkg/lang/vm/exec.go @@ -15,7 +15,7 @@ func (vm *VM) execPushFloat(x float64) { } func (vm *VM) execPushString(str string) error { - val, err := value.NewString(&vm.memory, str) + val, err := value.NewString(vm.memory, str) if err != nil { return err } @@ -33,7 +33,7 @@ func (vm *VM) execPushNull() { } func (vm *VM) execPushArray() error { - val, err := value.NewArray(&vm.memory, []value.Value{}) + val, err := value.NewArray(vm.memory, []value.Value{}) if err != nil { return err } @@ -52,7 +52,7 @@ func (vm *VM) execGetLocal(offset int) error { return err } - v := local.Clone(&vm.memory) + v := local.Clone(vm.memory) vm.stack.Push(v) return nil @@ -75,7 +75,7 @@ func (vm *VM) execGetEnv(envIndex int) error { if outletCell != nil { // Outlet is not null, so value escaped. outlet := outletCell.(value.OutletCell).Get() - val := outlet.Clone(&vm.memory) + val := outlet.Clone(vm.memory) vm.stack.Push(val) return nil } @@ -87,7 +87,7 @@ func (vm *VM) execGetEnv(envIndex int) error { return err } - val = val.Clone(&vm.memory) + val = val.Clone(vm.memory) vm.stack.Push(val) return nil @@ -114,7 +114,7 @@ func (vm *VM) execSetEnv(envIndex int) error { if outletCell != nil { // Outlet is not null, so value escaped. outlet := outletCell.(value.OutletCell).Get() - outlet.Drop(&vm.memory) + outlet.Drop(vm.memory) vm.memory.Set(outletPtr, value.OutletCell(new)) return nil } @@ -125,7 +125,7 @@ func (vm *VM) execSetEnv(envIndex int) error { return err } - old.Drop(&vm.memory) + old.Drop(vm.memory) return vm.stack.Set(stackIndex, new) } @@ -336,7 +336,7 @@ func (vm *VM) execIndex() error { switch i.Type().Kind { case value.IntType: idx := i.Data().(value.IntData).Get() - len, err := arr.Len(&vm.memory) + len, err := arr.Len(vm.memory) if err != nil { return err } @@ -347,11 +347,11 @@ func (vm *VM) execIndex() error { } } - val, err := arr.At(&vm.memory, int(idx)) + val, err := arr.At(vm.memory, int(idx)) if err != nil { return err } - val = val.Clone(&vm.memory) + val = val.Clone(vm.memory) vm.stack.Push(val) default: return ErrInvalidOperandTypes{ @@ -506,7 +506,7 @@ func (vm *VM) execTempArrLen() error { switch a.Type().Kind { case value.ArrayType: arr := a.Data().(value.ArrayData) - len, err := arr.Len(&vm.memory) + len, err := arr.Len(vm.memory) if err != nil { return err } @@ -535,7 +535,7 @@ func (vm *VM) execTempArrPush() error { switch a.Type().Kind { case value.ArrayType: arr := a.Data().(value.ArrayData) - arr.Push(&vm.memory, e) + arr.Push(vm.memory, e) default: return ErrInvalidOperandType{ Op: code.OpTempArrPush, diff --git a/pkg/lang/vm/mem/cell.go b/pkg/lang/vm/mem/cell.go index fcf9a50..830d382 100644 --- a/pkg/lang/vm/mem/cell.go +++ b/pkg/lang/vm/mem/cell.go @@ -39,5 +39,5 @@ type cell struct { } type CellData interface { - DropCell(*Mem) + DropCell(Mem) } diff --git a/pkg/lang/vm/mem/mem.go b/pkg/lang/vm/mem/mem.go index bdcf01f..a645ee2 100644 --- a/pkg/lang/vm/mem/mem.go +++ b/pkg/lang/vm/mem/mem.go @@ -1,6 +1,18 @@ package mem -type Mem struct { +type Mem interface { + Allocate(kind CellKind) (Ptr, error) + + Set(ptr Ptr, v CellData) error + Get(ptr Ptr) (CellData, error) + Is(ptr Ptr, kind CellKind) bool + Kind(ptr Ptr) CellKind + + Retain(ptr Ptr) error + Release(ptr Ptr) error +} + +type memImpl struct { cells []cell free []Ptr } @@ -11,13 +23,13 @@ func New() Mem { // Reserve NullPtr cells[NullPtr].kind = CellKindForbidden - return Mem{ + return &memImpl{ cells: cells, free: make([]Ptr, 0), } } -func (m *Mem) Allocate(kind CellKind) (Ptr, error) { +func (m *memImpl) Allocate(kind CellKind) (Ptr, error) { if len(m.free) > 0 { idx := m.free[len(m.free)-1] m.free = m.free[:len(m.free)-1] @@ -40,7 +52,7 @@ func (m *Mem) Allocate(kind CellKind) (Ptr, error) { } -func (m *Mem) Set(ptr Ptr, v CellData) error { +func (m *memImpl) Set(ptr Ptr, v CellData) error { if err := m.validPtr(ptr); err != nil { return err } @@ -49,7 +61,7 @@ func (m *Mem) Set(ptr Ptr, v CellData) error { return nil } -func (m *Mem) Get(ptr Ptr) (CellData, error) { +func (m *memImpl) Get(ptr Ptr) (CellData, error) { if err := m.validPtr(ptr); err != nil { return nil, err } @@ -57,7 +69,7 @@ func (m *Mem) Get(ptr Ptr) (CellData, error) { return m.cells[ptr].data, nil } -func (m *Mem) Is(ptr Ptr, kind CellKind) bool { +func (m *memImpl) Is(ptr Ptr, kind CellKind) bool { if ptr >= Ptr(len(m.cells)) { return false } @@ -65,7 +77,7 @@ func (m *Mem) Is(ptr Ptr, kind CellKind) bool { return m.cells[ptr].kind == kind } -func (m *Mem) Kind(ptr Ptr) CellKind { +func (m *memImpl) Kind(ptr Ptr) CellKind { if ptr >= Ptr(len(m.cells)) { return CellKindForbidden } @@ -73,7 +85,7 @@ func (m *Mem) Kind(ptr Ptr) CellKind { return m.cells[ptr].kind } -func (m *Mem) Retain(ptr Ptr) error { +func (m *memImpl) Retain(ptr Ptr) error { if err := m.validPtr(ptr); err != nil { return err } @@ -82,7 +94,7 @@ func (m *Mem) Retain(ptr Ptr) error { return nil } -func (m *Mem) Release(ptr Ptr) error { +func (m *memImpl) Release(ptr Ptr) error { if err := m.validPtr(ptr); err != nil { return err } @@ -99,7 +111,7 @@ func (m *Mem) Release(ptr Ptr) error { return nil } -func (m *Mem) validPtr(ptr Ptr) error { +func (m *memImpl) validPtr(ptr Ptr) error { if ptr >= Ptr(len(m.cells)) { return ErrInvalidMemAccess{ptr} } diff --git a/pkg/lang/vm/stack.go b/pkg/lang/vm/stack.go deleted file mode 100644 index a8965ec..0000000 --- a/pkg/lang/vm/stack.go +++ /dev/null @@ -1,158 +0,0 @@ -package vm - -import ( - "jinx/pkg/lang/vm/mem" - "jinx/pkg/lang/vm/value" -) - -type Stack struct { - data []value.Value - calls []callFrame -} - -func NewStack() Stack { - data := make([]value.Value, 0, 64) - calls := make([]callFrame, 0, 8) - - calls = append(calls, callFrame{ - pc: 0, - returnPc: 0, - base: 0, - }) - - return Stack{ - data: data, - calls: calls, - } -} - -func (stack *Stack) Push(value value.Value) { - stack.data = append(stack.data, value) -} - -func (stack *Stack) Pop() (value.Value, error) { - if stack.IsEmpty() || stack.ReachedBaseOfCall() { - return value.Value{}, ErrStackUnderflow - } - - v, err := stack.Top() - if err != nil { - return value.Value{}, err - } - - stack.data = stack.data[:stack.Len()-1] - return v, nil -} - -func (stack *Stack) Get(index int) (value.Value, error) { - if index < 0 || index >= stack.Len() { - return value.Value{}, ErrStackIndexOutOfBounds{Index: index, Len: stack.Len()} - } - - return stack.data[index], nil -} - -func (stack *Stack) Set(index int, value value.Value) error { - if index < 0 || index >= stack.Len() { - return ErrStackIndexOutOfBounds{Index: index, Len: stack.Len()} - } - - stack.data[index] = value - return nil -} - -func (stack *Stack) Local(offset int) (value.Value, error) { - if stack.ReachedBaseOfCall() { - return value.Value{}, ErrStackUnderflow - } - - return stack.Get(stack.LocalToStackIndex(offset)) -} - -func (stack *Stack) Top() (value.Value, error) { - if stack.IsEmpty() || stack.ReachedBaseOfCall() { - return value.Value{}, ErrStackUnderflow - } - - 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, env mem.Ptr) error { - if stack.CallDepth() == 1000 { - return ErrReachedMaxCallDepth - } - - stack.calls = append(stack.calls, callFrame{ - pc: newPc, - returnPc: returnPc, - base: stack.Len(), - env: env, - }) - - 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) CurrentCallEnv() mem.Ptr { - if stack.CallDepth() == 0 || stack.TopCall().env.IsNull() { - return mem.NullPtr - } - - return stack.TopCall().env -} - -func (stack *Stack) ShiftTopCallBase(by int) error { - call := stack.TopCall() - newBase := call.base - by - - if newBase < 0 { - return ErrCallBaseCantBeNegative - } - - call.base = newBase - return nil -} - -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() -} - -func (stack *Stack) LocalToStackIndex(local int) int { - if stack.CallDepth() == 0 { - return local - } - return stack.TopCall().base + local -} - -type callFrame struct { - pc int // Beginning of the called function. - returnPc int // Where to return to after the called function returns. - base int // Base of the local variables on the data stack. - env mem.Ptr // Environment of the called function. -} diff --git a/pkg/lang/vm/stack/errors.go b/pkg/lang/vm/stack/errors.go new file mode 100644 index 0000000..55ef2ea --- /dev/null +++ b/pkg/lang/vm/stack/errors.go @@ -0,0 +1,34 @@ +package stack + +import ( + "errors" + "fmt" +) + +var ( + ErrStackOverflow = errors.New("stack overflow (max depth: 1000)") + ErrStackUnderflow = errors.New("local stack underflow") + + ErrReachedMaxCallDepth = errors.New("reached max call depth (max depth: 1000)") + ErrReachedRootCallFrame = errors.New("reached root call frame") + + ErrCallBaseCantBeNegative = errors.New("call base cannot be negative") +) + +type ErrLocalIndexOutOfBounds struct { + Index int + Len int +} + +func (e ErrLocalIndexOutOfBounds) Error() string { + return fmt.Sprintf("local index out of bounds: %d (len: %d)", e.Index, e.Len) +} + +type ErrStackIndexOutOfBounds struct { + Index int + Len int +} + +func (e ErrStackIndexOutOfBounds) Error() string { + return fmt.Sprintf("stack index out of bounds: %d (len: %d)", e.Index, e.Len) +} diff --git a/pkg/lang/vm/stack/stack.go b/pkg/lang/vm/stack/stack.go new file mode 100644 index 0000000..314d0c6 --- /dev/null +++ b/pkg/lang/vm/stack/stack.go @@ -0,0 +1,180 @@ +package stack + +import ( + "jinx/pkg/lang/vm/mem" + "jinx/pkg/lang/vm/value" +) + +type Stack interface { + Push(value value.Value) + Pop() (value.Value, error) + + Get(index int) (value.Value, error) + Set(index int, value value.Value) error + Local(offset int) (value.Value, error) + Top() (value.Value, error) + + Len() int + IsEmpty() bool + + PushCall(newPc, returnPc int, env mem.Ptr) error + PopCall() (int, error) + ShiftTopCallBase(by int) error + + CurrentCallEnv() mem.Ptr + CallDepth() int + ReachedBaseOfCall() bool + LocalToStackIndex(local int) int +} + +type stackImpl struct { + data []value.Value + calls []callFrame +} + +func New() Stack { + data := make([]value.Value, 0, 64) + calls := make([]callFrame, 0, 8) + + calls = append(calls, callFrame{ + pc: 0, + returnPc: 0, + base: 0, + }) + + return &stackImpl{ + data: data, + calls: calls, + } +} + +func (stack *stackImpl) Push(value value.Value) { + stack.data = append(stack.data, value) +} + +func (stack *stackImpl) Pop() (value.Value, error) { + if stack.IsEmpty() || stack.ReachedBaseOfCall() { + return value.Value{}, ErrStackUnderflow + } + + v, err := stack.Top() + if err != nil { + return value.Value{}, err + } + + stack.data = stack.data[:stack.Len()-1] + return v, nil +} + +func (stack *stackImpl) Get(index int) (value.Value, error) { + if index < 0 || index >= stack.Len() { + return value.Value{}, ErrStackIndexOutOfBounds{Index: index, Len: stack.Len()} + } + + return stack.data[index], nil +} + +func (stack *stackImpl) Set(index int, value value.Value) error { + if index < 0 || index >= stack.Len() { + return ErrStackIndexOutOfBounds{Index: index, Len: stack.Len()} + } + + stack.data[index] = value + return nil +} + +func (stack *stackImpl) Local(offset int) (value.Value, error) { + if stack.ReachedBaseOfCall() { + return value.Value{}, ErrStackUnderflow + } + + return stack.Get(stack.LocalToStackIndex(offset)) +} + +func (stack *stackImpl) Top() (value.Value, error) { + if stack.IsEmpty() || stack.ReachedBaseOfCall() { + return value.Value{}, ErrStackUnderflow + } + + return stack.data[stack.Len()-1], nil +} + +func (stack *stackImpl) Len() int { + return len(stack.data) +} + +func (stack *stackImpl) IsEmpty() bool { + return len(stack.data) == 0 +} + +func (stack *stackImpl) PushCall(newPc, returnPc int, env mem.Ptr) error { + if stack.CallDepth() == 1000 { + return ErrReachedMaxCallDepth + } + + stack.calls = append(stack.calls, callFrame{ + pc: newPc, + returnPc: returnPc, + base: stack.Len(), + env: env, + }) + + return nil +} + +func (stack *stackImpl) 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 *stackImpl) ShiftTopCallBase(by int) error { + call := stack.topCall() + newBase := call.base - by + + if newBase < 0 { + return ErrCallBaseCantBeNegative + } + + call.base = newBase + return nil +} + +func (stack *stackImpl) CurrentCallEnv() mem.Ptr { + if stack.CallDepth() == 0 || stack.topCall().env.IsNull() { + return mem.NullPtr + } + + return stack.topCall().env +} + +func (stack *stackImpl) CallDepth() int { + return len(stack.calls) +} + +func (stack *stackImpl) ReachedBaseOfCall() bool { + return stack.topCall().base == stack.Len() +} + +func (stack *stackImpl) LocalToStackIndex(local int) int { + if stack.CallDepth() == 0 { + return local + } + return stack.topCall().base + local +} + +func (stack *stackImpl) topCall() *callFrame { + return &stack.calls[len(stack.calls)-1] +} + +type callFrame struct { + pc int // Beginning of the called function. + returnPc int // Where to return to after the called function returns. + base int // Base of the local variables on the data stack. + env mem.Ptr // Environment of the called function. +} diff --git a/pkg/lang/vm/utils.go b/pkg/lang/vm/utils.go index 95c0298..11c195e 100644 --- a/pkg/lang/vm/utils.go +++ b/pkg/lang/vm/utils.go @@ -10,7 +10,7 @@ func (vm *VM) popAndDrop() (value.Value, error) { if err != nil { return value.Value{}, err } - v.Drop(&vm.memory) + v.Drop(vm.memory) return v, nil } diff --git a/pkg/lang/vm/value/cells.go b/pkg/lang/vm/value/cells.go index 17a0916..1c34762 100644 --- a/pkg/lang/vm/value/cells.go +++ b/pkg/lang/vm/value/cells.go @@ -4,7 +4,7 @@ import "jinx/pkg/lang/vm/mem" type ArrayCell []Value -func (a ArrayCell) DropCell(m *mem.Mem) { +func (a ArrayCell) DropCell(m mem.Mem) { for _, v := range a { v.Drop(m) } @@ -16,7 +16,7 @@ func (a ArrayCell) Get() []Value { type StringCell string -func (s StringCell) DropCell(m *mem.Mem) { +func (s StringCell) DropCell(m mem.Mem) { } func (s StringCell) Get() string { @@ -25,7 +25,7 @@ func (s StringCell) Get() string { type OutletCell Value -func (o OutletCell) DropCell(m *mem.Mem) { +func (o OutletCell) DropCell(m mem.Mem) { Value(o).Drop(m) } @@ -35,7 +35,7 @@ func (o OutletCell) Get() Value { type EnvCell Env -func (e EnvCell) DropCell(m *mem.Mem) { +func (e EnvCell) DropCell(m mem.Mem) { for _, v := range e.references { m.Release(v.outlet) } diff --git a/pkg/lang/vm/value/data.go b/pkg/lang/vm/value/data.go index 2e3b3e6..4e39bc8 100644 --- a/pkg/lang/vm/value/data.go +++ b/pkg/lang/vm/value/data.go @@ -8,7 +8,7 @@ import ( ) type Data interface { - String(*mem.Mem) (string, error) + String(mem.Mem) (string, error) } type IntData int64 @@ -17,7 +17,7 @@ func (i IntData) Get() int64 { return int64(i) } -func (i IntData) String(_ *mem.Mem) (string, error) { +func (i IntData) String(_ mem.Mem) (string, error) { return strconv.FormatInt(int64(i), 10), nil } @@ -27,7 +27,7 @@ func (f FloatData) Get() float64 { return float64(f) } -func (f FloatData) String(_ *mem.Mem) (string, error) { +func (f FloatData) String(_ mem.Mem) (string, error) { return strconv.FormatFloat(float64(f), 'f', -1, 64), nil } @@ -35,7 +35,7 @@ type StringData struct { data mem.Ptr } -func (s StringData) String(m *mem.Mem) (string, error) { +func (s StringData) String(m mem.Mem) (string, error) { if data, err := m.Get(s.data); err == nil { return "\"" + data.(StringCell).Get() + "\"", nil } else { @@ -49,7 +49,7 @@ func (b BoolData) Get() bool { return bool(b) } -func (b BoolData) String(_ *mem.Mem) (string, error) { +func (b BoolData) String(_ mem.Mem) (string, error) { return strconv.FormatBool(bool(b)), nil } @@ -57,7 +57,7 @@ type ArrayData struct { data mem.Ptr } -func (a ArrayData) String(m *mem.Mem) (string, error) { +func (a ArrayData) String(m mem.Mem) (string, error) { val, err := m.Get(a.data) if err != nil { return "", err @@ -81,7 +81,7 @@ func (a ArrayData) String(m *mem.Mem) (string, error) { return builder.String(), nil } -func (a ArrayData) Len(m *mem.Mem) (int, error) { +func (a ArrayData) Len(m mem.Mem) (int, error) { data, err := m.Get(a.data) if err != nil { return 0, err @@ -90,7 +90,7 @@ func (a ArrayData) Len(m *mem.Mem) (int, error) { return len(arr), nil } -func (a ArrayData) At(m *mem.Mem, i int) (Value, error) { +func (a ArrayData) At(m mem.Mem, i int) (Value, error) { data, err := m.Get(a.data) if err != nil { return Value{}, err @@ -99,7 +99,7 @@ func (a ArrayData) At(m *mem.Mem, i int) (Value, error) { return arr[i], nil } -func (a ArrayData) Push(m *mem.Mem, v Value) error { +func (a ArrayData) Push(m mem.Mem, v Value) error { data, err := m.Get(a.data) if err != nil { return err @@ -131,7 +131,7 @@ func (f FunctionData) WithEnv(env mem.Ptr) FunctionData { return FunctionData{pc: f.pc, env: env} } -func (f FunctionData) String(_ *mem.Mem) (string, error) { +func (f FunctionData) String(_ mem.Mem) (string, error) { return fmt.Sprintf("", f.pc), nil } diff --git a/pkg/lang/vm/value/value.go b/pkg/lang/vm/value/value.go index f98740e..a2909ba 100644 --- a/pkg/lang/vm/value/value.go +++ b/pkg/lang/vm/value/value.go @@ -20,7 +20,7 @@ func NewFloat(x float64) Value { return Value{t: t, d: FloatData(x)} } -func NewString(m *mem.Mem, str string) (Value, error) { +func NewString(m mem.Mem, str string) (Value, error) { t := Type{Kind: StringType} ptr, err := m.Allocate(mem.CellKindString) @@ -38,7 +38,7 @@ func NewBool(b bool) Value { return Value{t: t, d: BoolData(b)} } -func NewArray(m *mem.Mem, arr []Value) (Value, error) { +func NewArray(m mem.Mem, arr []Value) (Value, error) { t := Type{Kind: ArrayType} ptr, err := m.Allocate(mem.CellKindArray) @@ -85,7 +85,7 @@ func (v Value) WithOutlet(outlet mem.Ptr) Value { return Value{t: v.t, d: v.d, outlet: outlet} } -func (v Value) Clone(m *mem.Mem) Value { +func (v Value) Clone(m mem.Mem) Value { if v.t.Kind == StringType { str := v.d.(StringData) m.Retain(str.data) @@ -104,7 +104,7 @@ func (v Value) Clone(m *mem.Mem) Value { return v } -func (v Value) Drop(m *mem.Mem) { +func (v Value) Drop(m mem.Mem) { // If value has an outlet, don't drop it and instead move it to the outlet. if !v.outlet.IsNull() { m.Set(v.outlet, OutletCell(v)) diff --git a/pkg/lang/vm/vm.go b/pkg/lang/vm/vm.go index 9c17a3f..2ac689b 100644 --- a/pkg/lang/vm/vm.go +++ b/pkg/lang/vm/vm.go @@ -3,12 +3,13 @@ package vm import ( "jinx/pkg/lang/vm/code" "jinx/pkg/lang/vm/mem" + "jinx/pkg/lang/vm/stack" ) type VM struct { code *code.Code pc int - stack Stack + stack stack.Stack memory mem.Mem } @@ -16,7 +17,7 @@ func New(code *code.Code) *VM { return &VM{ code: code, pc: 0, - stack: NewStack(), + stack: stack.New(), memory: mem.New(), } } @@ -27,7 +28,7 @@ func (vm *VM) GetResult() (string, error) { return "", err } - if str, err := res.Data().String(&vm.memory); err == nil { + if str, err := res.Data().String(vm.memory); err == nil { return str, nil } else { return "", err -- cgit 1.4.1