# HG changeset patch # User Anders Halager # Date 1208622582 -7200 # Node ID 2d28b21faad6549e6adfd74107f94f6b9abf171c # Parent dd18654b5131fe1f894f80081f51b7710ea85f92# Parent e331e4e816e4fe700875af90fe2212ff41aef465 New codegen! Rewritten codegen to use the llvm bindings Everything except struct are back to normal, and there a a few additions. 1. Correct code in more cases, return at the end of a while/if wont generate a "ret" followed by a "br". 2. Better scope, "int x = x" now illegal 3. Probably more diff -r dd18654b5131 -r 2d28b21faad6 ast/Decl.d --- a/ast/Decl.d Sat Apr 19 11:40:20 2008 +0200 +++ b/ast/Decl.d Sat Apr 19 18:29:42 2008 +0200 @@ -11,6 +11,7 @@ { VarDecl, FuncDecl, + StructDecl, } class Decl @@ -56,3 +57,17 @@ Stmt[] statements; } +class StructDecl : Decl +{ + this(Identifier identifier, + VarDecl[] vars) + { + super(DeclType.StructDecl); + this.identifier = identifier; + this.vars = vars; + } + + Identifier identifier; + VarDecl[] vars; +} + diff -r dd18654b5131 -r 2d28b21faad6 dang/compiler.d --- a/dang/compiler.d Sat Apr 19 11:40:20 2008 +0200 +++ b/dang/compiler.d Sat Apr 19 18:29:42 2008 +0200 @@ -139,7 +139,15 @@ auto src = DataSource(file); auto lexer = new Lexer(src); - +/* + auto t = lexer.next; + while(t.getType != "EOF") + { + Stdout(t.getType)(" : ")(t.get).newline; + t = lexer.next; + } + lexer = new Lexer(src); +*/ postLex(lexer); preParse(lexer); diff -r dd18654b5131 -r 2d28b21faad6 gen/LLVMGen.d --- a/gen/LLVMGen.d Sat Apr 19 11:40:20 2008 +0200 +++ b/gen/LLVMGen.d Sat Apr 19 18:29:42 2008 +0200 @@ -12,7 +12,17 @@ import lexer.Token; -import sema.SymbolTableBuilder; +import sema.SymbolTableBuilder, + sema.Visitor; + +private char[] genBuildCmp(char[] p) +{ + return ` + (Value l, Value r, char[] n) + { + return b.buildICmp(IntPredicate.`~p~`, l, r, n); + }`; +} class LLVMGen { @@ -31,34 +41,52 @@ "void" : Type.Void ]; alias BinaryExp.Operator op; + b = new Builder; + opToLLVM = [ - op.Add : "add"[], - op.Sub : "sub", - op.Mul : "mul", - op.Div : "div", - op.Eq : "icmp eq", - op.Ne : "icmp ne", - op.Lt : "icmp slt", - op.Le : "icmp sle", - op.Gt : "icmp sgt", - op.Ge : "icmp sge" + op.Add : &b.buildAdd, + op.Sub : &b.buildSub, + op.Mul : &b.buildMul, + op.Div : &b.buildSDiv, + op.Eq : mixin(genBuildCmp("EQ")), + op.Ne : mixin(genBuildCmp("NE")), + op.Lt : mixin(genBuildCmp("SLT")), + op.Le : mixin(genBuildCmp("SLE")), + op.Gt : mixin(genBuildCmp("SGT")), + op.Ge : mixin(genBuildCmp("SGE")) ]; table = new SimpleSymbolTable(); } + ~this() + { + b.dispose(); + } + void gen(Decl[] decls) { // create module m = new Module("main_module"); scope(exit) m.dispose(); - b = new Builder; - scope(exit) b.dispose(); table.enterScope; - foreach(decl ; decls) - genRootDecl(decl); + auto registerFunc = + (FuncDecl funcDecl) + { + Type[] param_types; + foreach (param; funcDecl.funcArgs) + param_types ~= typeToLLVM[param.type.get]; + auto ret_t = typeToLLVM[funcDecl.type.get]; + auto func_t = FunctionType.Get(ret_t, param_types); + auto llfunc = m.addFunction(func_t, funcDecl.identifier.get); + }; + auto visitor = new VisitFuncDecls(registerFunc); + visitor.visit(decls); + + foreach (decl; decls) + genRootDecl(decl); table.leaveScope; @@ -66,6 +94,8 @@ m.verify(err); Stderr(err).newline; + //m.optimize(false); + m.writeBitcodeToFile("test.bc"); } @@ -76,97 +106,42 @@ case DeclType.FuncDecl: FuncDecl funcDecl = cast(FuncDecl)decl; - Type[] param_types; - foreach (param; funcDecl.funcArgs) - param_types ~= typeToLLVM[param.type.get]; + auto llfunc = m.getNamedFunction(funcDecl.identifier.get); auto ret_t = typeToLLVM[funcDecl.type.get]; - auto func_t = FunctionType.Get(ret_t, param_types); - auto llfunc = m.addFunction(func_t, funcDecl.identifier.get); - - foreach (i, v; funcDecl.funcArgs) - llfunc.getParam(i).name = v.identifier.get; auto bb = llfunc.appendBasicBlock("entry"); b.positionAtEnd(bb); - if (ret_t is Type.Void) - b.buildRetVoid(); - else - b.buildRet(ConstantInt.GetS(ret_t, 0)); - - /* - auto return_type = typeToLLVM[funcDecl.type.token.get]; - - printBeginLine("define "); - print(return_type); - print(" @"); - genIdentifier(funcDecl.identifier); - print("("); - table.enterScope; - Identifier[] args; - foreach(i, funcArg ; funcDecl.funcArgs) + foreach (i, v; funcDecl.funcArgs) { - print(typeToLLVM[funcArg.type.token.get]); - print(" %"); - print("."~Integer.toString(i)); - args ~= funcArg.identifier; - table.find(funcArg.identifier.get); - if(i+1 < funcDecl.funcArgs.length) - print(", "); + llfunc.getParam(i).name = v.identifier.get; + auto name = v.identifier.get; + auto AI = b.buildAlloca(llfunc.getParam(i).type, name); + b.buildStore(llfunc.getParam(i), AI); + table[name] = AI; } - - printEndLine(") {"); - - indent; - - foreach(i, arg ; args) - { - auto sym = arg.env.find(arg); - auto type = typeToLLVM[sym.type.get]; - printBeginLine("%"~arg.get); - printEndLine(" = alloca " ~ type); - printBeginLine("store " ~ type ~ " %."); - print(Integer.toString(i)); - print(", " ~ type ~ "* %"); - printEndLine(arg.get); - } - - printEndLine(); foreach (stmt; funcDecl.statements) genStmt(stmt); - if (return_type == "void") - { - printBeginLine("ret void"); - printEndLine(); - } + + // if the function didn't end with a return, we automatically + // add one (return 0 as default) + if (b.getInsertBlock().terminated() is false) + if (ret_t is Type.Void) + b.buildRetVoid(); + else + b.buildRet(ConstantInt.GetS(ret_t, 0)); + table.leaveScope; - dedent; - printBeginLine("}"); - printEndLine(); - */ break; case DeclType.VarDecl: auto varDecl = cast(VarDecl)decl; - /* - printBeginLine("@"); - genIdentifier(varDecl.identifier); - - print(" = "); - if(varDecl.init) - { - if(cast(IntegerLit)varDecl.init) - printEndLine("global i32 " ~ (cast(IntegerLit)varDecl.init).token.get); - else - assert(0,"Declaring an variable to an expression is not allowed"); - } - else - printEndLine("i32 0"); - - printEndLine(); - */ + Type t = typeToLLVM[varDecl.type.get]; + GlobalVariable g = m.addGlobal(t, varDecl.identifier.get); + g.initializer = ConstantInt.GetS(t, 0); + table[varDecl.identifier.get] = g; break; default: @@ -180,52 +155,40 @@ { case DeclType.VarDecl: auto varDecl = cast(VarDecl)decl; - /* - printBeginLine("%"); - print(table.find(varDecl.identifier.get)); - print(" = alloca "); - printEndLine(typeToLLVM[varDecl.type.get]); - if(varDecl.init) - { - auto assignExp = new AssignExp(varDecl.identifier, varDecl.init); - assignExp.env = decl.env; - assignExp.identifier.env = decl.env; - genExpression(assignExp); - } - */ + Type t = typeToLLVM[varDecl.type.get]; + auto name = varDecl.identifier.get; + auto AI = b.buildAlloca(t, name); + table[name] = AI; + Stderr("env", varDecl.env.names).newline; + if (varDecl.init) + buildAssign(varDecl.env.find(varDecl.identifier), varDecl.init); break; default: } } - void unify(Ref* a, Ref* b) + void sextSmallerToLarger(ref Value left, ref Value right) { - if (a.type != b.type) + if (left.type != right.type) { - auto a_val = intTypes.find(a.type); - auto b_val = intTypes.find(b.type); - // swap types so a is always the "largest" type - if (a_val < b_val) - { - Ref* tmp = b; - b = a; - a = tmp; - } + // try to find a convertion - only works for iX + IntegerType l = cast(IntegerType) left.type; + IntegerType r = cast(IntegerType) right.type; + if (l is null || r is null) + throw new Exception( + "Can't find a valid convertion between " + "a " ~ left.type.toString ~ " and a " + ~ right.type.toString); - auto res = table.find("%.cast"); - printBeginLine(res); - printCastFromTo(b, a); - print(*b); - print(" to "); - printEndLine(a.type); - - b.type = a.type; - b.name = res; + if (l.numBits() < r.numBits()) + left = b.buildSExt(left, r, ".cast"); + else + right = b.buildSExt(right, l, ".cast"); } } - Ref genExpression(Exp exp) + Value genExpression(Exp exp) { switch(exp.expType) { @@ -235,112 +198,38 @@ auto left = genExpression(binaryExp.left); auto right = genExpression(binaryExp.right); - unify(&left, &right); - + sextSmallerToLarger(left, right); - auto res = Ref(left.type, table.find); - /* - printBeginLine(res.name); - print(" = "~opToLLVM[binaryExp.op]~" "); - print(left); - print(", "); - printEndLine(right.name); + OpBuilder op = opToLLVM[binaryExp.op]; - // exp always returns known type (== returns bool no matter - // what the params are) - if (binaryExp.resultType) - res.type = typeToLLVM[binaryExp.resultType]; + return op(left, right, "."); - */ - return res; case ExpType.IntegerLit: auto integetLit = cast(IntegerLit)exp; - auto t = integetLit.token; - return Ref("int", t.get, true); + auto val = integetLit.token.get; + return ConstantInt.GetS(Type.Int32, Integer.parse(val)); case ExpType.Negate: auto negateExp = cast(NegateExp)exp; auto target = genExpression(negateExp.exp); - auto res = table.find; - /* - printBeginLine(res); - print(" = sub "~target.type~" 0, "); - printEndLine(target.name); - */ - return Ref(target.type, res); + return b.buildNeg(target, "neg"); case ExpType.AssignExp: auto assignExp = cast(AssignExp)exp; - auto sym = exp.env.find(assignExp.identifier); - - /* - Ref val = genExpression(assignExp.exp); - Ref r = Ref(typeToLLVM[sym.type.get], val.name); - - if (val.type != r.type) - { - auto res = table.find("%.cast"); - printBeginLine(res); - printCastFromTo(val.type, r.type); - print(val); - print(" to "); - printEndLine(r.type); - r.name = res; - } - - printBeginLine("store "); - print(r); - print(", "); - print(r.type ~ "* %"); - printEndLine(assignExp.identifier.get); - */ - break; + buildAssign(exp.env.find(assignExp.identifier), assignExp.exp); + return null; case ExpType.CallExp: auto callExp = cast(CallExp)exp; auto func_sym = exp.env.find(cast(Identifier)callExp.exp); - /* - auto func_type = typeToLLVM[func_sym.type.get]; - Ref[] args; - foreach(i, arg ; callExp.args) + Value[] args; + foreach (arg; callExp.args) args ~= genExpression(arg); - - char[] res = ""; - if (func_type != "void") - { - res = table.find; - printBeginLine(res); - print(" = call "); - } - else - printBeginLine("call "); - - print(func_type); - print(" @"); - - print(func_sym.id.get); - - print("("); - foreach(i, arg ; args) - { - print(arg); - if(i+1 < args.length) - print(", "); - } - printEndLine(")"); - */ - return Ref(func_sym.type.get, ""); + return b.buildCall(m.getNamedFunction(func_sym.id.get), args, ".call"); case ExpType.Identifier: auto identifier = cast(Identifier)exp; auto sym = exp.env.find(identifier); - char[] res = table.find; - /* - printBeginLine(res); - print(" = load "); - print(typeToLLVM[sym.type.get]); - print("* %"); - printEndLine(sym.id.name); - */ - return Ref(sym.type.get, res); + return b.buildLoad(table.find(sym.id.get), sym.id.get); } - return Ref(); + assert(0, "Reached end of switch in genExpression"); + return null; } void genStmt(Stmt stmt) @@ -350,25 +239,22 @@ case StmtType.Return: auto ret = cast(ReturnStmt)stmt; auto sym = stmt.env.parentFunction(); - /* - auto type = typeToLLVM[sym.type.get]; - - Ref res = genExpression(ret.exp); - - if (type != res.type) + Type t = typeToLLVM[sym.type.get]; + Value v = genExpression(ret.exp); + if (v.type != t) { - auto cast_res = table.find("%.cast"); - printBeginLine(cast_res); - printCastFromTo(res.type, type); - print(res); - print(" to "); - printEndLine(type); - res.name = cast_res; - res.type = type; + IntegerType v_t = cast(IntegerType) v.type; + IntegerType i_t = cast(IntegerType) t; + if (v_t is null || i_t is null) + throw new Exception( + "Inappropriate assignment" + ", types dont match"); + if (v_t.numBits() < i_t.numBits()) + v = b.buildSExt(v, t, ".cast"); + else + v = b.buildTrunc(v, t, ".cast"); } - printBeginLine("ret "); - printEndLine(res); - */ + b.buildRet(v); break; case StmtType.Decl: auto declStmt = cast(DeclStmt)stmt; @@ -380,163 +266,89 @@ break; case StmtType.If: auto ifStmt = cast(IfStmt)stmt; - Ref val = genExpression(ifStmt.cond); - /* - auto cond = table.find("%.cond"); - printBeginLine(cond); - print(" = icmp ne "); - print(val); - printEndLine(", 0"); + Value cond = genExpression(ifStmt.cond); + if (cond.type !is Type.Int1) + { + Value False = ConstantInt.GetS(cond.type, 0); + cond = b.buildICmp(IntPredicate.NE, cond, False, ".cond"); + } + auto func_name = stmt.env.parentFunction().id.get; + Function func = m.getNamedFunction(func_name); + bool has_else = ifStmt.else_body.length > 0; - 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(ifStmt.else_body? else_branch : done_label); + auto thenBB = func.appendBasicBlock("then"); + auto elseBB = has_else? func.appendBasicBlock("else") : null; + auto mergeBB = func.appendBasicBlock("merge"); - printBeginLine(then_branch); - printEndLine(":"); - - indent(); + b.buildCondBr(cond, thenBB, has_else? elseBB : mergeBB); + b.positionAtEnd(thenBB); foreach (s; ifStmt.then_body) genStmt(s); - printBeginLine("br label %"); - printEndLine(done_label); - dedent(); + if (b.getInsertBlock().terminated() is false) + b.buildBr(mergeBB); + thenBB = b.getInsertBlock(); - if (ifStmt.else_body) + if (has_else) { - printBeginLine(else_branch); - printEndLine(":"); - - indent(); + b.positionAtEnd(elseBB); foreach (s; ifStmt.else_body) genStmt(s); - printBeginLine("br label %"); - printEndLine(done_label); - dedent(); + b.buildBr(mergeBB); + elseBB = b.getInsertBlock(); } - printBeginLine(done_label); - printEndLine(":"); - */ - + b.positionAtEnd(mergeBB); 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"); + auto func_name = stmt.env.parentFunction().id.get; + Function func = m.getNamedFunction(func_name); - printBeginLine("br label %"); - printEndLine(cond_label); - - printBeginLine(cond_label); - printEndLine(":"); - - indent(); - - Ref val = genExpression(wStmt.cond); - auto cond = table.find("%.cond"); + auto condBB = func.appendBasicBlock("cond"); + auto bodyBB = func.appendBasicBlock("body"); + auto doneBB = func.appendBasicBlock("done"); - printBeginLine(cond); - print(" = icmp ne "); - print(val); - printEndLine(", 0"); + b.buildBr(condBB); + b.positionAtEnd(condBB); + Value cond = genExpression(wStmt.cond); + if (cond.type !is Type.Int1) + { + Value False = ConstantInt.GetS(cond.type, 0); + cond = b.buildICmp(IntPredicate.NE, cond, False, ".cond"); + } + b.buildCondBr(cond, bodyBB, doneBB); - printBeginLine("br i1 "); - print(cond); - print(", label %"); - print(body_label); - print(", label %"); - printEndLine(done_label); - - dedent(); - - printBeginLine(body_label); - printEndLine(":"); - - indent(); + b.positionAtEnd(bodyBB); foreach (s; wStmt.stmts) genStmt(s); - printBeginLine("br label %"); - printEndLine(cond_label); - dedent(); + if (b.getInsertBlock().terminated() is false) + b.buildBr(condBB); - printBeginLine(done_label); - printEndLine(":"); - - */ + b.positionAtEnd(doneBB); break; } } - void genIdentifier(Identifier identifier) - { - print(identifier.get); - } - - void indent() - { - tabIndex ~= tabType; - } - - void dedent() + private void buildAssign(Symbol sym, Exp exp) { - tabIndex = tabIndex[0 .. $-tabType.length]; - } - - void printBeginLine(char[] line = "") - { - Stdout(tabIndex~line); - } - void printBeginLine(Ref r) - { - Stdout(tabIndex~r.type~" "~r.name); - } - - void printEndLine(char[] line = "") - { - Stdout(line).newline; - } + Type t = typeToLLVM[sym.type.get]; + auto name = sym.id.get; + auto AI = table.find(name); + Value v = genExpression(exp); + if (v.type != t) + { + IntegerType v_t = cast(IntegerType) v.type; + IntegerType i_t = cast(IntegerType) t; + if (v_t is null || i_t is null) + throw new Exception( + "Inappropriate assignment, types don't match"); - void printEndLine(Ref r) - { - Stdout(r.type~" "~r.name).newline; - } - - void print(char[] line) - { - Stdout(line); - } - - void print(Ref r) - { - Stdout(r.type~" "~r.name); - } - - void printCastFromTo(size_t t1, size_t t2) - { - if (t1 < t2) - print(" = zext "); - else - print(" = trunc "); - } - - void printCastFromTo(char[] t1, char[] t2) - { - printCastFromTo(intTypes.find(t1), intTypes.find(t2)); - } - - void printCastFromTo(Ref* t1, Ref* t2) - { - printCastFromTo(intTypes.find(t1.type), intTypes.find(t2.type)); + if (v_t.numBits() < i_t.numBits()) + v = b.buildSExt(v, t, ".cast"); + else + v = b.buildTrunc(v, t, ".cast"); + } + b.buildStore(v, AI); } private: @@ -545,59 +357,59 @@ Module m; Builder b; - char[] tabIndex; - const char[] tabType = " "; // 4 spaces FuncDecl[char[]] functions; SimpleSymbolTable table; - SymbolTable symbolTable; static Type[char[]] typeToLLVM; - static char[][BinaryExp.Operator] opToLLVM; - - static char[][] intTypes = [ "i1", "i8", "i16", "i32", "i64" ]; + alias Value delegate(Value, Value, char[]) OpBuilder; + static OpBuilder[BinaryExp.Operator] opToLLVM; } -struct Ref +private class VisitFuncDecls : Visitor!(void) { - char[] type; - char[] name; - bool atomic = false; - static Ref opCall(char[] type = "void", char[] name = "", bool atomic = false) + void delegate(FuncDecl) dg; + this(void delegate(FuncDecl funcDecl) dg) { - Ref r; - //if(auto llvm_t = type in LLVMGen.typeToLLVM) - // r.type = *llvm_t; - //else - r.type = type; - r.name = name; - r.atomic = atomic; - return r; + this.dg = dg; + } + + override void visit(Decl[] decls) + { + foreach (decl; decls) + if (auto f = cast(FuncDecl)decl) + dg(f); } } -class SimpleSymbolTable +private class SimpleSymbolTable { - int[char[]][] variables; + Value[char[]][] namedValues; void enterScope() { - variables ~= cast(int[char[]])["__dollar":-1]; + namedValues ~= cast(Value[char[]])["__dollar":null]; } void leaveScope() { - variables.length = variables.length - 1; + namedValues.length = namedValues.length - 1; + } + + Value put(Value val, char[] key) + { + namedValues[$ - 1][key] = val; + return val; } - char[] find(char[] v = "%.tmp") + Value find(char[] key) { - foreach_reverse(map ; variables) - { - if(v in map) - return v~"."~Integer.toString(++map[v]); - } - variables[$-1][v] = 0; - return v; + foreach_reverse (map; namedValues) + if(auto val_ptr = key in map) + return *val_ptr; + return null; } + + alias find opIndex; + alias put opIndexAssign; } diff -r dd18654b5131 -r 2d28b21faad6 lexer/Keyword.d --- a/lexer/Keyword.d Sat Apr 19 11:40:20 2008 +0200 +++ b/lexer/Keyword.d Sat Apr 19 18:29:42 2008 +0200 @@ -25,6 +25,7 @@ "if" : Tok.If, "else" : Tok.Else, "while" : Tok.While, - "return" : Tok.Return + "return" : Tok.Return, + "struct" : Tok.Struct ]; } diff -r dd18654b5131 -r 2d28b21faad6 lexer/Token.d --- a/lexer/Token.d Sat Apr 19 11:40:20 2008 +0200 +++ b/lexer/Token.d Sat Apr 19 18:29:42 2008 +0200 @@ -76,6 +76,8 @@ Bool, + Struct, + If, Else, While, Return, @@ -115,6 +117,7 @@ Tok.While:"While", Tok.Comma:"Comma", Tok.Return:"Return", + Tok.Struct:"Struct", Tok.Seperator:"Seperator" ]; } diff -r dd18654b5131 -r 2d28b21faad6 misc/Error.d --- a/misc/Error.d Sat Apr 19 11:40:20 2008 +0200 +++ b/misc/Error.d Sat Apr 19 18:29:42 2008 +0200 @@ -11,7 +11,7 @@ this(char[] message, Location errorLocation) { - super(message ~ " at line " ~ errorLocation.toString); + super(errorLocation.toString ~ " " ~ message); this.message = message; this.errorLocation = errorLocation; } diff -r dd18654b5131 -r 2d28b21faad6 misc/Location.d --- a/misc/Location.d Sat Apr 19 11:40:20 2008 +0200 +++ b/misc/Location.d Sat Apr 19 18:29:42 2008 +0200 @@ -13,7 +13,7 @@ char[] toString () { int lineNumber = split(source.get(0, position), "\n").length; - return Integer.toString(lineNumber) ~" in "~source.name; + return source.name ~ ":" ~ Integer.toString(lineNumber); } char[] get(uint length) diff -r dd18654b5131 -r 2d28b21faad6 parser/Parser.d --- a/parser/Parser.d Sat Apr 19 11:40:20 2008 +0200 +++ b/parser/Parser.d Sat Apr 19 18:29:42 2008 +0200 @@ -75,7 +75,17 @@ error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__)); } break; - + case Tok.Struct: + Token iden = lexer.next; + switch(iden.type) + { + case Tok.Identifier: + Identifier identifier = new Identifier(iden); + return new StructDecl (identifier, parseStruct()); + default: + throw new Error("Expected struct identifier, but got "~iden.getType, + iden.location); + } case Tok.EOF: return null; default: @@ -84,6 +94,19 @@ } } + VarDecl[] parseStruct() + { + VarDecl[] varDecls; + require(Tok.OpenBrace); + while(lexer.peek.type != Tok.CloseBrace) + { + varDecls ~= cast(VarDecl)parseDecl; + } + + require(Tok.CloseBrace); + return varDecls; + } + Stmt parseStatement() { Token t = lexer.peek; @@ -132,6 +155,9 @@ require(Tok.Seperator); return stmt; break; + case Tok.Identifier: + auto decl = new DeclStmt(parseDecl()); + return decl; default: auto e = new ExpStmt(parseExpression()); diff -r dd18654b5131 -r 2d28b21faad6 sema/Declarations.d --- a/sema/Declarations.d Sat Apr 19 11:40:20 2008 +0200 +++ b/sema/Declarations.d Sat Apr 19 18:29:42 2008 +0200 @@ -21,7 +21,8 @@ "uint":5, "long":6, "ulong":7, - "bool":8 + "bool":8, + "void":9 ]; } @@ -36,7 +37,7 @@ override void visitVarDecl(VarDecl d) { - if(!isType(d.type.get)) + if(!isType(d.type.get) && d.env.findType(d.identifier)) throw new Error("Undefined type: '"~d.type.get~"'",d.type.token.location); visitExp(d.type); @@ -52,3 +53,4 @@ } } + diff -r dd18654b5131 -r 2d28b21faad6 sema/SymbolTable.d --- a/sema/SymbolTable.d Sat Apr 19 11:40:20 2008 +0200 +++ b/sema/SymbolTable.d Sat Apr 19 18:29:42 2008 +0200 @@ -38,9 +38,21 @@ return null; } + Symbol findType(Identifier id) + { + if (auto sym = id in symbols) + if(symbols[id].type == null) + return *sym; + if (enclosing !is null) + return enclosing.find(id); + return null; + } + char[][] names() { char[][] res; + if (enclosing) + res = enclosing.names; foreach (id, sym; symbols) res ~= sym.id.name ~ " : " ~ sym.type.name; return res; diff -r dd18654b5131 -r 2d28b21faad6 sema/SymbolTableBuilder.d --- a/sema/SymbolTableBuilder.d Sat Apr 19 11:40:20 2008 +0200 +++ b/sema/SymbolTableBuilder.d Sat Apr 19 18:29:42 2008 +0200 @@ -56,17 +56,36 @@ override void visitVarDecl(VarDecl d) { + if (d.init) + visitExp(d.init); + + if (need_push > 0) { + push(); + --need_push; + } + auto sc = current(); auto sym = sc.add(d.identifier); sym.type = d.type; - super.visitVarDecl(d); + d.env = sc; + visitExp(d.type); + visitExp(d.identifier); + } + + override void visitStructDecl(StructDecl s) + { + auto sc = current(); + auto sym = sc.add(s.identifier); +// sym.type = Tok.Struct; + super.visitStructDecl(s); } override void visitDeclStmt(DeclStmt d) { + ++need_push; super.visitDeclStmt(d); - push(); } + private uint need_push = 0; override void visitIfStmt(IfStmt s) { diff -r dd18654b5131 -r 2d28b21faad6 sema/Visitor.d --- a/sema/Visitor.d Sat Apr 19 11:40:20 2008 +0200 +++ b/sema/Visitor.d Sat Apr 19 18:29:42 2008 +0200 @@ -30,6 +30,8 @@ return visitFuncDecl(cast(FuncDecl)decl); case DeclType.VarDecl: return visitVarDecl(cast(VarDecl)decl); + case DeclType.StructDecl: + return visitStructDecl(cast(StructDecl)decl); default: throw new Exception("Unknown declaration type"); } @@ -104,6 +106,19 @@ return DeclT.init; } + DeclT visitStructDecl(StructDecl s) + { + visitExp(s.identifier); + + foreach (arg; s.vars) + visitDecl(arg); + + static if (is(DeclT == void)) + return; + else + return DeclT.init; + } + // Statements: StmtT visitReturnStmt(ReturnStmt s) { diff -r dd18654b5131 -r 2d28b21faad6 test.td --- a/test.td Sat Apr 19 11:40:20 2008 +0200 +++ b/test.td Sat Apr 19 18:29:42 2008 +0200 @@ -3,21 +3,28 @@ int main() { - return fib(10); + int y = 4; + while (y > 0) + y = y - 1; + return y; +} + +int add(int x, int y) +{ + return x + y; } int fib(int n) { if(n < 2) return n; - + return fib(n-1) + fib(n-2); } -int nice(long s, short t) +int nice(long s, short t, int p) { - int y; - byte x = 5 + t + y; + byte x = 5 + t + 0; if (x != 0) t = 5 + 1 * 5 * s + t; return 2 * (t + -1) - x; @@ -30,6 +37,7 @@ { res = res * n; n = n - 1; + return n; } return res; } diff -r dd18654b5131 -r 2d28b21faad6 tests/code/basic_2.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/code/basic_2.d Sat Apr 19 18:29:42 2008 +0200 @@ -0,0 +1,8 @@ +//test fail +int main() +{ + int x = y; + int y = 1; + return y; +} + diff -r dd18654b5131 -r 2d28b21faad6 tests/code/if_4.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/code/if_4.d Sat Apr 19 18:29:42 2008 +0200 @@ -0,0 +1,13 @@ +int main() +{ + int x = 0; + int y = 1; + if (x) + return 1; + else if (y == 2) + return 1; + else + y = 0; + return y; +} + diff -r dd18654b5131 -r 2d28b21faad6 tests/code/math_1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/code/math_1.d Sat Apr 19 18:29:42 2008 +0200 @@ -0,0 +1,6 @@ +int main() +{ + int x = 2; + int y = 3; + return 2 * (x + y); +} diff -r dd18654b5131 -r 2d28b21faad6 tests/code/math_2.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/code/math_2.d Sat Apr 19 18:29:42 2008 +0200 @@ -0,0 +1,6 @@ +int main() +{ + int x = 1 + 2 * 3 + 4 + 5; + int y = x - x; + return y + x - 15; +} diff -r dd18654b5131 -r 2d28b21faad6 tests/code/math_3.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/code/math_3.d Sat Apr 19 18:29:42 2008 +0200 @@ -0,0 +1,6 @@ +//test fail +int main() +{ + int x = x; + return x; +}