@@ -94,9 +94,9 @@ static int count_returns_at_end_of_control_flow(const FunctionDefinition& funcDe
9494 switch (stmt.kind ()) {
9595 case Statement::Kind::kBlock : {
9696 // Check only the last statement of a block.
97- const auto & blockStmts = stmt.as <Block>(). fStatements ;
98- return (blockStmts. size () > 0 ) ? this -> visitStatement (*blockStmts. back ())
99- : false ;
97+ const auto & block = stmt.as <Block>();
98+ return block. children (). size () &&
99+ this -> visitStatement (*block. children (). back ()) ;
100100 }
101101 case Statement::Kind::kSwitch :
102102 case Statement::Kind::kWhile :
@@ -210,7 +210,7 @@ static Statement* find_parent_statement(const std::vector<std::unique_ptr<Statem
210210 // Anything counts as a parent statement other than a scopeless Block.
211211 for (; iter != stmtStack.rend (); ++iter) {
212212 Statement* stmt = (*iter)->get ();
213- if (!stmt->is <Block>() || stmt->as <Block>().fIsScope ) {
213+ if (!stmt->is <Block>() || stmt->as <Block>().isScope () ) {
214214 return stmt;
215215 }
216216 }
@@ -243,23 +243,23 @@ void Inliner::ensureScopedBlocks(Statement* inlinedBody, Statement* parentStmt)
243243 // issues--if we don't represent the Block textually somehow, we run the risk of accidentally
244244 // absorbing the following statement into our loop--so we also add a scope to these.
245245 for (Block* nestedBlock = █; ) {
246- if (nestedBlock->fIsScope ) {
246+ if (nestedBlock->isScope () ) {
247247 // We found an explicit scope; all is well.
248248 return ;
249249 }
250- if (nestedBlock->fStatements .size () != 1 ) {
250+ if (nestedBlock->children () .size () != 1 ) {
251251 // We found a block with multiple (or zero) statements, but no scope? Let's add a scope
252252 // to the outermost block.
253- block.fIsScope = true ;
253+ block.setIsScope ( true ) ;
254254 return ;
255255 }
256- if (!nestedBlock->fStatements [0 ]->is <Block>()) {
256+ if (!nestedBlock->children () [0 ]->is <Block>()) {
257257 // This block has exactly one thing inside, and it's not another block. No need to scope
258258 // it.
259259 return ;
260260 }
261261 // We have to go deeper.
262- nestedBlock = &nestedBlock->fStatements [0 ]->as <Block>();
262+ nestedBlock = &nestedBlock->children () [0 ]->as <Block>();
263263 }
264264}
265265
@@ -400,6 +400,13 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
400400 }
401401 return nullptr ;
402402 };
403+ auto blockStmts = [&](const Block& block) {
404+ std::vector<std::unique_ptr<Statement>> result;
405+ for (const std::unique_ptr<Statement>& child : block.children ()) {
406+ result.push_back (stmt (child));
407+ }
408+ return result;
409+ };
403410 auto stmts = [&](const std::vector<std::unique_ptr<Statement>>& ss) {
404411 std::vector<std::unique_ptr<Statement>> result;
405412 for (const auto & s : ss) {
@@ -416,7 +423,7 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
416423 switch (statement.kind ()) {
417424 case Statement::Kind::kBlock : {
418425 const Block& b = statement.as <Block>();
419- return std::make_unique<Block>(offset, stmts (b. fStatements ), b.fSymbols , b.fIsScope );
426+ return std::make_unique<Block>(offset, blockStmts (b ), b.symbolTable () , b.isScope () );
420427 }
421428
422429 case Statement::Kind::kBreak :
@@ -558,14 +565,16 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
558565 /* symbols=*/ nullptr ,
559566 /* isScope=*/ false );
560567
561- std::vector<std::unique_ptr<Statement>>& inlinedBody = inlinedCall.fInlinedBody ->fStatements ;
562- inlinedBody.reserve (1 + // Inline marker
563- 1 + // Result variable
564- arguments.size () + // Function arguments (passing in)
565- arguments.size () + // Function arguments (copy out-parameters back)
566- 1 ); // Inlined code (either as a Block or do-while loop)
568+ Block& inlinedBody = *inlinedCall.fInlinedBody ;
569+ inlinedBody.children ().reserve (1 + // Inline marker
570+ 1 + // Result variable
571+ arguments.size () + // Function arguments (passing in)
572+ arguments.size () + // Function arguments (copy out-parameters
573+ // back)
574+ 1 ); // Inlined code (either as a Block or do-while
575+ // loop)
567576
568- inlinedBody.push_back (std::make_unique<InlineMarker>(call->fFunction ));
577+ inlinedBody.children (). push_back (std::make_unique<InlineMarker>(call->fFunction ));
569578
570579 auto makeInlineVar = [&](const String& baseName, const Type* type, Modifiers modifiers,
571580 std::unique_ptr<Expression>* initialValue) -> const Variable* {
@@ -605,7 +614,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
605614 }
606615
607616 // Add the new variable-declaration statement to our block of extra statements.
608- inlinedBody.push_back (std::make_unique<VarDeclarationsStatement>(
617+ inlinedBody.children (). push_back (std::make_unique<VarDeclarationsStatement>(
609618 std::make_unique<VarDeclarations>(offset, type, std::move (variables))));
610619
611620 return variableSymbol;
@@ -643,24 +652,24 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
643652
644653 const Block& body = function.fBody ->as <Block>();
645654 auto inlineBlock = std::make_unique<Block>(offset, std::vector<std::unique_ptr<Statement>>{});
646- inlineBlock->fStatements .reserve (body.fStatements .size ());
647- for (const std::unique_ptr<Statement>& stmt : body.fStatements ) {
648- inlineBlock->fStatements .push_back (this ->inlineStatement (
655+ inlineBlock->children () .reserve (body.children () .size ());
656+ for (const std::unique_ptr<Statement>& stmt : body.children () ) {
657+ inlineBlock->children () .push_back (this ->inlineStatement (
649658 offset, &varMap, symbolTableForCall, resultExpr, hasEarlyReturn, *stmt));
650659 }
651660 if (hasEarlyReturn) {
652661 // Since we output to backends that don't have a goto statement (which would normally be
653662 // used to perform an early return), we fake it by wrapping the function in a
654663 // do { } while (false); and then use break statements to jump to the end in order to
655664 // emulate a goto.
656- inlinedBody.push_back (std::make_unique<DoStatement>(
665+ inlinedBody.children (). push_back (std::make_unique<DoStatement>(
657666 /* offset=*/ -1 ,
658667 std::move (inlineBlock),
659668 std::make_unique<BoolLiteral>(*fContext , offset, /* value=*/ false )));
660669 } else {
661670 // No early returns, so we can just dump the code in. We still need to keep the block so we
662671 // don't get name conflicts with locals.
663- inlinedBody.push_back (std::move (inlineBlock));
672+ inlinedBody.children (). push_back (std::move (inlineBlock));
664673 }
665674
666675 // Copy the values of `out` parameters into their destinations.
@@ -675,7 +684,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
675684 continue ;
676685 }
677686 auto varRef = std::make_unique<VariableReference>(offset, varMap[p]);
678- inlinedBody.push_back (std::make_unique<ExpressionStatement>(
687+ inlinedBody.children (). push_back (std::make_unique<ExpressionStatement>(
679688 std::make_unique<BinaryExpression>(offset,
680689 arguments[i]->clone (),
681690 Token::Kind::TK_EQ,
@@ -805,12 +814,12 @@ bool Inliner::analyze(Program& program) {
805814
806815 case Statement::Kind::kBlock : {
807816 Block& block = (*stmt)->as <Block>();
808- if (block.fSymbols ) {
809- fSymbolTableStack .push_back (block.fSymbols .get ());
817+ if (block.symbolTable () ) {
818+ fSymbolTableStack .push_back (block.symbolTable () .get ());
810819 }
811820
812- for (std::unique_ptr<Statement>& blockStmt : block.fStatements ) {
813- this ->visitStatement (&blockStmt );
821+ for (std::unique_ptr<Statement>& stmt : block.children () ) {
822+ this ->visitStatement (&stmt );
814823 }
815824 break ;
816825 }
@@ -1082,7 +1091,7 @@ bool Inliner::analyze(Program& program) {
10821091 // After:
10831092 // fInlinedBody = null
10841093 // fEnclosingStmt = Block{ stmt1, stmt2, stmt3, stmt4 }
1085- inlinedCall.fInlinedBody ->fStatements .push_back (std::move (*candidate.fEnclosingStmt ));
1094+ inlinedCall.fInlinedBody ->children () .push_back (std::move (*candidate.fEnclosingStmt ));
10861095 *candidate.fEnclosingStmt = std::move (inlinedCall.fInlinedBody );
10871096 }
10881097
0 commit comments