1
0

コンパイルして実行できるようにした

This commit is contained in:
otya128
2015-06-04 22:53:15 +09:00
parent de5db9282c
commit c33df7e4ac
5 changed files with 187 additions and 23 deletions

View File

@@ -1,32 +1,112 @@
module otya.smilebasic.vm; module otya.smilebasic.vm;
import otya.smilebasic.type;
import otya.smilebasic.token;
import std.uni;
import std.conv;
import std.stdio;
class VM class VM
{ {
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];
}
} }
enum CodeType enum CodeType
{ {
PushI, Push,
PushD,
PushS,
Operate, Operate,
Return, Return,
Goto, Goto,
Gosub, Gosub,
Print,
} }
abstract class Code abstract class Code
{ {
CodeType type; CodeType type;
abstract void execute(VM vm); abstract void execute(VM vm);
} }
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;
}
}
}
}
/* /*
* スタックにPush * スタックにPush
*/ */
class Push : Code class Push : Code
{ {
Value imm;
this(Value imm)
{
this.type = CodeType.Push;
this.imm = imm;
}
override void execute(VM vm)
{
vm.push(imm);
}
} }
class Operate : Code class Operate : Code
{ {
TokenType operator;
this(TokenType op)
{
this.operator = op;
}
override void execute(VM vm)
{
Value l;
Value r;
vm.pop(l);
vm.pop(r);
//とりあえずInteger
l.integerValue += r.integerValue;
vm.push(l);
}
} }
class Goto : Code class Goto : Code
{ {

View File

@@ -1,6 +1,8 @@
module otya.smilebasic.compiler; module otya.smilebasic.compiler;
import otya.smilebasic.node; import otya.smilebasic.node;
import otya.smilebasic.token;
import otya.smilebasic.vm; import otya.smilebasic.vm;
import otya.smilebasic.type;
import std.stdio; import std.stdio;
class Compiler class Compiler
{ {
@@ -8,18 +10,85 @@ class Compiler
this(Statements statements) this(Statements statements)
{ {
this.statements = statements; this.statements = statements;
code = new Code[0];
} }
void compile() Code[] code;
void genCodeImm(Value value)
{
code ~= new Push(value);
}
void genCodeOP(TokenType op)
{
code ~= new Operate(op);
}
void compileExpression(Expression exp)
{
switch(exp.type)
{
case NodeType.Constant:
genCodeImm((cast(Constant)exp).value);
break;
case NodeType.BinaryOperator:
{
auto binop = cast(BinaryOperator)exp;
compileExpression(binop.item1);
compileExpression(binop.item2);
genCodeOP(binop.operator);
}
break;
case NodeType.Variable:
break;
case NodeType.CallFunction:
{
auto func = cast(CallFunction)exp;
if(func.name == "ADD")
{
foreach_reverse(Expression i ; func.args)
{
compileExpression(i);
}
}
}
break;
default:
break;
}
}
VM compile()
{ {
Code[] code = new Code[0];
foreach(Statement i ; statements.statements) foreach(Statement i ; statements.statements)
{ {
switch(i.type) switch(i.type)
{ {
case NodeType.Print:
{
auto print = cast(Print)i;
foreach_reverse(PrintArgument j ; print.args)
{
switch(j.type)
{
case PrintArgumentType.Expression:
compileExpression(j.expression);
break;
case PrintArgumentType.Line:
genCodeImm(Value("\n"));
break;
case PrintArgumentType.Tab:
genCodeImm(Value("\t"));
break;
default:
break;
}
}
code ~= new PrintCode(print.args.length);
}
break;
default: default:
stderr.writeln("Compile:NotImpl ", i.type); stderr.writeln("Compile:NotImpl ", i.type);
} }
} }
return new VM(code);
} }
} }

View File

@@ -2,15 +2,15 @@ import std.stdio;
import otya.smilebasic.parser; import otya.smilebasic.parser;
int main(string[] argv) int main(string[] argv)
{ {
writeln("Hello D-World!");
version(none) version(none)
{ {
auto parser = new Parser("ADD(ADD(1,2,3,4,5,6),2,3,4,5,6)"); auto parser = new Parser("ADD(ADD(1,2,3,4,5,6),2,3,4,5,6)");
writeln(parser.calc()); writeln(parser.calc());
} }
auto parser = new Parser("PRINT 1+1"); auto parser = new Parser("PRINT 1+1,2+3;10-5");
parser.compile(); auto vm = parser.compile();
vm.run();
readln(); readln();
return 0; return 0;
} }

View File

@@ -260,10 +260,10 @@ class Parser
return - - -1; return - - -1;
} }
} }
void compile() auto compile()
{ {
auto compiler = new Compiler(parseProgram()); auto compiler = new Compiler(parseProgram());
compiler.compile(); return compiler.compile();
} }
Statements parseProgram() Statements parseProgram()
{ {
@@ -305,17 +305,6 @@ class Parser
print.addLine(); print.addLine();
break; break;
} }
if(token.type == TokenType.Semicolon)
{
addline = false;
continue;
}
if(token.type == TokenType.Comma)
{
print.addTab();
addline = false;
continue;
}
addline = true; addline = true;
auto exp = expression(); auto exp = expression();
if(exp is null) if(exp is null)
@@ -324,13 +313,28 @@ class Parser
continue; continue;
} }
print.addArgument(exp); print.addArgument(exp);
lex.popFront();
token = lex.front(); token = lex.front();
if(lex.empty()) break; if(lex.empty()) break;
if(token.type != TokenType.Colon && token.type != TokenType.NewLine && token.type != TokenType.Semicolon && token.type != TokenType.Comma) if(token.type != TokenType.Colon && token.type != TokenType.NewLine && token.type != TokenType.Semicolon && token.type != TokenType.Comma)
{ {
syntaxError(); syntaxError();
} }
else
{
lex.popFront();
if(token.type == TokenType.Semicolon)
{
addline = false;
continue;
}
if(token.type == TokenType.Comma)
{
print.addTab();
addline = false;
continue;
}
token = lex.front();
}
} }
return print; return print;
} }

View File

@@ -34,4 +34,15 @@ struct Value
this.type = ValueType.String; this.type = ValueType.String;
stringValue = value; stringValue = value;
} }
void castOp(ValueType type)
{
switch(type)
{
case ValueType.Double:
break;
default:
break;
}
}
} }