diff options
Diffstat (limited to 'pkg/lang/vm/value')
| -rw-r--r-- | pkg/lang/vm/value/core_ptrs.go | 2 | ||||
| -rw-r--r-- | pkg/lang/vm/value/data.go | 39 | ||||
| -rw-r--r-- | pkg/lang/vm/value/env.go | 37 | ||||
| -rw-r--r-- | pkg/lang/vm/value/type.go | 4 | ||||
| -rw-r--r-- | pkg/lang/vm/value/value.go | 21 |
5 files changed, 103 insertions, 0 deletions
diff --git a/pkg/lang/vm/value/core_ptrs.go b/pkg/lang/vm/value/core_ptrs.go index 5462a8f..a1f0365 100644 --- a/pkg/lang/vm/value/core_ptrs.go +++ b/pkg/lang/vm/value/core_ptrs.go @@ -12,4 +12,6 @@ const ( CORE_TYPE_BOOL CORE_TYPE_ARRAY CORE_TYPE_FUNCTION + + CORE_TYPE_TYPE_REF ) diff --git a/pkg/lang/vm/value/data.go b/pkg/lang/vm/value/data.go index 9a8f7b6..e51904e 100644 --- a/pkg/lang/vm/value/data.go +++ b/pkg/lang/vm/value/data.go @@ -43,6 +43,14 @@ func (s StringData) String(m mem.Mem) (string, error) { } } +func (s StringData) RawString(m mem.Mem) (string, error) { + if data, err := m.Get(s.data); err == nil { + return data.(StringCell).Get(), nil + } else { + return "", err + } +} + type BoolData bool func (b BoolData) Get() bool { @@ -114,6 +122,10 @@ func (a ArrayData) Push(m mem.Mem, v Value) error { type NullData struct{} +func (n NullData) String(_ mem.Mem) (string, error) { + return "null", nil +} + type FunctionData struct { pc int args uint @@ -151,6 +163,33 @@ func (f FunctionData) String(_ mem.Mem) (string, error) { } } +type TypeRefData struct { + typeRef mem.Ptr +} + +func (t TypeRefData) String(_ mem.Mem) (string, error) { + return fmt.Sprintf("<type %v>", t.typeRef), nil +} + +func (t TypeRefData) TypeRef() mem.Ptr { + return t.typeRef +} + +func (t TypeRefData) AddMethod(m mem.Mem, name string, method FunctionData) error { + cell, err := m.Get(t.typeRef) + if err != nil { + return err + } + + typ := cell.(TypeCell).Get() + typ.Methods[name] = method + + if err := m.Set(t.typeRef, TypeCell(typ)); err != nil { + return err + } + return nil +} + type ObjectData struct { obj mem.Ptr } diff --git a/pkg/lang/vm/value/env.go b/pkg/lang/vm/value/env.go index 34a396c..2617699 100644 --- a/pkg/lang/vm/value/env.go +++ b/pkg/lang/vm/value/env.go @@ -12,6 +12,19 @@ func NewEnv() Env { } } +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, @@ -19,6 +32,30 @@ func (e *Env) Add(stackIndex int, outlet mem.Ptr) { }) } +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 } diff --git a/pkg/lang/vm/value/type.go b/pkg/lang/vm/value/type.go index 4bda3c1..d25c20f 100644 --- a/pkg/lang/vm/value/type.go +++ b/pkg/lang/vm/value/type.go @@ -11,6 +11,7 @@ const ( ArrayType FunctionType + TypeRefType ObjectType ) @@ -30,6 +31,8 @@ func (t TypeKind) String() string { return "null" case FunctionType: return "function" + case TypeRefType: + return "type" case ObjectType: return "object" } @@ -39,6 +42,7 @@ func (t TypeKind) String() string { type Type struct { Kind TypeKind + Name string Methods map[string]FunctionData Statics map[string]Value } diff --git a/pkg/lang/vm/value/value.go b/pkg/lang/vm/value/value.go index f1ccc2d..953ac8b 100644 --- a/pkg/lang/vm/value/value.go +++ b/pkg/lang/vm/value/value.go @@ -73,6 +73,21 @@ func NewObject(m mem.Mem, t mem.Ptr) (Value, error) { return Value{t: t, d: ObjectData{obj: ptr}}, nil } +func NewType(m mem.Mem, name string) (Value, error) { + ptr, err := m.Allocate(mem.CellKindType) + if err != nil { + return Value{}, err + } + + t := Type{Kind: ObjectType, Name: name, Methods: make(map[string]FunctionData), Statics: make(map[string]Value)} + + if err = m.Set(ptr, TypeCell(t)); err != nil { + return Value{}, err + } + + return Value{t: CORE_TYPE_TYPE_REF, d: TypeRefData{typeRef: ptr}}, nil +} + func (v Value) TypePtr() mem.Ptr { return v.t } @@ -93,11 +108,17 @@ func (v Value) Type() TypeKind { return ArrayType case CORE_TYPE_FUNCTION: return FunctionType + case CORE_TYPE_TYPE_REF: + return TypeRefType default: return ObjectType } } +func (v Value) WithType(t mem.Ptr) Value { + return Value{t: t, d: v.d, outlet: v.outlet} +} + func (v Value) Data() Data { return v.d } |
