# HG changeset patch # User Anders Halager # Date 1208519139 -7200 # Node ID 642c6a998fd9f9d1dcb78f2509d15b8fe1d30ea2 # Parent 2f493057cf17d8720e057b1b6919bc2271642af6 Support for while statements and fixed scope for if diff -r 2f493057cf17 -r 642c6a998fd9 ast/Stmt.d --- a/ast/Stmt.d Fri Apr 18 13:01:11 2008 +0200 +++ b/ast/Stmt.d Fri Apr 18 13:45:39 2008 +0200 @@ -12,6 +12,7 @@ Exp, Return, If, + While, } class Stmt @@ -59,14 +60,29 @@ class IfStmt : Stmt { - this(Exp cond, Stmt[] then) + this(Exp cond, Stmt[] then, Stmt[] el = null) { super(StmtType.If); this.cond = cond; - this.then = then; + this.then_body = then; + this.else_body = el; } Exp cond; - Stmt[] then; + Stmt[] then_body; + Stmt[] else_body; } +class WhileStmt : Stmt +{ + this(Exp cond, Stmt[] stmts) + { + super(StmtType.While); + this.cond = cond; + this.stmts = stmts; + } + + Exp cond; + Stmt[] stmts; +} + diff -r 2f493057cf17 -r 642c6a998fd9 gen/LLVMGen.d --- a/gen/LLVMGen.d Fri Apr 18 13:01:11 2008 +0200 +++ b/gen/LLVMGen.d Fri Apr 18 13:45:39 2008 +0200 @@ -337,24 +337,81 @@ auto then_branch = table.find("then"); auto else_branch = table.find("else"); + auto done_label = table.find("done"); printBeginLine("br i1 "); print(cond); print(", label %"); print(then_branch); print(", label %"); - printEndLine(else_branch); + printEndLine(ifStmt.else_body? else_branch : done_label); printBeginLine(then_branch); printEndLine(":"); indent(); - foreach (s; ifStmt.then) + foreach (s; ifStmt.then_body) genStmt(s); printBeginLine("br label %"); - printEndLine(else_branch); + printEndLine(done_label); dedent(); - printBeginLine(else_branch); + if (ifStmt.else_body) + { + printBeginLine(else_branch); + printEndLine(":"); + + indent(); + foreach (s; ifStmt.else_body) + genStmt(s); + printBeginLine("br label %"); + printEndLine(done_label); + dedent(); + } + + printBeginLine(done_label); + printEndLine(":"); + + break; + case StmtType.While: + auto wStmt = cast(WhileStmt)stmt; + + auto body_label = table.find("while_body"); + auto cond_label = table.find("while_cond"); + auto done_label = table.find("while_done"); + + printBeginLine(cond_label); + printEndLine(":"); + + indent(); + + Ref val = genExpression(wStmt.cond); + auto cond = table.find("%.cond"); + + printBeginLine(cond); + print(" = icmp ne "); + print(val); + printEndLine(", 0"); + + printBeginLine("br i1 "); + print(cond); + print(", label %"); + print(body_label); + print(", label %"); + printEndLine(done_label); + + dedent(); + + printBeginLine(body_label); + printEndLine(":"); + + indent(); + foreach (s; wStmt.stmts) + genStmt(s); + printBeginLine("br label %"); + printEndLine(cond_label); + dedent(); + + printBeginLine(done_label); printEndLine(":"); break; diff -r 2f493057cf17 -r 642c6a998fd9 lexer/Keyword.d --- a/lexer/Keyword.d Fri Apr 18 13:01:11 2008 +0200 +++ b/lexer/Keyword.d Fri Apr 18 13:45:39 2008 +0200 @@ -21,6 +21,8 @@ "double" : Tok.Double, "if" : Tok.If, + "else" : Tok.Else, + "while" : Tok.While, "return" : Tok.Return ]; } diff -r 2f493057cf17 -r 642c6a998fd9 lexer/Token.d --- a/lexer/Token.d Fri Apr 18 13:01:11 2008 +0200 +++ b/lexer/Token.d Fri Apr 18 13:45:39 2008 +0200 @@ -76,7 +76,8 @@ Bool, - If, + If, Else, + While, Return, } @@ -111,6 +112,7 @@ Tok.Div:"Div", Tok.Integer:"Integer", Tok.If:"If", + Tok.While:"While", Tok.Return:"Return", Tok.Seperator:"Seperator" ]; diff -r 2f493057cf17 -r 642c6a998fd9 parser/Parser.d --- a/parser/Parser.d Fri Apr 18 13:01:11 2008 +0200 +++ b/parser/Parser.d Fri Apr 18 13:45:39 2008 +0200 @@ -99,18 +99,23 @@ auto condition = parseExpression(); require(Tok.CloseParentheses); - Stmt[] stmts; - if (lexer.peek.type == Tok.OpenBrace) + auto then_body = parseBlockOrSingleStmt(); + + Stmt[] else_body; + if (lexer.peek.type == Tok.Else) { lexer.next; - while(lexer.peek.type != Tok.CloseBrace) - stmts ~= parseStatement(); - lexer.next; + else_body = parseBlockOrSingleStmt(); } - else - stmts ~= parseStatement(); + + return new IfStmt(condition, then_body, else_body); - return new IfStmt(condition, stmts); + case Tok.While: + lexer.next; + require(Tok.OpenParentheses); + auto condition = parseExpression(); + require(Tok.CloseParentheses); + return new WhileStmt(condition, parseBlockOrSingleStmt()); case Tok.Identifier: Token n = lexer.peek(1); @@ -269,6 +274,22 @@ assert(0, "Should not happen"); } + private Stmt[] parseBlockOrSingleStmt() + { + Stmt[] stmts; + if (lexer.peek.type == Tok.OpenBrace) + { + lexer.next; + while(lexer.peek.type != Tok.CloseBrace) + stmts ~= parseStatement(); + lexer.next; + } + else + stmts ~= parseStatement(); + + return stmts; + } + struct UnOp { Tok tokenType; diff -r 2f493057cf17 -r 642c6a998fd9 sema/SymbolTableBuilder.d --- a/sema/SymbolTableBuilder.d Fri Apr 18 13:01:11 2008 +0200 +++ b/sema/SymbolTableBuilder.d Fri Apr 18 13:45:39 2008 +0200 @@ -61,6 +61,29 @@ super.visitVarDecl(d); } + override void visitIfStmt(IfStmt s) + { + s.env = current(); + visitExp(s.cond); + push(); + foreach (stmt; s.then_body) + visitStmt(stmt); + pop(); + + push(); + foreach (stmt; s.else_body) + visitStmt(stmt); + pop(); + } + + override void visitWhileStmt(WhileStmt s) + { + s.env = current(); + push(); + super.visitWhileStmt(s); + pop(); + } + private: Scope[] table; diff -r 2f493057cf17 -r 642c6a998fd9 sema/Visitor.d --- a/sema/Visitor.d Fri Apr 18 13:01:11 2008 +0200 +++ b/sema/Visitor.d Fri Apr 18 13:45:39 2008 +0200 @@ -47,6 +47,8 @@ return visitExpStmt(cast(ExpStmt)stmt); case StmtType.If: return visitIfStmt(cast(IfStmt)stmt); + case StmtType.While: + return visitWhileStmt(cast(WhileStmt)stmt); default: throw new Exception("Unknown statement type"); } @@ -124,7 +126,20 @@ StmtT visitIfStmt(IfStmt s) { visitExp(s.cond); - foreach (stmt; s.then) + foreach (stmt; s.then_body) + visitStmt(stmt); + foreach (stmt; s.else_body) + visitStmt(stmt); + static if (is(StmtT == void)) + return; + else + return StmtT.init; + } + + StmtT visitWhileStmt(WhileStmt s) + { + visitExp(s.cond); + foreach (stmt; s.stmts) visitStmt(stmt); static if (is(StmtT == void)) return; diff -r 2f493057cf17 -r 642c6a998fd9 test.td --- a/test.td Fri Apr 18 13:01:11 2008 +0200 +++ b/test.td Fri Apr 18 13:45:39 2008 +0200 @@ -10,17 +10,27 @@ int fac(int n) { - if (n - 1) - return n * fac(n - 1); - return 1; + if (n == 1) + return 1; + return n * fac(n - 1); } int nice(long s, short t) { byte x = 5 + t; - if (x == 0) + if (x != 0) t = 5 + 1 * 5 * s + t; return 2 * (t + -1) - x; } +int fac2(int n) +{ + int res = 1; + while (n != 1) + { + res = res * n; + n = n - 1; + } + return res; +}