[ast] Remove more set methods.

This CL updates the SPIRV-Reader to not require set methods for various
AST expressions.

Change-Id: Ieb9a8fcc1746d3051e5b663559127ca63b45a388
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34642
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Auto-Submit: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/case_statement.h b/src/ast/case_statement.h
index cea4327..35cb495 100644
--- a/src/ast/case_statement.h
+++ b/src/ast/case_statement.h
@@ -57,9 +57,6 @@
   /// @returns true if this is a default statement
   bool IsDefault() const { return selectors_.empty(); }
 
-  /// Sets the case body
-  /// @param body the case body
-  void set_body(BlockStatement* body) { body_ = body; }
   /// @returns the case body
   const BlockStatement* body() const { return body_; }
   /// @returns the case body
diff --git a/src/ast/if_statement.h b/src/ast/if_statement.h
index 5087f28..32a4d31 100644
--- a/src/ast/if_statement.h
+++ b/src/ast/if_statement.h
@@ -44,15 +44,8 @@
   IfStatement(IfStatement&&);
   ~IfStatement() override;
 
-  /// Sets the condition for the if statement
-  /// @param condition the condition to set
-  void set_condition(Expression* condition) { condition_ = condition; }
   /// @returns the if condition or nullptr if none set
   Expression* condition() const { return condition_; }
-
-  /// Sets the if body
-  /// @param body the if body
-  void set_body(BlockStatement* body) { body_ = body; }
   /// @returns the if body
   const BlockStatement* body() const { return body_; }
   /// @returns the if body
diff --git a/src/ast/loop_statement.h b/src/ast/loop_statement.h
index 374c669..64e1140 100644
--- a/src/ast/loop_statement.h
+++ b/src/ast/loop_statement.h
@@ -42,17 +42,11 @@
   LoopStatement(LoopStatement&&);
   ~LoopStatement() override;
 
-  /// Sets the body statements
-  /// @param body the body statements
-  void set_body(BlockStatement* body) { body_ = body; }
   /// @returns the body statements
   const BlockStatement* body() const { return body_; }
   /// @returns the body statements
   BlockStatement* body() { return body_; }
 
-  /// Sets the continuing statements
-  /// @param continuing the continuing statements
-  void set_continuing(BlockStatement* continuing) { continuing_ = continuing; }
   /// @returns the continuing statements
   const BlockStatement* continuing() const { return continuing_; }
   /// @returns the continuing statements
diff --git a/src/ast/switch_statement.h b/src/ast/switch_statement.h
index d44a45f..22f0b3e 100644
--- a/src/ast/switch_statement.h
+++ b/src/ast/switch_statement.h
@@ -49,9 +49,8 @@
   /// @returns true if this is a default statement
   bool IsDefault() const { return condition_ == nullptr; }
 
