[WHLSL] Desugar for loops and while loops
https://bugs.webkit.org/show_bug.cgi?id=199726

Reviewed by Myles C. Maxfield.

Source/WebCore:

This patch makes loops behave a lot more similarly to the spec.
In particular, while loops are just degenerate for loops, so they can be desugared in the parser.
And for loops can themselves be heavily desugared, into having no initializer, one condition and one increment
by putting any initializer in a block around the loop, putting true in the condition if there is none, and putting any litteral in the increment if there is none.

Debugging this patch revealed an unrelated bug where the parser would generate an empty comma expression on ";", which the checker would then choke on.
The parser now generates an empty block in that case (as specified in the spec), which fixes the problem.

Finally, while updating the NameResolver for the new structure of loops I realized that it was needlessly generating extra NameContext.
They are not expected by the spec, that forbids naked variable declarations outside of blocks anyway.
So I removed this unnecessary work, and fixed the parser to correctly forbid such naked variable declarations.

* Modules/webgpu/WHLSL/AST/WHLSLAST.h:
* Modules/webgpu/WHLSL/AST/WHLSLForLoop.h:
(WebCore::WHLSL::AST::ForLoop::ForLoop):
(WebCore::WHLSL::AST::ForLoop::condition):
(WebCore::WHLSL::AST::ForLoop::increment):
* Modules/webgpu/WHLSL/AST/WHLSLStatement.h:
(WebCore::WHLSL::AST::Statement::isVariableDeclarationsStatement const):
* Modules/webgpu/WHLSL/AST/WHLSLWhileLoop.h: Removed.
* Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp:
(WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit):
* Modules/webgpu/WHLSL/WHLSLASTDumper.cpp:
(WebCore::WHLSL::ASTDumper::visit):
* Modules/webgpu/WHLSL/WHLSLASTDumper.h:
* Modules/webgpu/WHLSL/WHLSLChecker.cpp:
(WebCore::WHLSL::Checker::visit):
* Modules/webgpu/WHLSL/WHLSLNameResolver.cpp:
(WebCore::WHLSL::NameResolver::visit):
* Modules/webgpu/WHLSL/WHLSLNameResolver.h:
* Modules/webgpu/WHLSL/WHLSLParser.cpp:
(WebCore::WHLSL::Parser::parseBlockBody):
(WebCore::WHLSL::Parser::parseForLoop):
(WebCore::WHLSL::Parser::parseWhileLoop):
(WebCore::WHLSL::Parser::parseStatement):
(WebCore::WHLSL::Parser::parseEffectfulExpression):
* Modules/webgpu/WHLSL/WHLSLParser.h:
* Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp:
* Modules/webgpu/WHLSL/WHLSLVisitor.cpp:
(WebCore::WHLSL::Visitor::visit):
* Modules/webgpu/WHLSL/WHLSLVisitor.h:
* WebCore.xcodeproj/project.pbxproj:

LayoutTests:

I added the for-loop tests from Test.mjs (with help from Saam).
I did not add the foo9 and foo10 tests, as they are forbidden by the behavior checker in the C++ implementation (and by the spec).

I also changed one test from whlsl-return-spec-tests.html to assert_fail, because it relied on a lone variable declaration in an if, which is forbidden by the spec.

* webgpu/whlsl-for-loop-expected.txt: Added.
* webgpu/whlsl-for-loop.html: Added.
* webgpu/whlsl-return-spec-tests.html:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@247493 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index ffd7769..bd651a8 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,19 @@
+2019-07-16  Robin Morisset  <rmorisset@apple.com>
+
+        [WHLSL] Desugar for loops and while loops
+        https://bugs.webkit.org/show_bug.cgi?id=199726
+
+        Reviewed by Myles C. Maxfield.
+
+        I added the for-loop tests from Test.mjs (with help from Saam).
+        I did not add the foo9 and foo10 tests, as they are forbidden by the behavior checker in the C++ implementation (and by the spec).
+
+        I also changed one test from whlsl-return-spec-tests.html to assert_fail, because it relied on a lone variable declaration in an if, which is forbidden by the spec.
+
+        * webgpu/whlsl-for-loop-expected.txt: Added.
+        * webgpu/whlsl-for-loop.html: Added.
+        * webgpu/whlsl-return-spec-tests.html:
+
 2019-07-16  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         [Text autosizing] [iPadOS] Paragraph text on the front page of LinkedIn.com is not boosted
