about summary refs log tree commit diff
path: root/pkg/lang/vm/value
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-05-27 23:34:40 +0000
committerGitHub <noreply@github.com>2022-05-27 23:34:40 +0000
commit83d1dc87f3336d70ccda476627c70c282b7b6e11 (patch)
tree70610879d3de1ddf02bbe9067076fe65b52979a9 /pkg/lang/vm/value
parent47c4cd3705bee9d7154c42ce95aef6f8a19e0661 (diff)
downloadjinx-83d1dc87f3336d70ccda476627c70c282b7b6e11.tar.zst
jinx-83d1dc87f3336d70ccda476627c70c282b7b6e11.zip
Function envs and value escaping
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)
+	}
 }