ExprBlock::ExprBlock (SourceRange range, SourceToken token, std::initializer_list<Expr *> statements) : Expr (range, token) { for (auto *i : statements) addStatement (i); }
AtRule* Stylesheet::createAtRule(const Token& keyword) { AtRule* r = new AtRule(keyword); addStatement(*r); atrules.push_back(r); return r; }
void WhileStatement::setStatement( Statement* a_pStatement ) { o_assert(m_pStatement == nullptr); m_pStatement = a_pStatement; if(m_pStatement) addStatement(a_pStatement); }
LessMediaQuery* LessStylesheet::createLessMediaQuery() { LessMediaQuery* q = new LessMediaQuery(); #ifdef WITH_LIBGLOG VLOG(3) << "Adding Media Query"; #endif addStatement(*q); q->setLessStylesheet(*this); return q; }
Mixin* LessStylesheet::createMixin() { Mixin* m = new Mixin(); #ifdef WITH_LIBGLOG VLOG(3) << "Creating mixin"; #endif addStatement(*m); m->setLessStylesheet(*this); return m; }
void RecursiveCFGBuilder::visit(ShPtr<EmptyStmt> stmt) { addStatement(stmt); }
MediaQuery* Stylesheet::createMediaQuery(const TokenList &selector) { MediaQuery* q = new MediaQuery(selector); addStatement(*q); return q; }
CssComment* Stylesheet::createComment() { CssComment* c = new CssComment(); addStatement(*c); return c; }
void Stylesheet::addAtRule(AtRule& rule) { addStatement(rule); atrules.push_back(&rule); }
void Stylesheet::addRuleset(Ruleset& ruleset) { addStatement(ruleset); rulesets.push_back(&ruleset); }
SQLParserResult::SQLParserResult(SQLStatement* stmt) : isValid_(false), errorMsg_(nullptr) { addStatement(stmt); };
void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) { switch ((*s)->fKind) { case Statement::kBlock_Kind: for (auto& child : ((Block&) **s).fStatements) { addStatement(cfg, &child); } break; case Statement::kIf_Kind: { IfStatement& ifs = (IfStatement&) **s; this->addExpression(cfg, &ifs.fTest, true); cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, nullptr, s }); BlockId start = cfg.fCurrent; cfg.newBlock(); this->addStatement(cfg, &ifs.fIfTrue); BlockId next = cfg.newBlock(); if (ifs.fIfFalse) { cfg.fCurrent = start; cfg.newBlock(); this->addStatement(cfg, &ifs.fIfFalse); cfg.addExit(cfg.fCurrent, next); cfg.fCurrent = next; } else { cfg.addExit(start, next); } break; } case Statement::kExpression_Kind: { this->addExpression(cfg, &((ExpressionStatement&) **s).fExpression, true); cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, nullptr, s }); break; } case Statement::kVarDeclarations_Kind: { VarDeclarationsStatement& decls = ((VarDeclarationsStatement&) **s); for (auto& stmt : decls.fDeclaration->fVars) { if (stmt->fKind == Statement::kNop_Kind) { continue; } VarDeclaration& vd = (VarDeclaration&) *stmt; if (vd.fValue) { this->addExpression(cfg, &vd.fValue, true); } cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, nullptr, &stmt }); } cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, nullptr, s }); break; } case Statement::kDiscard_Kind: cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, nullptr, s }); cfg.fCurrent = cfg.newIsolatedBlock(); break; case Statement::kReturn_Kind: { ReturnStatement& r = ((ReturnStatement&) **s); if (r.fExpression) { this->addExpression(cfg, &r.fExpression, true); } cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, nullptr, s }); cfg.fCurrent = cfg.newIsolatedBlock(); break; } case Statement::kBreak_Kind: cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, nullptr, s }); cfg.addExit(cfg.fCurrent, fLoopExits.top()); cfg.fCurrent = cfg.newIsolatedBlock(); break; case Statement::kContinue_Kind: cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, nullptr, s }); cfg.addExit(cfg.fCurrent, fLoopContinues.top()); cfg.fCurrent = cfg.newIsolatedBlock(); break; case Statement::kWhile_Kind: { WhileStatement& w = (WhileStatement&) **s; BlockId loopStart = cfg.newBlock(); fLoopContinues.push(loopStart); BlockId loopExit = cfg.newIsolatedBlock(); fLoopExits.push(loopExit); this->addExpression(cfg, &w.fTest, true); BlockId test = cfg.fCurrent; cfg.addExit(test, loopExit); cfg.newBlock(); this->addStatement(cfg, &w.fStatement); cfg.addExit(cfg.fCurrent, loopStart); fLoopContinues.pop(); fLoopExits.pop(); cfg.fCurrent = loopExit; break; } case Statement::kDo_Kind: { DoStatement& d = (DoStatement&) **s; BlockId loopStart = cfg.newBlock(); fLoopContinues.push(loopStart); BlockId loopExit = cfg.newIsolatedBlock(); fLoopExits.push(loopExit); this->addStatement(cfg, &d.fStatement); this->addExpression(cfg, &d.fTest, true); cfg.addExit(cfg.fCurrent, loopExit); cfg.addExit(cfg.fCurrent, loopStart); fLoopContinues.pop(); fLoopExits.pop(); cfg.fCurrent = loopExit; break; } case Statement::kFor_Kind: { ForStatement& f = (ForStatement&) **s; if (f.fInitializer) { this->addStatement(cfg, &f.fInitializer); } BlockId loopStart = cfg.newBlock(); BlockId next = cfg.newIsolatedBlock(); fLoopContinues.push(next); BlockId loopExit = cfg.newIsolatedBlock(); fLoopExits.push(loopExit); if (f.fTest) { this->addExpression(cfg, &f.fTest, true); // this isn't quite right; we should have an exit from here to the loop exit, and // remove the exit from the loop body to the loop exit. Structuring it like this // forces the optimizer to believe that the loop body is always executed at least // once. While not strictly correct, this avoids incorrect "variable not assigned" // errors on variables which are assigned within the loop. The correct solution to // this is to analyze the loop to see whether or not at least one iteration is // guaranteed to happen, but for the time being we take the easy way out. } cfg.newBlock(); this->addStatement(cfg, &f.fStatement); cfg.addExit(cfg.fCurrent, next); cfg.fCurrent = next; if (f.fNext) { this->addExpression(cfg, &f.fNext, true); } cfg.addExit(cfg.fCurrent, loopStart); cfg.addExit(cfg.fCurrent, loopExit); fLoopContinues.pop(); fLoopExits.pop(); cfg.fCurrent = loopExit; break; } case Statement::kSwitch_Kind: { SwitchStatement& ss = (SwitchStatement&) **s; this->addExpression(cfg, &ss.fValue, true); cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, nullptr, s }); BlockId start = cfg.fCurrent; BlockId switchExit = cfg.newIsolatedBlock(); fLoopExits.push(switchExit); for (const auto& c : ss.fCases) { cfg.newBlock(); cfg.addExit(start, cfg.fCurrent); if (c->fValue) { // technically this should go in the start block, but it doesn't actually matter // because it must be constant. Not worth running two loops for. this->addExpression(cfg, &c->fValue, true); } for (auto& caseStatement : c->fStatements) { this->addStatement(cfg, &caseStatement); } } cfg.addExit(cfg.fCurrent, switchExit); // note that unlike GLSL, our grammar requires the default case to be last if (0 == ss.fCases.size() || ss.fCases[ss.fCases.size() - 1]->fValue) { // switch does not have a default clause, mark that it can skip straight to the end cfg.addExit(start, switchExit); } fLoopExits.pop(); cfg.fCurrent = switchExit; break; } case Statement::kNop_Kind: break; default: printf("statement: %s\n", (*s)->description().c_str()); ABORT("unsupported statement kind"); } }