1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
#include "stdafx.h"
#include "Loop.h"
#include "Compiler/Exception.h"
namespace storm {
namespace bs {
Loop::Loop(SrcPos pos, Block *parent) : Breakable(pos, parent), anyBreak(false) {}
void Loop::cond(Condition *cond) {
condition = cond;
whileExpr = new (this) CondSuccess(pos, this, cond);
}
Condition *Loop::cond() {
if (!condition)
throw new (this) UsageError(S("Must call 'cond' before creating a while body!"));
return condition;
}
void Loop::condExpr(Expr *e) {
cond(new (this) BoolCondition(e));
}
void Loop::doBody(Expr *e) {
doExpr = e;
if (Block *b = as<Block>(e))
liftVars(b);
}
void Loop::whileBody(Expr *e) {
if (!whileExpr)
whileBlock();
whileExpr->set(e);
}
CondSuccess *Loop::whileBlock() {
if (!whileExpr)
throw new (this) UsageError(S("Must call 'cond' before using the while body!"));
return whileExpr;
}
ExprResult Loop::result() {
if (condition || anyBreak) {
// No reliable value, the last expression in the do part could be used.
return ExprResult();
} else {
// If we don't have a condition, we never return.
return noReturn();
}
}
void Loop::code(CodeGen *s, CodeResult *r) {
using namespace code;
// Outer state where we store our control variable!
CodeGen *outer = s->child();
*s->l << begin(outer->block);
// Inner state, which represents the actual block we're in.
CodeGen *inner = outer->child();
// Initialize variables in the scope.
initVariables(inner);
code(outer, inner, r);
*s->l << end(outer->block);
}
void Loop::code(CodeGen *outerState, CodeGen *innerState, CodeResult *r) {
using namespace code;
Listing *l = innerState->l;
breakBlock = innerState->block;
continueBlock = outerState->block;
before = l->label();
after = l->label();
*l << before;
*l << begin(innerState->block);
// Things in the do-part.
if (doExpr) {
CodeResult *doResult = new (this) CodeResult();
doExpr->code(innerState, doResult);
}
// Check the condition.
if (condition) {
CodeResult *condResult = new (this) CodeResult(Value(StormInfo<Bool>::type(engine())), innerState->block);
condition->code(innerState, condResult);
code::Var c = condResult->location(innerState);
*l << cmp(c, byteConst(0));
*l << jmp(after, ifEqual);
}
// Things in the while-part.
if (whileExpr && whileExpr->any()) {
Label after = innerState->l->label();
CodeResult *whileResult = new (this) CodeResult();
whileExpr->code(innerState, whileResult);
*l << after;
}
// Jump back to the start.
*l << jmpBlock(before, outerState->block);
*l << after;
*l << end(innerState->block);
}
void Loop::willBreak() {
anyBreak = true;
}
void Loop::willContinue() {}
Breakable::To Loop::breakTo() {
return Breakable::To(after, breakBlock);
}
Breakable::To Loop::continueTo() {
return Breakable::To(before, continueBlock);
}
void Loop::toS(StrBuf *to) const {
Bool any = false;
if (doExpr) {
*to << S("do ") << doExpr;
any = true;
}
if (condition) {
if (doExpr)
*to << S(" ");
*to << S("while (") << condition << S(") ");
any = true;
}
if (whileExpr && whileExpr->any()) {
*to << whileExpr;
any = true;
}
if (!any)
*to << S("do {}");
}
}
}
|