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
|
#include "stdafx.h"
#include "Unless.h"
#include "Compiler/Exception.h"
namespace storm {
namespace bs {
Unless::Unless(Block *parent, Condition *cond) : Block(cond->pos(), parent), cond(cond) {
successBlock = new (this) CondSuccess(pos, this, cond);
}
void Unless::fail(Expr *expr) {
if (expr->result() != noReturn())
throw new (this) SyntaxError(pos, S("The block in 'until' must always do a 'return', 'throw', 'break' or 'continue'.!"));
failStmt = expr;
}
void Unless::success(Expr *expr) {
successBlock->set(expr);
}
ExprResult Unless::result() {
return successBlock->result();
}
void Unless::blockCode(CodeGen *state, CodeResult *r) {
using namespace code;
if (!failStmt)
throw new (this) SyntaxError(pos, S("The fail statement was never set for this unless statemet."));
CodeResult *ok = new (this) CodeResult(Value(StormInfo<Bool>::type(engine())), state->block);
cond->code(state, ok);
Label skipLbl = state->l->label();
*state->l << cmp(ok->location(state), byteConst(0));
*state->l << jmp(skipLbl, ifNotEqual);
CodeResult *failResult = new (this) CodeResult();
failStmt->code(state, failResult);
// We have verified that 'failStmt' never returns, no worry about extra jumps!
*state->l << skipLbl;
successBlock->code(state, r);
}
void Unless::toS(StrBuf *to) const {
*to << S("unless (") << cond << S(") ") << failStmt << S(";\n") << successBlock;
}
}
}
|