diff options
Diffstat (limited to 'pkg/lang/vm/value')
| -rw-r--r-- | pkg/lang/vm/value/data.go | 11 | ||||
| -rw-r--r-- | pkg/lang/vm/value/env.go | 33 | ||||
| -rw-r--r-- | pkg/lang/vm/value/value.go | 33 |
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) + } } |
