Mercurial > projects > dang
view ast/Stmt.d @ 177:491b5fc4782a
Small fixes to type checks.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Thu, 24 Jul 2008 23:36:10 +0200 |
parents | ee202c72cd30 |
children | 8ea749b7da91 |
line wrap: on
line source
module ast.Stmt; import Array = tango.core.Array, Integer = tango.text.convert.Integer, tango.io.Stdout; import ast.Exp, ast.Decl; import sema.Scope, sema.VC, basic.Message, basic.SourceLocation; enum StmtType { Stmt, Compound, Decl, Exp, Return, If, While, For, Switch, } abstract class Stmt { this(StmtType stmtType = StmtType.Stmt) { this.stmtType = stmtType; } void simplify() { } void verify(VC vc) {} /// The "main" location of the expression. SourceLocation loc; /// Return the starting location of this statement SourceLocation startLoc() { return loc; } /// Get the full extents of the expression SourceRange sourceRange() { return SourceRange(loc, loc + 1); } StmtType stmtType; Scope env; int stmtIndex; } class CompoundStatement : Stmt { this(Stmt[] stmts) { super(StmtType.Compound); this.statements = stmts; } override void simplify() { foreach (stmt; statements ) stmt.simplify(); } Stmt[] statements; } class ReturnStmt : Stmt { this() { super(StmtType.Return); } // Needed? override void simplify() { FuncDecl f = env.parentFunction; if (exp) exp = exp.simplify(); if (f !is null && f.sret) { auto i = new Identifier("ret.val"); i.env = f.env; auto ass = new AssignExp(SLoc.Invalid, BinaryExp.Operator.Assign, i, exp); ass.env = f.env; auto assStmt = new ExpStmt(ass); assStmt.env = f.env; Stmt[] stmts; foreach(index, stmt ; f.statements) { if(stmtIndex == index) stmts ~= assStmt; stmts ~= stmt; } f.statements = stmts; exp = null; } } public Exp exp; } class DeclStmt : Stmt { this(Decl decl) { super(StmtType.Decl); this.decl = decl; } override void simplify() { decl.simplify(); } public Decl decl; } class ExpStmt : Stmt { this(Exp exp) { super(StmtType.Exp); this.exp = exp; } override void simplify() { exp = exp.simplify(); } public Exp exp; } class IfStmt : Stmt { this(Exp cond, Stmt then, Stmt el = null) { super(StmtType.If); this.cond = cond; this.then_body = then; this.else_body = el; } override void simplify() { cond = cond.simplify(); then_body.simplify(); if (else_body) else_body.simplify(); } Exp cond; Stmt then_body; Stmt else_body; } class WhileStmt : Stmt { this(Exp cond, Stmt stmts) { super(StmtType.While); this.cond = cond; this.whileBody = stmts; } override void simplify() { cond = cond.simplify(); whileBody.simplify(); } Exp cond; Stmt whileBody; } class ForStmt : Stmt { this(Stmt init, Exp cond, Exp incre, Stmt stmts) { super(StmtType.For); this.init = init; this.cond = cond; this.incre = incre; this.forBody = stmts; } override void simplify() { cond = cond.simplify(); forBody.simplify(); } Exp cond, incre; Stmt init, forBody; } class SwitchStmt : Stmt { this(SourceLocation loc, Exp target) { super(StmtType.Switch); cond = target; this.loc = loc; } void addCase(SourceLocation _case, Exp[] values, Stmt[] stmts) { cases ~= Case(_case, values, stmts); } void setDefault(SourceLocation _default, Stmt[] stmts) { if (defaultBlock !is null) extraDefaultBlocks = true; defaultBlock = stmts; defaultLoc = _default; if (cases.length > 0) cases[$ - 1].followedByDefault = true; } override void simplify() { cond = cond.simplify(); foreach ( stmt ; defaultBlock ) stmt.simplify(); foreach ( c ; cases ) foreach ( stmt ; c.stmts ) stmt.simplify(); } override void verify(VC vc) { if (extraDefaultBlocks) vc.msg.report(MultipleDefaults, defaultLoc); if (cases.length == 0) return; scope long[] all_values; foreach (ref Case; cases) { long[] new_values; foreach (exp; Case.values) if (auto lit = cast(IntegerLit)exp) new_values ~= Integer.parse(lit.get); else // We flag all non-literals and ignore them vc.msg.report(InvalidCaseValue, exp.loc); Case.values_converted = new_values; all_values ~= new_values; } Array.sort(all_values); char[][] overlapping; size_t i = 0; while ((i = Array.findAdj(all_values)) < all_values.length && all_values.length > 0) { overlapping ~= Integer.toString(all_values[i]); auto similar = Array.count(all_values, all_values[i]); all_values = all_values[i + similar .. $]; } if (overlapping.length > 0) vc.msg.report(OverlappingCases, loc).arg(overlapping); } Exp cond; Case[] cases; Stmt[] defaultBlock; private bool extraDefaultBlocks = false; private SourceLocation defaultLoc; struct Case { SourceLocation caseLoc; Exp[] values; Stmt[] stmts; long[] values_converted; bool followedByDefault = false; } }