aboutsummaryrefslogtreecommitdiff
path: root/pkg/lang/vm/value
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/vm/value
parent83d1dc87f3336d70ccda476627c70c282b7b6e11 (diff)
downloadjinx-0a7700112f82e634a957685bee0cbaa3458f4945.tar.zst
jinx-0a7700112f82e634a957685bee0cbaa3458f4945.zip
Harden VM Mem
Diffstat (limited to 'pkg/lang/vm/value')
-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
3 files changed, 115 insertions, 37 deletions
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
}