slot
This commit is contained in:
158
SMILEBASIC/VM.d
158
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -495,6 +495,11 @@ class Parser
|
||||
return - - -1;
|
||||
}
|
||||
}
|
||||
auto compiler()
|
||||
{
|
||||
auto compiler = new Compiler(parseProgram());
|
||||
return compiler;
|
||||
}
|
||||
auto compile()
|
||||
{
|
||||
auto compiler = new Compiler(parseProgram());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user