# HG changeset patch # User Anders Johnsen # Date 1208683228 -7200 # Node ID 69464d4652848d7096eaacd1459f4f2f50da52ab # Parent 9031487e97d7f15a34ac41c37d8d5d824d87c63d Now supporting structs - both read and write. Still a few errors though, so watch out. diff -r 9031487e97d7 -r 69464d465284 ast/Exp.d --- 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) diff -r 9031487e97d7 -r 69464d465284 gen/LLVMGen.d --- 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: diff -r 9031487e97d7 -r 69464d465284 gen/LuaGen.d --- 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; diff -r 9031487e97d7 -r 69464d465284 lexer/Lexer.d --- 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 '!': diff -r 9031487e97d7 -r 69464d465284 lexer/Token.d --- 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", diff -r 9031487e97d7 -r 69464d465284 parser/Parser.d --- 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) diff -r 9031487e97d7 -r 69464d465284 sema/DType.d --- 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 diff -r 9031487e97d7 -r 69464d465284 sema/Declarations.d --- 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) diff -r 9031487e97d7 -r 69464d465284 sema/SymbolTable.d --- 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; diff -r 9031487e97d7 -r 69464d465284 sema/SymbolTableBuilder.d --- 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; } diff -r 9031487e97d7 -r 69464d465284 sema/Visitor.d --- 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; + } } diff -r 9031487e97d7 -r 69464d465284 test.td --- 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; } - +*/ diff -r 9031487e97d7 -r 69464d465284 tools/AstPrinter.d --- 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; diff -r 9031487e97d7 -r 69464d465284 tools/DotPrinter.d --- 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;