changeset 48:b6c1dc30ca4b new_gen

Only tests that dont pass now are structs and switches As far as the parser is concerned assignments are binary expressions Fixed a bug in codegen of if's - it is important to remember that the builder might be positioned at a new block after generating sub-statements
author Anders Halager <halager@gmail.com>
date Thu, 24 Apr 2008 19:42:53 +0200
parents b0a691727a0c
children c7cde6af0095
files ast/Exp.d gen/LLVMGen.d lexer/Token.d parser/Action.d parser/Parser.d
diffstat 5 files changed, 118 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/ast/Exp.d	Wed Apr 23 17:09:44 2008 +0200
+++ b/ast/Exp.d	Thu Apr 24 19:42:53 2008 +0200
@@ -59,6 +59,8 @@
 {
     public enum Operator
     {
+        Assign,
+
         Eq, Ne,
 
         Lt, Le,
--- a/gen/LLVMGen.d	Wed Apr 23 17:09:44 2008 +0200
+++ b/gen/LLVMGen.d	Thu Apr 24 19:42:53 2008 +0200
@@ -347,17 +347,17 @@
                 b.buildCondBr(cond, thenBB, has_else? elseBB : mergeBB);
                 b.positionAtEnd(thenBB);
                 genStmt(ifStmt.then_body);
+                thenBB = b.getInsertBlock();
                 if (b.getInsertBlock().terminated() is false)
                     b.buildBr(mergeBB);
-                thenBB = b.getInsertBlock();
 
                 if (has_else)
                 {
                     b.positionAtEnd(elseBB);
                     genStmt(ifStmt.else_body);
+                    elseBB = b.getInsertBlock();
                     if (elseBB.terminated() is false)
                         b.buildBr(mergeBB);
-                    elseBB = b.getInsertBlock();
                 }
 
                 b.positionAtEnd(mergeBB);
--- a/lexer/Token.d	Wed Apr 23 17:09:44 2008 +0200
+++ b/lexer/Token.d	Thu Apr 24 19:42:53 2008 +0200
@@ -67,6 +67,14 @@
     }
 
     /**
+      Returns true for all the various assignments (=, +=, *= ...)
+     */
+    bool isAssignment()
+    {
+        return type == Tok.Assign;
+    }
+
+    /**
       Just a shortcut to avoid `token.type == Tok.Identifier`.
      */
     bool isIdentifier()
--- a/parser/Action.d	Wed Apr 23 17:09:44 2008 +0200
+++ b/parser/Action.d	Thu Apr 24 19:42:53 2008 +0200
@@ -17,6 +17,8 @@
  */
 public enum Operator
 {
+    Assign,
+
     Eq, Ne,
 
     Lt, Le,
@@ -121,6 +123,19 @@
     }
 
     /**
+      An expression was used as a statement - this includes assignments,
+      function calls.
+
+      Additionally the D spec dictates that expressions with no effect are not
+      legal as statements, but the parser can't test for this so it has to be
+      done in the later stages.
+     */
+    StmtT actOnExprStmt(ExprT exp)
+    {
+        return null;
+    }
+
+    /**
       Called after parsing return statements.
 
       loc is the return token.
@@ -145,6 +160,13 @@
         return null;
     }
 
+    /**
+     */
+    StmtT actOnDeclStmt(DeclT decl)
+    {
+        return null;
+    }
+
     StmtT actOnStartOfSwitchStmt()
     {
         return null;
@@ -207,6 +229,18 @@
     {
         return null;
     }
+
+    /**
+      Called when function calls are encountered.
+
+      Note that args is temporary and might point into the stack. Remember to
+      copy before saving a reference to it.
+     */
+    ExprT actOnCallExpr(ExprT func, ref Token left_paren, ExprT[] args,
+                        ref Token right_paren)
+    {
+        return null;
+    }
 }
 
 /**
@@ -245,7 +279,12 @@
     {
         StmtT[] array = stmts.dup;
         Stmt[] statements = cast(Stmt[])array;
-        return new CompoundStatement(cast(Stmt[])array);
+        return new CompoundStatement(statements);
+    }
+
+    override StmtT actOnExprStmt(ExprT exp)
+    {
+        return new ExpStmt(cast(Exp)exp);
     }
 
     override StmtT actOnReturnStmt(ref Token loc, ExprT exp)
@@ -272,6 +311,12 @@
         return new WhileStmt(c, b);
     }
 
+    override StmtT actOnDeclStmt(DeclT decl)
+    {
+        Decl d = cast(Decl)decl;
+        return new DeclStmt(d);
+    }
+
     // -- Expressions --
     override ExprT actOnNumericConstant(Token c)
     {
@@ -287,7 +332,10 @@
     {
         Exp left = cast(Exp)l;
         Exp right = cast(Exp)r;
-        return new BinaryExp(cast(BinaryExp.Operator)op, left, right);
+        if (op == Operator.Assign)
+            return new AssignExp(left, right);
+        else
+            return new BinaryExp(cast(BinaryExp.Operator)op, left, right);
     }
 
     override ExprT actOnUnaryOp(Token op, ExprT operand)
@@ -296,5 +344,12 @@
         // can only be -x for now
         return new NegateExp(target);
     }
+
+    override ExprT actOnCallExpr(ExprT fn, ref Token, ExprT[] args, ref Token)
+    {
+        Exp f = cast(Exp)fn;
+        Exp[] arguments = cast(Exp[])args.dup;
+        return new CallExp(f, arguments);
+    }
 }
 
--- a/parser/Parser.d	Wed Apr 23 17:09:44 2008 +0200
+++ b/parser/Parser.d	Thu Apr 24 19:42:53 2008 +0200
@@ -29,12 +29,12 @@
         Decl[] declarations;
 
         while(lexer.peek.type != Tok.EOF)
-            declarations ~= parseRootDecl();
+            declarations ~= parseDecl();
 
         return declarations;
     }
 
-    Decl parseRootDecl()
+    Decl parseDecl()
     {
         Token t = lexer.peek;
 
@@ -127,21 +127,57 @@
                 Stmt bodyStmt = parseSingleOrCompoundStatement();
                 return action.actOnWhileStmt(_while, cond, bodyStmt);
 
+            /*
+               One of four things:
+               A declaration of a function/variable `type id ...`
+               A direct assignment `id = exp;`
+               An indirect assignment `id.id = exp`
+               Some sort of free standing expression
+
+               The assignments should be handled as binary expressions?
+             */
             case Tok.Identifier:
-                return null;
+                Token iden = lexer.peek;
+                Token n = lexer.peek(1);
+                // Must be an decl, if we start with a basic type, or two
+                // identifiers in a row
+                if (iden.isBasicType() || n.isIdentifier())
+                {
+                    // manually hardcoded to only support "type id [= exp];"
+                    // as that is the only thing the codegen understands
+                    Id type = Id(lexer.next);
+                    Id id = Id(lexer.next);
+                    Exp init;
+                    if (skip(Tok.Assign))
+                        init = parseExpression();
+                    require(Tok.Seperator);
+                    Decl d = action.actOnDeclarator(type, id, init);
+                    return action.actOnDeclStmt(d);
+                }
+                // Expression: a.b, a = b, a(b) etc.
+                else
+                {
+                    Exp exp = parseExpression();
+                    require(Tok.Seperator);
+                    return action.actOnExprStmt(exp);
+                }
+                break;
 
             case Tok.Switch:
+                throw error(__LINE__, ":(").tok(lexer.peek);
                 return null;
 
             default:
-                return null;
+                if (t.isBasicType())
+                    goto case Tok.Identifier;
+                throw error(__LINE__, ":(").tok(lexer.peek);
         }
