diff options
| author | Mel <einebeere@gmail.com> | 2022-05-31 01:01:32 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-31 01:02:20 +0000 |
| commit | 338744d066704e48e22d8ec56a43acb4b20da7f1 (patch) | |
| tree | b508eb6764efc64ac611b6ea063ab44d9e6b0a9c /pkg | |
| parent | 78a29c41098db5e5f8291e0345a3cd443c52b329 (diff) | |
| download | jinx-338744d066704e48e22d8ec56a43acb4b20da7f1.tar.zst jinx-338744d066704e48e22d8ec56a43acb4b20da7f1.zip | |
Add untyped Objects (for now)
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/lang/vm/code/op.go | 1 | ||||
| -rw-r--r-- | pkg/lang/vm/exec.go | 74 | ||||
| -rw-r--r-- | pkg/lang/vm/mem/cell.go | 3 | ||||
| -rw-r--r-- | pkg/lang/vm/text/op.go | 1 | ||||
| -rw-r--r-- | pkg/lang/vm/utils.go | 2 | ||||
| -rw-r--r-- | pkg/lang/vm/value/cells.go | 18 | ||||
| -rw-r--r-- | pkg/lang/vm/value/data.go | 11 | ||||
| -rw-r--r-- | pkg/lang/vm/value/value.go | 21 | ||||
| -rw-r--r-- | pkg/lang/vm/vm.go | 9 | ||||
| -rw-r--r-- | pkg/lang/vm/vm_test.go | 19 |
10 files changed, 151 insertions, 8 deletions
diff --git a/pkg/lang/vm/code/op.go b/pkg/lang/vm/code/op.go index 272674a..1fa8afc 100644 --- a/pkg/lang/vm/code/op.go +++ b/pkg/lang/vm/code/op.go @@ -21,6 +21,7 @@ const ( OpGetGlobal OpGetLocal OpGetMember + OpSetMember OpGetEnv OpSetEnv 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(), } } diff --git a/pkg/lang/vm/mem/cell.go b/pkg/lang/vm/mem/cell.go index 5a0e9fb..73aa0c6 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 + CellKindObject CellKindType CellKindEnv @@ -22,6 +23,8 @@ func (c CellKind) String() string { return "string" case CellKindArray: return "array" + case CellKindObject: + return "object" case CellKindType: return "type" case CellKindEnv: diff --git a/pkg/lang/vm/text/op.go b/pkg/lang/vm/text/op.go index 2d6eb7e..37b89dc 100644 --- a/pkg/lang/vm/text/op.go +++ b/pkg/lang/vm/text/op.go @@ -19,6 +19,7 @@ var ( code.OpGetGlobal: "get_global", code.OpGetLocal: "get_local", code.OpGetMember: "get_member", + code.OpSetMember: "set_member", code.OpGetEnv: "get_env", code.OpSetEnv: "set_env", code.OpAddToEnv: "add_to_env", diff --git a/pkg/lang/vm/utils.go b/pkg/lang/vm/utils.go index 1a884d0..a40a14f 100644 --- a/pkg/lang/vm/utils.go +++ b/pkg/lang/vm/utils.go @@ -61,6 +61,8 @@ func (vm *VM) getMemCell(ptr mem.Ptr, kind mem.CellKind, allowNil bool) (mem.Cel _, ok = cell.(value.OutletCell) case mem.CellKindType: _, ok = cell.(value.TypeCell) + case mem.CellKindObject: + _, ok = cell.(value.ObjectCell) } if !ok { diff --git a/pkg/lang/vm/value/cells.go b/pkg/lang/vm/value/cells.go index a700940..5abb032 100644 --- a/pkg/lang/vm/value/cells.go +++ b/pkg/lang/vm/value/cells.go @@ -31,6 +31,24 @@ func (s StringCell) Get() string { return string(s) } +type ObjectCell struct { + Members map[string]Value +} + +func (o ObjectCell) DropCell(m mem.Mem) { + for _, v := range o.Members { + v.Drop(m) + } +} + +func (o ObjectCell) MatchingCellKind() mem.CellKind { + return mem.CellKindObject +} + +func (o ObjectCell) Get() map[string]Value { + return o.Members +} + type TypeCell Type func (t TypeCell) DropCell(m mem.Mem) { diff --git a/pkg/lang/vm/value/data.go b/pkg/lang/vm/value/data.go index 13716fd..9a8f7b6 100644 --- a/pkg/lang/vm/value/data.go +++ b/pkg/lang/vm/value/data.go @@ -150,6 +150,15 @@ func (f FunctionData) String(_ mem.Mem) (string, error) { return fmt.Sprintf("<fn(%d) %d>", f.args, f.pc), nil } } + +type ObjectData struct { + obj mem.Ptr +} + +func (o ObjectData) String(_ mem.Mem) (string, error) { + return fmt.Sprintf("<object %v>", o.obj), nil } -type ObjectData struct{} // TODO +func (o ObjectData) Ptr() mem.Ptr { + return o.obj +} diff --git a/pkg/lang/vm/value/value.go b/pkg/lang/vm/value/value.go index 05d3f09..5e222a3 100644 --- a/pkg/lang/vm/value/value.go +++ b/pkg/lang/vm/value/value.go @@ -24,7 +24,9 @@ func NewString(m mem.Mem, str string) (Value, error) { return Value{}, err } - m.Set(ptr, StringCell(str)) + if err = m.Set(ptr, StringCell(str)); err != nil { + return Value{}, err + } return Value{t: CORE_TYPE_STRING, d: StringData{data: ptr}}, nil } @@ -39,7 +41,9 @@ func NewArray(m mem.Mem, arr []Value) (Value, error) { return Value{}, err } - m.Set(ptr, ArrayCell(arr)) + if err = m.Set(ptr, ArrayCell(arr)); err != nil { + return Value{}, err + } return Value{t: CORE_TYPE_ARRAY, d: ArrayData{data: ptr}}, nil } @@ -56,8 +60,17 @@ func NewNativeFunction(f NativeFunc, args uint) Value { return Value{t: CORE_TYPE_FUNCTION, d: FunctionData{native: f, args: args}} } -func NewObject() Value { - panic("not implemented") +func NewObject(m mem.Mem, t mem.Ptr) (Value, error) { + ptr, err := m.Allocate(mem.CellKindObject) + if err != nil { + return Value{}, err + } + + if err = m.Set(ptr, ObjectCell{make(map[string]Value)}); err != nil { + return Value{}, err + } + + return Value{t: t, d: ObjectData{obj: ptr}}, nil } func (v Value) TypePtr() mem.Ptr { diff --git a/pkg/lang/vm/vm.go b/pkg/lang/vm/vm.go index 2377d89..8422299 100644 --- a/pkg/lang/vm/vm.go +++ b/pkg/lang/vm/vm.go @@ -89,7 +89,7 @@ func (vm *VM) step(op code.Op) (stepDecision, error) { str, advance := vm.code.GetString(vm.pc) vm.pc += advance - vm.execPushString(str) + err = vm.execPushString(str) case code.OpPushNull: vm.execPushNull() case code.OpPushTrue: @@ -104,7 +104,7 @@ func (vm *VM) step(op code.Op) (stepDecision, error) { vm.execPushFunction(int(x)) case code.OpPushObject: - panic("not implemented") + err = vm.execPushObject() case code.OpDrop: _, err = vm.stack.Pop() @@ -121,6 +121,11 @@ func (vm *VM) step(op code.Op) (stepDecision, error) { vm.pc += advance err = vm.execGetMember(name) + case code.OpSetMember: + name, advance := vm.code.GetString(vm.pc) + vm.pc += advance + + err = vm.execSetMember(name) case code.OpGetEnv: envIndex, advance := vm.code.GetUint(vm.pc) diff --git a/pkg/lang/vm/vm_test.go b/pkg/lang/vm/vm_test.go index 9f6efc0..287e7a8 100644 --- a/pkg/lang/vm/vm_test.go +++ b/pkg/lang/vm/vm_test.go @@ -210,6 +210,25 @@ func TestMember(t *testing.T) { test(t, src, "3") } +func TestObject(t *testing.T) { + src := ` + push_object + + push_string "Petronij" + get_local 0 + set_member "name" + + push_int 10 + get_local 0 + set_member "age" + + get_local 0 + get_member "name" + ` + + test(t, src, "\"Petronij\"") +} + func test(t *testing.T, src string, expected string) { bc := compile(t, src) vm := vm.New(&bc) |
