changeset 28:69464d465284 new_gen

Now supporting structs - both read and write. Still a few errors though, so watch out.
author Anders Johnsen <skabet@gmail.com>
date Sun, 20 Apr 2008 11:20:28 +0200
parents 9031487e97d7
children 41d23f2762c3
files ast/Exp.d gen/LLVMGen.d gen/LuaGen.d lexer/Lexer.d lexer/Token.d parser/Parser.d sema/DType.d sema/Declarations.d sema/SymbolTable.d sema/SymbolTableBuilder.d sema/Visitor.d test.td tools/AstPrinter.d tools/DotPrinter.d
diffstat 14 files changed, 316 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/ast/Exp.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/ast/Exp.d	Sun Apr 20 11:20:28 2008 +0200
@@ -11,6 +11,8 @@
     Binary,
     Negate,
     IntegerLit,
+    MemberLookup,
+    ArrayLookup,
     Identifier,
     AssignExp,
     CallExp,
@@ -42,14 +44,14 @@
 
 class AssignExp : Exp
 {
-    this(Identifier identifier, Exp exp)
+    this(Exp identifier, Exp exp)
     {
         super(ExpType.AssignExp);
         this.identifier = identifier;
         this.exp = exp;
     }
 
-    Identifier identifier;
+    Exp identifier;
     Exp exp;
 }
 
@@ -105,6 +107,32 @@
     Token token;
 }
 
+class MemberLookup : Exp
+{
+    this(Exp target, Identifier child)
+    {
+        super(ExpType.MemberLookup);
+        this.target = target;
+        this.child = child;
+    }
+
+    Identifier child;
+    Exp target;
+}
+
+class ArrayLookup : Exp
+{
+    this(Exp target, IntegerLit pos)
+    {
+        super(ExpType.ArrayLookup);
+        this.target = target;
+        this.pos = pos;
+    }
+
+    Exp target;
+    IntegerLit pos;
+}
+
 class Identifier : Exp
 {
     this(Token t)
--- a/gen/LLVMGen.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/gen/LLVMGen.d	Sun Apr 20 11:20:28 2008 +0200
@@ -136,6 +136,22 @@
                 table[varDecl.identifier.get] = g;
                 break;
         
+            case DeclType.StructDecl:
+                auto structDecl = cast(StructDecl)decl;
+                Type[] types;
+                foreach(varDecl ; structDecl.vars)
+                {
+                    auto sym = varDecl.env.find(varDecl.identifier);
+                    Type t = sym.type.llvm();
+                    types ~= t;
+                }
+
+                StructType t = StructType.Get(types);
+                m.addTypeName(structDecl.identifier.get, t);
+//                table[structDecl.identifier.get] = g;
+
+                break;
+
             default:
                 break;
         }
@@ -152,7 +168,7 @@
                 auto AI = b.buildAlloca(sym.type.llvm(), name);
                 table[name] = AI;
                 if (varDecl.init)
-                    buildAssign(sym, varDecl.init);
+                    buildAssign(varDecl.identifier, varDecl.init);
                 break;
         
             default:
@@ -205,7 +221,7 @@
                 return b.buildNeg(target, "neg");
             case ExpType.AssignExp:
                 auto assignExp = cast(AssignExp)exp;
-                return buildAssign(exp.env.find(assignExp.identifier), assignExp.exp);
+                return buildAssign(assignExp.identifier, assignExp.exp);
             case ExpType.CallExp:
                 auto callExp = cast(CallExp)exp;
                 auto func_sym = exp.env.find(cast(Identifier)callExp.exp);
@@ -217,6 +233,9 @@
                 auto identifier = cast(Identifier)exp;
                 auto sym = exp.env.find(identifier);
                 return b.buildLoad(table.find(sym.id.get), sym.id.get);
+            case ExpType.MemberLookup:
+                auto v = getPointer(exp);
+                return b.buildLoad(v, v.name);
         }
         assert(0, "Reached end of switch in genExpression");
         return null;
@@ -319,26 +338,70 @@
         }
     }
 
