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) Allocate(m mem.Mem) (mem.Ptr, error) { ptr, err := m.Allocate(mem.CellKindEnv) if err != nil { return mem.NullPtr, err } if err = m.Set(ptr, EnvCell(*e)); err != nil { return mem.NullPtr, err } return ptr, nil } func (e *Env) Add(stackIndex int, outlet mem.Ptr) { e.references = append(e.references, reference{ stackIndex: stackIndex, outlet: outlet, }) } func (e *Env) Prepend(stackIndex int, outlet mem.Ptr) { e.references = append([]reference{ { stackIndex: stackIndex, outlet: outlet, }, }, e.references...) } func (e *Env) Clone(m mem.Mem) (Env, error) { cloned := NewEnv() for i := 0; i < e.Len(); i++ { differentOutlet := e.GetOutlet(i) if err := m.Retain(differentOutlet); err != nil { return Env{}, err } cloned.Add(e.GetStackIndex(i), differentOutlet) } return cloned, nil } // TODO: Add bounds checking 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 } func (e *Env) Len() int { return len(e.references) } type reference struct { stackIndex int outlet mem.Ptr }