型チェックをするようにした
This commit is contained in:
@@ -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" />
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
vm.run();
|
try
|
||||||
|
{
|
||||||
|
vm.run();
|
||||||
|
}
|
||||||
|
catch(SmileBasicError sbe)
|
||||||
|
{
|
||||||
|
writeln(sbe);
|
||||||
|
}
|
||||||
readln();
|
readln();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user