-    private Value buildAssign(Symbol sym, Exp exp)
+    Value getPointer(Exp exp)
     {
-        Type t = sym.type.llvm();
-        auto name = sym.id.get;
-        auto AI = table.find(name);
+        switch(exp.expType)
+        {
+            case ExpType.Identifier:
+                auto identifier = cast(Identifier)exp;
+                auto sym = exp.env.find(identifier);
+                return table.find(sym.id.get);
+            case ExpType.MemberLookup:
+                auto mem = cast(MemberLookup)exp;
+                switch(mem.target.expType)
+                {
+                    case ExpType.Identifier:
+                        auto identifier = cast(Identifier)mem.target;
+                        auto child = mem.child;
+                        auto sym = exp.env.find(identifier);
+                        auto symChild = child.env.find(child);
+                        Value v = table.find(sym.id.get);
+                        DType t = sym.type;
+                        auto st = cast(DStruct)t;
+
+                        int i = 0;
+                        foreach(char[] name, DType type ; st.members)
+                            if(name == child.get)
+                                break;
+                            else
+                                i++;
+
+                        Value[] vals;   
+                        vals ~= ConstantInt.Get(IntegerType.Int32, 0, false);
+                        vals ~= ConstantInt.Get(IntegerType.Int32, i, false);
+
+                        Value val = b.buildGEP(v, vals, sym.id.get~"."~child.get);
+                        return val;
+                }
+        }
+        assert(0, "Reached end of switch in getPointer");
+        return null;
+    }
+    private Value buildAssign(Exp target, Exp exp)
+    {
+        Value t = getPointer(target);
         Value v = genExpression(exp);
-        if (v.type != t)
+
+        auto a = (cast(PointerType)(t.type));
+
+        assert(a, "Assing to type have to be of type PointerType");
+
+        if (v.type != a.elementType)
         {
             IntegerType v_t = cast(IntegerType) v.type;
-            IntegerType i_t = cast(IntegerType) t;
+            IntegerType i_t = cast(IntegerType) t.type;
+            Stdout(v.type).newline;
+            Stdout(t.type).newline;
             if (v_t is null || i_t is null)
                 throw new Exception(
                         "Inappropriate assignment, types don't match");
 
             if (v_t.numBits() < i_t.numBits())
-                v = b.buildSExt(v, t, ".cast");
+                v = b.buildSExt(v, t.type, ".cast");
             else
-                v = b.buildTrunc(v, t, ".cast");
+                v = b.buildTrunc(v, t.type, ".cast");
         }
-        return b.buildStore(v, AI);
+        return b.buildStore(v, t);
     }
 
 private:
--- a/gen/LuaGen.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/gen/LuaGen.d	Sun Apr 20 11:20:28 2008 +0200
@@ -119,7 +119,7 @@
                 break;
             case ExpType.AssignExp:
                 auto assignExp = cast(AssignExp)exp;
-                genIdentifier(assignExp.identifier);
+                genExpression(assignExp.identifier);
                 print(" = ");
                 genExpression(assignExp.exp);
                 break;
--- a/lexer/Lexer.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/lexer/Lexer.d	Sun Apr 20 11:20:28 2008 +0200
@@ -81,6 +81,8 @@
                 return Token(Tok.CloseBrace, Location(position - 1, this.source), 1);
             case ';':
                 return Token(Tok.Seperator, Location(position - 1, this.source), 1);
+            case '.':
+                return Token(Tok.Dot, Location(position - 1, this.source), 1);
             case ',':
                 return Token(Tok.Comma, Location(position - 1, this.source), 1);
             case '=':
@@ -212,6 +214,7 @@
             case '{':
             case '}':
             case ';':
+            case '.':
             case ',':
             case '=':
             case '!':
--- a/lexer/Token.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/lexer/Token.d	Sun Apr 20 11:20:28 2008 +0200
@@ -58,6 +58,7 @@
     OpenBrace,
     CloseBrace,
     Seperator,
+    Dot,
 
     /* Comparator operators */
     Eq, Ne,
@@ -107,6 +108,7 @@
         Tok.CloseParentheses:"CloseParentheses",
         Tok.OpenBrace:"OpenBrace",
         Tok.CloseBrace:"CloseBrace",
+        Tok.Dot:"Dot",
         Tok.Assign:"Assign",
         Tok.Add:"Add",
         Tok.Sub:"Sub",
--- a/parser/Parser.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/parser/Parser.d	Sun Apr 20 11:20:28 2008 +0200
@@ -25,15 +25,15 @@
 
         while(lexer.peek.type != Tok.EOF)
         {
-            declarations ~= parseDecl;
+            declarations ~= parseRootDecl;
         }
 
         return declarations;
     }
 
