1
0

型チェックをするようにした

This commit is contained in:
otya128
2015-06-07 16:38:53 +09:00
parent 1201467230
commit c871927bc3
6 changed files with 80 additions and 20 deletions

View File

@@ -206,6 +206,7 @@
</Config> </Config>
<Folder name="SMILEBASIC"> <Folder name="SMILEBASIC">
<File path="compiler.d" /> <File path="compiler.d" />
<File path="error.d" />
<File path="main.d" /> <File path="main.d" />
<File path="node.d" /> <File path="node.d" />
<File path="parser.d" /> <File path="parser.d" />

View File

@@ -1,6 +1,7 @@
module otya.smilebasic.vm; module otya.smilebasic.vm;
import otya.smilebasic.type; import otya.smilebasic.type;
import otya.smilebasic.token; import otya.smilebasic.token;
import otya.smilebasic.error;
import std.uni; import std.uni;
import std.utf; import std.utf;
import std.conv; import std.conv;
@@ -12,13 +13,32 @@ class VM
int pc; int pc;
Value[] stack; Value[] stack;
Value[] global; Value[] global;
int[wstring] debugTable; int[wstring] globalTable;
this(Code[] code, int len, int[wstring] debugTable) 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.code = code;
this.stack = new Value[1024 * 1024]; this.stack = new Value[1024 * 1024];
this.global = new Value[len]; 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() void run()
{ {
@@ -44,9 +64,9 @@ class VM
} }
value = stack[--stacki]; value = stack[--stacki];
} }
Value testGetGlobaVariable(wstring name) Value testGetGlobalVariable(wstring name)
{ {
return global[debugTable[name]]; return global[globalTable[name]];
} }
} }
enum CodeType enum CodeType
@@ -137,7 +157,29 @@ class PopG : Code
} }
override void execute(VM vm) 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 class Operate : Code
@@ -185,8 +227,7 @@ class Operate : Code
return; return;
default: default:
//type mismatch //type mismatch
stderr.writeln("Type mismatch"); throw new TypeMismatch();
return;
} }
} }
if(r.type == ValueType.Integer || r.type == ValueType.Double) if(r.type == ValueType.Integer || r.type == ValueType.Double)
@@ -214,8 +255,7 @@ class Operate : Code
return; return;
default: default:
//type mismatch //type mismatch
stderr.writeln("Type mismatch"); throw new TypeMismatch();
return;
} }
} }
} }

View File

@@ -70,7 +70,7 @@ class Compiler
int global = this.global.get(name, 0); int global = this.global.get(name, 0);
if(global == 0) if(global == 0)
{ {
this.global[name] = ++globalIndex = global; this.global[name] = global = ++globalIndex;
} }
else else
{ {
@@ -85,7 +85,7 @@ class Compiler
{ {
//local変数をあたる //local変数をあたる
//それでもだめならOPTION STRICTならエラー //それでもだめならOPTION STRICTならエラー
this.global[name] = ++globalIndex = global; this.global[name] = global = ++globalIndex;
} }
return global; return global;
} }
@@ -276,6 +276,6 @@ unittest
auto parser = new Parser("A=1+2+3+4*5/4-5+(6+6)*7"); auto parser = new Parser("A=1+2+3+4*5/4-5+(6+6)*7");
auto vm = parser.compile(); auto vm = parser.compile();
vm.run(); vm.run();
writeln(vm.testGetGlobaVariable("A").integerValue); writeln(vm.testGetGlobalVariable("A").integerValue);
assert(vm.testGetGlobaVariable("A").integerValue == 1+2+3+4*5/4-5+(6+6)*7); assert(vm.testGetGlobalVariable("A").integerValue == 1+2+3+4*5/4-5+(6+6)*7);
} }

View File

@@ -3,6 +3,7 @@ import std.utf;
import std.conv; import std.conv;
import std.file; import std.file;
import otya.smilebasic.parser; import otya.smilebasic.parser;
import otya.smilebasic.error;
int main(string[] argv) int main(string[] argv)
{ {
version(none) version(none)
@@ -11,8 +12,7 @@ int main(string[] argv)
writeln(parser.calc()); writeln(parser.calc());
} }
version(none)
{
auto parser = new Parser( auto parser = new Parser(
//"@A\nA=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2 PRINT A //"@A\nA=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2 PRINT A
"IF 1 THEN PRINT 2 "IF 1 THEN PRINT 2
@@ -44,11 +44,21 @@ FOR I=0 TO 100
ENDIF ENDIF
ENDIF ENDIF
NEXT NEXT
A$=\"A\"
?A$
A$=2
?A$
"); ");
} version(none) auto parser = new Parser(readText("FIZZBUZZ.TXT").to!wstring);
auto parser = new Parser(readText("FIZZBUZZ.TXT").to!wstring);
auto vm = parser.compile(); auto vm = parser.compile();
try
{
vm.run(); vm.run();
}
catch(SmileBasicError sbe)
{
writeln(sbe);
}
readln(); readln();
return 0; return 0;
} }

View File

@@ -774,5 +774,5 @@ unittest
//Eval("test(2+5)") = 2+5; //Eval("test(2+5)") = 2+5;
//Eval("test(2+5, test(2, 3+5))") = 3+5; //Eval("test(2+5, test(2, 3+5))") = 3+5;
Test!"2-3*4-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";
} }

View File

@@ -1,6 +1,7 @@
module otya.smilebasic.type; module otya.smilebasic.type;
enum ValueType : byte enum ValueType : byte
{ {
Void,//DEF A()ENDの返り値とか未初期化の変数とか
Integer, Integer,
Double, Double,
String, String,
@@ -34,6 +35,14 @@ struct Value
this.type = ValueType.String; this.type = ValueType.String;
stringValue = value; stringValue = value;
} }
this(ValueType type)
{
this.type = type;
if(type == ValueType.String)
{
stringValue = "";
}
}
void castOp(ValueType type) void castOp(ValueType type)
{ {
switch(type) switch(type)