1
0
Files
otyaSMILEBASIC/SMILEBASIC/compiler.d

138 lines
4.0 KiB
D
Raw Normal View History

module otya.smilebasic.compiler;
import otya.smilebasic.node;
import otya.smilebasic.token;
import otya.smilebasic.vm;
import otya.smilebasic.type;
import std.stdio;
class Compiler
{
Statements statements;
this(Statements statements)
{
this.statements = statements;
code = new Code[0];
}
Code[] code;
2015-06-05 19:57:35 +09:00
int[wstring] global;
int globalIndex = 0;
void genCodeImm(Value value)
{
code ~= new Push(value);
}
2015-06-05 19:57:35 +09:00
void genCodePushGlobal(int ind)
{
code ~= new PushG(ind);
}
2015-06-05 21:41:40 +09:00
void genCodePopGlobal(int ind)
{
code ~= new PopG(ind);
}
void genCodeOP(TokenType op)
{
code ~= new Operate(op);
}
2015-06-05 21:41:40 +09:00
int defineGlobalVarIndex(wstring name)
{
int global = this.global.get(name, 0);
if(global == 0)
{
this.global[name] = ++globalIndex = global;
}
else
{
//error:二重定義
}
return global;
}
int getGlobalVarIndex(wstring name)
{
int global = this.global.get(name, 0);
if(global == 0)
{
//local変数をあたる
//それでもだめならOPTION STRICTならエラー
this.global[name] = ++globalIndex = global;
}
return global;
}
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:
2015-06-05 19:57:35 +09:00
auto var = cast(Variable)exp;
2015-06-05 21:41:40 +09:00
genCodePushGlobal(getGlobalVarIndex(var.name));
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()
{
foreach(Statement i ; statements.statements)
{
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;
2015-06-05 21:41:40 +09:00
case NodeType.Assign:
{
auto assign = cast(Assign)i;
compileExpression(assign.expression);
genCodePopGlobal(getGlobalVarIndex(assign.name));
}
break;
default:
stderr.writeln("Compile:NotImpl ", i.type);
}
}
2015-06-05 19:57:35 +09:00
return new VM(code, globalIndex + 1);
}
}