resolver: Resolve for-loops

Still nothing creates these, yet.

Bug: tint:952
Change-Id: If35f9c68ede6c6e41b6e9510f0b60751fea5bd49
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56762
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index 8bd7aa0..307f807 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -28,6 +28,7 @@
 #include "src/ast/disable_validation_decoration.h"
 #include "src/ast/discard_statement.h"
 #include "src/ast/fallthrough_statement.h"
+#include "src/ast/for_loop_statement.h"
 #include "src/ast/if_statement.h"
 #include "src/ast/internal_decoration.h"
 #include "src/ast/interpolate_decoration.h"
@@ -1701,6 +1702,9 @@
   if (auto* l = stmt->As<ast::LoopStatement>()) {
     return LoopStatement(l);
   }
+  if (auto* l = stmt->As<ast::ForLoopStatement>()) {
+    return ForLoopStatement(l);
+  }
   if (auto* r = stmt->As<ast::ReturnStatement>()) {
     return Return(r);
   }
@@ -1824,6 +1828,45 @@
   });
 }
 
+bool Resolver::ForLoopStatement(ast::ForLoopStatement* stmt) {
+  Mark(stmt->body());
+
+  auto* sem_block_body = builder_->create<sem::LoopBlockStatement>(
+      stmt->body(), current_statement_);
+  builder_->Sem().Add(stmt->body(), sem_block_body);
+  TINT_SCOPED_ASSIGNMENT(current_statement_, sem_block_body);
+
+  if (auto* initializer = stmt->initializer()) {
+    Mark(initializer);
+    if (!Statement(initializer)) {
+      return false;
+    }
+  }
+
+  if (auto* condition = stmt->condition()) {
+    Mark(condition);
+    if (!Expression(condition)) {
+      return false;
+    }
+
+    if (!TypeOf(condition)->Is<sem::Bool>()) {
+      AddError("for-loop condition must be bool, got " + TypeNameOf(condition),
+               condition->source());
+      return false;
+    }
+  }
+
+  if (auto* continuing = stmt->continuing()) {
+    Mark(continuing);
+    if (!Statement(continuing)) {
+      return false;
+    }
+  }
+
+  return BlockScope(stmt->body(),
+                    [&] { return Statements(stmt->body()->list()); });
+}
+
 bool Resolver::Expressions(const ast::ExpressionList& list) {
   for (auto* expr : list) {
     Mark(expr);