changeset 11:642c6a998fd9

Support for while statements and fixed scope for if
author Anders Halager <halager@gmail.com>
date Fri, 18 Apr 2008 13:45:39 +0200
parents 2f493057cf17
children 6282db07115f
files ast/Stmt.d gen/LLVMGen.d lexer/Keyword.d lexer/Token.d parser/Parser.d sema/SymbolTableBuilder.d sema/Visitor.d test.td
diffstat 8 files changed, 167 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- 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;
+}
+
--- 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;
--- 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
     ];
 }
--- 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"
     ];
--- 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;
--- 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;
 
--- 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;
--- 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;
+}