# HG changeset patch # User Anders Halager # Date 1208961822 -7200 # Node ID 9bc660cbdbecb4a9c304bb182a76655b6b8ac64a # Parent 495188f9078e82ae7575028b7dc52a5c80e9330c If statements are back Also fixed a bug in the codegen preventing return in the else branch, now it is optional. Also found an issue with the way we are generating our llvm from ifs - it doesn't mean anything but the code looks ugly. if (cond_1) if (cond_2) statement; return 0; Becomes: br cond_1, then, merge then: br cond_2 then2, merge2 merge: ret 0 then2: statements merge2: br merge This is because we use appendBasicBlock on the function diff -r 495188f9078e -r 9bc660cbdbec ast/Stmt.d --- a/ast/Stmt.d Wed Apr 23 00:57:45 2008 +0200 +++ b/ast/Stmt.d Wed Apr 23 16:43:42 2008 +0200 @@ -77,7 +77,7 @@ class IfStmt : Stmt { - this(Exp cond, Stmt[] then, Stmt[] el = null) + this(Exp cond, Stmt then, Stmt el = null) { super(StmtType.If); this.cond = cond; @@ -86,8 +86,8 @@ } Exp cond; - Stmt[] then_body; - Stmt[] else_body; + Stmt then_body; + Stmt else_body; } class WhileStmt : Stmt diff -r 495188f9078e -r 9bc660cbdbec gen/LLVMGen.d --- a/gen/LLVMGen.d Wed Apr 23 00:57:45 2008 +0200 +++ b/gen/LLVMGen.d Wed Apr 23 16:43:42 2008 +0200 @@ -338,7 +338,7 @@ } auto func_name = stmt.env.parentFunction().id.get; Function func = m.getNamedFunction(func_name); - bool has_else = ifStmt.else_body.length > 0; + bool has_else = (ifStmt.else_body !is null); auto thenBB = func.appendBasicBlock("then"); auto elseBB = has_else? func.appendBasicBlock("else") : null; @@ -346,8 +346,7 @@ b.buildCondBr(cond, thenBB, has_else? elseBB : mergeBB); b.positionAtEnd(thenBB); - foreach (s; ifStmt.then_body) - genStmt(s); + genStmt(ifStmt.then_body); if (b.getInsertBlock().terminated() is false) b.buildBr(mergeBB); thenBB = b.getInsertBlock(); @@ -355,9 +354,9 @@ if (has_else) { b.positionAtEnd(elseBB); - foreach (s; ifStmt.else_body) - genStmt(s); - b.buildBr(mergeBB); + genStmt(ifStmt.else_body); + if (elseBB.terminated() is false) + b.buildBr(mergeBB); elseBB = b.getInsertBlock(); } diff -r 495188f9078e -r 9bc660cbdbec parser/Action.d --- a/parser/Action.d Wed Apr 23 00:57:45 2008 +0200 +++ b/parser/Action.d Wed Apr 23 16:43:42 2008 +0200 @@ -130,6 +130,14 @@ return null; } + /** + */ + StmtT actOnIfStmt(ref Token ifTok, ExprT cond, StmtT thenBody, + ref Token elseTok, StmtT elseBody) + { + return null; + } + StmtT actOnStartOfSwitchStmt() { return null; @@ -200,6 +208,7 @@ */ class AstAction : Action { + // -- Declarations -- override DeclT actOnDeclarator(ref Id type, ref Id id, ExprT init) { Exp exp = cast(Exp)init; @@ -224,11 +233,11 @@ return fd; } + // -- Statements -- override StmtT actOnCompoundStmt(ref Token l, ref Token r, StmtT[] stmts) { StmtT[] array = stmts.dup; Stmt[] statements = cast(Stmt[])array; - Stdout(statements).newline; return new CompoundStatement(cast(Stmt[])array); } @@ -240,6 +249,16 @@ return res; } + override StmtT actOnIfStmt(ref Token ifTok, ExprT cond, StmtT thenBody, + ref Token elseTok, StmtT elseBody) + { + Exp c = cast(Exp)cond; + Stmt t = cast(Stmt)thenBody; + Stmt e = cast(Stmt)elseBody; + return new IfStmt(c, t, e); + } + + // -- Expressions -- override ExprT actOnNumericConstant(Token c) { return new IntegerLit(c); diff -r 495188f9078e -r 9bc660cbdbec parser/Parser.d --- a/parser/Parser.d Wed Apr 23 00:57:45 2008 +0200 +++ b/parser/Parser.d Wed Apr 23 16:43:42 2008 +0200 @@ -86,8 +86,32 @@ require(Tok.Seperator); return action.actOnReturnStmt(ret, exp); + /* + if (cond) + single statement | compound statement + [else + single statement | compound statement] + */ case Tok.If: - return null; + Token _if = lexer.next(); + + require(Tok.OpenParentheses); + Exp cond = parseExpression(); + require(Tok.CloseParentheses); + + Stmt thenB = parseSingleOrCompoundStatement(); + + // if there is no else part we use the if as token, to have + // something than can be passed along + Token _else = _if; + Stmt elseB; + if (lexer.peek.type == Tok.Else) + { + _else = lexer.next; + elseB = parseSingleOrCompoundStatement(); + } + + return action.actOnIfStmt(_if, cond, thenB, _else, elseB); case Tok.While: return null; @@ -142,6 +166,16 @@ } /** + Parse either a block, or a single statement as allowed after if, while + and for. + */ + Stmt parseSingleOrCompoundStatement() + { + if (lexer.peek.type == Tok.OpenBrace) + return parseCompoundStatement(); + return parseStatement(); + } + /** Parses a function-body or similar, expects { to be current token. Will consume both the starting { and ending } diff -r 495188f9078e -r 9bc660cbdbec sema/SymbolTableBuilder.d --- a/sema/SymbolTableBuilder.d Wed Apr 23 00:57:45 2008 +0200 +++ b/sema/SymbolTableBuilder.d Wed Apr 23 16:43:42 2008 +0200 @@ -115,14 +115,15 @@ s.env = current(); visitExp(s.cond); auto sc = push(); - foreach (stmt; s.then_body) - visitStmt(stmt); + visitStmt(s.then_body); pop(sc); - sc = push(); - foreach (stmt; s.else_body) - visitStmt(stmt); - pop(sc); + if (s.else_body !is null) + { + sc = push(); + visitStmt(s.else_body); + pop(sc); + } } override void visitWhileStmt(WhileStmt s) diff -r 495188f9078e -r 9bc660cbdbec sema/Visitor.d --- a/sema/Visitor.d Wed Apr 23 00:57:45 2008 +0200 +++ b/sema/Visitor.d Wed Apr 23 16:43:42 2008 +0200 @@ -158,10 +158,9 @@ StmtT visitIfStmt(IfStmt s) { visitExp(s.cond); - foreach (stmt; s.then_body) - visitStmt(stmt); - foreach (stmt; s.else_body) - visitStmt(stmt); + visitStmt(s.then_body); + if (s.else_body !is null) + visitStmt(s.else_body); static if (is(StmtT == void)) return; else