-        error(__LINE__, "").tok(t);
+        throw error(__LINE__, "").tok(t);
         return null;
     }
 
     /**
-      Parses a function/method given the already parsed
+      Parses a function/method given the already parsed return type and name
      */
     Decl parseFunc(ref Id type, ref Id name)
     {
@@ -150,8 +186,7 @@
 
         Stmt stmt = parseCompoundStatement();
 
-        action.actOnEndOfFunction(func, stmt);
-        return func;
+        return action.actOnEndOfFunction(func, stmt);
     }
 
     /**
@@ -282,21 +317,18 @@
             Exp iden = parseExpIdentifier(value);
             switch(lexer.peek.type)
             {
-                // TODO: Function calls are parsed but ignored
                 case Tok.OpenParentheses:
-                    lexer.next;
-                    Exp[] args;
+                    Token lp = lexer.next;
+                    SmallArray!(Exp, 8) args;
                     while(lexer.peek.type != Tok.CloseParentheses)
                     {
                         if(lexer.peek.type == Tok.Comma)
-                        {
                             lexer.next;
-                        }
                         args ~= parseExpression();
                     }
 
-                    lexer.next();
-                    return null;//new CallExp(iden, args);
+                    Token rp = lexer.next();
+                    return action.actOnCallExpr(iden, lp, args.unsafe(), rp);
 
                 default:
                     return iden;
@@ -334,6 +366,8 @@
 
     static const BinOp[] _binary =
     [
+        {Tok.Assign,    1, false, Operator.Assign},
+
         {Tok.Eq,        2, true, Operator.Eq},
         {Tok.Ne,        2, true, Operator.Ne},