void ASTVisitor.Accept(NodeWhile value) { Accept(value); }
internal void Accept(NodeWhile expr) { var isResultRequired = expr.isResultRequired; var hasEl = expr.fail != null; var condition = expr.condition; uint initFailLoc = 0, initPassLoc = 0, start, failLoc; // Disable scopes, we'll do them ourselves if (expr.pass is NodeBlock) (expr.pass as NodeBlock).createScope = false; if (expr.fail != null && expr.fail is NodeBlock) (expr.fail as NodeBlock).createScope = false; expr.pass.isResultRequired = isResultRequired; expr.pass.inTailPosition = expr.inTailPosition; builder.StartScope(); if (hasEl) { expr.fail.isResultRequired = isResultRequired; expr.fail.inTailPosition = expr.inTailPosition; // initial if condition.Visit(this); initFailLoc = builder.InsnCount; if (expr.not) builder.OpJumpT(0); else builder.OpJumpF(0); } // while loop if (isResultRequired) builder.OpList(0); if (hasEl) initPassLoc = builder.OpJump(0); //*/ Handle cont if (isResultRequired) builder.OpJump(builder.InsnCount + 2); builder.StartFlowBlock(expr.label); if (isResultRequired) builder.OpPop(false); // END Handle cont */ start = builder.InsnCount; { condition.Visit(this); failLoc = builder.InsnCount; if (expr.not) builder.OpJumpT(0); else builder.OpJumpF(0); } if (hasEl) builder.SetOpC(initPassLoc, builder.InsnCount); if (isResultRequired) builder.OpDup(); expr.pass.Visit(this); if (isResultRequired) { builder.OpOIStore("+"); builder.OpPop(); } builder.OpJump(start); //*/ Handle break if (isResultRequired) builder.OpJump(builder.InsnCount + 2); builder.EndFlowBlock(); if (isResultRequired) builder.OpPop(false); // END Handle break */ builder.EndScope(); builder.SetOpC(failLoc, builder.InsnCount); uint finalFailLoc = builder.OpJump(0); // el if (hasEl) { builder.SetOpC(initFailLoc, builder.InsnCount); builder.StartScope(); expr.fail.Visit(this); builder.EndScope(); } builder.SetOpC(finalFailLoc, builder.InsnCount); }
private Node ParseWhile() { var expr = new NodeWhile(Location); Advance(); // while not (condition) is allowed and handled specially. if (Check(NOT)) { expr.not = true; Advance(); } if (Check(COLON)) { Advance(); ExpectIdentifier(out expr.label, "Expected an identifier for loop label."); } // Conditions must be in braces () Expect(OPEN_BRACE, "An open brace ('(') is expected to start the condition of a 'while' expression."); if (!TokensRemain) { log.Error(expr.location, "Expected expression for 'while' condition, but the end of the file was reached."); return expr; } expr.condition = Expression(); Expect(CLOSE_BRACE, "A close brace (')') is expected to end the condition of a 'while' expression."); // Get the body: if (!TokensRemain) { log.Error(expr.location, "Expected expression for 'while' block, but the end of the file was reached."); return expr; } expr.pass = Expression(); // Check for an 'el' (fail) condition if (Check(EL)) { Advance(); expr.fail = Expression(); } return expr; }