about summary refs log tree commit diff
path: root/pkg/lang/vm/exec.go
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-05-31 01:01:32 +0000
committerGitHub <noreply@github.com>2022-05-31 01:02:20 +0000
commit338744d066704e48e22d8ec56a43acb4b20da7f1 (patch)
treeb508eb6764efc64ac611b6ea063ab44d9e6b0a9c /pkg/lang/vm/exec.go
parent78a29c41098db5e5f8291e0345a3cd443c52b329 (diff)
downloadjinx-338744d066704e48e22d8ec56a43acb4b20da7f1.tar.zst
jinx-338744d066704e48e22d8ec56a43acb4b20da7f1.zip
Add untyped Objects (for now)
Diffstat (limited to 'pkg/lang/vm/exec.go')
-rw-r--r--pkg/lang/vm/exec.go74
1 files changed, 73 insertions, 1 deletions
diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go
index 41b7019..d4426e1 100644
--- a/pkg/lang/vm/exec.go
+++ b/pkg/lang/vm/exec.go
@@ -47,6 +47,16 @@ func (vm *VM) execPushFunction(pc int) {
 	vm.stack.Push(value.NewFunction(pc, 0))
 }
 
+func (vm *VM) execPushObject() error {
+	obj, err := value.NewObject(vm.memory, mem.NullPtr)
+	if err != nil {
+		return err
+	}
+
+	vm.stack.Push(obj)
+	return nil
+}
+
 func (vm *VM) execGetLocal(offset int) error {
 	local, err := vm.stack.Local(int(offset))
 	if err != nil {
@@ -65,6 +75,28 @@ func (vm *VM) execGetMember(name string) error {
 		return err
 	}
 
+	if parent.Type() == value.ObjectType {
+		obj := parent.Data().(value.ObjectData)
+		ptr := obj.Ptr()
+
+		cell, err := vm.getMemCell(ptr, mem.CellKindObject, false)
+		if err != nil {
+			return err
+		}
+
+		objCell := cell.(value.ObjectCell)
+		member, ok := objCell.Get()[name]
+		if ok {
+			member = member.Clone(vm.memory)
+		} else {
+			member = value.NewNull()
+		}
+
+		vm.stack.Push(member)
+		parent.Drop(vm.memory)
+		return nil
+	}
+
 	typeCell, err := vm.getMemCell(parent.TypePtr(), mem.CellKindType, false)
 	if err != nil {
 		return err
@@ -135,6 +167,46 @@ func (vm *VM) execGetMember(name string) error {
 	return nil
 }
 
+func (vm *VM) execSetMember(name string) error {
+	parent, err := vm.stack.Pop()
+	if err != nil {
+		return err
+	}
+
+	v, err := vm.stack.Pop()
+	if err != nil {
+		return err
+	}
+
+	if parent.Type() != value.ObjectType {
+		return ErrInvalidOperandType{
+			Op: code.OpSetMember,
+			X:  parent.Type(),
+		}
+	}
+
+	ptr := parent.Data().(value.ObjectData).Ptr()
+
+	cell, err := vm.getMemCell(ptr, mem.CellKindObject, false)
+	if err != nil {
+		return err
+	}
+
+	objCell := cell.(value.ObjectCell)
+	obj := objCell.Get()
+
+	obj[name] = v
+
+	if err := vm.memory.Set(ptr, value.ObjectCell{Members: obj}); err != nil {
+		return err
+	}
+
+	parent.Drop(vm.memory)
+	// v was moved, no need to drop it.
+
+	return nil
+}
+
 func (vm *VM) execGetEnv(envIndex int) error {
 	envCell, err := vm.getMemCell(vm.stack.CurrentCallEnv(), mem.CellKindEnv, false)
 	if err != nil {
@@ -522,7 +594,7 @@ func (vm *VM) execCall(argCount uint) error {
 
 	if argCount != fn.Args() {
 		return ErrNotEnoughArguments{
-			Got:   argCount,
+			Got:    argCount,
 			Needed: fn.Args(),
 		}
 	}