about summary refs log tree commit diff
path: root/pkg/lang/vm/mem
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/mem')
-rw-r--r--pkg/lang/vm/mem/cell.go3
-rw-r--r--pkg/lang/vm/mem/mem.go30
-rw-r--r--pkg/lang/vm/mem/mem_test.go9
3 files changed, 42 insertions, 0 deletions
diff --git a/pkg/lang/vm/mem/cell.go b/pkg/lang/vm/mem/cell.go
index 562d4da..5a0e9fb 100644
--- a/pkg/lang/vm/mem/cell.go
+++ b/pkg/lang/vm/mem/cell.go
@@ -6,6 +6,7 @@ const (
 	CellKindEmpty CellKind = iota
 	CellKindString
 	CellKindArray
+	CellKindType
 
 	CellKindEnv
 	CellKindOutlet
@@ -21,6 +22,8 @@ func (c CellKind) String() string {
 		return "string"
 	case CellKindArray:
 		return "array"
+	case CellKindType:
+		return "type"
 	case CellKindEnv:
 		return "env"
 	case CellKindOutlet:
diff --git a/pkg/lang/vm/mem/mem.go b/pkg/lang/vm/mem/mem.go
index 0f15743..6c1d58d 100644
--- a/pkg/lang/vm/mem/mem.go
+++ b/pkg/lang/vm/mem/mem.go
@@ -2,6 +2,7 @@ package mem
 
 type Mem interface {
 	Allocate(kind CellKind) (Ptr, error)
+	AllocateAt(ptr Ptr, kind CellKind) error
 
 	Set(ptr Ptr, v CellData) error
 	Get(ptr Ptr) (CellData, error)
@@ -55,7 +56,36 @@ func (m *memImpl) Allocate(kind CellKind) (Ptr, error) {
 		m.cells = append(m.cells, cell{kind: kind, refs: 1})
 		return Ptr(idx), nil
 	}
+}
+
+func (m *memImpl) AllocateAt(ptr Ptr, kind CellKind) error {
+	if kind == CellKindForbidden || kind == CellKindEmpty {
+		return ErrInvalidCellKind{kind}
+	}
+
+	if ptr < Ptr(len(m.cells)) && m.cells[ptr].kind != CellKindEmpty {
+		return ErrInvalidMemAccess{ptr}
+	}
+
+	if ptr > 10000 {
+		return ErrMemOverflow
+	}
 
+	if ptr >= Ptr(len(m.cells)) {
+		m.cells = append(m.cells, make([]cell, ptr-Ptr(len(m.cells))+1)...)
+	}
+
+	m.cells[ptr] = cell{kind: kind, refs: 1}
+
+	// Remove cell from free list, if it was there.
+	for i, f := range m.free {
+		if f == ptr {
+			m.free = append(m.free[:i], m.free[i+1:]...)
+			break
+		}
+	}
+
+	return nil
 }
 
 func (m *memImpl) Set(ptr Ptr, v CellData) error {
diff --git a/pkg/lang/vm/mem/mem_test.go b/pkg/lang/vm/mem/mem_test.go
index a75753c..f916e49 100644
--- a/pkg/lang/vm/mem/mem_test.go
+++ b/pkg/lang/vm/mem/mem_test.go
@@ -21,6 +21,15 @@ func TestAllocation(t *testing.T) {
 	assert.Equal(t, two, mem.Ptr(2))
 }
 
+func TestSpecificAllocation(t *testing.T) {
+	m := mem.New()
+
+	assert.NoError(t, m.AllocateAt(mem.Ptr(123), mem.CellKindString))
+	assert.Error(t, m.AllocateAt(mem.NullPtr, mem.CellKindString))
+	assert.Error(t, m.AllocateAt(mem.Ptr(124), mem.CellKindEmpty))
+	assert.Error(t, m.AllocateAt(mem.Ptr(123), mem.CellKindArray))
+}
+
 func TestGetSet(t *testing.T) {
 	m := mem.New()