diff --git a/SMILEBASIC/SMILEBASIC.visualdproj b/SMILEBASIC/SMILEBASIC.visualdproj index a36e6c6..e59c89c 100644 --- a/SMILEBASIC/SMILEBASIC.visualdproj +++ b/SMILEBASIC/SMILEBASIC.visualdproj @@ -206,6 +206,7 @@ + diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index 901bc4f..a1ea627 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -1,6 +1,7 @@ module otya.smilebasic.vm; import otya.smilebasic.type; import otya.smilebasic.token; +import otya.smilebasic.error; import std.uni; import std.utf; import std.conv; @@ -12,13 +13,32 @@ class VM int pc; Value[] stack; Value[] global; - int[wstring] debugTable; - this(Code[] code, int len, int[wstring] debugTable) + int[wstring] globalTable; + ValueType getType(wstring name) + { + wchar s = name[name.length - 1]; + switch(s) + { + case '$': + return ValueType.String; + case '#': + return ValueType.Double; + case '%': + return ValueType.Integer; + default: + return ValueType.Integer;//DEFINT時 + } + } + this(Code[] code, int len, int[wstring] globalTable) { this.code = code; this.stack = new Value[1024 * 1024]; this.global = new Value[len]; - this.debugTable = debugTable; + this.globalTable = globalTable; + foreach(wstring k, int v ; globalTable) + { + this.global[v] = Value(getType(k)); + } } void run() { @@ -44,9 +64,9 @@ class VM } value = stack[--stacki]; } - Value testGetGlobaVariable(wstring name) + Value testGetGlobalVariable(wstring name) { - return global[debugTable[name]]; + return global[globalTable[name]]; } } enum CodeType @@ -137,7 +157,29 @@ class PopG : Code } override void execute(VM vm) { - vm.pop(vm.global[var]); + Value v; + Value g = vm.global[var]; + vm.pop(v); + if(v.type == ValueType.Integer && g.type == ValueType.Double) + { + vm.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); + return; + } + if(v.type == ValueType.Void) + { + vm.global[var] = v; + return; + } + if(v.type != g.type) + { + throw new TypeMismatch(); + } + vm.global[var] = v; } } class Operate : Code @@ -185,8 +227,7 @@ class Operate : Code return; default: //type mismatch - stderr.writeln("Type mismatch"); - return; + throw new TypeMismatch(); } } if(r.type == ValueType.Integer || r.type == ValueType.Double) @@ -214,8 +255,7 @@ class Operate : Code return; default: //type mismatch - stderr.writeln("Type mismatch"); - return; + throw new TypeMismatch(); } } } diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index c6e3187..9aceb51 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -70,7 +70,7 @@ class Compiler int global = this.global.get(name, 0); if(global == 0) { - this.global[name] = ++globalIndex = global; + this.global[name] = global = ++globalIndex; } else { @@ -85,7 +85,7 @@ class Compiler { //local変数をあたる //それでもだめならOPTION STRICTならエラー - this.global[name] = ++globalIndex = global; + this.global[name] = global = ++globalIndex; } return global; } @@ -276,6 +276,6 @@ unittest auto parser = new Parser("A=1+2+3+4*5/4-5+(6+6)*7"); auto vm = parser.compile(); vm.run(); - writeln(vm.testGetGlobaVariable("A").integerValue); - assert(vm.testGetGlobaVariable("A").integerValue == 1+2+3+4*5/4-5+(6+6)*7); + writeln(vm.testGetGlobalVariable("A").integerValue); + assert(vm.testGetGlobalVariable("A").integerValue == 1+2+3+4*5/4-5+(6+6)*7); } diff --git a/SMILEBASIC/main.d b/SMILEBASIC/main.d index 2da5d92..e360c89 100644 --- a/SMILEBASIC/main.d +++ b/SMILEBASIC/main.d @@ -3,6 +3,7 @@ import std.utf; import std.conv; import std.file; import otya.smilebasic.parser; +import otya.smilebasic.error; int main(string[] argv) { version(none) @@ -11,8 +12,7 @@ int main(string[] argv) writeln(parser.calc()); } - version(none) - { + auto parser = new Parser( //"@A\nA=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2 PRINT A "IF 1 THEN PRINT 2 @@ -44,11 +44,21 @@ FOR I=0 TO 100 ENDIF ENDIF NEXT +A$=\"A\" +?A$ +A$=2 +?A$ "); - } - auto parser = new Parser(readText("FIZZBUZZ.TXT").to!wstring); + version(none) auto parser = new Parser(readText("FIZZBUZZ.TXT").to!wstring); auto vm = parser.compile(); - vm.run(); + try + { + vm.run(); + } + catch(SmileBasicError sbe) + { + writeln(sbe); + } readln(); return 0; } diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index 0f3da9d..277c8f9 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -774,5 +774,5 @@ unittest //Eval("test(2+5)") = 2+5; //Eval("test(2+5, test(2, 3+5))") = 3+5; Test!"2-3*4-5"(); - Test!"1+2+3+4*5/4-5+(6+6)*7"(); + Test!"1+2+3+4*5/4-5+(6+6)*7"; } diff --git a/SMILEBASIC/type.d b/SMILEBASIC/type.d index fa86277..f86567a 100644 --- a/SMILEBASIC/type.d +++ b/SMILEBASIC/type.d @@ -1,6 +1,7 @@ module otya.smilebasic.type; enum ValueType : byte { + Void,//DEF A()ENDの返り値とか未初期化の変数とか Integer, Double, String, @@ -34,6 +35,14 @@ struct Value this.type = ValueType.String; stringValue = value; } + this(ValueType type) + { + this.type = type; + if(type == ValueType.String) + { + stringValue = ""; + } + } void castOp(ValueType type) { switch(type)