about summary refs log tree commit diff
path: root/pkg/lang/vm/value/value.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/value/value.go')
-rw-r--r--pkg/lang/vm/value/value.go33
1 files changed, 31 insertions, 2 deletions
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)
+	}
 }