aboutsummaryrefslogtreecommitdiff
path: root/pkg/lang/vm/value
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/value')
-rw-r--r--pkg/lang/vm/value/data.go11
-rw-r--r--pkg/lang/vm/value/env.go33
-rw-r--r--pkg/lang/vm/value/value.go33
3 files changed, 74 insertions, 3 deletions
diff --git a/pkg/lang/vm/value/data.go b/pkg/lang/vm/value/data.go
index fecf8cf..a49753e 100644
--- a/pkg/lang/vm/value/data.go
+++ b/pkg/lang/vm/value/data.go
@@ -91,13 +91,22 @@ func (a ArrayData) Push(m *mem.Mem, v Value) {
type NullData struct{}
type FunctionData struct {
- pc int
+ pc int
+ env mem.Ptr
}
func (f FunctionData) Pc() int {
return f.pc
}
+func (f FunctionData) Env() mem.Ptr {
+ return f.env
+}
+
+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)
}
diff --git a/pkg/lang/vm/value/env.go b/pkg/lang/vm/value/env.go
new file mode 100644
index 0000000..b7bb3ab
--- /dev/null
+++ b/pkg/lang/vm/value/env.go
@@ -0,0 +1,33 @@
+package value
+
+import "jinx/pkg/lang/vm/mem"
+
+type Env struct {
+ references []reference
+}
+
+func NewEnv() Env {
+ return Env{
+ references: make([]reference, 0),
+ }
+}
+
+func (e *Env) Add(stackIndex int, outlet mem.Ptr) {
+ e.references = append(e.references, reference{
+ stackIndex: stackIndex,
+ outlet: outlet,
+ })
+}
+
+func (e *Env) GetOutlet(envIndex int) mem.Ptr {
+ return e.references[envIndex].outlet
+}
+
+func (e *Env) GetStackIndex(envIndex int) int {
+ return e.references[envIndex].stackIndex
+}
+
+type reference struct {
+ stackIndex int
+ outlet mem.Ptr
+}
diff --git a/pkg/lang/vm/value/value.go b/pkg/lang/vm/value/value.go
index 06306df..d19bbd6 100644
--- a/pkg/lang/vm/value/value.go
+++ b/pkg/lang/vm/value/value.go
@@ -5,8 +5,9 @@ import (
)
type Value struct {
- t Type
- d Data
+ t Type
+ d Data
+ outlet mem.Ptr
}
func NewInt(x int64) Value {
@@ -64,6 +65,18 @@ func (v Value) Data() Data {
return v.d
}
+func (v Value) WithData(d Data) Value {
+ return Value{t: v.t, d: d, outlet: v.outlet}
+}
+
+func (v Value) Outlet() mem.Ptr {
+ return v.outlet
+}
+
+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 {
if v.t.Kind == StringType {
str := v.d.(StringData)
@@ -75,10 +88,21 @@ func (v Value) Clone(m *mem.Mem) Value {
m.Retain(arr.data)
}
+ if v.t.Kind == FunctionType {
+ fn := v.d.(FunctionData)
+ m.Retain(fn.env)
+ }
+
return v
}
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)
+ return
+ }
+
if v.t.Kind == StringType {
str := v.d.(StringData)
m.Release(str.data)
@@ -88,4 +112,9 @@ func (v Value) Drop(m *mem.Mem) {
arr := v.d.(ArrayData)
m.Release(arr.data)
}
+
+ if v.t.Kind == FunctionType {
+ f := v.d.(FunctionData)
+ m.Release(f.env)
+ }
}