about summary refs log tree commit diff
path: root/pkg/lang/vm/value
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/value')
-rw-r--r--pkg/lang/vm/value/core_ptrs.go2
-rw-r--r--pkg/lang/vm/value/data.go39
-rw-r--r--pkg/lang/vm/value/env.go37
-rw-r--r--pkg/lang/vm/value/type.go4
-rw-r--r--pkg/lang/vm/value/value.go21
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
 }