-    Decl parseDecl()
+    Decl parseRootDecl()
     {
-        Token t = lexer.next;
+        Token t = lexer.peek;
 
         switch(t.type)
         {
@@ -46,21 +46,24 @@
                  Tok.Identifier:
                 Identifier type = new Identifier(t);
 
-                Token iden = lexer.next;
+                Token iden = lexer.peek(1);
 
                 switch(iden.type)
                 {
                     case Tok.Identifier:
                         Identifier identifier = new Identifier(iden);
-                        Token p = lexer.peek();
+                        Token p = lexer.peek(2);
                         switch(p.type)
                         {
                             case Tok.OpenParentheses:
+                                lexer.next; lexer.next;
                                 return parseFunc(type, identifier);
                             case Tok.Seperator:
+                                lexer.next; lexer.next;
                                 require(Tok.Seperator);
                                 return new VarDecl(type, identifier, null);
                             case Tok.Assign:
+                                lexer.next; lexer.next;
                                 lexer.next();
                                 auto exp = parseExpression();
                                 require(Tok.Seperator);
@@ -76,6 +79,7 @@
                 }
                 break;
             case Tok.Struct:
+                lexer.next;
                 Token iden = lexer.next;
                 switch(iden.type)
                 {
@@ -94,6 +98,61 @@
         }
     }
 
+    Decl parseDecl()
+    {
+        Token t = lexer.peek;
+
+        switch(t.type)
+        {
+            case Tok.Byte,  Tok.Ubyte,
+                 Tok.Short, Tok.Ushort,
+                 Tok.Int,   Tok.Uint,
+                 Tok.Long,  Tok.Ulong,
+                 Tok.Float, Tok.Double,
+                 Tok.Bool,
+                 Tok.Identifier:
+                Identifier type = new Identifier(t);
+
+                Token iden = lexer.peek(1);
+
+                switch(iden.type)
+                {
+                    case Tok.Identifier:
+                        Identifier identifier = new Identifier(iden);
+                        Token p = lexer.peek(2);
+                        switch(p.type)
+                        {
+                            case Tok.OpenParentheses:
+                                lexer.next; lexer.next;
+                                return parseFunc(type, identifier);
+                            case Tok.Seperator:
+                                lexer.next; lexer.next;
+                                require(Tok.Seperator);
+                                return new VarDecl(type, identifier, null);
+                            case Tok.Assign:
+                                lexer.next; lexer.next;
+                                lexer.next();
+                                auto exp = parseExpression();
+                                require(Tok.Seperator);
+                                return new VarDecl(type, identifier, exp);
+                            default:
+                                char[] c = t.getType;
+                                error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__));
+                        }
+                        break;
+                    default:
+                        char[] c = t.getType;
+                        error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__));
+                }
+                break;
+            case Tok.EOF:
+                return null;
+            default:
+                char[] c = t.getType;
+                error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__));
+        }
+    }
+
     VarDecl[] parseStruct()
     {
         VarDecl[] varDecls;
@@ -148,6 +207,17 @@
                 Token n = lexer.peek(1);
                 switch(n.type)
                 {
+                    case Tok.Dot:
+                        Exp iden = parseExpIdentifier(new Identifier(lexer.next));
+                        switch(lexer.peek.type)
+                        {
+                            case Tok.Assign:
+                                lexer.next;
+                                auto stmt = new ExpStmt(new AssignExp(iden , parseExpression()));
+                                require(Tok.Seperator);
+                                return stmt;
+                                break;
+                        }
                     case Tok.Assign:
                         lexer.next;
                         lexer.next;
@@ -249,6 +319,25 @@
 
     // -- Expression parsing -- //
 private:
+    Exp parseExpIdentifier(Exp target)
+    {
+        switch(lexer.peek.type)
+        {
+            case Tok.Dot:
+                switch(lexer.peek(1).type)
+                {
+                    case Tok.Identifier:
+                        lexer.next;
+                        return parseExpIdentifier(
+                                new MemberLookup(target, new Identifier(lexer.next)));
+                    default:
+                        throw new Error("Expected identifier after '.'", lexer.peek(1).location);
+                }
+            default:
+                return target;
+        }
+    }
+
     Exp parseExpression(int p = 0)
     {
         auto exp = P();
@@ -279,6 +368,7 @@
         }
         else if (next.type == Tok.Identifier)
         {
+            Exp iden = parseExpIdentifier(new Identifier(next));
             switch(lexer.peek.type)
             {
                 case Tok.OpenParentheses:
@@ -294,10 +384,10 @@
                     }
 
                     lexer.next();
-                    return new CallExp(new Identifier(next), args);
+                    return new CallExp(iden, args);
 
                 default:
-                    return new Identifier(next);
+                    return iden;
             }
         }
         else if (next.type == Tok.Integer)
--- a/sema/DType.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/sema/DType.d	Sun Apr 20 11:20:28 2008 +0200
@@ -7,6 +7,8 @@
 import lexer.Token,
        ast.Exp;
 
+import tango.io.Stdout;
+
 class DType
 {
     private char[] id;
@@ -50,6 +52,7 @@
     }
 
     char[] name() { return id; }
+    Location getLoc() { return loc; }
     LLVM.Type llvm() { return llvmType; }
 
     static DInteger
@@ -95,7 +98,20 @@
     {
         super(id, actual);
     }
-    DType[] members;
+
+    void setMembers(DType[char[]] members)
+    {
+        this.members = members;
+
+        LLVM.Type[] types;
+
+        foreach( type ; members)
+            types ~= type.llvm;
+
+        this.llvmType = LLVM.StructType.Get(types);
+
+    }
+    DType[char[]] members;
 }
 
 class DFunction : DType
