2015-06-04 20:51:03 +09:00
|
|
|
module otya.smilebasic.vm;
|
2015-06-04 22:53:15 +09:00
|
|
|
import otya.smilebasic.type;
|
|
|
|
|
import otya.smilebasic.token;
|
|
|
|
|
import std.uni;
|
|
|
|
|
import std.conv;
|
|
|
|
|
import std.stdio;
|
2015-06-04 19:12:17 +09:00
|
|
|
class VM
|
|
|
|
|
{
|
2015-06-04 22:53:15 +09:00
|
|
|
Code[] code;
|
|
|
|
|
int stacki;
|
|
|
|
|
Value[] stack;
|
|
|
|
|
this(Code[] code)
|
|
|
|
|
{
|
|
|
|
|
this.code = code;
|
|
|
|
|
this.stack = new Value[1024 * 1024];
|
|
|
|
|
}
|
|
|
|
|
void run()
|
|
|
|
|
{
|
|
|
|
|
for(int i = 0; i < this.code.length; i++)
|
|
|
|
|
{
|
|
|
|
|
code[i].execute(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void push(ref Value value)
|
|
|
|
|
{
|
|
|
|
|
stack[stacki++] = value;
|
|
|
|
|
}
|
|
|
|
|
void pop(out Value value)
|
|
|
|
|
{
|
|
|
|
|
value = stack[--stacki];
|
|
|
|
|
}
|
2015-06-04 19:12:17 +09:00
|
|
|
}
|
|
|
|
|
enum CodeType
|
|
|
|
|
{
|
2015-06-04 22:53:15 +09:00
|
|
|
Push,
|
2015-06-04 19:12:17 +09:00
|
|
|
Operate,
|
|
|
|
|
Return,
|
|
|
|
|
Goto,
|
|
|
|
|
Gosub,
|
2015-06-04 22:53:15 +09:00
|
|
|
Print,
|
2015-06-04 19:12:17 +09:00
|
|
|
}
|
|
|
|
|
abstract class Code
|
|
|
|
|
{
|
|
|
|
|
CodeType type;
|
|
|
|
|
abstract void execute(VM vm);
|
|
|
|
|
}
|
2015-06-04 22:53:15 +09:00
|
|
|
class PrintCode : Code
|
|
|
|
|
{
|
|
|
|
|
int count;
|
|
|
|
|
this(int count)
|
|
|
|
|
{
|
|
|
|
|
this.type = CodeType.Print;
|
|
|
|
|
this.count = count;
|
|
|
|
|
}
|
|
|
|
|
override void execute(VM vm)
|
|
|
|
|
{
|
|
|
|
|
for(int i = 0;i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
Value arg;
|
|
|
|
|
vm.pop(arg);
|
|
|
|
|
switch(arg.type)
|
|
|
|
|
{
|
|
|
|
|
case ValueType.Integer:
|
|
|
|
|
write(arg.integerValue);
|
|
|
|
|
break;
|
|
|
|
|
case ValueType.String:
|
|
|
|
|
write(cast(string)arg.stringValue);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
//type missmatch
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-06-04 19:12:17 +09:00
|
|
|
/*
|
|
|
|
|
* スタックにPush
|
|
|
|
|
*/
|
|
|
|
|
class Push : Code
|
|
|
|
|
{
|
2015-06-04 22:53:15 +09:00
|
|
|
Value imm;
|
|
|
|
|
this(Value imm)
|
|
|
|
|
{
|
|
|
|
|
this.type = CodeType.Push;
|
|
|
|
|
this.imm = imm;
|
|
|
|
|
}
|
|
|
|
|
override void execute(VM vm)
|
|
|
|
|
{
|
|
|
|
|
vm.push(imm);
|
|
|
|
|
}
|
2015-06-04 19:12:17 +09:00
|
|
|
}
|
|
|
|
|
class Operate : Code
|
|
|
|
|
{
|
2015-06-04 22:53:15 +09:00
|
|
|
TokenType operator;
|
|
|
|
|
this(TokenType op)
|
|
|
|
|
{
|
|
|
|
|
this.operator = op;
|
|
|
|
|
}
|
2015-06-04 19:12:17 +09:00
|
|
|
|
2015-06-04 22:53:15 +09:00
|
|
|
override void execute(VM vm)
|
|
|
|
|
{
|
|
|
|
|
Value l;
|
|
|
|
|
Value r;
|
|
|
|
|
vm.pop(l);
|
|
|
|
|
vm.pop(r);
|
|
|
|
|
//とりあえずInteger
|
|
|
|
|
l.integerValue += r.integerValue;
|
|
|
|
|
vm.push(l);
|
|
|
|
|
}
|
2015-06-04 19:12:17 +09:00
|
|
|
}
|
|
|
|
|
class Goto : Code
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
class Gosub : Code
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|