From 42e514a9890262ce5495438efe615e8e8701f979 Mon Sep 17 00:00:00 2001 From: otya128 Date: Sat, 5 Sep 2015 16:24:09 +0900 Subject: [PATCH] slot --- SMILEBASIC/VM.d | 158 ++++++++++++++++++++++++------------- SMILEBASIC/compiler.d | 25 +++++- SMILEBASIC/parser.d | 5 ++ SMILEBASIC/petitcomputer.d | 16 +++- SMILEBASIC/type.d | 8 ++ 5 files changed, 151 insertions(+), 61 deletions(-) diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index 0498631..1936e57 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -23,48 +23,69 @@ struct VMVariable this.index = index; } } -class VM +class VMSlot { + bool isUsed; DataTable globalDataTable; Code[] code; SourceLocation[] location; - int stacki; - int pc; - Value[] stack; Value[] global; VMVariable[wstring] globalTable; Function[wstring] functions; int[wstring] globalLabel; + DebugInfo debugInfo; +} +class VM +{ + static const directModeSlot = 5; + VMSlot[6] slots; + int slot; + VMSlot currentSlot; + int stacki; + int pc; + Value[] stack; int bp; PetitComputer petitcomputer; - DebugInfo debugInfo; - this(Code[] code, int len, VMVariable[wstring] globalTable, Function[wstring] functions, DataTable gdt/*GNU Debugging Tools*/, + this() + { + this.stack = new Value[16384]; + for(int i = 0; i < slots.length; i++) + { + slots[i] = new VMSlot(); + } + } + void setCurrentSlot(int slot) + { + currentSlot = slots[slot]; + } + void loadSlot(int slot, Code[] code, int len, VMVariable[wstring] globalTable, Function[wstring] functions, DataTable gdt/*GNU Debugging Tools*/, int[wstring] globalLabel, DebugInfo dinfo) { - this.code = code; - this.stack = new Value[16384]; - this.global = new Value[len]; - this.globalTable = globalTable; + auto s = this.slots[slot]; + s.isUsed = true; + s.code = code; + s.global = new Value[len]; + s.globalTable = globalTable; foreach(wstring k, VMVariable v ; globalTable) { if(v.index >= 0) - this.global[v.index] = Value(v.type); + s.global[v.index] = Value(v.type); } - this.functions = functions; - this.globalDataTable = gdt; - this.globalLabel = globalLabel; - this.debugInfo = dinfo; + s.functions = functions; + s.globalDataTable = gdt; + s.globalLabel = globalLabel; + s.debugInfo = dinfo; } Code getCurrent() { - return code[pc]; + return currentSlot.code[pc]; } void run() { bp = 0;//globalを実行なのでbaseは0(グローバル変数をスタックに取るようにしない限り)(挙動的にスタックに確保していなさそう) - for(pc = 0; pc < this.code.length; pc++) + for(pc = 0; pc < this.currentSlot.code.length; pc++) { - code[pc].execute(this); + currentSlot.code[pc].execute(this); } if(stacki != 0) { @@ -73,7 +94,7 @@ class VM } SourceLocation currentLocation() { - return debugInfo.getLocationByAddress(pc); + return currentSlot.debugInfo.getLocationByAddress(pc); } void init(PetitComputer petitcomputer) { @@ -82,14 +103,38 @@ class VM } bool runStep() { - if(pc < this.code.length) + if(pc < this.currentSlot.code.length) { - code[pc].execute(this); + currentSlot.code[pc].execute(this); pc++; return true; } return false; } + void poppc() + { + Value value; + pop(value); + if(value.type == ValueType.InternalAddress) + { + pc = value.integerValue; + return; + } + if(value.type == ValueType.InternalSlotAddress) + { + pc = value.internalAddress.address; + setCurrentSlot(value.internalAddress.slot); + return; + } + assert(false, "internal error, compiler bug?"); + } + void pushpc() + { + Value value; + value.type = ValueType.InternalAddress; + value.integerValue = pc; + push(value); + } void push(ref Value value) { if(stacki >= this.stack.length) @@ -127,20 +172,20 @@ class VM } Value testGetGlobalVariable(wstring name) { - return global[globalTable[name].index]; + return currentSlot.global[currentSlot.globalTable[name].index]; } void end() { - pc = cast(int)code.length; + pc = cast(int)currentSlot.code.length; } void dump() { - foreach(i, c; code) + foreach(i, c; currentSlot.code) writefln("%04X:%s", i, c.toString(this)); } wstring getGlobalVarName(int index) { - foreach(k, v; globalTable) + foreach(k, v; currentSlot.globalTable) { if(v.index == index) return k; } @@ -149,21 +194,21 @@ class VM Value readData() { Value value; - this.globalDataTable.read(value, this); + this.currentSlot.globalDataTable.read(value, this); return value; } void restoreData(wstring label) { - this.globalDataTable.dataIndex = this.globalDataTable.label[label]; + this.currentSlot.globalDataTable.dataIndex = this.currentSlot.globalDataTable.label[label]; } int olddti; void pushDataIndex() { - olddti = this.globalDataTable.dataIndex; + olddti = this.currentSlot.globalDataTable.dataIndex; } void popDataIndex() { - this.globalDataTable.dataIndex = olddti; + this.currentSlot.globalDataTable.dataIndex = olddti; } } enum CodeType @@ -269,7 +314,7 @@ class PushG : Code } override void execute(VM vm) { - vm.push(vm.global[var]); + vm.push(vm.currentSlot.global[var]); } override string toString(VM vm) { @@ -287,28 +332,28 @@ class PopG : Code override void execute(VM vm) { Value v; - Value g = vm.global[var]; + Value g = vm.currentSlot.global[var]; vm.pop(v); if(v.type == ValueType.Integer && g.type == ValueType.Double) { - vm.global[var] = Value(cast(double)v.integerValue); + vm.currentSlot.global[var] = Value(cast(double)v.integerValue); return; } if(g.type == ValueType.Integer && v.type == ValueType.Double) { - vm.global[var] = Value(cast(int)v.doubleValue); + vm.currentSlot.global[var] = Value(cast(int)v.doubleValue); return; } if(g.type == ValueType.Void) { - vm.global[var] = v; + vm.currentSlot.global[var] = v; return; } if(v.type != g.type) { throw new TypeMismatch(); } - vm.global[var] = v; + vm.currentSlot.global[var] = v; } override string toString(VM vm) { @@ -654,7 +699,7 @@ class GotoExpr : Code vm.pop(label); if(!label.isString) { - vm.pc = vm.globalLabel[label.castString] - 1; + vm.pc = vm.currentSlot.globalLabel[label.castString] - 1; } else { @@ -672,7 +717,7 @@ class GosubAddr : Code } override void execute(VM vm) { - vm.push(Value(vm.pc)); + vm.pushpc;//vm.push(Value(vm.pc)); vm.pc = address - 1; } override string toString(VM vm) @@ -708,8 +753,8 @@ class GosubExpr : Code vm.pop(label); if(label.isString) { - vm.push(Value(vm.pc)); - vm.pc = vm.globalLabel[label.castString] - 1; + vm.pushpc;//vm.push(Value(vm.pc)); + vm.pc = vm.currentSlot.globalLabel[label.castString] - 1; } else { @@ -730,14 +775,16 @@ class ReturnSubroutine : Code { throw new ReturnWithoutGosub(); } - vm.pop(pc); - if(pc.type != ValueType.Integer || pc.integerValue < 0 || pc.integerValue >= vm.code.length) + /*vm.pop(pc); + if(pc.type != ValueType.Integer || pc.integerValue < 0 || pc.integerValue >= vm.currentSlot.code.length) { stderr.writeln("Internal error:Compiler bug?"); readln(); return; } vm.pc = pc.integerValue; + */ + vm.poppc; } override string toString(VM vm) { @@ -896,7 +943,7 @@ class PopArray : Code } else { - array = vm.global[var]; + array = vm.currentSlot.global[var]; } if(!array.isArray) { @@ -969,10 +1016,12 @@ class ReturnFunction : Code { vm.pop(retexpr); } - vm.stacki = vm.bp + 2; + vm.stacki = vm.bp + Function.frameSize;//2; Value bp, pc; - vm.pop(pc); + vm.poppc;//(pc); vm.pop(bp); + Value hae; + vm.pop(hae); vm.stacki -= func.argCount; if(func.returnExpr) { @@ -983,10 +1032,10 @@ class ReturnFunction : Code //OUTの実装 for(int i = 0; i < func.outArgCount; i++) { - vm.push(vm.stack[vm.bp + i + 2]); + vm.push(vm.stack[vm.bp + i + /*2*/Function.frameSize]); } } - vm.pc = pc.integerValue; + //vm.pc = pc.integerValue; vm.bp = bp.integerValue; } override string toString(VM vm) @@ -1013,7 +1062,7 @@ class CallFunctionCode : Code } override void execute(VM vm) { - Function func = vm.functions.get(name, null); + Function func = vm.currentSlot.functions.get(name, null); if(!func) { throw new SyntaxError(name); @@ -1028,8 +1077,9 @@ class CallFunctionCode : Code } //TODO:args auto bp = vm.stacki; + vm.push(Value()); vm.push(Value(vm.bp)); - vm.push(Value(vm.pc)); + vm.pushpc;//vm.push(Value(vm.pc)); vm.bp = bp; vm.pc = func.address - 1; vm.stacki += func.variableIndex - 1; @@ -1104,7 +1154,7 @@ class IncCodeG : Code override void execute(VM vm) { Value v; - Value g = vm.global[var]; + Value g = vm.currentSlot.global[var]; vm.pop(v); if(!g.isNumber() && g.type != ValueType.String) { @@ -1119,15 +1169,15 @@ class IncCodeG : Code double l = g.castDouble; double r = v.castDouble; if(v.type == ValueType.Double) - vm.global[var] = Value(l + r); + vm.currentSlot.global[var] = Value(l + r); else - vm.global[var] = Value(cast(int)(l + r)); + vm.currentSlot.global[var] = Value(cast(int)(l + r)); } else { wstring l = g.stringValue; wstring r = v.stringValue; - vm.global[var] = Value(l ~ r); + vm.currentSlot.global[var] = Value(l ~ r); } } override string toString(VM vm) @@ -1244,7 +1294,7 @@ class OnGosub : OnBase { int index = on(vm); if(index < 0) return; - vm.push(Value(vm.pc)); + vm.pushpc;//vm.push(Value(vm.pc)); vm.pc = index - 1; } override string toString(VM vm) @@ -1352,7 +1402,7 @@ class ReadCode : Code for(int i = 0; i < count; i++) { Value data; - vm.globalDataTable.read(data, vm); + vm.currentSlot.globalDataTable.read(data, vm); vm.push(data); } } diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 4f6df42..3d22c57 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -73,6 +73,7 @@ class DataTable } class Function { + static const frameSize = 3; int address; wstring name; int argCount; @@ -82,13 +83,20 @@ class Function int[wstring] label; bool returnExpr; int outArgCount; + /** + 0:bp + 1:pc + 2:data table(global) + 3:data index + 4:function pointer + */ this(int address, wstring name, bool returnExpr, int argCount) { this.address = address; this.name = name; this.returnExpr = returnExpr; this.argCount = argCount; - this.variableIndex = 1;//0,bp,1,pc + this.variableIndex = frameSize - 1;//1;//0,bp,1,pc if(returnExpr) { outArgCount = 1; @@ -962,9 +970,10 @@ class Compiler } this.debugInfo.addLocation(i.location, code); } - VM compile() + Scope globalScope; + Code[] compileProgram() { - Scope s = new Scope(); + Scope s = globalScope = new Scope(); foreach(Statement i ; statements.statements) { if(i.type == NodeType.DefineFunction) @@ -1038,7 +1047,15 @@ class Compiler code[i] = new RestoreCode(s.data.label[restore.label], s.data); } } - VM vm = new VM(code, globalIndex + 1, global, functions, s.data, globalLabel, debugInfo); + genCode(new EndVM()); + return code; + } + VM compile() + { + compileProgram(); + VM vm = new VM(); + vm.loadSlot(0, code, globalIndex + 1, global, functions, globalScope.data, globalLabel, debugInfo); + vm.setCurrentSlot(0); registerSystemVariable(vm); return vm; } diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index 7e31379..3c0d6b4 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -495,6 +495,11 @@ class Parser return - - -1; } } + auto compiler() + { + auto compiler = new Compiler(parseProgram()); + return compiler; + } auto compile() { auto compiler = new Compiler(parseProgram()); diff --git a/SMILEBASIC/petitcomputer.d b/SMILEBASIC/petitcomputer.d index 65690bf..9d2b936 100644 --- a/SMILEBASIC/petitcomputer.d +++ b/SMILEBASIC/petitcomputer.d @@ -1052,11 +1052,11 @@ class PetitComputer parser = new Parser( //readText("./SYS/GAME6TALK.TXT").to!wstring //readText("./SYS/GAME7EXPAD.TXT").to!wstring - //readText("./SYS/GAME4SHOOTER.TXT").to!wstring + readText("./SYS/GAME4SHOOTER.TXT").to!wstring //readText("./SYS/GAME2RPG.TXT").to!wstring //readText("./SYS/GAME1DOTRC.TXT").to!wstring //readText(input("LOAD PROGRAM:", true).to!string).to!wstring - readText("./SYS/EX8TECDEMO.TXT").to!wstring + //readText("./SYS/EX8TECDEMO.TXT").to!wstring //readText("./SYS/EX1TEXT.TXT").to!wstring //readText("FIZZBUZZ.TXT").to!wstring //readText("TEST.TXT").to!wstring @@ -1119,7 +1119,17 @@ class PetitComputer } } else - { + {/* + if(!vm) + { + import otya.smilebasic.vm; + vm = new VM(); + vm.init(this); + } + auto prg = input("", true); + parser = new Parser(prg); + vm.code.append(parser.compiler.compileProgram());*/ + version(none) do { auto file = input("LOAD PROGRAM:", true).to!string; diff --git a/SMILEBASIC/type.d b/SMILEBASIC/type.d index 9080bd7..3a6f4fc 100644 --- a/SMILEBASIC/type.d +++ b/SMILEBASIC/type.d @@ -10,6 +10,13 @@ enum ValueType : byte IntegerArray, DoubleArray, StringArray, + InternalAddress, + InternalSlotAddress, +} +struct VMAddress +{ + byte slot; + uint address; } struct Value { @@ -23,6 +30,7 @@ struct Value Array!int integerArray; Array!double doubleArray; Array!wstring stringArray; + VMAddress internalAddress; } this(int value) {