--- a/sema/Declarations.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/sema/Declarations.d	Sun Apr 20 11:20:28 2008 +0200
@@ -1,6 +1,7 @@
 module sema.Declarations;
 
-import sema.Visitor;
+import sema.Visitor,
+       sema.DType;
 
 import tango.io.Stdout;
 
@@ -10,41 +11,44 @@
 {
     int[char[]] types;
 
-    this()
-    {
-        types = [
-            "byte"[]:0,
-            "ubyte":1,
-            "short":2,
-            "ushort":3,
-            "int":4,
-            "uint":5,
-            "long":6,
-            "ulong":7,
-            "bool":8,
-            "void":9
-                ];
-    }
-
     override void visitIdentifier(Identifier i)
     {
         auto symbol = i.env.find(i);
 
-        if(symbol is null && !isType(i.get))
+        if(symbol is null)
             throw new Error("Undefined identifier: '"~i.get~"'",i.token.location);
 
     }
 
     override void visitVarDecl(VarDecl d)
     {
-        if(!isType(d.type.get) && d.env.findType(d.identifier))
+        if(!d.env.findType(d.type))
             throw new Error("Undefined type: '"~d.type.get~"'",d.type.token.location);
 
-        visitExp(d.type);
         visitExp(d.identifier);
         if (d.init)
             visitExp(d.init);
     }
+    override void visitFuncDecl(FuncDecl f)
+    {
+        visitExp(f.identifier);
+
+        foreach (stmt; f.statements)
+            visitStmt(stmt);
+    }
+
+    override void visitMemberLookup(MemberLookup m)
+    {
+        switch(m.target.expType)
+        {
+            case ExpType.Identifier:
+                auto target = cast(Identifier)m.target;
+                auto child = m.child;
+                auto st = cast(DStruct)(target.env.find(target).type);
+                if((child.get in st.members) == null)
+                    throw new Error("Undefined member in "~target.get~" with type "~st.name,st.getLoc);
+        }
+    }
 
 
     bool isType(char[] s)
--- a/sema/SymbolTable.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/sema/SymbolTable.d	Sun Apr 20 11:20:28 2008 +0200
@@ -5,6 +5,8 @@
 import lexer.Token,
        ast.Exp;
 
+import sema.DType;
+
 public
 import sema.Symbol;
 
@@ -36,13 +38,12 @@
         return null;
     }
 
-    Symbol findType(Identifier id)
+    DType findType(Identifier id)
     {
-        if (auto sym = id in symbols)
-            if(symbols[id].type == null)
-                return *sym;
+        if (auto type = id.get in types)
+                return *type;
         if (enclosing !is null)
-            return enclosing.find(id);
+            return enclosing.findType(id);
         return null;
     }
 
@@ -83,6 +84,7 @@
         func = f;
         return f;
     }
+    DType[char[]] types;
 private:
     Symbol[Identifier] symbols;
     Symbol func;
--- a/sema/SymbolTableBuilder.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/sema/SymbolTableBuilder.d	Sun Apr 20 11:20:28 2008 +0200
@@ -13,16 +13,16 @@
     this()
     {
         table ~= new Scope;
-        types["void"]    = DType.Void;
-        types["bool"]    = DType.Bool;
-        types["byte"]    = DType.Byte;
-        types["ubyte"]   = DType.UByte;
-        types["short"]   = DType.Short;
-        types["ushort"]  = DType.UShort;
-        types["int"]     = DType.Int;
-        types["uint"]    = DType.UInt;
-        types["long"]    = DType.Long;
-        types["ulong"]   = DType.ULong;
+        table[0].types["void"]    = DType.Void;
+        table[0].types["bool"]    = DType.Bool;
+        table[0].types["byte"]    = DType.Byte;
+        table[0].types["ubyte"]   = DType.UByte;
+        table[0].types["short"]   = DType.Short;
+        table[0].types["ushort"]  = DType.UShort;
+        table[0].types["int"]     = DType.Int;
+        table[0].types["uint"]    = DType.UInt;
+        table[0].types["long"]    = DType.Long;
+        table[0].types["ulong"]   = DType.ULong;
     }
 
     override void visit(Decl[] decls)