-  /// Sets the switch body
-  /// @param body the switch body
-  void set_body(CaseStatementList body) { body_ = std::move(body); }
+  /// @returns the Switch body
+  CaseStatementList& body() { return body_; }
   /// @returns the Switch body
   const CaseStatementList& body() const { return body_; }
 
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 05e0b61..94b54ff 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -520,7 +520,7 @@
       namer_(pi->namer()),
       function_(function),
       ep_info_(ep_info) {
-  PushNewStatementBlock(nullptr, 0, nullptr);
+  PushNewStatementBlock(nullptr, 0, nullptr, nullptr, nullptr);
 }
 
 FunctionEmitter::FunctionEmitter(ParserImpl* pi,
@@ -538,8 +538,8 @@
     : construct_(construct),
       end_id_(end_id),
       completion_action_(completion_action),
-      statements_(std::move(statements)),
-      cases_(std::move(cases)) {}
+      statements_(statements),
+      cases_(cases) {}
 
 FunctionEmitter::StatementBlock::StatementBlock(StatementBlock&&) = default;
 
@@ -547,9 +547,15 @@
 
 void FunctionEmitter::PushNewStatementBlock(const Construct* construct,
                                             uint32_t end_id,
+                                            ast::BlockStatement* block,
+                                            ast::CaseStatementList* cases,
                                             CompletionAction action) {
-  statements_stack_.emplace_back(StatementBlock{
-      construct, end_id, action, create<ast::BlockStatement>(), nullptr});
+  if (block == nullptr) {
+    block = create<ast::BlockStatement>();
+  }
+
+  statements_stack_.emplace_back(
+      StatementBlock{construct, end_id, action, block, cases});
 }
 
 void FunctionEmitter::PushGuard(const std::string& guard_name,
@@ -560,28 +566,21 @@
   // if-selection with a then-clause ending at the same block
   // as the statement block at the top of the stack.
   const auto& top = statements_stack_.back();
+
   auto* cond = create<ast::IdentifierExpression>(guard_name);
   auto* body = create<ast::BlockStatement>();
-  auto* const guard_stmt = AddStatement(create<ast::IfStatement>(cond, body))
-                               ->As<ast::IfStatement>();
-  PushNewStatementBlock(top.construct_, end_id,
-                        [guard_stmt](StatementBlock* s) {
-                          guard_stmt->set_body(s->statements_);
-                        });
+  AddStatement(create<ast::IfStatement>(cond, body));
+  PushNewStatementBlock(top.construct_, end_id, body, nullptr, nullptr);
 }
 
 void FunctionEmitter::PushTrueGuard(uint32_t end_id) {
   assert(!statements_stack_.empty());
   const auto& top = statements_stack_.back();
+
   auto* cond = MakeTrue();
   auto* body = create<ast::BlockStatement>();
-  auto* const guard_stmt = AddStatement(create<ast::IfStatement>(cond, body))
-                               ->As<ast::IfStatement>();
-  guard_stmt->set_condition(MakeTrue());
-  PushNewStatementBlock(top.construct_, end_id,
-                        [guard_stmt](StatementBlock* s) {
-                          guard_stmt->set_body(s->statements_);
-                        });
+  AddStatement(create<ast::IfStatement>(cond, body));
+  PushNewStatementBlock(top.construct_, end_id, body, nullptr, nullptr);
 }
 
 const ast::BlockStatement* FunctionEmitter::ast_body() {
@@ -640,7 +639,7 @@
   parser_impl_.get_module().functions().back()->set_body(body);
   // Maintain the invariant by repopulating the one and only element.
   statements_stack_.clear();
-  PushNewStatementBlock(constructs_[0].get(), 0, nullptr);
+  PushNewStatementBlock(constructs_[0].get(), 0, nullptr, nullptr, nullptr);
 
   return success();
 }
@@ -1828,7 +1827,9 @@
   while (!statements_stack_.empty() &&
          (statements_stack_.back().end_id_ == block_info.id)) {
     StatementBlock& sb = statements_stack_.back();
-    sb.completion_action_(&sb);
+    if (sb.completion_action_ != nullptr) {
+      sb.completion_action_();
+    }
     statements_stack_.pop_back();
   }
   if (statements_stack_.empty()) {
@@ -2066,27 +2067,18 @@
   // Push statement blocks for the then-clause and the else-clause.
   // But make sure we do it in the right order.
 
-  auto push_then = [this, if_stmt, then_end, construct]() {
-    // Push the then clause onto the stack.
-    PushNewStatementBlock(construct, then_end, [if_stmt](StatementBlock* s) {
-      // The "then" consists of the statement list
-      // from the top of statments stack, without an
-      // elseif condition.
-      if_stmt->set_body(s->statements_);
-    });
-  };
-
   auto push_else = [this, if_stmt, else_end, construct]() {
     // Push the else clause onto the stack first.
+    auto* else_body = create<ast::BlockStatement>();
     PushNewStatementBlock(
-        construct, else_end, [this, if_stmt](StatementBlock* s) {
+        construct, else_end, else_body, nullptr, [this, if_stmt, else_body]() {
           // Only set the else-clause if there are statements to fill it.
-          if (!s->statements_->empty()) {
+          if (!else_body->empty()) {
             // The "else" consists of the statement list from the top of
             // statments stack, without an elseif condition.
             ast::ElseStatementList else_stmts;
             else_stmts.emplace_back(
-                create<ast::ElseStatement>(nullptr, s->statements_));
+                create<ast::ElseStatement>(nullptr, else_body));
             if_stmt->set_else_statements(else_stmts);
           }
         });
@@ -2124,7 +2116,9 @@
       // We have to guard the start of the else.
       PushGuard(guard_name, else_end);
     }
-    push_then();
+
+    // Push the then clause onto the stack.
+    PushNewStatementBlock(construct, then_end, body, nullptr, nullptr);
   }
 
   return success();
@@ -2141,20 +2135,15 @@
   // Generate the code for the selector.
   auto selector = MakeExpression(selector_id);
 
-  ast::CaseStatementList list;
-  auto* swch = create<ast::SwitchStatement>(selector.expr, list);
-  auto* const switch_stmt = AddStatement(swch)->As<ast::SwitchStatement>();
+  // First, push the statement block for the entire switch.
+  ast::CaseStatementList case_list;
+  auto* swch = create<ast::SwitchStatement>(selector.expr, case_list);
+  AddStatement(swch)->As<ast::SwitchStatement>();
 
-  // First, push the statement block for the entire switch.  All the actual
-  // work is done by completion actions of the case/default clauses.
-  PushNewStatementBlock(
-      construct, construct->end_id, [switch_stmt](StatementBlock* s) {
-        switch_stmt->set_body(std::move(*std::move(s->cases_)));
-      });
-  statements_stack_.back().cases_ = std::make_unique<ast::CaseStatementList>();
   // Grab a pointer to the case list.  It will get buried in the statement block
   // stack.
-  auto* cases = statements_stack_.back().cases_.get();
+  auto* cases = &(swch->body());
+  PushNewStatementBlock(construct, construct->end_id, nullptr, cases, nullptr);
 
   // We will push statement-blocks onto the stack to gather the statements in
   // the default clause and cases clauses. Determine the list of blocks
@@ -2223,14 +2212,10 @@
 
     // Create the case clause.  Temporarily put it in the wrong order
     // on the case statement list.
-    cases->emplace_back(create<ast::CaseStatement>(selectors, nullptr));
-    auto* clause = cases->back();
+    auto* body = create<ast::BlockStatement>();
+    cases->emplace_back(create<ast::CaseStatement>(selectors, body));
 
-    PushNewStatementBlock(construct, end_id, [clause](StatementBlock* s) {
-      // The `set_body` method of CaseStatement can be removed if this set
-      // is removed.
-      clause->set_body(s->statements_);
-    });
+    PushNewStatementBlock(construct, end_id, body, nullptr, nullptr);
 
     if ((default_info == clause_heads[i]) && has_selectors &&
         construct->ContainsPos(default_info->pos)) {
@@ -2254,13 +2239,9 @@
 }
 
 bool FunctionEmitter::EmitLoopStart(const Construct* construct) {
-  auto* loop =
-      AddStatement(create<ast::LoopStatement>(create<ast::BlockStatement>(),
-                                              create<ast::BlockStatement>()))
-          ->As<ast::LoopStatement>();
-  PushNewStatementBlock(
-      construct, construct->end_id,
-      [loop](StatementBlock* s) { loop->set_body(s->statements_); });
+  auto* body = create<ast::BlockStatement>();
+  AddStatement(create<ast::LoopStatement>(body, create<ast::BlockStatement>()));
+  PushNewStatementBlock(construct, construct->end_id, body, nullptr, nullptr);
   return success();
 }
 
@@ -2273,9 +2254,9 @@
     return Fail() << "internal error: starting continue construct, "
                      "expected loop on top of stack";
   }
-  PushNewStatementBlock(
-      construct, construct->end_id,
-      [loop](StatementBlock* s) { loop->set_continuing(s->statements_); });
+  PushNewStatementBlock(construct, construct->end_id, loop->continuing(),
+                        nullptr, nullptr);
+
   return success();
 }
 
