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/vm.go | |
| parent | 45b6f073fe398e820e9e4a82900bc282ee32af9b (diff) | |
| download | jinx-22a69393f58abcf3bcf9e7039f994dae78422213.tar.zst jinx-22a69393f58abcf3bcf9e7039f994dae78422213.zip | |
Implement VM modules and globals
Diffstat (limited to 'pkg/lang/vm/vm.go')
| -rw-r--r-- | pkg/lang/vm/vm.go | 163 |
1 files changed, 114 insertions, 49 deletions
diff --git a/pkg/lang/vm/vm.go b/pkg/lang/vm/vm.go index 8b47915..4a4aa68 100644 --- a/pkg/lang/vm/vm.go +++ b/pkg/lang/vm/vm.go @@ -7,18 +7,28 @@ import ( ) type VM struct { - code *code.Code - pc int + pos code.Pos + + modules []*code.Code + stack stack.Stack memory mem.Mem + + canAddGlobals bool + globals map[string]mem.Ptr } -func New(code *code.Code) *VM { +func New(main *code.Code, deps []*code.Code) *VM { vm := &VM{ - code: code, - pc: 0, + pos: code.NewPos(0, 0), + + modules: append([]*code.Code{main}, deps...), + stack: stack.New(), memory: mem.New(), + + canAddGlobals: false, + globals: make(map[string]mem.Ptr), } if err := vm.setup(); err != nil { @@ -46,14 +56,56 @@ func (vm *VM) GetResult() (string, error) { } func (vm *VM) Run() error { - for vm.pc < vm.code.Len() { - op, advance := vm.code.GetOp(vm.pc) - vm.pc += advance + vm.canAddGlobals = true + for i := 1; i < len(vm.modules); i++ { + if err := vm.executeModule(i); err != nil { + return err + } + + // Drop all calls from the stack after the module has finished + for vm.stack.CallDepth() > 1 { + if _, err := vm.popCallAndDrop(); err != nil { + return err + } + } + + // Drop the root stack values + for !vm.stack.IsEmpty() { + if _, err := vm.popAndDrop(); err != nil { + return err + } + } + } + + vm.canAddGlobals = false + if err := vm.executeModule(0); err != nil { + return err + } + + return nil +} + +func (vm *VM) executeModule(moduleID int) error { + vm.pos = code.NewPos(moduleID, 0) + + if err := vm.stack.PutRootCall(vm.pos); err != nil { + return err + } + + for { + module := vm.modules[vm.module()] - if decision, err := vm.step(op); err != nil { + if vm.pc() >= module.Len() { + return nil + } + + op, advance := module.GetOp(vm.pc()) + vm.advancePC(advance) + + if decision, err := vm.step(module, op); err != nil { return Error{ - Pc: vm.pc, - Line: vm.code.Debug().PCToLine(vm.pc), + Pos: vm.pos, + Line: module.Debug().PCToLine(vm.pc()), Err: err, } } else if decision == stepDecisionHalt { @@ -71,7 +123,7 @@ const ( stepDecisionHalt ) -func (vm *VM) step(op code.Op) (stepDecision, error) { +func (vm *VM) step(module *code.Code, op code.Op) (stepDecision, error) { var err error switch op { case code.OpNop: @@ -80,18 +132,18 @@ func (vm *VM) step(op code.Op) (stepDecision, error) { return stepDecisionHalt, nil case code.OpPushInt: - x, advance := vm.code.GetInt(vm.pc) - vm.pc += advance + x, advance := module.GetInt(vm.pc()) + vm.advancePC(advance) vm.execPushInt(x) case code.OpPushFloat: - x, advance := vm.code.GetFloat(vm.pc) - vm.pc += advance + x, advance := module.GetFloat(vm.pc()) + vm.advancePC(advance) vm.execPushFloat(x) case code.OpPushString: - str, advance := vm.code.GetString(vm.pc) - vm.pc += advance + str, advance := module.GetString(vm.pc()) + vm.advancePC(advance) err = vm.execPushString(str) case code.OpPushNull: @@ -103,60 +155,73 @@ func (vm *VM) step(op code.Op) (stepDecision, error) { case code.OpPushArray: vm.execPushArray() case code.OpPushFunction: - x, advance := vm.code.GetUint(vm.pc) - vm.pc += advance + x, advance := module.GetUint(vm.pc()) + vm.advancePC(advance) vm.execPushFunction(int(x)) case code.OpPushObject: err = vm.execPushObject() case code.OpPushType: - name, advance := vm.code.GetString(vm.pc) - vm.pc += advance + name, advance := module.GetString(vm.pc()) + vm.advancePC(advance) err = vm.execPushType(name) case code.OpDrop: - dropAmount, advance := vm.code.GetUint(vm.pc) - vm.pc += advance + dropAmount, advance := module.GetUint(vm.pc()) + vm.advancePC(advance) err = vm.execDrop(uint(dropAmount)) + case code.OpAddGlobal: + globalName, advance := module.GetString(vm.pc()) + vm.advancePC(advance) + + err = vm.execAddGlobal(globalName) case code.OpGetGlobal: - panic("not implemented") + globalName, advance := module.GetString(vm.pc()) + vm.advancePC(advance) + + err = vm.execGetGlobal(globalName) + case code.OpSetGlobal: + globalName, advance := module.GetString(vm.pc()) + vm.advancePC(advance) + + err = vm.execSetGlobal(globalName) case code.OpGetLocal: - offset, advance := vm.code.GetInt(vm.pc) - vm.pc += advance + offset, advance := module.GetInt(vm.pc()) + vm.advancePC(advance) err = vm.execGetLocal(int(offset)) case code.OpSetLocal: - offset, advance := vm.code.GetInt(vm.pc) - vm.pc += advance + offset, advance := module.GetInt(vm.pc()) + vm.advancePC(advance) err = vm.execSetLocal(int(offset)) case code.OpGetMember: - name, advance := vm.code.GetString(vm.pc) - vm.pc += advance + name, advance := module.GetString(vm.pc()) + vm.advancePC(advance) err = vm.execGetMember(name) case code.OpSetMember: - name, advance := vm.code.GetString(vm.pc) - vm.pc += advance + name, advance := module.GetString(vm.pc()) + vm.advancePC(advance) err = vm.execSetMember(name) case code.OpGetEnv: - envIndex, advance := vm.code.GetUint(vm.pc) - vm.pc += advance + envIndex, advance := module.GetUint(vm.pc()) + vm.advancePC(advance) err = vm.execGetEnv(int(envIndex)) case code.OpSetEnv: - envIndex, advance := vm.code.GetUint(vm.pc) - vm.pc += advance + envIndex, advance := module.GetUint(vm.pc()) + vm.advancePC(advance) err = vm.execSetEnv(int(envIndex)) case code.OpAddToEnv: - local, advance := vm.code.GetUint(vm.pc) - vm.pc += advance + local, advance := module.GetUint(vm.pc()) + vm.advancePC(advance) err = vm.execAddToEnv(int(local)) @@ -164,8 +229,8 @@ func (vm *VM) step(op code.Op) (stepDecision, error) { err = vm.execAnchorType() case code.OpSetArgCount: - argCount, advance := vm.code.GetUint(vm.pc) - vm.pc += advance + argCount, advance := module.GetUint(vm.pc()) + vm.advancePC(advance) err = vm.execSetArgCount(uint(argCount)) @@ -193,21 +258,21 @@ func (vm *VM) step(op code.Op) (stepDecision, error) { case code.OpIndex: err = vm.execIndex() case code.OpCall: - argCount, advance := vm.code.GetUint(vm.pc) - vm.pc += advance + argCount, advance := module.GetUint(vm.pc()) + vm.advancePC(advance) err = vm.execCall(uint(argCount)) case code.OpJmp: - pc, _ := vm.code.GetUint(vm.pc) - vm.pc = int(pc) + pc, _ := module.GetUint(vm.pc()) + vm.setPC(int(pc)) case code.OpJt: - pc, advance := vm.code.GetUint(vm.pc) - vm.pc += advance + pc, advance := module.GetUint(vm.pc()) + vm.advancePC(advance) err = vm.execJumpIf(int(pc), true) case code.OpJf: - pc, advance := vm.code.GetUint(vm.pc) - vm.pc += advance + pc, advance := module.GetUint(vm.pc()) + vm.advancePC(advance) err = vm.execJumpIf(int(pc), false) case code.OpRet: err = vm.execRet() |