@@ -52,11 +52,11 @@
     override void visitFuncDecl(FuncDecl d)
     {
         auto sym = current().add(d.identifier);
-        sym.type = typeOf(d.type);
+        auto sc = push();
+        sym.type = typeOf(d.type, sc);
         visitExp(d.type);
         visitExp(d.identifier);
         d.env = current();
-        auto sc = push();
         sc.parentFunction = sym;
         foreach (arg; d.funcArgs)
             visitDecl(arg);
@@ -77,7 +77,7 @@
 
         auto sc = current();
         auto sym = sc.add(d.identifier);
-        sym.type = typeOf(d.type);
+        sym.type = typeOf(d.type, sc);
         d.env = sc;
         visitExp(d.type);
         visitExp(d.identifier);
@@ -87,7 +87,19 @@
     {
         auto sc = current();
         auto sym = sc.add(s.identifier);
-//        sym.type = Tok.Struct;
+        DType[char[]] types;
+        foreach(varDecl ; s.vars)
+        {
+            types[varDecl.identifier.get] = typeOf(varDecl.type, sc);
+        }
+
+        auto type = new DStruct(s.identifier);
+        
+        type.setMembers(types);
+
+        sc.types[s.identifier.get] = type;
+        sym.type = type;
+        s.env = sc;
         super.visitStructDecl(s);
     }
 
@@ -149,13 +161,16 @@
         return table[$ - 1];
     }
 
-    DType typeOf(Identifier id)
+    DType typeOf(Identifier id, Scope sc)
     {
+        return sc.findType(id);
+
+        /*
         if (auto type = id.get in types)
             return *type;
         DType res = new DType(id);
         types[id.get] = res;
-        return res;
+        return res;*/
     }
     DType[char[]] types;
 }
--- a/sema/Visitor.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/sema/Visitor.d	Sun Apr 20 11:20:28 2008 +0200
@@ -72,6 +72,8 @@
                 return visitCallExp(cast(CallExp)exp);
             case ExpType.Identifier:
                 return visitIdentifier(cast(Identifier)exp);
+            case ExpType.MemberLookup:
+                return visitMemberLookup(cast(MemberLookup)exp);
             default:
                 throw new Exception("Unknown expression type");
         }
@@ -227,5 +229,16 @@
         else
             return ExpT.init;
     }
+
+    ExpT visitMemberLookup(MemberLookup mem)
+    {
+        visitExp(mem.target);
+        visitExp(mem.child);
+
+        static if (is(ExpT == void))
+            return;
+        else
+            return ExpT.init;
+    }
 }
 
--- a/test.td	Sun Apr 20 01:08:50 2008 +0200
+++ b/test.td	Sun Apr 20 11:20:28 2008 +0200
@@ -1,14 +1,27 @@
 
 int x = 4;
 
+struct mystruct
+{
+    int s;
+    int t;
+}
+
 int main()
 {
     int y = 4;
+
+    mystruct z;
+    z.s = 6;
+//    y.x = 6;
+
     while (y > 0)
         y = y - 1;
+
+    y = z.s;
     return y;
 }
-
+/*
 int add(int x, int y)
 {
     return x + y;
@@ -41,4 +54,4 @@
     }
     return res;
 }
-
+*/
--- a/tools/AstPrinter.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/tools/AstPrinter.d	Sun Apr 20 11:20:28 2008 +0200
@@ -103,7 +103,7 @@
                 break;
             case ExpType.AssignExp:
                 auto assignExp = cast(AssignExp)exp;
-                printIdentifier(assignExp.identifier);
+                printExp(assignExp.identifier);
                 print("= ");
                 printExp(assignExp.exp);
                 break;
--- a/tools/DotPrinter.d	Sun Apr 20 01:08:50 2008 +0200
+++ b/tools/DotPrinter.d	Sun Apr 20 11:20:28 2008 +0200
@@ -127,7 +127,7 @@
             case ExpType.AssignExp:
                 auto ass = cast(AssignExp)exp;
                 Stdout(parent)(` [label="Assign"]`).newline;
-                Stdout(id)(` [label="`)(text(ass.identifier))(`"]`).newline;
+//                Stdout(id)(` [label="`)(text(ass.identifier))(`"]`).newline;
                 printExpression(parent, ass.exp);
                 break;