aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-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