about summary refs log tree commit diff
path: root/pkg/lang/vm
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-07-26 19:52:31 +0000
committerMel <einebeere@gmail.com>2022-07-26 19:52:31 +0000
commit7392283d9e6b8c1ee31a3ad74ce8d13d4e8b19ec (patch)
tree434350324985297cd16dd1df68a417223a334332 /pkg/lang/vm
parent20bd5570465c73b89458de58c9fb8cd4e5919b44 (diff)
downloadjinx-7392283d9e6b8c1ee31a3ad74ce8d13d4e8b19ec.tar.zst
jinx-7392283d9e6b8c1ee31a3ad74ce8d13d4e8b19ec.zip
Fix cloning of outlets and don't drop nil cells
Diffstat (limited to 'pkg/lang/vm')
-rw-r--r--pkg/lang/vm/mem/mem.go5
-rw-r--r--pkg/lang/vm/value/value.go5
-rw-r--r--pkg/lang/vm/vm_test.go39
3 files changed, 48 insertions, 1 deletions
diff --git a/pkg/lang/vm/mem/mem.go b/pkg/lang/vm/mem/mem.go
index 6c1d58d..99412ea 100644
--- a/pkg/lang/vm/mem/mem.go
+++ b/pkg/lang/vm/mem/mem.go
@@ -142,7 +142,10 @@ func (m *memImpl) Release(ptr Ptr) error {
 	m.cells[ptr].refs--
 	if m.cells[ptr].refs == 0 {
 		c := m.cells[ptr].data
-		c.DropCell(m)
+
+		if c != nil {
+			c.DropCell(m)
+		}
 
 		m.cells[ptr] = cell{}
 		m.free = append(m.free, ptr)
diff --git a/pkg/lang/vm/value/value.go b/pkg/lang/vm/value/value.go
index 953ac8b..5dd5012 100644
--- a/pkg/lang/vm/value/value.go
+++ b/pkg/lang/vm/value/value.go
@@ -155,6 +155,11 @@ func (v Value) Clone(m mem.Mem) Value {
 		m.Retain(fn.env)
 	}
 
+	// If value has an outlet don't copy it into the clone,
+	// otherwise when the clone is dropped it will also drop the outlet.
+	// I don't know if this fixes the entire problem, but it seems to work.
+	v.outlet = mem.NullPtr
+
 	return v
 }
 
diff --git a/pkg/lang/vm/vm_test.go b/pkg/lang/vm/vm_test.go
index 7e749a4..ae0b8e6 100644
--- a/pkg/lang/vm/vm_test.go
+++ b/pkg/lang/vm/vm_test.go
@@ -184,6 +184,45 @@ func TestEscapedEnv(t *testing.T) {
 	test(t, src, "[1, 2, 3]")
 }
 
+func TestEnvNotEscaped(t *testing.T) {
+	/*
+		var x = 1
+
+		fn f() {
+		    x = x + 1
+		    return
+		}
+
+		f()
+		var result = x
+	*/
+
+	src := `
+	push_int 1
+
+	push_function @f
+	add_to_env 0
+	get_local 1
+
+	call 0
+	drop 1
+
+	get_local 0
+	halt
+
+	@f:
+	get_env 0
+	push_int 1
+	add
+	set_env 0
+
+	push_null
+	ret
+	`
+
+	test(t, src, "2")
+}
+
 func TestMember(t *testing.T) {
 	src := `
 	push_array