aboutsummaryrefslogtreecommitdiff
path: root/pkg/lang
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-05-28 01:22:17 +0000
committerGitHub <noreply@github.com>2022-05-28 01:22:17 +0000
commit0a7700112f82e634a957685bee0cbaa3458f4945 (patch)
tree847c397970d7d852bc988a7a01f4625eae443edb /pkg/lang
parent83d1dc87f3336d70ccda476627c70c282b7b6e11 (diff)
downloadjinx-0a7700112f82e634a957685bee0cbaa3458f4945.tar.zst
jinx-0a7700112f82e634a957685bee0cbaa3458f4945.zip
Harden VM Mem
Diffstat (limited to 'pkg/lang')
-rw-r--r--pkg/lang/vm/errors.go29
-rw-r--r--pkg/lang/vm/exec.go103
-rw-r--r--pkg/lang/vm/mem/cell.go25
-rw-r--r--pkg/lang/vm/mem/errors.go17
-rw-r--r--pkg/lang/vm/mem/mem.go74
-rw-r--r--pkg/lang/vm/utils.go69
-rw-r--r--pkg/lang/vm/value/cells.go46
-rw-r--r--pkg/lang/vm/value/data.go80
-rw-r--r--pkg/lang/vm/value/value.go26
-rw-r--r--pkg/lang/vm/vm.go31
10 files changed, 389 insertions, 111 deletions
diff --git a/pkg/lang/vm/errors.go b/pkg/lang/vm/errors.go
index 264dd3a..2f5b56a 100644
--- a/pkg/lang/vm/errors.go
+++ b/pkg/lang/vm/errors.go
@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"jinx/pkg/lang/vm/code"
+ "jinx/pkg/lang/vm/mem"
"jinx/pkg/lang/vm/text"
"jinx/pkg/lang/vm/value"
)
@@ -31,6 +32,8 @@ var (
ErrReachedRootCallFrame = errors.New("reached root call frame")
ErrCallBaseCantBeNegative = errors.New("call base cannot be negative")
+
+ ErrEnvNotSet = errors.New("env not set")
)
type ErrLocalIndexOutOfBounds struct {
@@ -59,6 +62,32 @@ func (e ErrInvalidOp) Error() string {
return fmt.Sprintf("invalid opcode: %d", e.Op)
}
+type ErrUnexpectedMemCell struct {
+ Ptr mem.Ptr
+ Expected mem.CellKind
+ Got mem.CellKind
+}
+
+func (e ErrUnexpectedMemCell) Error() string {
+ return fmt.Sprintf("unexpected memory cell at %s: expected %v, got %v", e.Ptr.String(), e.Expected, e.Got)
+}
+
+type ErrMemNilCell struct {
+ Ptr mem.Ptr
+}
+
+func (e ErrMemNilCell) Error() string {
+ return fmt.Sprintf("found no value at %s", e.Ptr.String())
+}
+
+type ErrCorruptedMemCell struct {
+ Ptr mem.Ptr
+}
+
+func (e ErrCorruptedMemCell) Error() string {
+ return fmt.Sprintf("corrupted memory cell at %s", e.Ptr.String())
+}
+
// Non-fatal errors, which will later be implemented as catchable exceptions
type ErrInvalidOperandType struct {
diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go
index ee977b7..c9b8615 100644
--- a/pkg/lang/vm/exec.go
+++ b/pkg/lang/vm/exec.go
@@ -14,8 +14,14 @@ func (vm *VM) execPushFloat(x float64) {
vm.stack.Push(value.NewFloat(x))
}
-func (vm *VM) execPushString(str string) {
- vm.stack.Push(value.NewString(&vm.memory, str))
+func (vm *VM) execPushString(str string) error {
+ val, err := value.NewString(&vm.memory, str)
+ if err != nil {
+ return err
+ }
+
+ vm.stack.Push(val)
+ return nil
}
func (vm *VM) execPushBool(b bool) {
@@ -26,8 +32,14 @@ func (vm *VM) execPushNull() {
vm.stack.Push(value.NewNull())
}
-func (vm *VM) execPushArray() {
- vm.stack.Push(value.NewArray(&vm.memory, []value.Value{}))
+func (vm *VM) execPushArray() error {
+ val, err := value.NewArray(&vm.memory, []value.Value{})
+ if err != nil {
+ return err
+ }
+
+ vm.stack.Push(val)
+ return nil
}
func (vm *VM) execPushFunction(pc int) {
@@ -47,15 +59,23 @@ func (vm *VM) execGetLocal(offset int) error {
}
func (vm *VM) execGetEnv(envIndex int) error {
- envPtr := vm.stack.CurrentCallEnv()
- env := vm.memory.Get(envPtr).(value.Env)
+ envCell, err := vm.getMemCell(vm.stack.CurrentCallEnv(), mem.CellKindEnv, false)
+ if err != nil {
+ return err
+ }
+ env := envCell.(value.EnvCell).Get()
// First check outlet.
outletPtr := env.GetOutlet(envIndex)
- outlet := vm.memory.Get(outletPtr)
- if outlet != nil {
+ outletCell, err := vm.getMemCell(outletPtr, mem.CellKindOutlet, true)
+ if err != nil {
+ return err
+ }
+
+ if outletCell != nil {
// Outlet is not null, so value escaped.
- val := outlet.(value.Value).Clone(&vm.memory)
+ outlet := outletCell.(value.OutletCell).Get()
+ val := outlet.Clone(&vm.memory)
vm.stack.Push(val)
return nil
}
@@ -79,14 +99,23 @@ func (vm *VM) execSetEnv(envIndex int) error {
return err
}
- envPtr := vm.stack.CurrentCallEnv()
- env := vm.memory.Get(envPtr).(value.Env)
+ envCell, err := vm.getMemCell(vm.stack.CurrentCallEnv(), mem.CellKindEnv, false)
+ if err != nil {
+ return err
+ }
+ env := envCell.(value.EnvCell).Get()
outletPtr := env.GetOutlet(envIndex)
- outlet := vm.memory.Get(outletPtr)
- if outlet != nil {
- outlet.(value.Value).Drop(&vm.memory)
- vm.memory.Set(outletPtr, new)
+ outletCell, err := vm.getMemCell(outletPtr, mem.CellKindOutlet, true)
+ if err != nil {
+ return err
+ }
+
+ if outletCell != nil {
+ // Outlet is not null, so value escaped.
+ outlet := outletCell.(value.OutletCell).Get()
+ outlet.Drop(&vm.memory)
+ vm.memory.Set(outletPtr, value.OutletCell(new))
return nil
}
@@ -119,8 +148,12 @@ func (vm *VM) execAddToEnv(localIndex int) error {
var envPtr mem.Ptr
if fn.Env().IsNull() {
// Allocate new Env.
- envPtr = vm.memory.Allocate(mem.CellKindEnv)
- vm.memory.Set(envPtr, value.NewEnv())
+ envPtr, err = vm.memory.Allocate(mem.CellKindEnv)
+ if err != nil {
+ return err
+ }
+
+ vm.memory.Set(envPtr, value.EnvCell(value.NewEnv()))
fn = fn.WithEnv(envPtr)
} else {
envPtr = fn.Env()
@@ -133,16 +166,24 @@ func (vm *VM) execAddToEnv(localIndex int) error {
}
if local.Outlet().IsNull() {
- outlet := vm.memory.Allocate(mem.CellKindOutlet)
- local = local.WithOutlet(outlet)
+ outletPtr, err := vm.memory.Allocate(mem.CellKindOutlet)
+ if err != nil {
+ return err
+ }
+ local = local.WithOutlet(outletPtr)
}
// Add local to env.
stackIndex := vm.stack.LocalToStackIndex(localIndex)
- env := vm.memory.Get(envPtr).(value.Env)
+ envCell, err := vm.getMemCell(envPtr, mem.CellKindEnv, false)
+ if err != nil {
+ return err
+ }
+
+ env := envCell.(value.EnvCell).Get()
env.Add(stackIndex, local.Outlet())
- vm.memory.Set(envPtr, env)
+ vm.memory.Set(envPtr, value.EnvCell(env))
// Push function back onto stack.
f = f.WithData(fn)
@@ -295,15 +336,22 @@ func (vm *VM) execIndex() error {
switch i.Type().Kind {
case value.IntType:
idx := i.Data().(value.IntData).Get()
- len := int64(arr.Len(&vm.memory))
- if idx < 0 || idx >= len {
+ len, err := arr.Len(&vm.memory)
+ if err != nil {
+ return err
+ }
+ if idx < 0 || idx >= int64(len) {
return ErrArrayIndexOutOfBounds{
Index: int(idx),
Len: int(len),
}
}
- val := arr.At(&vm.memory, int(idx)).Clone(&vm.memory)
+ val, err := arr.At(&vm.memory, int(idx))
+ if err != nil {
+ return err
+ }
+ val = val.Clone(&vm.memory)
vm.stack.Push(val)
default:
return ErrInvalidOperandTypes{
@@ -458,8 +506,11 @@ func (vm *VM) execTempArrLen() error {
switch a.Type().Kind {
case value.ArrayType:
arr := a.Data().(value.ArrayData)
- len := int64(arr.Len(&vm.memory))
- res := value.NewInt(len)
+ len, err := arr.Len(&vm.memory)
+ if err != nil {
+ return err
+ }
+ res := value.NewInt(int64(len))
vm.stack.Push(res)
default:
return ErrInvalidOperandTypes{
diff --git a/pkg/lang/vm/mem/cell.go b/pkg/lang/vm/mem/cell.go
index 3f052d5..fcf9a50 100644
--- a/pkg/lang/vm/mem/cell.go
+++ b/pkg/lang/vm/mem/cell.go
@@ -13,8 +13,31 @@ const (
CellKindForbidden
)
+func (c CellKind) String() string {
+ switch c {
+ case CellKindEmpty:
+ return "empty"
+ case CellKindString:
+ return "string"
+ case CellKindArray:
+ return "array"
+ case CellKindEnv:
+ return "env"
+ case CellKindOutlet:
+ return "outlet"
+ case CellKindForbidden:
+ return "forbidden"
+ default:
+ return "unknown"
+ }
+}
+
type cell struct {
kind CellKind
refs int
- data any
+ data CellData
+}
+
+type CellData interface {
+ DropCell(*Mem)
}
diff --git a/pkg/lang/vm/mem/errors.go b/pkg/lang/vm/mem/errors.go
new file mode 100644
index 0000000..e7a3f8f
--- /dev/null
+++ b/pkg/lang/vm/mem/errors.go
@@ -0,0 +1,17 @@
+package mem
+
+import "errors"
+
+var (
+ ErrMemOverflow = errors.New("memory overflow, cannot allocate more than 10000 memory cells")
+
+ ErrFatalNonFreeCell = errors.New("non-free cell marked as free")
+)
+
+type ErrInvalidMemAccess struct {
+ Ptr Ptr
+}
+
+func (e ErrInvalidMemAccess) Error() string {
+ return "invalid memory access at " + e.Ptr.String()
+}
diff --git a/pkg/lang/vm/mem/mem.go b/pkg/lang/vm/mem/mem.go
index 4cb6fc4..bdcf01f 100644
--- a/pkg/lang/vm/mem/mem.go
+++ b/pkg/lang/vm/mem/mem.go
@@ -2,7 +2,7 @@ package mem
type Mem struct {
cells []cell
- free []int
+ free []Ptr
}
func New() Mem {
@@ -13,69 +13,101 @@ func New() Mem {
return Mem{
cells: cells,
- free: make([]int, 0),
+ free: make([]Ptr, 0),
}
}
-func (m *Mem) Allocate(kind CellKind) Ptr {
+func (m *Mem) 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]
if m.cells[idx].kind != CellKindEmpty {
- panic("invalid free cell")
+ return NullPtr, ErrFatalNonFreeCell
}
m.cells[idx].kind = kind
- return Ptr(idx)
+ return Ptr(idx), nil
} else {
+ if len(m.cells) > 10000 {
+ return NullPtr, ErrMemOverflow
+ }
+
idx := len(m.cells)
m.cells = append(m.cells, cell{kind: kind, refs: 1})
- return Ptr(idx)
+ return Ptr(idx), nil
}
}
-func (m *Mem) Set(ptr Ptr, v any) {
- if ptr >= Ptr(len(m.cells)) {
- panic("out of bounds")
+func (m *Mem) Set(ptr Ptr, v CellData) error {
+ if err := m.validPtr(ptr); err != nil {
+ return err
}
m.cells[ptr].data = v
+ return nil
}
-func (m *Mem) Get(ptr Ptr) any {
- if ptr >= Ptr(len(m.cells)) {
- panic("out of bounds")
+func (m *Mem) Get(ptr Ptr) (CellData, error) {
+ if err := m.validPtr(ptr); err != nil {
+ return nil, err
}
- return m.cells[ptr].data
+ return m.cells[ptr].data, nil
}
func (m *Mem) Is(ptr Ptr, kind CellKind) bool {
if ptr >= Ptr(len(m.cells)) {
- panic("out of bounds")
+ return false
}
return m.cells[ptr].kind == kind
}
-func (m *Mem) Retain(ptr Ptr) {
+func (m *Mem) Kind(ptr Ptr) CellKind {
if ptr >= Ptr(len(m.cells)) {
- panic("out of bounds")
+ return CellKindForbidden
+ }
+
+ return m.cells[ptr].kind
+}
+
+func (m *Mem) Retain(ptr Ptr) error {
+ if err := m.validPtr(ptr); err != nil {
+ return err
}
m.cells[ptr].refs++
+ return nil
}
-func (m *Mem) Release(ptr Ptr) {
- if ptr >= Ptr(len(m.cells)) {
- panic("out of bounds")
+func (m *Mem) Release(ptr Ptr) error {
+ if err := m.validPtr(ptr); err != nil {
+ return err
}
m.cells[ptr].refs--
if m.cells[ptr].refs == 0 {
- m.cells[ptr].kind = CellKindEmpty
- m.free = append(m.free, int(ptr))
+ c := m.cells[ptr].data
+ c.DropCell(m)
+
+ m.cells[ptr] = cell{}
+ m.free = append(m.free, ptr)
}
+
+ return nil
+}
+
+func (m *Mem) validPtr(ptr Ptr) error {
+ if ptr >= Ptr(len(m.cells)) {
+ return ErrInvalidMemAccess{ptr}
+ }
+
+ kind := m.cells[ptr].kind
+ if kind == CellKindForbidden || kind == CellKindEmpty {
+ return ErrInvalidMemAccess{ptr}
+ }
+
+ return nil
}
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
+}
diff --git a/pkg/lang/vm/value/cells.go b/pkg/lang/vm/value/cells.go
new file mode 100644
index 0000000..17a0916
--- /dev/null
+++ b/pkg/lang/vm/value/cells.go
@@ -0,0 +1,46 @@
+package value
+
+import "jinx/pkg/lang/vm/mem"
+
+type ArrayCell []Value
+
+func (a ArrayCell) DropCell(m *mem.Mem) {
+ for _, v := range a {
+ v.Drop(m)
+ }
+}
+
+func (a ArrayCell) Get() []Value {
+ return a
+}
+
+type StringCell string
+
+func (s StringCell) DropCell(m *mem.Mem) {
+}
+
+func (s StringCell) Get() string {
+ return string(s)
+}
+
+type OutletCell Value
+
+func (o OutletCell) DropCell(m *mem.Mem) {
+ Value(o).Drop(m)
+}
+
+func (o OutletCell) Get() Value {
+ return Value(o)
+}
+
+type EnvCell Env
+
+func (e EnvCell) DropCell(m *mem.Mem) {
+ for _, v := range e.references {
+ m.Release(v.outlet)
+ }
+}
+
+func (e EnvCell) Get() Env {
+ return Env(e)
+}
diff --git a/pkg/lang/vm/value/data.go b/pkg/lang/vm/value/data.go
index a49753e..2e3b3e6 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
+ String(*mem.Mem) (string, error)
}
type IntData int64
@@ -17,8 +17,8 @@ func (i IntData) Get() int64 {
return int64(i)
}
-func (i IntData) String(_ *mem.Mem) string {
- return strconv.FormatInt(int64(i), 10)
+func (i IntData) String(_ *mem.Mem) (string, error) {
+ return strconv.FormatInt(int64(i), 10), nil
}
type FloatData float64
@@ -27,17 +27,20 @@ func (f FloatData) Get() float64 {
return float64(f)
}
-func (f FloatData) String(_ *mem.Mem) string {
- return strconv.FormatFloat(float64(f), 'f', -1, 64)
+func (f FloatData) String(_ *mem.Mem) (string, error) {
+ return strconv.FormatFloat(float64(f), 'f', -1, 64), nil
}
type StringData struct {
data mem.Ptr
}
-func (s StringData) String(m *mem.Mem) string {
- data := m.Get(s.data)
- return "\"" + data.(string) + "\""
+func (s StringData) String(m *mem.Mem) (string, error) {
+ if data, err := m.Get(s.data); err == nil {
+ return "\"" + data.(StringCell).Get() + "\"", nil
+ } else {
+ return "", err
+ }
}
type BoolData bool
@@ -46,16 +49,21 @@ func (b BoolData) Get() bool {
return bool(b)
}
-func (b BoolData) String(_ *mem.Mem) string {
- return strconv.FormatBool(bool(b))
+func (b BoolData) String(_ *mem.Mem) (string, error) {
+ return strconv.FormatBool(bool(b)), nil
}
type ArrayData struct {
data mem.Ptr
}
-func (a ArrayData) String(m *mem.Mem) string {
- arr := m.Get(a.data).([]Value)
+func (a ArrayData) String(m *mem.Mem) (string, error) {
+ val, err := m.Get(a.data)
+ if err != nil {
+ return "", err
+ }
+
+ arr := val.(ArrayCell).Get()
builder := strings.Builder{}
builder.WriteString("[")
@@ -63,29 +71,45 @@ func (a ArrayData) String(m *mem.Mem) string {
if i > 0 {
builder.WriteString(", ")
}
- builder.WriteString(v.Data().String(m))
+ if s, err := v.Data().String(m); err == nil {
+ builder.WriteString(s)
+ } else {
+ return "", err
+ }
}
builder.WriteString("]")
- return builder.String()
+ return builder.String(), nil
}
-func (a ArrayData) Len(m *mem.Mem) int {
- data := m.Get(a.data)
- arr := data.([]Value)
- return len(arr)
+func (a ArrayData) Len(m *mem.Mem) (int, error) {
+ data, err := m.Get(a.data)
+ if err != nil {
+ return 0, err
+ }
+ arr := data.(ArrayCell).Get()
+ return len(arr), nil
}
-func (a ArrayData) At(m *mem.Mem, i int) Value {
- data := m.Get(a.data)
- arr := data.([]Value)
- return arr[i]
+func (a ArrayData) At(m *mem.Mem, i int) (Value, error) {
+ data, err := m.Get(a.data)
+ if err != nil {
+ return Value{}, err
+ }
+ arr := data.(ArrayCell).Get()
+ return arr[i], nil
}
-func (a ArrayData) Push(m *mem.Mem, v Value) {
- data := m.Get(a.data)
- arr := data.([]Value)
+func (a ArrayData) Push(m *mem.Mem, v Value) error {
+ data, err := m.Get(a.data)
+ if err != nil {
+ return err
+ }
+
+ arr := data.(ArrayCell).Get()
arr = append(arr, v)
- m.Set(a.data, arr)
+ m.Set(a.data, ArrayCell(arr))
+
+ return nil
}
type NullData struct{}
@@ -107,8 +131,8 @@ func (f FunctionData) WithEnv(env mem.Ptr) FunctionData {
return FunctionData{pc: f.pc, env: env}
}
-func (f FunctionData) String(_ *mem.Mem) string {
- return fmt.Sprintf("<fn %d>", f.pc)
+func (f FunctionData) String(_ *mem.Mem) (string, error) {
+ return fmt.Sprintf("<fn %d>", f.pc), nil
}
type ObjectData struct{} // TODO
diff --git a/pkg/lang/vm/value/value.go b/pkg/lang/vm/value/value.go
index d19bbd6..f98740e 100644
--- a/pkg/lang/vm/value/value.go
+++ b/pkg/lang/vm/value/value.go
@@ -20,13 +20,17 @@ func NewFloat(x float64) Value {
return Value{t: t, d: FloatData(x)}
}
-func NewString(m *mem.Mem, str string) Value {
+func NewString(m *mem.Mem, str string) (Value, error) {
t := Type{Kind: StringType}
- ptr := m.Allocate(mem.CellKindString)
- m.Set(ptr, str)
+ ptr, err := m.Allocate(mem.CellKindString)
+ if err != nil {
+ return Value{}, err
+ }
+
+ m.Set(ptr, StringCell(str))
- return Value{t: t, d: StringData{data: ptr}}
+ return Value{t: t, d: StringData{data: ptr}}, nil
}
func NewBool(b bool) Value {
@@ -34,13 +38,17 @@ func NewBool(b bool) Value {
return Value{t: t, d: BoolData(b)}
}
-func NewArray(m *mem.Mem, arr []Value) Value {
+func NewArray(m *mem.Mem, arr []Value) (Value, error) {
t := Type{Kind: ArrayType}
- ptr := m.Allocate(mem.CellKindArray)
- m.Set(ptr, arr)
+ ptr, err := m.Allocate(mem.CellKindArray)
+ if err != nil {
+ return Value{}, err
+ }
+
+ m.Set(ptr, ArrayCell(arr))
- return Value{t: t, d: ArrayData{data: ptr}}
+ return Value{t: t, d: ArrayData{data: ptr}}, nil
}
func NewNull() Value {
@@ -99,7 +107,7 @@ func (v Value) Clone(m *mem.Mem) Value {
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, v)
+ m.Set(v.outlet, OutletCell(v))
return
}
diff --git a/pkg/lang/vm/vm.go b/pkg/lang/vm/vm.go
index c933af4..9c17a3f 100644
--- a/pkg/lang/vm/vm.go
+++ b/pkg/lang/vm/vm.go
@@ -3,7 +3,6 @@ package vm
import (
"jinx/pkg/lang/vm/code"
"jinx/pkg/lang/vm/mem"
- "jinx/pkg/lang/vm/value"
)
type VM struct {
@@ -28,8 +27,11 @@ func (vm *VM) GetResult() (string, error) {
return "", err
}
- str := res.Data().String(&vm.memory)
- return str, nil
+ if str, err := res.Data().String(&vm.memory); err == nil {
+ return str, nil
+ } else {
+ return "", err
+ }
}
func (vm *VM) Run() error {
@@ -169,26 +171,3 @@ func (vm *VM) step(op code.Op) (stepDecision, error) {
return stepDecisionContinue, err
}
-
-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()
-}