IF文を実�
This commit is contained in:
@@ -37,6 +37,24 @@ class Compiler
|
||||
{
|
||||
code ~= new GotoS(label);
|
||||
}
|
||||
GotoAddr genCodeGoto()
|
||||
{
|
||||
auto c = new GotoAddr(-1);
|
||||
code ~= c;
|
||||
return c;
|
||||
}
|
||||
GotoTrue genCodeGotoTrue()
|
||||
{
|
||||
auto c = new GotoTrue(-1);
|
||||
code ~= c;
|
||||
return c;
|
||||
}
|
||||
GotoFalse genCodeGotoFalse()
|
||||
{
|
||||
auto c = new GotoFalse(-1);
|
||||
code ~= c;
|
||||
return c;
|
||||
}
|
||||
int defineGlobalVarIndex(wstring name)
|
||||
{
|
||||
int global = this.global.get(name, 0);
|
||||
@@ -98,56 +116,92 @@ class Compiler
|
||||
break;
|
||||
}
|
||||
}
|
||||
void compileIf(If node)
|
||||
{
|
||||
compileExpression(node.condition);
|
||||
//条件式がfalseならendif or elseに飛ぶ
|
||||
auto else_ = genCodeGotoFalse();
|
||||
compileStatements(node.then);
|
||||
//もしelseもあるのならば、endifに飛ぶ
|
||||
GotoAddr then;
|
||||
if(node.hasElse)
|
||||
{
|
||||
then = genCodeGoto();
|
||||
else_.address = code.length;
|
||||
compileStatements(node.else_);
|
||||
then.address = code.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
//endifに飛ばす
|
||||
else_.address = code.length;
|
||||
}
|
||||
}
|
||||
|
||||
void compileStatements(Statements statements)
|
||||
{
|
||||
foreach(Statement s ; statements.statements)
|
||||
{
|
||||
compileStatement(s);
|
||||
}
|
||||
}
|
||||
void compileStatement(Statement i)
|
||||
{
|
||||
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;
|
||||
case NodeType.Assign:
|
||||
{
|
||||
auto assign = cast(Assign)i;
|
||||
compileExpression(assign.expression);
|
||||
genCodePopGlobal(getGlobalVarIndex(assign.name));
|
||||
}
|
||||
break;
|
||||
case NodeType.Label:
|
||||
{
|
||||
auto label = cast(Label)i;
|
||||
globalLabel[label.label] = code.length;
|
||||
}
|
||||
break;
|
||||
case NodeType.Goto:
|
||||
{
|
||||
genCodeGoto((cast(Goto)i).label);
|
||||
}
|
||||
break;
|
||||
case NodeType.If:
|
||||
compileIf(cast(If)i);
|
||||
break;
|
||||
default:
|
||||
stderr.writeln("Compile:NotImpl ", i.type);
|
||||
}
|
||||
}
|
||||
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;
|
||||
case NodeType.Assign:
|
||||
{
|
||||
auto assign = cast(Assign)i;
|
||||
compileExpression(assign.expression);
|
||||
genCodePopGlobal(getGlobalVarIndex(assign.name));
|
||||
}
|
||||
break;
|
||||
case NodeType.Label:
|
||||
{
|
||||
auto label = cast(Label)i;
|
||||
globalLabel[label.label] = code.length;
|
||||
}
|
||||
break;
|
||||
case NodeType.Goto:
|
||||
{
|
||||
genCodeGoto((cast(Goto)i).label);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
stderr.writeln("Compile:NotImpl ", i.type);
|
||||
}
|
||||
compileStatement(i);
|
||||
}
|
||||
foreach(int i, Code c; code)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ int main(string[] argv)
|
||||
auto parser = new Parser(
|
||||
"@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 3 THEN PRINT 4 ELSE PRINT 5
|
||||
IF 0 THEN PRINT 4 ELSE PRINT 5
|
||||
");
|
||||
auto vm = parser.compile();
|
||||
vm.run();
|
||||
|
||||
@@ -204,4 +204,8 @@ class If : Statement
|
||||
this.then = t;
|
||||
this.else_ = e;
|
||||
}
|
||||
bool hasElse()
|
||||
{
|
||||
return !(else_ is null) && else_.statements.length != 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user