Mercurial > projects > dang
changeset 45:9bc660cbdbec new_gen
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
author | Anders Halager <halager@gmail.com> |
---|---|
date | Wed, 23 Apr 2008 16:43:42 +0200 |
parents | 495188f9078e |
children | 90fb4fdfefdd |
files | ast/Stmt.d gen/LLVMGen.d parser/Action.d parser/Parser.d sema/SymbolTableBuilder.d sema/Visitor.d |
diffstat | 6 files changed, 73 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- 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
--- 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(); }
--- 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);
--- 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 }
--- 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)
--- 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