diff options
| author | Mel <einebeere@gmail.com> | 2022-07-27 11:01:29 +0000 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-07-27 11:01:29 +0000 |
| commit | 22a69393f58abcf3bcf9e7039f994dae78422213 (patch) | |
| tree | 6f88f586bd57d298d54e345a6c4b8d7144a5d2ec /pkg/lang/vm/exec.go | |
| parent | 45b6f073fe398e820e9e4a82900bc282ee32af9b (diff) | |
| download | jinx-22a69393f58abcf3bcf9e7039f994dae78422213.tar.zst jinx-22a69393f58abcf3bcf9e7039f994dae78422213.zip | |
Implement VM modules and globals
Diffstat (limited to 'pkg/lang/vm/exec.go')
| -rw-r--r-- | pkg/lang/vm/exec.go | 82 |
1 files changed, 74 insertions, 8 deletions
diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go index c5b0539..5a8eb05 100644 --- a/pkg/lang/vm/exec.go +++ b/pkg/lang/vm/exec.go @@ -44,7 +44,7 @@ func (vm *VM) execPushArray() error { func (vm *VM) execPushFunction(pc int) { // TODO: Make push ops into functions, where the argCount can be passed. - vm.stack.Push(value.NewFunction(pc, 0)) + vm.stack.Push(value.NewFunction(code.NewPos(vm.module(), pc), 0)) } func (vm *VM) execPushObject() error { @@ -57,6 +57,72 @@ func (vm *VM) execPushObject() error { return nil } +func (vm *VM) execAddGlobal(name string) error { + if !vm.canAddGlobals { + return ErrCantAddGlobalFromMain{GlobalName: name} + } + + if _, ok := vm.globals[name]; ok { + return ErrGlobalAlreadyExists{GlobalName: name} + } + + v, err := vm.stack.Pop() + if err != nil { + return err + } + + globalPtr, err := vm.memory.Allocate(mem.CellKindGlobal) + if err != nil { + return err + } + + globalCell := value.GlobalCell(v) + if err := vm.memory.Set(globalPtr, globalCell); err != nil { + return err + } + + vm.globals[name] = globalPtr + + return nil +} + +func (vm *VM) execGetGlobal(name string) error { + ptr, ok := vm.globals[name] + if !ok { + return ErrNoSuchGlobal{GlobalName: name} + } + + cell, err := vm.getMemCell(ptr, mem.CellKindGlobal, false) + if err != nil { + return err + } + + v := cell.(value.GlobalCell).Get() + v = v.Clone(vm.memory) + + vm.stack.Push(v) + return nil +} + +func (vm *VM) execSetGlobal(name string) error { + ptr, ok := vm.globals[name] + if !ok { + return ErrNoSuchGlobal{GlobalName: name} + } + + new, err := vm.stack.Pop() + if err != nil { + return err + } + + globalCell := value.GlobalCell(new) + if err := vm.memory.Set(ptr, globalCell); err != nil { + return err + } + + return nil +} + func (vm *VM) execGetLocal(offset int) error { local, err := vm.stack.Local(int(offset)) if err != nil { @@ -165,7 +231,7 @@ func (vm *VM) execGetMember(name string) error { return err } - method := value.NewFunction(0, 0).WithData(methodData.WithEnv(envPtr)) + method := value.NewFunction(code.Pos{}, 0).WithData(methodData.WithEnv(envPtr)) // method = method.Clone(vm.memory) will only be necessary when we support methods with environments. vm.stack.Push(method) @@ -219,7 +285,7 @@ func (vm *VM) execGetMember(name string) error { member = member.WithEnv(envPtr) - val := value.NewFunction(0, 0).WithData(member) + val := value.NewFunction(code.Pos{}, 0).WithData(member) vm.stack.Push(val) parent.Drop(vm.memory) @@ -781,7 +847,7 @@ func (vm *VM) execCall(argCount uint) error { } } - if err = vm.stack.PushCall(fn.Pc(), vm.pc, fn.Env()); err != nil { + if err = vm.stack.PushCall(fn.Pos(), vm.pos, fn.Env()); err != nil { return err } @@ -806,7 +872,7 @@ func (vm *VM) execCall(argCount uint) error { vm.stack.Push(arg) } - vm.pc = fn.Pc() + vm.setPos(fn.Pos()) return nil } @@ -821,7 +887,7 @@ func (vm *VM) execJumpIf(pc int, cond bool) error { case value.BoolType: bl := b.Data().(value.BoolData) if bl.Get() == cond { - vm.pc = pc + vm.setPC(pc) } default: var op code.Op @@ -846,13 +912,13 @@ func (vm *VM) execRet() error { return err } - pc, err := vm.popCallAndDrop() + pos, err := vm.popCallAndDrop() if err != nil { return err } vm.stack.Push(returned) - vm.pc = pc + vm.setPos(pos) return nil } |
