diff options
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/lang/vm/exec.go | 91 | ||||
| -rw-r--r-- | pkg/lang/vm/mem/cell.go | 2 | ||||
| -rw-r--r-- | pkg/lang/vm/mem/mem.go | 4 | ||||
| -rw-r--r-- | pkg/lang/vm/mem/mem_test.go | 2 | ||||
| -rw-r--r-- | pkg/lang/vm/utils.go | 4 | ||||
| -rw-r--r-- | pkg/lang/vm/value/cells.go | 48 | ||||
| -rw-r--r-- | pkg/lang/vm/value/value.go | 35 |
7 files changed, 138 insertions, 48 deletions
diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go index a64751a..8cdcdcc 100644 --- a/pkg/lang/vm/exec.go +++ b/pkg/lang/vm/exec.go @@ -120,7 +120,11 @@ func (vm *VM) execGetGlobal(name string) error { return ErrNoSuchGlobal{GlobalName: name} } - v = v.Clone(vm.memory) + v, err = v.Clone(vm.memory) + if err != nil { + return err + } + vm.stack.Push(v) return nil } @@ -150,7 +154,10 @@ func (vm *VM) execGetLocal(offset int) error { return err } - v := local.Clone(vm.memory) + v, err := local.Clone(vm.memory) + if err != nil { + return err + } vm.stack.Push(v) return nil @@ -167,7 +174,9 @@ func (vm *VM) execSetLocal(offset int) error { return err } - local.Drop(vm.memory) + if err := local.Drop(vm.memory); err != nil { + return err + } stackIndex := vm.stack.LocalToStackIndex(offset) return vm.stack.Set(stackIndex, new) @@ -211,10 +220,17 @@ func (vm *VM) execGetMember(name string) error { objCell := cell.(value.ObjectCell) member, ok := objCell.Get()[name] if ok { - member = member.Clone(vm.memory) + member, err = member.Clone(vm.memory) + if err != nil { + return err + } vm.stack.Push(member) - parent.Drop(vm.memory) + + if err := parent.Drop(vm.memory); err != nil { + return err + } + return nil } } @@ -250,7 +266,11 @@ func (vm *VM) execGetMember(name string) error { // method = method.Clone(vm.memory) will only be necessary when we support methods with environments. vm.stack.Push(method) - parent.Drop(vm.memory) + + if err := parent.Drop(vm.memory); err != nil { + return err + } + return nil } } @@ -303,7 +323,9 @@ func (vm *VM) execGetMember(name string) error { val := value.NewFunction(code.Pos{}, 0).WithData(member) vm.stack.Push(val) - parent.Drop(vm.memory) + if err := parent.Drop(vm.memory); err != nil { + return err + } return nil } @@ -342,7 +364,9 @@ func (vm *VM) execSetMember(name string) error { return err } - parent.Drop(vm.memory) + if err := parent.Drop(vm.memory); err != nil { + return err + } // v was moved, no need to drop it. return nil @@ -365,7 +389,11 @@ 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, err := outlet.Clone(vm.memory) + if err != nil { + return err + } + vm.stack.Push(val) return nil } @@ -377,7 +405,11 @@ func (vm *VM) execGetEnv(envIndex int) error { return err } - val = val.Clone(vm.memory) + val, err = val.Clone(vm.memory) + if err != nil { + return err + } + vm.stack.Push(val) return nil @@ -404,7 +436,10 @@ 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) + if err := outlet.Drop(vm.memory); err != nil { + return err + } + vm.memory.Set(outletPtr, value.OutletCell(new)) return nil } @@ -415,7 +450,9 @@ func (vm *VM) execSetEnv(envIndex int) error { return err } - old.Drop(vm.memory) + if err := old.Drop(vm.memory); err != nil { + return err + } return vm.stack.Set(stackIndex, new) } @@ -583,8 +620,13 @@ func (vm *VM) execGenericBinaryOperation(op code.Op, fns typesToBinaryOperation) return err } - x.Drop(vm.memory) - y.Drop(vm.memory) + if err := x.Drop(vm.memory); err != nil { + return err + } + + if err := y.Drop(vm.memory); err != nil { + return err + } vm.stack.Push(res) return nil @@ -735,8 +777,13 @@ func (vm *VM) execEq() error { } result := func(res bool) error { - x.Drop(vm.memory) - y.Drop(vm.memory) + if err := x.Drop(vm.memory); err != nil { + return err + } + + if err := y.Drop(vm.memory); err != nil { + return err + } vm.stack.Push(value.NewBool(res)) return nil @@ -812,7 +859,12 @@ func (vm *VM) execIndex() error { if err != nil { return err } - val = val.Clone(vm.memory) + + val, err = val.Clone(vm.memory) + if err != nil { + return err + } + vm.stack.Push(val) default: return ErrInvalidOperandTypes{ @@ -1027,7 +1079,10 @@ func (vm *VM) execTempArrLen() error { } res := value.NewInt(int64(len)) vm.stack.Push(res) - a.Drop(vm.memory) + + if err := a.Drop(vm.memory); err != nil { + return err + } default: return ErrInvalidOperandTypes{ Op: code.OpTempArrLen, diff --git a/pkg/lang/vm/mem/cell.go b/pkg/lang/vm/mem/cell.go index 85d6c34..0a5e80c 100644 --- a/pkg/lang/vm/mem/cell.go +++ b/pkg/lang/vm/mem/cell.go @@ -49,6 +49,6 @@ type cell struct { } type CellData interface { - DropCell(Mem) + DropCell(Mem) error MatchingCellKind() CellKind } diff --git a/pkg/lang/vm/mem/mem.go b/pkg/lang/vm/mem/mem.go index 99412ea..b590bcc 100644 --- a/pkg/lang/vm/mem/mem.go +++ b/pkg/lang/vm/mem/mem.go @@ -144,7 +144,9 @@ func (m *memImpl) Release(ptr Ptr) error { c := m.cells[ptr].data if c != nil { - c.DropCell(m) + if err := c.DropCell(m); err != nil { + return err + } } m.cells[ptr] = cell{} diff --git a/pkg/lang/vm/mem/mem_test.go b/pkg/lang/vm/mem/mem_test.go index f916e49..0c74093 100644 --- a/pkg/lang/vm/mem/mem_test.go +++ b/pkg/lang/vm/mem/mem_test.go @@ -208,7 +208,7 @@ func TestChainDrop(t *testing.T) { assert.Equal(t, mem.CellKindArray, m.Kind(mem.Ptr(5))) assert.Equal(t, mem.CellKindEmpty, m.Kind(mem.Ptr(6))) - val.Drop(m) + assert.NoError(t, val.Drop(m)) for _, ptr := range []mem.Ptr{1, 2, 3, 4, 5, 6} { assert.Equal(t, mem.CellKindEmpty, m.Kind(ptr)) diff --git a/pkg/lang/vm/utils.go b/pkg/lang/vm/utils.go index 975d31b..eddcc11 100644 --- a/pkg/lang/vm/utils.go +++ b/pkg/lang/vm/utils.go @@ -12,7 +12,9 @@ func (vm *VM) popAndDrop() (value.Value, error) { if err != nil { return value.Value{}, err } - v.Drop(vm.memory) + if err := v.Drop(vm.memory); err != nil { + return value.Value{}, err + } return v, nil } diff --git a/pkg/lang/vm/value/cells.go b/pkg/lang/vm/value/cells.go index 19ecfde..646f3c1 100644 --- a/pkg/lang/vm/value/cells.go +++ b/pkg/lang/vm/value/cells.go @@ -1,16 +1,21 @@ package value import ( + "fmt" "jinx/pkg/lang/vm/code" "jinx/pkg/lang/vm/mem" ) type ArrayCell []Value -func (a ArrayCell) DropCell(m mem.Mem) { +func (a ArrayCell) DropCell(m mem.Mem) error { for _, v := range a { - v.Drop(m) + if err := v.Drop(m); err != nil { + return err + } } + + return nil } func (a ArrayCell) MatchingCellKind() mem.CellKind { @@ -23,7 +28,8 @@ func (a ArrayCell) Get() []Value { type StringCell string -func (s StringCell) DropCell(m mem.Mem) { +func (s StringCell) DropCell(m mem.Mem) error { + return nil } func (s StringCell) MatchingCellKind() mem.CellKind { @@ -38,10 +44,14 @@ type ObjectCell struct { Members map[string]Value } -func (o ObjectCell) DropCell(m mem.Mem) { +func (o ObjectCell) DropCell(m mem.Mem) error { for _, v := range o.Members { - v.Drop(m) + if err := v.Drop(m); err != nil { + return err + } } + + return nil } func (o ObjectCell) MatchingCellKind() mem.CellKind { @@ -54,17 +64,23 @@ func (o ObjectCell) Get() map[string]Value { type TypeCell Type -func (t TypeCell) DropCell(m mem.Mem) { +func (t TypeCell) DropCell(m mem.Mem) error { typ := t.Get() for _, f := range typ.Methods { // Wrap data in a Value to drop it. val := NewFunction(code.Pos{}, 0).WithData(f) - val.Drop(m) + if err := val.Drop(m); err != nil { + return err + } } for _, v := range typ.Statics { - v.Drop(m) + if err := v.Drop(m); err != nil { + return err + } } + + return nil } func (t TypeCell) MatchingCellKind() mem.CellKind { @@ -77,8 +93,8 @@ func (t TypeCell) Get() Type { type OutletCell Value -func (o OutletCell) DropCell(m mem.Mem) { - Value(o).Drop(m) +func (o OutletCell) DropCell(m mem.Mem) error { + return Value(o).Drop(m) } func (o OutletCell) MatchingCellKind() mem.CellKind { @@ -91,10 +107,14 @@ func (o OutletCell) Get() Value { type EnvCell Env -func (e EnvCell) DropCell(m mem.Mem) { +func (e EnvCell) DropCell(m mem.Mem) error { for _, v := range e.references { - m.Release(v.outlet) + if err := m.Release(v.outlet); err != nil { + return err + } } + + return nil } func (e EnvCell) MatchingCellKind() mem.CellKind { @@ -107,8 +127,8 @@ func (e EnvCell) Get() Env { type GlobalCell Value -func (g GlobalCell) DropCell(m mem.Mem) { - panic("global cell cannot be dropped") +func (g GlobalCell) DropCell(m mem.Mem) error { + return fmt.Errorf("global cell cannot be dropped") } func (g GlobalCell) MatchingCellKind() mem.CellKind { diff --git a/pkg/lang/vm/value/value.go b/pkg/lang/vm/value/value.go index cce2f5e..e2750f4 100644 --- a/pkg/lang/vm/value/value.go +++ b/pkg/lang/vm/value/value.go @@ -142,20 +142,28 @@ func (v Value) IsEmpty() bool { return v == Value{} } -func (v Value) Clone(m mem.Mem) Value { +func (v Value) Clone(m mem.Mem) (Value, error) { if v.t == StringType { str := v.d.(StringData) - m.Retain(str.data) + if err := m.Retain(str.data); err != nil { + return Value{}, err + } } if v.t == ArrayType { arr := v.d.(ArrayData) - m.Retain(arr.data) + if err := m.Retain(arr.data); err != nil { + return Value{}, err + } } if v.t == FunctionType { fn := v.d.(FunctionData) - m.Retain(fn.env) + if !fn.env.IsNull() { + if err := m.Retain(fn.env); err != nil { + return Value{}, err + } + } } // If value has an outlet don't copy it into the clone, @@ -163,28 +171,31 @@ func (v Value) Clone(m mem.Mem) Value { // I don't know if this fixes the entire problem, but it seems to work. v.outlet = mem.NullPtr - return v + return v, nil } -func (v Value) Drop(m mem.Mem) { +func (v Value) Drop(m mem.Mem) error { // 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)) - return + return m.Set(v.outlet, OutletCell(v)) } if v.t == StringType { str := v.d.(StringData) - m.Release(str.data) + return m.Release(str.data) } if v.t == ArrayType { arr := v.d.(ArrayData) - m.Release(arr.data) + return m.Release(arr.data) } if v.t == FunctionType { - f := v.d.(FunctionData) - m.Release(f.env) + fn := v.d.(FunctionData) + if !fn.env.IsNull() { + return m.Release(fn.env) + } } + + return nil } |