@@ -2455,16 +2436,15 @@
   if ((then_stmt == nullptr) && (else_stmt == nullptr)) {
     return nullptr;
   }
-  auto* if_stmt =
-      create<ast::IfStatement>(condition, create<ast::BlockStatement>());
+  auto* if_block = create<ast::BlockStatement>();
+  auto* if_stmt = create<ast::IfStatement>(condition, if_block);
   if (then_stmt != nullptr) {
-    auto* stmts = create<ast::BlockStatement>();
-    stmts->append(then_stmt);
-    if_stmt->set_body(stmts);
+    if_block->append(then_stmt);
   }
   if (else_stmt != nullptr) {
     auto* stmts = create<ast::BlockStatement>();
     stmts->append(else_stmt);
+
     ast::ElseStatementList else_stmts;
     else_stmts.emplace_back(create<ast::ElseStatement>(nullptr, stmts));
     if_stmt->set_else_statements(else_stmts);
diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h
index 47e286b..3bc36f2 100644
--- a/src/reader/spirv/function.h
+++ b/src/reader/spirv/function.h
@@ -796,8 +796,7 @@
   /// @returns the last statetment in the top of the statement stack.
   ast::Statement* LastStatement();
 
-  struct StatementBlock;
-  using CompletionAction = std::function<void(StatementBlock*)>;
+  using CompletionAction = std::function<void()>;
 
   // A StatementBlock represents a braced-list of statements while it is being
   // constructed.
@@ -824,16 +823,17 @@
     // The list of statements being built, if this construct is not a switch.
     ast::BlockStatement* statements_ = nullptr;
     // The list of switch cases being built, if this construct is a switch.
-    // The algorithm will cache a pointer to the vector.  We want that pointer
-    // to be stable no matter how |statements_stack_| is resized.  That's
-    // why we make this a unique_ptr rather than just a plain vector.
-    std::unique_ptr<ast::CaseStatementList> cases_ = nullptr;
+    ast::CaseStatementList* cases_ = nullptr;
   };
 
   /// Pushes an empty statement block onto the statements stack.
+  /// @param block the block to push into
+  /// @param cases the case list to push into
   /// @param action the completion action for this block
   void PushNewStatementBlock(const Construct* construct,
                              uint32_t end_id,
+                             ast::BlockStatement* block,
+                             ast::CaseStatementList* cases,
                              CompletionAction action);
 
   /// Emits an if-statement whose condition is the given flow guard