2015-06-04 20:51:03 +09:00
|
|
|
module otya.smilebasic.compiler;
|
|
|
|
|
import otya.smilebasic.node;
|
2015-06-04 22:53:15 +09:00
|
|
|
import otya.smilebasic.token;
|
2015-06-04 20:51:03 +09:00
|
|
|
import otya.smilebasic.vm;
|
2015-06-04 22:53:15 +09:00
|
|
|
import otya.smilebasic.type;
|
2015-06-04 20:51:03 +09:00
|
|
|
import std.stdio;
|
|
|
|
|
class Compiler
|
|
|
|
|
{
|
|
|
|
|
Statements statements;
|
|
|
|
|
this(Statements statements)
|
|
|
|
|
{
|
|
|
|
|
this.statements = statements;
|
2015-06-04 22:53:15 +09:00
|
|
|
code = new Code[0];
|
2015-06-04 20:51:03 +09:00
|
|
|
}
|
|
|
|
|
|
2015-06-04 22:53:15 +09:00
|
|
|
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()
|
2015-06-04 20:51:03 +09:00
|
|
|
{
|
|
|
|
|
foreach(Statement i ; statements.statements)
|
|
|
|
|
{
|
|
|
|
|
switch(i.type)
|
|
|
|
|
{
|
2015-06-04 22:53:15 +09:00
|
|
|
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;
|
2015-06-04 20:51:03 +09:00
|
|
|
default:
|
|
|
|
|
stderr.writeln("Compile:NotImpl ", i.type);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-06-04 22:53:15 +09:00
|
|
|
return new VM(code);
|
2015-06-04 20:51:03 +09:00
|
|
|
}
|
|
|
|
|
}
|