# HG changeset patch # User Anders Halager # Date 1209058973 -7200 # Node ID b6c1dc30ca4bedbcd458366cc3b9b1726597e95f # Parent b0a691727a0cc4493e68f7f340f8f060aca72a08 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 diff -r b0a691727a0c -r b6c1dc30ca4b ast/Exp.d --- 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, diff -r b0a691727a0c -r b6c1dc30ca4b gen/LLVMGen.d --- 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); diff -r b0a691727a0c -r b6c1dc30ca4b lexer/Token.d --- 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() diff -r b0a691727a0c -r b6c1dc30ca4b parser/Action.d --- 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); + } } diff -r b0a691727a0c -r b6c1dc30ca4b parser/Parser.d --- 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},