protected override ICode VisitDoLoop(StmtDoLoop s) { var body = (Stmt)this.Visit(s.Body); StmtIf lastIf = null; IEnumerable <Stmt> preIf = null; if (body.StmtType == Stmt.NodeType.Block) { var sBlock = (StmtBlock)body; if (sBlock.Statements.Any()) { var sLast = sBlock.Statements.Last(); if (sLast.StmtType == Stmt.NodeType.If) { lastIf = (StmtIf)sLast; preIf = sBlock.Statements.Take(sBlock.Statements.Count() - 1).ToArray(); } } } else if (body.StmtType == Stmt.NodeType.If) { lastIf = (StmtIf)body; preIf = Enumerable.Empty <Stmt>(); } if (lastIf != null) { Stmt afterLoop = null; StmtIf newIf = null; // See if final 'if' condition is same as the 'do' condition. // TODO: This may lead to a non-terminating situation... if (lastIf.Condition.DoesEqual(s.While)) { afterLoop = lastIf.Else; newIf = new StmtIf(s.Ctx, lastIf.Condition, lastIf.Then, null); } else if (lastIf.Condition.DoesEqualNot(s.While)) { afterLoop = lastIf.Then; newIf = new StmtIf(s.Ctx, lastIf.Condition, null, lastIf.Else); } if (afterLoop != null) { var loopBody = new StmtBlock(s.Ctx, preIf.Concat(newIf)); var loop = new StmtDoLoop(s.Ctx, loopBody, s.While); var ret = new StmtBlock(s.Ctx, loop, afterLoop); return(ret); } } if (body != s.Body) { return(new StmtDoLoop(s.Ctx, body, s.While)); } else { return(s); } }
protected override ICode VisitDoLoop(StmtDoLoop s) { this.NewLine(); this.js.Append("do {"); this.indent++; this.Visit(s.Body); this.indent--; this.NewLine(); this.js.Append("} while ("); this.Visit(s.While); this.js.Append(");"); return(s); }
protected virtual ICode VisitDoLoop(StmtDoLoop s) { this.ThrowOnNoOverride(); var body = this.Visit(s.Body); var @while = this.Visit(s.While); if (body != s.Body || @while != s.While) { return(new StmtDoLoop(s.Ctx, (Stmt)body, (Expr)@while)); } else { return(s); } }
protected override ICode VisitDoLoop(StmtDoLoop s) { var ctx = s.Ctx; var body = (Stmt)this.Visit(s.Body); var @while = (Expr)this.Visit(s.While); // This order matters - body must be visited before while GetVarsVisitor.GetAll(@while); this.AddKnownTrue(ctx.ExprGen.Not(@while)); if (body != s.Body || @while != s.While) { return(new StmtDoLoop(ctx, body, @while)); } else { return(s); } }
protected override ICode VisitDoLoop(StmtDoLoop s) { var ctx = s.Ctx; var body = (Stmt)this.Visit(s.Body); var @while = (Expr)this.Visit(s.While); var conditionVars = VisitorFindVars.V(@while); var needAssigning = conditionVars.Except(this.stack.SelectMany(x => x), (IEqualityComparer <ExprVar>) this.phiComparer).ToArray(); if (needAssigning.Any()) { var replacements = needAssigning.Select(x => { var newExpr = ctx.Local(x.Type); var phi = new ExprVarPhi(ctx) { Exprs = new[] { x, newExpr } }; return(new { orgExpr = x, newExpr, phi }); }).ToArray(); foreach (var replace in replacements) { this.stack.Peek().Add(replace.newExpr); this.stack.Peek().Add(replace.phi); @while = (Expr)VisitorReplace.V(@while, replace.orgExpr, replace.phi); } var assignmentStmts = replacements .Select(x => new StmtAssignment(ctx, x.newExpr, new ExprDefaultValue(ctx, x.newExpr.Type))) .ToArray(); body = new StmtBlock(ctx, assignmentStmts.Concat(body)); } if (body != s.Body || @while != s.While) { return(new StmtDoLoop(ctx, body, @while)); } else { return(s); } }
protected override ICode VisitDoLoop(StmtDoLoop s) { var body = (Stmt)this.Visit(s.Body); if (body == null) { // Loop has no body return(null); } if (s.While.IsLiteralBoolean(false)) { // Will never loop return(body); } if (body != s.Body) { return(new StmtDoLoop(s.Ctx, body, s.While)); } else { return(s); } }
protected override ICode VisitDoLoop(StmtDoLoop s) { return(this.Isolate(() => base.VisitDoLoop(s))); }
protected override ICode VisitContinuation(StmtContinuation s) { // TODO: Why is this de-recursing blocks in continuations? Why doesn't it just derecurse itself (if possible)??? if (s.To.StmtType != Stmt.NodeType.Block) { return(base.VisitContinuation(s)); } if (!this.seen.Add(s.To)) { return(base.VisitContinuation(s)); } var block = (StmtBlock)s.To; foreach (var stmt in block.Statements) { if (stmt.StmtType == Stmt.NodeType.Continuation) { // Continuation not inside 'if' var sCont = (StmtContinuation)stmt; if (sCont.To == block) { // Recursive, so derecurse with no condition on loop var body = new StmtBlock(s.Ctx, block.Statements.TakeWhile(x => x != stmt).ToArray()); var replaceWith = new StmtDoLoop(s.Ctx, body, new ExprLiteral(s.Ctx, true, s.Ctx.Boolean)); this.replaces.Add(s.To, replaceWith); return(base.VisitContinuation(s)); } } if (stmt.StmtType == Stmt.NodeType.If) { // Continuation only statement within 'if' with only a 'then' clause var sIf = (StmtIf)stmt; if (sIf.Else == null && sIf.Then.StmtType == Stmt.NodeType.Continuation) { var sThen = (StmtContinuation)sIf.Then; if (sThen.To == block) { // Recursive, so derecurse var condition = sIf.Condition; var bodyStmts = block.Statements.TakeWhile(x => x != stmt).ToArray(); var bodyLast = bodyStmts.LastOrDefault(); var body = new StmtBlock(s.Ctx, bodyStmts); var loop = new StmtDoLoop(s.Ctx, body, condition); var afterLoop = block.Statements.SkipWhile(x => x != stmt).Skip(1).ToArray(); if (VisitorFindContinuations.Get(new StmtBlock(s.Ctx, afterLoop)).Any(x => x.To == block)) { // Cannot de-recurse yet, must wait for continuations to be merged return(base.VisitContinuation(s)); } Stmt replaceWith; if (afterLoop.Any()) { var loopAndAfter = new[] { loop }.Concat(afterLoop).ToArray(); replaceWith = new StmtBlock(s.Ctx, loopAndAfter); } else { replaceWith = loop; } this.replaces.Add(s.To, replaceWith); return(base.VisitContinuation(s)); } } } if (VisitorFindContinuations.Any(stmt)) { // Another continuation present, cannot derecurse break; } } return(base.VisitContinuation(s)); }