Mercurial > projects > dang
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},