diff --git a/LayoutTests/webgpu/whlsl-for-loop-expected.txt b/LayoutTests/webgpu/whlsl-for-loop-expected.txt
new file mode 100644
index 0000000..ae67e5f
--- /dev/null
+++ b/LayoutTests/webgpu/whlsl-for-loop-expected.txt
@@ -0,0 +1,3 @@
+
+PASS forLoop 
+
diff --git a/LayoutTests/webgpu/whlsl-for-loop.html b/LayoutTests/webgpu/whlsl-for-loop.html
new file mode 100644
index 0000000..299a9cf
--- /dev/null
+++ b/LayoutTests/webgpu/whlsl-for-loop.html
@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>Lvalues.</title>
+<script src="js/whlsl-test-harness.js"></script>
+<script src="js/webgpu-functions.js"></script>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+const whlslTests = {};
+
+whlslTests.forLoop = async () =>
+{
+    let program = `
+        int foo1(int x)
+        {
+            int sum = 0;
+            int i;
+            for (i = 0; i < x; i = i + 1) {
+                sum = sum + i;
+            }
+            return sum;
+        }
+        int foo2(int x)
+        {
+            int sum = 0;
+            for (int i = 0; i < x; i = i + 1) {
+                sum = sum + i;
+            }
+            return sum;
+        }
+        int foo3(int x)
+        {
+            int sum = 0;
+            int i = 100;
+            for (int i = 0; i < x; i = i + 1) {
+                sum = sum + i;
+            }
+            return sum;
+        }
+        int foo4(int x)
+        {
+            int sum = 0;
+            for (int i = 0; i < x; i = i + 1) {
+                if (i == 4)
+                    continue;
+                sum = sum + i;
+            }
+            return sum;
+        }
+        int foo5(int x)
+        {
+            int sum = 0;
+            for (int i = 0; i < x; i = i + 1) {
+                if (i == 5)
+                    break;
+                sum = sum + i;
+            }
+            return sum;
+        }
+        int foo6(int x)
+        {
+            int sum = 0;
+            for (int i = 0; ; i = i + 1) {
+                if (i >= x)
+                    break;
+                sum = sum + i;
+            }
+            return sum;
+        }
+        int foo7(int x)
+        {
+            int sum = 0;
+            int i = 0;
+            for ( ; ; i = i + 1) {
+                if (i >= x)
+                    break;
+                sum = sum + i;
+            }
+            return sum;
+        }
+        int foo8(int x)
+        {
+            int sum = 0;
+            int i = 0;
+            for ( ; ; ) {
+                if (i >= x)
+                    break;
+                sum = sum + i;
+                i = i + 1;
+            }
+            return sum;
+        }
+    `;
+    assert_equals(await callIntFunction(program, "foo1", [makeInt(3)]), 3);
+    assert_equals(await callIntFunction(program, "foo1", [makeInt(4)]), 6);
+    assert_equals(await callIntFunction(program, "foo1", [makeInt(5)]), 10);
+    assert_equals(await callIntFunction(program, "foo2", [makeInt(3)]), 3);
+    assert_equals(await callIntFunction(program, "foo2", [makeInt(4)]), 6);
+    assert_equals(await callIntFunction(program, "foo2", [makeInt(5)]), 10);
+    assert_equals(await callIntFunction(program, "foo3", [makeInt(3)]), 3);
+    assert_equals(await callIntFunction(program, "foo3", [makeInt(4)]), 6);
+    assert_equals(await callIntFunction(program, "foo3", [makeInt(5)]), 10);
+    assert_equals(await callIntFunction(program, "foo4", [makeInt(3)]), 3);
+    assert_equals(await callIntFunction(program, "foo4", [makeInt(4)]), 6);
+    assert_equals(await callIntFunction(program, "foo4", [makeInt(5)]), 6);
+    assert_equals(await callIntFunction(program, "foo4", [makeInt(6)]), 11);
+    assert_equals(await callIntFunction(program, "foo5", [makeInt(3)]), 3);
+    assert_equals(await callIntFunction(program, "foo5", [makeInt(4)]), 6);
+    assert_equals(await callIntFunction(program, "foo5", [makeInt(5)]), 10);
+    assert_equals(await callIntFunction(program, "foo5", [makeInt(6)]), 10);
+    assert_equals(await callIntFunction(program, "foo5", [makeInt(7)]), 10);
+    assert_equals(await callIntFunction(program, "foo6", [makeInt(3)]), 3);
+    assert_equals(await callIntFunction(program, "foo6", [makeInt(4)]), 6);
+    assert_equals(await callIntFunction(program, "foo6", [makeInt(5)]), 10);
+    assert_equals(await callIntFunction(program, "foo6", [makeInt(6)]), 15);
+    assert_equals(await callIntFunction(program, "foo6", [makeInt(7)]), 21);
+    assert_equals(await callIntFunction(program, "foo7", [makeInt(3)]), 3);
+    assert_equals(await callIntFunction(program, "foo7", [makeInt(4)]), 6);
+    assert_equals(await callIntFunction(program, "foo7", [makeInt(5)]), 10);
+    assert_equals(await callIntFunction(program, "foo7", [makeInt(6)]), 15);
+    assert_equals(await callIntFunction(program, "foo7", [makeInt(7)]), 21);
+    assert_equals(await callIntFunction(program, "foo8", [makeInt(3)]), 3);
+    assert_equals(await callIntFunction(program, "foo8", [makeInt(4)]), 6);
+    assert_equals(await callIntFunction(program, "foo8", [makeInt(5)]), 10);
+    assert_equals(await callIntFunction(program, "foo8", [makeInt(6)]), 15);
+    assert_equals(await callIntFunction(program, "foo8", [makeInt(7)]), 21);
+    await checkFail(
+        `
+            void foo(int x)
+            {
+                for (int i = 0; ; i = i + 1) {
+                    break;
+                    x = i;
+                }
+            }
+        `);
+    await checkFail(
+        `
+            int foo(int x)
+            {
+                for ( ; x < 10; ) {
+                    return 7;
+                }
+            }
+        `);
+}
+
+runTests(whlslTests);
+</script>
+</html>
+
diff --git a/LayoutTests/webgpu/whlsl-return-spec-tests.html b/LayoutTests/webgpu/whlsl-return-spec-tests.html
index 2621a40..e12c309 100644
--- a/LayoutTests/webgpu/whlsl-return-spec-tests.html
+++ b/LayoutTests/webgpu/whlsl-return-spec-tests.html
@@ -111,17 +111,16 @@
                 return 11;
             }
         `);
-
-    program = `
-        int foo(int x)
-        {
-            int y = 6;
-            if (x == 7)
-                int y = 8;
-            return y;
-        }
-    `;
-    assert_equals(await callIntFunction(program, "foo", [makeInt(7)]), 6);
+    await checkFail(
+        `
+            int foo(int x)
+            {
+                int y = 6;
+                if (x == 7)
+                    int y = 8;
+                return y;
+            }
+        `);
 };
 
 whlslTests.returnReferenceToSameParameter = async () => {
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 58c9895..bca5655 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,53 @@
+2019-07-16  Robin Morisset  <rmorisset@apple.com>
+
+        [WHLSL] Desugar for loops and while loops
+        https://bugs.webkit.org/show_bug.cgi?id=199726
+
+        Reviewed by Myles C. Maxfield.
+
+        This patch makes loops behave a lot more similarly to the spec.
+        In particular, while loops are just degenerate for loops, so they can be desugared in the parser.
+        And for loops can themselves be heavily desugared, into having no initializer, one condition and one increment
+        by putting any initializer in a block around the loop, putting true in the condition if there is none, and putting any litteral in the increment if there is none.
+
+        Debugging this patch revealed an unrelated bug where the parser would generate an empty comma expression on ";", which the checker would then choke on.
+        The parser now generates an empty block in that case (as specified in the spec), which fixes the problem.
+
+        Finally, while updating the NameResolver for the new structure of loops I realized that it was needlessly generating extra NameContext.
+        They are not expected by the spec, that forbids naked variable declarations outside of blocks anyway.
+        So I removed this unnecessary work, and fixed the parser to correctly forbid such naked variable declarations.
+
+        * Modules/webgpu/WHLSL/AST/WHLSLAST.h:
+        * Modules/webgpu/WHLSL/AST/WHLSLForLoop.h:
+        (WebCore::WHLSL::AST::ForLoop::ForLoop):
+        (WebCore::WHLSL::AST::ForLoop::condition):
+        (WebCore::WHLSL::AST::ForLoop::increment):
+        * Modules/webgpu/WHLSL/AST/WHLSLStatement.h:
+        (WebCore::WHLSL::AST::Statement::isVariableDeclarationsStatement const):
+        * Modules/webgpu/WHLSL/AST/WHLSLWhileLoop.h: Removed.
+        * Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp:
+        (WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit):
+        * Modules/webgpu/WHLSL/WHLSLASTDumper.cpp:
+        (WebCore::WHLSL::ASTDumper::visit):
+        * Modules/webgpu/WHLSL/WHLSLASTDumper.h:
+        * Modules/webgpu/WHLSL/WHLSLChecker.cpp:
+        (WebCore::WHLSL::Checker::visit):
+        * Modules/webgpu/WHLSL/WHLSLNameResolver.cpp:
+        (WebCore::WHLSL::NameResolver::visit):
+        * Modules/webgpu/WHLSL/WHLSLNameResolver.h:
+        * Modules/webgpu/WHLSL/WHLSLParser.cpp:
+        (WebCore::WHLSL::Parser::parseBlockBody):
+        (WebCore::WHLSL::Parser::parseForLoop):
+        (WebCore::WHLSL::Parser::parseWhileLoop):
+        (WebCore::WHLSL::Parser::parseStatement):
+        (WebCore::WHLSL::Parser::parseEffectfulExpression):
+        * Modules/webgpu/WHLSL/WHLSLParser.h:
+        * Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp:
+        * Modules/webgpu/WHLSL/WHLSLVisitor.cpp:
+        (WebCore::WHLSL::Visitor::visit):
+        * Modules/webgpu/WHLSL/WHLSLVisitor.h:
+        * WebCore.xcodeproj/project.pbxproj:
+
 2019-07-16  Tim Horton  <timothy_horton@apple.com>
 
         NSTextFinder holes don't scroll with the page
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h
index 5794d4e..0e44612 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h
@@ -101,6 +101,5 @@
 #include "WHLSLVariableDeclaration.h"
 #include "WHLSLVariableDeclarationsStatement.h"
 #include "WHLSLVariableReference.h"
-#include "WHLSLWhileLoop.h"
 
 #endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h
index f45b974..fe5936c 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h
@@ -44,33 +44,28 @@
 
 class ForLoop : public Statement {
 public:
-    ForLoop(CodeLocation location, Variant<UniqueRef<Statement>, UniqueRef<Expression>>&& initialization, std::unique_ptr<Expression>&& condition, std::unique_ptr<Expression>&& increment, UniqueRef<Statement>&& body)
+    ForLoop(CodeLocation location, UniqueRef<Expression>&& condition, UniqueRef<Expression>&& increment, UniqueRef<Statement>&& body)
         : Statement(location)
-        , m_initialization(WTFMove(initialization))
         , m_condition(WTFMove(condition))
         , m_increment(WTFMove(increment))
         , m_body(WTFMove(body))
     {
     }
 
-    virtual ~ForLoop()
-    {
-    }
+    virtual ~ForLoop() = default;
 
     ForLoop(const ForLoop&) = delete;
     ForLoop(ForLoop&&) = default;
 
     bool isForLoop() const override { return true; }
 
-    Variant<UniqueRef<Statement>, UniqueRef<Expression>>& initialization() { return m_initialization; }
-    Expression* condition() { return m_condition.get(); }
-    Expression* increment() { return m_increment.get(); }
+    Expression& condition() { return m_condition; }
+    Expression& increment() { return m_increment; }
     Statement& body() { return m_body; }
 
 private:
-    Variant<UniqueRef<Statement>, UniqueRef<Expression>> m_initialization;
-    std::unique_ptr<Expression> m_condition;
-    std::unique_ptr<Expression> m_increment;
+    UniqueRef<Expression> m_condition;
+    UniqueRef<Expression> m_increment;
     UniqueRef<Statement> m_body;
 };
 
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLStatement.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLStatement.h
index 278ad2b..bad93ed 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLStatement.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLStatement.h
@@ -62,7 +62,6 @@
     virtual bool isSwitchStatement() const { return false; }
     virtual bool isTrap() const { return false; }
     virtual bool isVariableDeclarationsStatement() const { return false; }
-    virtual bool isWhileLoop() const { return false; }
 
     CodeLocation codeLocation() const { return m_codeLocation; }
     void updateCodeLocation(CodeLocation location) { m_codeLocation = location; }
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLWhileLoop.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLWhileLoop.h
deleted file mode 100644
index 55c0377..0000000
--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLWhileLoop.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#if ENABLE(WEBGPU)
-
-#include "WHLSLExpression.h"
-#include "WHLSLLexer.h"
-#include "WHLSLStatement.h"
-#include <wtf/UniqueRef.h>
-
-namespace WebCore {
-
-namespace WHLSL {
-
-namespace AST {
-
-class WhileLoop : public Statement {
-public:
-    WhileLoop(CodeLocation location, UniqueRef<Expression>&& conditional, UniqueRef<Statement>&& body)
-        : Statement(location)
-        , m_conditional(WTFMove(conditional))
-        , m_body(WTFMove(body))
-    {
-    }
-
-    virtual ~WhileLoop() = default;
-
-    WhileLoop(const WhileLoop&) = delete;
-    WhileLoop(WhileLoop&&) = default;
-
-    bool isWhileLoop() const override { return true; }
-
-    Expression& conditional() { return m_conditional; }
-    Statement& body() { return m_body; }
-
-private:
-    UniqueRef<Expression> m_conditional;
-    UniqueRef<Statement> m_body;
-};
-
-} // namespace AST
-
-}
-
-}
-
-SPECIALIZE_TYPE_TRAITS_WHLSL_STATEMENT(WhileLoop, isWhileLoop())
-
-#endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp
index 2b57933..a206b45 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp
@@ -128,7 +128,6 @@
     void visit(AST::SwitchCase&) override;
     void visit(AST::Trap&) override;
     void visit(AST::VariableDeclarationsStatement&) override;
-    void visit(AST::WhileLoop&) override;
     void visit(AST::IntegerLiteral&) override;
     void visit(AST::UnsignedIntegerLiteral&) override;
     void visit(AST::FloatLiteral&) override;
@@ -350,24 +349,9 @@
     emitLoop(LoopConditionLocation::AfterBody, &doWhileLoop.conditional(), nullptr, doWhileLoop.body());
 }
 
-void FunctionDefinitionWriter::visit(AST::WhileLoop& whileLoop)
-{
-    emitLoop(LoopConditionLocation::BeforeBody, &whileLoop.conditional(), nullptr, whileLoop.body());
-}
-
 void FunctionDefinitionWriter::visit(AST::ForLoop& forLoop)
 {
-    m_stringBuilder.append("{\n");
-
-    WTF::visit(WTF::makeVisitor([&](AST::Statement& statement) {
-        checkErrorAndVisit(statement);
-    }, [&](UniqueRef<AST::Expression>& expression) {
-        checkErrorAndVisit(expression);
-        takeLastValue(); // We don't need to do anything with the result.
-    }), forLoop.initialization());
-
-    emitLoop(LoopConditionLocation::BeforeBody, forLoop.condition(), forLoop.increment(), forLoop.body());
-    m_stringBuilder.append("}\n");
+    emitLoop(LoopConditionLocation::BeforeBody, &forLoop.condition(), &forLoop.increment(), forLoop.body());
 }
 
 void FunctionDefinitionWriter::visit(AST::IfStatement& ifStatement)
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp
index 5cfc8e2..362a862 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp
@@ -393,14 +393,6 @@
     m_out.print("continue");
 }
 
-void ASTDumper::visit(AST::WhileLoop& whileLoop)
-{
-    m_out.print("while (");
-    visit(whileLoop.conditional());
-    m_out.print(")");
-    visit(whileLoop.body());
-}
-
 void ASTDumper::visit(AST::DoWhileLoop& doWhileLoop)
 {
     m_out.print("do ");
@@ -412,18 +404,10 @@
 
 void ASTDumper::visit(AST::ForLoop& forLoop)
 {
-    m_out.print("for (");
-    WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) {
-        visit(statement);
-    }, [&](UniqueRef<AST::Expression>& expression) {
-        visit(expression);
-    }), forLoop.initialization());
+    m_out.print("for (; ");
+    visit(forLoop.condition());
     m_out.print("; ");
-    if (forLoop.condition())
-        visit(*forLoop.condition());
-    m_out.print("; ");
-    if (forLoop.increment())
-        visit(*forLoop.increment());
+    visit(forLoop.increment());
     m_out.print(") ");
     visit(forLoop.body());
 }
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h
index 0ab09ff..cb3e110 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h
@@ -100,7 +100,6 @@
     void visit(AST::SwitchStatement&) override;
     void visit(AST::Trap&) override;
     void visit(AST::VariableDeclarationsStatement&) override;
-    void visit(AST::WhileLoop&) override;
     void visit(AST::VariableDeclaration&) override;
     void visit(AST::AssignmentExpression&) override;
     void visit(AST::CallExpression&) override;
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp
index 06997bf..721e0ba 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp
@@ -57,7 +57,6 @@
 #include "WHLSLSwitchStatement.h"
 #include "WHLSLTernaryExpression.h"
 #include "WHLSLVisitor.h"
-#include "WHLSLWhileLoop.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/Ref.h>
@@ -501,7 +500,6 @@
     void visit(AST::LogicalNotExpression&) override;
     void visit(AST::LogicalExpression&) override;
     void visit(AST::IfStatement&) override;
-    void visit(AST::WhileLoop&) override;
     void visit(AST::DoWhileLoop&) override;
     void visit(AST::ForLoop&) override;
     void visit(AST::SwitchStatement&) override;
@@ -1247,13 +1245,6 @@
         checkErrorAndVisit(*ifStatement.elseBody());
 }
 
-void Checker::visit(AST::WhileLoop& whileLoop)
-{
-    if (!recurseAndRequireBoolType(whileLoop.conditional()))
-        return;
-    checkErrorAndVisit(whileLoop.body());
-}
-
 void Checker::visit(AST::DoWhileLoop& doWhileLoop)
 {
     checkErrorAndVisit(doWhileLoop.body());
@@ -1262,19 +1253,9 @@
 
 void Checker::visit(AST::ForLoop& forLoop)
 {
-    WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) {
-        checkErrorAndVisit(statement);
-    }, [&](UniqueRef<AST::Expression>& expression) {
-        checkErrorAndVisit(expression);
-    }), forLoop.initialization());
-    if (error())
+    if (!recurseAndRequireBoolType(forLoop.condition()))
         return;
-    if (forLoop.condition()) {
-        if (!recurseAndRequireBoolType(*forLoop.condition()))
-            return;
-    }
-    if (forLoop.increment())
-        checkErrorAndVisit(*forLoop.increment());
+    checkErrorAndVisit(forLoop.increment());
     checkErrorAndVisit(forLoop.body());
 }
 
@@ -1434,7 +1415,7 @@
 
 void Checker::visit(AST::CommaExpression& commaExpression)
 {
-    ASSERT(commaExpression.list().size() > 0);
+    ASSERT(!commaExpression.list().isEmpty());
     Visitor::visit(commaExpression);
     if (error())
         return;
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp
index 3660439..6991fb3 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp
@@ -43,7 +43,6 @@
 #include "WHLSLTypeReference.h"
 #include "WHLSLVariableDeclaration.h"
 #include "WHLSLVariableReference.h"
-#include "WHLSLWhileLoop.h"
 
 namespace WebCore {
 
@@ -120,48 +119,33 @@
     if (error())
         return;
 
-    {
-        NameContext nameContext(&m_nameContext);
-        NameResolver newNameResolver(*this, nameContext);
-        newNameResolver.checkErrorAndVisit(ifStatement.body());
-    }
+    checkErrorAndVisit(ifStatement.body());
     if (error())
         return;
 
-    if (ifStatement.elseBody()) {
-        NameContext nameContext(&m_nameContext);
-        NameResolver newNameResolver(*this, nameContext);
-        newNameResolver.checkErrorAndVisit(*ifStatement.elseBody());
-    }
-}
-
-void NameResolver::visit(AST::WhileLoop& whileLoop)
-{
-    checkErrorAndVisit(whileLoop.conditional());
-    if (error())
-        return;
-
-    NameContext nameContext(&m_nameContext);
-    NameResolver newNameResolver(*this, nameContext);
-    newNameResolver.checkErrorAndVisit(whileLoop.body());
+    if (ifStatement.elseBody())
+        checkErrorAndVisit(*ifStatement.elseBody());
 }
 
 void NameResolver::visit(AST::DoWhileLoop& whileLoop)
 {
-    {
-        NameContext nameContext(&m_nameContext);
-        NameResolver newNameResolver(*this, nameContext);
-        newNameResolver.checkErrorAndVisit(whileLoop.body());
-    }
+    checkErrorAndVisit(whileLoop.body());
+    if (error())
+        return;
 
     checkErrorAndVisit(whileLoop.conditional());
 }
 
 void NameResolver::visit(AST::ForLoop& forLoop)
 {
-    NameContext nameContext(&m_nameContext);
-    NameResolver newNameResolver(*this, nameContext);
-    newNameResolver.Visitor::visit(forLoop);
+    checkErrorAndVisit(forLoop.condition());
+    if (error())
+        return;
+    checkErrorAndVisit(forLoop.increment());
+    if (error())
+        return;
+
+    checkErrorAndVisit(forLoop.body());
 }
 
 void NameResolver::visit(AST::VariableDeclaration& variableDeclaration)
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h
index 3acdadf..14cfb65 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h
@@ -50,7 +50,6 @@
     void visit(AST::TypeReference&) override;
     void visit(AST::Block&) override;
     void visit(AST::IfStatement&) override;
-    void visit(AST::WhileLoop&) override;
     void visit(AST::DoWhileLoop&) override;
     void visit(AST::ForLoop&) override;
     void visit(AST::VariableDeclaration&) override;
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp
index 20cb939..2be1217 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp
@@ -1063,7 +1063,8 @@
 
     AST::Statements statements;
     while (!peekTypes<Token::Type::RightCurlyBracket, Token::Type::Case, Token::Type::Default>()) {
-        PARSE(statement, Statement);
+        bool allowVariableDeclarations = true;
+        PARSE(statement, Statement, allowVariableDeclarations);
         statements.append(WTFMove(*statement));
     }
 
@@ -1142,51 +1143,52 @@
     }
 }
 
-auto Parser::parseForLoop() -> Expected<AST::ForLoop, Error>
+auto Parser::parseForLoop() -> Expected<AST::Block, Error>
 {
     CONSUME_TYPE(origin, For);
     CONSUME_TYPE(leftParenthesis, LeftParenthesis);
 
-    auto parseRemainder = [&](Variant<UniqueRef<AST::Statement>, UniqueRef<AST::Expression>>&& initialization) -> Expected<AST::ForLoop, Error> {
-        CONSUME_TYPE(semicolon, Semicolon);
-
-        std::unique_ptr<AST::Expression> condition(nullptr);
-        if (!tryType(Token::Type::Semicolon)) {
-            if (auto expression = parseExpression())
-                condition = (*expression).moveToUniquePtr();
-            else
-                return Unexpected<Error>(expression.error());
-            CONSUME_TYPE(secondSemicolon, Semicolon);
-        }
-
-        std::unique_ptr<AST::Expression> increment(nullptr);
-        if (!tryType(Token::Type::RightParenthesis)) {
-            if (auto expression = parseExpression())
-                increment = (*expression).moveToUniquePtr();
-            else
-                return Unexpected<Error>(expression.error());
-            CONSUME_TYPE(rightParenthesis, RightParenthesis);
-        }
-
-        PARSE(body, Statement);
-        AST::CodeLocation location(origin->codeLocation,  (*body)->codeLocation());
-        return AST::ForLoop(location, WTFMove(initialization), WTFMove(condition), WTFMove(increment), WTFMove(*body));
-    };
 
     auto variableDeclarations = backtrackingScope<Expected<AST::VariableDeclarationsStatement, Error>>([&]() {
         return parseVariableDeclarations();
     });
-    if (variableDeclarations) {
-        UniqueRef<AST::Statement> declarationStatement = makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations));
-        return parseRemainder(WTFMove(declarationStatement));
+    Optional<UniqueRef<AST::Statement>> initialization;
+    if (variableDeclarations)
+        initialization = static_cast<UniqueRef<AST::Statement>>(makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)));
+    else {
+        PARSE(effectfulExpression, EffectfulExpression);
+        initialization = WTFMove(*effectfulExpression);
     }
 
-    PARSE(effectfulExpression, EffectfulExpression);
+    CONSUME_TYPE(semicolon, Semicolon);
 
-    return parseRemainder(WTFMove(*effectfulExpression));
+    Optional<UniqueRef<AST::Expression>> condition;
+    auto secondSemicolon = tryType(Token::Type::Semicolon);
+    if (!secondSemicolon) {
+        PARSE(expression, Expression);
+        condition = WTFMove(*expression);
+        CONSUME_TYPE(secondSemicolon, Semicolon);
+    } else
+        condition = static_cast<UniqueRef<AST::Expression>>(makeUniqueRef<AST::BooleanLiteral>(*secondSemicolon, true));
+
+    Optional<UniqueRef<AST::Expression>> increment;
+    auto rightParenthesis = tryType(Token::Type::RightParenthesis);
+    if (!rightParenthesis) {
+        PARSE(expression, Expression);
+        increment = WTFMove(*expression);
+        CONSUME_TYPE(rightParenthesis, RightParenthesis);
+    } else
+        increment = static_cast<UniqueRef<AST::Expression>>(makeUniqueRef<AST::BooleanLiteral>(*origin, true)); // FIXME: NullLiteral would make more sense, but is buggy right now. Anything side-effect free is fine.
+
+    PARSE(body, Statement);
+    AST::CodeLocation location(origin->codeLocation,  (*body)->codeLocation());
+
+    auto forLoop = makeUniqueRef<AST::ForLoop>(location, WTFMove(*condition), WTFMove(*increment), WTFMove(*body));
+    AST::Statements statements = Vector<UniqueRef<AST::Statement>>::from(WTFMove(*initialization), WTFMove(forLoop));
+    return AST::Block(location, WTFMove(statements));
 }
 
-auto Parser::parseWhileLoop() -> Expected<AST::WhileLoop, Error>
+auto Parser::parseWhileLoop() -> Expected<AST::ForLoop, Error>
 {
     CONSUME_TYPE(origin, While);
     CONSUME_TYPE(leftParenthesis, LeftParenthesis);
@@ -1195,7 +1197,8 @@
     PARSE(body, Statement);
 
     AST::CodeLocation location(origin->codeLocation,  (*body)->codeLocation());
-    return AST::WhileLoop(location, WTFMove(*conditional), WTFMove(*body));
+    auto increment = makeUniqueRef<AST::BooleanLiteral>(*origin, true); // FIXME: NullLiteral would make more sense, but is buggy right now. Anything side-effect free is fine.
+    return AST::ForLoop(location, WTFMove(*conditional), WTFMove(increment), WTFMove(*body));
 }
 
 auto Parser::parseDoWhileLoop() -> Expected<AST::DoWhileLoop, Error>
@@ -1254,7 +1257,7 @@
     return AST::VariableDeclarationsStatement({ origin->startOffset(), endOffset }, WTFMove(result));
 }
 
-auto Parser::parseStatement() -> Expected<UniqueRef<AST::Statement>, Error>
+auto Parser::parseStatement(bool allowVariableDeclarations) -> Expected<UniqueRef<AST::Statement>, Error>
 {
     PEEK(token);
     switch (token->type) {
@@ -1272,11 +1275,11 @@
     }
     case Token::Type::For: {
         PARSE(forLoop, ForLoop);
-        return { makeUniqueRef<AST::ForLoop>(WTFMove(*forLoop)) };
+        return { makeUniqueRef<AST::Block>(WTFMove(*forLoop)) };
     }
     case Token::Type::While: {
         PARSE(whileLoop, WhileLoop);
-        return { makeUniqueRef<AST::WhileLoop>(WTFMove(*whileLoop)) };
+        return { makeUniqueRef<AST::ForLoop>(WTFMove(*whileLoop)) };
     }
     case Token::Type::Do: {
         PARSE(doWhileLoop, DoWhileLoop);
@@ -1346,27 +1349,33 @@
     }
 
     {
-        auto effectfulExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> {
+        auto effectfulExpressionStatement = backtrackingScope<Expected<UniqueRef<AST::Statement>, Error>>([&]() -> Expected<UniqueRef<AST::Statement>, Error> {
             PARSE(result, EffectfulExpression);
             CONSUME_TYPE(semicolon, Semicolon);
             return result;
         });
-        if (effectfulExpression)
-            return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(*effectfulExpression)) };
+        if (effectfulExpressionStatement)
+            return effectfulExpressionStatement;
     }
 
-    PARSE(variableDeclarations, VariableDeclarations);
-    CONSUME_TYPE(semicolon, Semicolon);
-    return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
+    if (allowVariableDeclarations) {
+        PARSE(variableDeclarations, VariableDeclarations);
+        CONSUME_TYPE(semicolon, Semicolon);
+        return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
+    }
+
+    return Unexpected<Error>("A variable declaration is only valid inside a block");
 }
 
-auto Parser::parseEffectfulExpression() -> Expected<UniqueRef<AST::Expression>, Error>
+auto Parser::parseEffectfulExpression() -> Expected<UniqueRef<AST::Statement>, Error>
 {
     PEEK(origin);
-    Vector<UniqueRef<AST::Expression>> expressions;
-    if (origin->type == Token::Type::Semicolon)
-        return { makeUniqueRef<AST::CommaExpression>(*origin, WTFMove(expressions)) };
+    if (origin->type == Token::Type::Semicolon) {
+        AST::Statements statements;
+        return { makeUniqueRef<AST::Block>(*origin, WTFMove(statements)) };
+    }
 
+    Vector<UniqueRef<AST::Expression>> expressions;
     PARSE(effectfulExpression, EffectfulAssignment);
     expressions.append(WTFMove(*effectfulExpression));
 
@@ -1376,10 +1385,11 @@
     }
 
     if (expressions.size() == 1)
-        return WTFMove(expressions[0]);
+        return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(expressions[0])) };
     unsigned endOffset = m_lexer.peek().startOffset();
     AST::CodeLocation location(origin->startOffset(), endOffset);
-    return { makeUniqueRef<AST::CommaExpression>(location, WTFMove(expressions)) };
+    auto expression = makeUniqueRef<AST::CommaExpression>(location, WTFMove(expressions));
+    return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(expression)) };
 }
 
 auto Parser::parseEffectfulAssignment() -> Expected<UniqueRef<AST::Expression>, Error>
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h
index 400ce66..901097d 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h
@@ -91,7 +91,6 @@
 #include "WHLSLVariableDeclaration.h"
 #include "WHLSLVariableDeclarationsStatement.h"
 #include "WHLSLVariableReference.h"
-#include "WHLSLWhileLoop.h"
 #include <wtf/Expected.h>
 #include <wtf/Optional.h>
 #include <wtf/PrintStream.h>
@@ -203,14 +202,14 @@
     Expected<AST::IfStatement, Error> parseIfStatement();
     Expected<AST::SwitchStatement, Error> parseSwitchStatement();
     Expected<AST::SwitchCase, Error> parseSwitchCase();
-    Expected<AST::ForLoop, Error> parseForLoop();
-    Expected<AST::WhileLoop, Error> parseWhileLoop();
+    Expected<AST::Block, Error> parseForLoop();
+    Expected<AST::ForLoop, Error> parseWhileLoop();
     Expected<AST::DoWhileLoop, Error> parseDoWhileLoop();
     Expected<AST::VariableDeclaration, Error> parseVariableDeclaration(UniqueRef<AST::UnnamedType>&&);
     Expected<AST::VariableDeclarationsStatement, Error> parseVariableDeclarations();
-    Expected<UniqueRef<AST::Statement>, Error> parseStatement();
+    Expected<UniqueRef<AST::Statement>, Error> parseStatement(bool allowVariableDeclaration = false);
 
-    Expected<UniqueRef<AST::Expression>, Error> parseEffectfulExpression();
+    Expected<UniqueRef<AST::Statement>, Error> parseEffectfulExpression();
     Expected<UniqueRef<AST::Expression>, Error> parseEffectfulAssignment();
     struct SuffixExpression {
         SuffixExpression(UniqueRef<AST::Expression>&& result, bool success)
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp
index b4bcd61..474fc80 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp
@@ -44,7 +44,6 @@
 #include "WHLSLTrap.h"
 #include "WHLSLVariableDeclarationsStatement.h"
 #include "WHLSLVisitor.h"
-#include "WHLSLWhileLoop.h"
 #include <cstdint>
 #include <wtf/OptionSet.h>
 #include <wtf/Vector.h>
@@ -109,9 +108,6 @@
 
     void visit(AST::ForLoop& forLoop) override
     {
-        // The initialization always has a behavior of Nothing, which we already add unconditionally below,
-        // so we can just ignore the initialization.
-
         checkErrorAndVisit(forLoop.body());
         if (error())
             return;
@@ -122,18 +118,6 @@
         m_stack.append(b);
     }
 
-    void visit(AST::WhileLoop& whileLoop) override
-    {
-        checkErrorAndVisit(whileLoop.body());
-        if (error())
-            return;
-        auto b = m_stack.takeLast();
-        b.remove(Behavior::Break);
-        b.remove(Behavior::Continue);
-        b.add(Behavior::Nothing);
-        m_stack.append(b);
-    }
-
     void visit(AST::SwitchCase& switchCase) override
     {
         Visitor::visit(switchCase);
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp
index bf12e63..372e661 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp
@@ -331,10 +331,10 @@
         checkErrorAndVisit(downcast<AST::SwitchStatement>(statement));
     else if (is<AST::Trap>(statement))
         checkErrorAndVisit(downcast<AST::Trap>(statement));
-    else if (is<AST::VariableDeclarationsStatement>(statement))
+    else {
+        ASSERT(is<AST::VariableDeclarationsStatement>(statement));
         checkErrorAndVisit(downcast<AST::VariableDeclarationsStatement>(statement));
-    else
-        checkErrorAndVisit(downcast<AST::WhileLoop>(statement));
+    }
 }
 
 void Visitor::visit(AST::Break&)
@@ -427,15 +427,8 @@
 
 void Visitor::visit(AST::ForLoop& forLoop)
 {
-    WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) {
-        checkErrorAndVisit(statement);
-    }, [&](UniqueRef<AST::Expression>& expression) {
-        checkErrorAndVisit(expression);
-    }), forLoop.initialization());
-    if (forLoop.condition())
-        checkErrorAndVisit(*forLoop.condition());
-    if (forLoop.increment())
-        checkErrorAndVisit(*forLoop.increment());
+    checkErrorAndVisit(forLoop.condition());
+    checkErrorAndVisit(forLoop.increment());
     checkErrorAndVisit(forLoop.body());
 }
 
@@ -477,12 +470,6 @@
         checkErrorAndVisit(variableDeclaration.get());
 }
 
-void Visitor::visit(AST::WhileLoop& whileLoop)
-{
-    checkErrorAndVisit(whileLoop.conditional());
-    checkErrorAndVisit(whileLoop.body());
-}
-
 void Visitor::visit(AST::VariableDeclaration& variableDeclaration)
 {
     if (variableDeclaration.type())
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h
index ec396fd..a3fa247 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h
@@ -85,7 +85,6 @@
 class SwitchStatement;
 class Trap;
 class VariableDeclarationsStatement;
-class WhileLoop;
 class VariableDeclaration;
 class AssignmentExpression;
 class CallExpression;
@@ -166,7 +165,6 @@
     virtual void visit(AST::SwitchStatement&);
     virtual void visit(AST::Trap&);
     virtual void visit(AST::VariableDeclarationsStatement&);
-    virtual void visit(AST::WhileLoop&);
     virtual void visit(AST::VariableDeclaration&);
     virtual void visit(AST::AssignmentExpression&);
     virtual void visit(AST::CallExpression&);
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 70ef35a..2674e46 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -13256,7 +13256,6 @@
 		C21BF70121CD89C400227979 /* WHLSLDereferenceExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLDereferenceExpression.h; sourceTree = "<group>"; };
 		C21BF70221CD89C400227979 /* WHLSLEnumerationMemberLiteral.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLEnumerationMemberLiteral.h; sourceTree = "<group>"; };
 		C21BF70321CD89C500227979 /* WHLSLReturn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLReturn.h; sourceTree = "<group>"; };
-		C21BF70421CD89C600227979 /* WHLSLWhileLoop.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLWhileLoop.h; sourceTree = "<group>"; };
 		C21BF70521CD89C700227979 /* WHLSLFunctionAttribute.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLFunctionAttribute.h; sourceTree = "<group>"; };
 		C21BF70621CD89C700227979 /* WHLSLCommaExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLCommaExpression.h; sourceTree = "<group>"; };
 		C21BF70721CD89C800227979 /* WHLSLNullLiteral.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLNullLiteral.h; sourceTree = "<group>"; };
@@ -17132,7 +17131,6 @@
 				C21BF71021CD89D000227979 /* WHLSLVariableDeclaration.h */,
 				C21BF71421CD89D300227979 /* WHLSLVariableDeclarationsStatement.h */,
 				C21BF71321CD89D200227979 /* WHLSLVariableReference.h */,
-				C21BF70421CD89C600227979 /* WHLSLWhileLoop.h */,
 			);
 			path = AST;
 			sourceTree = "<group>";