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
|
#include "stdafx.h"
#include "For.h"
#include "Cast.h"
namespace storm {
namespace bs {
For::For(SrcPos pos, Block *parent) : Breakable(pos, parent) {}
void For::test(Expr *e) {
testExpr = expectCastTo(e, Value(StormInfo<Bool>::type(engine())), scope);
}
void For::update(Expr *e) {
updateExpr = e;
}
void For::body(Expr *e) {
bodyExpr = e;
}
ExprResult For::result() {
return ExprResult();
}
void For::blockCode(CodeGen *s, CodeResult *to, code::Block block) {
using namespace code;
this->block = block;
Label begin = s->l->label();
Label end = s->l->label();
brk = end;
cont = s->l->label();
CodeGen *subState = s->child(block);
*s->l << begin;
*s->l << code::begin(block);
// Put this outside the current block, so we can use it later.
CodeResult *testResult = new (this) CodeResult(Value(StormInfo<Bool>::type(engine())), block);
testExpr->code(subState, testResult);
code::Var r = testResult->location(subState);
*s->l << cmp(r, byteConst(0));
*s->l << jmp(end, ifEqual);
CodeResult *bodyResult = new (this) CodeResult();
if (bodyExpr->isolate()) {
// Isolate into its own block to ensure that any local variables are not destroyed
// if the loop is executed zero times.
code::Block bodyBlock = s->l->createBlock(block);
*s->l << code::begin(bodyBlock);
bodyExpr->code(subState->child(bodyBlock), bodyResult);
*s->l << code::end(bodyBlock);
} else {
bodyExpr->code(subState, bodyResult);
}
*s->l << cont;
CodeResult *updateResult = new (this) CodeResult();
updateExpr->code(subState, updateResult);
// Jump back.
*s->l << jmpBlock(begin, s->block);
*s->l << end;
*s->l << code::end(block);
}
void For::willBreak() {}
void For::willContinue() {}
Breakable::To For::breakTo() {
return Breakable::To(brk, block);
}
Breakable::To For::continueTo() {
return Breakable::To(cont, block);
}
void For::toS(StrBuf *to) const {
*to << S("for (") << testExpr << S("; ") << updateExpr << S(") ") << bodyExpr;
}
}
}
|