IF文を実�
This commit is contained in:
@@ -37,6 +37,24 @@ class Compiler
|
|||||||
{
|
{
|
||||||
code ~= new GotoS(label);
|
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 defineGlobalVarIndex(wstring name)
|
||||||
{
|
{
|
||||||
int global = this.global.get(name, 0);
|
int global = this.global.get(name, 0);
|
||||||
@@ -98,56 +116,92 @@ class Compiler
|
|||||||
break;
|
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()
|
VM compile()
|
||||||
{
|
{
|
||||||
foreach(Statement i ; statements.statements)
|
foreach(Statement i ; statements.statements)
|
||||||
{
|
{
|
||||||
switch(i.type)
|
compileStatement(i);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
foreach(int i, Code c; code)
|
foreach(int i, Code c; code)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ int main(string[] argv)
|
|||||||
auto parser = new Parser(
|
auto parser = new Parser(
|
||||||
"@A\nA=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2:PRINT A
|
"@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 1 THEN PRINT 2
|
||||||
IF 3 THEN PRINT 4 ELSE PRINT 5
|
IF 0 THEN PRINT 4 ELSE PRINT 5
|
||||||
");
|
");
|
||||||
auto vm = parser.compile();
|
auto vm = parser.compile();
|
||||||
vm.run();
|
vm.run();
|
||||||
|
|||||||
@@ -204,4 +204,8 @@ class If : Statement
|
|||||||
this.then = t;
|
this.then = t;
|
||||||
this.else_ = e;
|
this.else_ = e;
|
||||||
}
|
}
|
||||||
|
bool hasElse()
|
||||||
|
{
|
||||||
|
return !(else_ is null) && else_.statements.length != 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user