Changeset 247493 in webkit


Ignore:
Timestamp:
Jul 16, 2019 1:26:01 PM (5 years ago)
Author:
rmorisset@apple.com
Message:

[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:
Location:
trunk
Files:
2 added
1 deleted
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r247484 r247493  
     12019-07-16  Robin Morisset  <rmorisset@apple.com>
     2
     3        [WHLSL] Desugar for loops and while loops
     4        https://bugs.webkit.org/show_bug.cgi?id=199726
     5
     6        Reviewed by Myles C. Maxfield.
     7
     8        I added the for-loop tests from Test.mjs (with help from Saam).
     9        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).
     10
     11        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.
     12
     13        * webgpu/whlsl-for-loop-expected.txt: Added.
     14        * webgpu/whlsl-for-loop.html: Added.
     15        * webgpu/whlsl-return-spec-tests.html:
     16
    1172019-07-16  Wenson Hsieh  <wenson_hsieh@apple.com>
    218
  • trunk/LayoutTests/webgpu/whlsl-return-spec-tests.html

    r247289 r247493  
    112112            }
    113113        `);
    114 
    115     program = `
    116         int foo(int x)
    117         {
    118             int y = 6;
    119             if (x == 7)
    120                 int y = 8;
    121             return y;
    122         }
    123     `;
    124     assert_equals(await callIntFunction(program, "foo", [makeInt(7)]), 6);
     114    await checkFail(
     115        `
     116            int foo(int x)
     117            {
     118                int y = 6;
     119                if (x == 7)
     120                    int y = 8;
     121                return y;
     122            }
     123        `);
    125124};
    126125
  • trunk/Source/WebCore/ChangeLog

    r247490 r247493  
     12019-07-16  Robin Morisset  <rmorisset@apple.com>
     2
     3        [WHLSL] Desugar for loops and while loops
     4        https://bugs.webkit.org/show_bug.cgi?id=199726
     5
     6        Reviewed by Myles C. Maxfield.
     7
     8        This patch makes loops behave a lot more similarly to the spec.
     9        In particular, while loops are just degenerate for loops, so they can be desugared in the parser.
     10        And for loops can themselves be heavily desugared, into having no initializer, one condition and one increment
     11        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.
     12
     13        Debugging this patch revealed an unrelated bug where the parser would generate an empty comma expression on ";", which the checker would then choke on.
     14        The parser now generates an empty block in that case (as specified in the spec), which fixes the problem.
     15
     16        Finally, while updating the NameResolver for the new structure of loops I realized that it was needlessly generating extra NameContext.
     17        They are not expected by the spec, that forbids naked variable declarations outside of blocks anyway.
     18        So I removed this unnecessary work, and fixed the parser to correctly forbid such naked variable declarations.
     19
     20        * Modules/webgpu/WHLSL/AST/WHLSLAST.h:
     21        * Modules/webgpu/WHLSL/AST/WHLSLForLoop.h:
     22        (WebCore::WHLSL::AST::ForLoop::ForLoop):
     23        (WebCore::WHLSL::AST::ForLoop::condition):
     24        (WebCore::WHLSL::AST::ForLoop::increment):
     25        * Modules/webgpu/WHLSL/AST/WHLSLStatement.h:
     26        (WebCore::WHLSL::AST::Statement::isVariableDeclarationsStatement const):
     27        * Modules/webgpu/WHLSL/AST/WHLSLWhileLoop.h: Removed.
     28        * Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp:
     29        (WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit):
     30        * Modules/webgpu/WHLSL/WHLSLASTDumper.cpp:
     31        (WebCore::WHLSL::ASTDumper::visit):
     32        * Modules/webgpu/WHLSL/WHLSLASTDumper.h:
     33        * Modules/webgpu/WHLSL/WHLSLChecker.cpp:
     34        (WebCore::WHLSL::Checker::visit):
     35        * Modules/webgpu/WHLSL/WHLSLNameResolver.cpp:
     36        (WebCore::WHLSL::NameResolver::visit):
     37        * Modules/webgpu/WHLSL/WHLSLNameResolver.h:
     38        * Modules/webgpu/WHLSL/WHLSLParser.cpp:
     39        (WebCore::WHLSL::Parser::parseBlockBody):
     40        (WebCore::WHLSL::Parser::parseForLoop):
     41        (WebCore::WHLSL::Parser::parseWhileLoop):
     42        (WebCore::WHLSL::Parser::parseStatement):
     43        (WebCore::WHLSL::Parser::parseEffectfulExpression):
     44        * Modules/webgpu/WHLSL/WHLSLParser.h:
     45        * Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp:
     46        * Modules/webgpu/WHLSL/WHLSLVisitor.cpp:
     47        (WebCore::WHLSL::Visitor::visit):
     48        * Modules/webgpu/WHLSL/WHLSLVisitor.h:
     49        * WebCore.xcodeproj/project.pbxproj:
     50
    1512019-07-16  Tim Horton  <timothy_horton@apple.com>
    252
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h

    r247124 r247493  
    102102#include "WHLSLVariableDeclarationsStatement.h"
    103103#include "WHLSLVariableReference.h"
    104 #include "WHLSLWhileLoop.h"
    105104
    106105#endif
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h

    r247341 r247493  
    4545class ForLoop : public Statement {
    4646public:
    47     ForLoop(CodeLocation location, Variant<UniqueRef<Statement>, UniqueRef<Expression>>&& initialization, std::unique_ptr<Expression>&& condition, std::unique_ptr<Expression>&& increment, UniqueRef<Statement>&& body)
     47    ForLoop(CodeLocation location, UniqueRef<Expression>&& condition, UniqueRef<Expression>&& increment, UniqueRef<Statement>&& body)
    4848        : Statement(location)
    49         , m_initialization(WTFMove(initialization))
    5049        , m_condition(WTFMove(condition))
    5150        , m_increment(WTFMove(increment))
     
    5453    }
    5554
    56     virtual ~ForLoop()
    57     {
    58     }
     55    virtual ~ForLoop() = default;
    5956
    6057    ForLoop(const ForLoop&) = delete;
     
    6360    bool isForLoop() const override { return true; }
    6461
    65     Variant<UniqueRef<Statement>, UniqueRef<Expression>>& initialization() { return m_initialization; }
    66     Expression* condition() { return m_condition.get(); }
    67     Expression* increment() { return m_increment.get(); }
     62    Expression& condition() { return m_condition; }
     63    Expression& increment() { return m_increment; }
    6864    Statement& body() { return m_body; }
    6965
    7066private:
    71     Variant<UniqueRef<Statement>, UniqueRef<Expression>> m_initialization;
    72     std::unique_ptr<Expression> m_condition;
    73     std::unique_ptr<Expression> m_increment;
     67    UniqueRef<Expression> m_condition;
     68    UniqueRef<Expression> m_increment;
    7469    UniqueRef<Statement> m_body;
    7570};
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLStatement.h

    r247329 r247493  
    6363    virtual bool isTrap() const { return false; }
    6464    virtual bool isVariableDeclarationsStatement() const { return false; }
    65     virtual bool isWhileLoop() const { return false; }
    6665
    6766    CodeLocation codeLocation() const { return m_codeLocation; }
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp

    r247450 r247493  
    129129    void visit(AST::Trap&) override;
    130130    void visit(AST::VariableDeclarationsStatement&) override;
    131     void visit(AST::WhileLoop&) override;
    132131    void visit(AST::IntegerLiteral&) override;
    133132    void visit(AST::UnsignedIntegerLiteral&) override;
     
    351350}
    352351
    353 void FunctionDefinitionWriter::visit(AST::WhileLoop& whileLoop)
    354 {
    355     emitLoop(LoopConditionLocation::BeforeBody, &whileLoop.conditional(), nullptr, whileLoop.body());
    356 }
    357 
    358352void FunctionDefinitionWriter::visit(AST::ForLoop& forLoop)
    359353{
    360     m_stringBuilder.append("{\n");
    361 
    362     WTF::visit(WTF::makeVisitor([&](AST::Statement& statement) {
    363         checkErrorAndVisit(statement);
    364     }, [&](UniqueRef<AST::Expression>& expression) {
    365         checkErrorAndVisit(expression);
    366         takeLastValue(); // We don't need to do anything with the result.
    367     }), forLoop.initialization());
    368 
    369     emitLoop(LoopConditionLocation::BeforeBody, forLoop.condition(), forLoop.increment(), forLoop.body());
    370     m_stringBuilder.append("}\n");
     354    emitLoop(LoopConditionLocation::BeforeBody, &forLoop.condition(), &forLoop.increment(), forLoop.body());
    371355}
    372356
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp

    r246625 r247493  
    394394}
    395395
    396 void ASTDumper::visit(AST::WhileLoop& whileLoop)
    397 {
    398     m_out.print("while (");
    399     visit(whileLoop.conditional());
    400     m_out.print(")");
    401     visit(whileLoop.body());
    402 }
    403 
    404396void ASTDumper::visit(AST::DoWhileLoop& doWhileLoop)
    405397{
     
    413405void ASTDumper::visit(AST::ForLoop& forLoop)
    414406{
    415     m_out.print("for (");
    416     WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) {
    417         visit(statement);
    418     }, [&](UniqueRef<AST::Expression>& expression) {
    419         visit(expression);
    420     }), forLoop.initialization());
     407    m_out.print("for (; ");
     408    visit(forLoop.condition());
    421409    m_out.print("; ");
    422     if (forLoop.condition())
    423         visit(*forLoop.condition());
    424     m_out.print("; ");
    425     if (forLoop.increment())
    426         visit(*forLoop.increment());
     410    visit(forLoop.increment());
    427411    m_out.print(") ");
    428412    visit(forLoop.body());
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h

    r246550 r247493  
    101101    void visit(AST::Trap&) override;
    102102    void visit(AST::VariableDeclarationsStatement&) override;
    103     void visit(AST::WhileLoop&) override;
    104103    void visit(AST::VariableDeclaration&) override;
    105104    void visit(AST::AssignmentExpression&) override;
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp

    r247419 r247493  
    5858#include "WHLSLTernaryExpression.h"
    5959#include "WHLSLVisitor.h"
    60 #include "WHLSLWhileLoop.h"
    6160#include <wtf/HashMap.h>
    6261#include <wtf/HashSet.h>
     
    502501    void visit(AST::LogicalExpression&) override;
    503502    void visit(AST::IfStatement&) override;
    504     void visit(AST::WhileLoop&) override;
    505503    void visit(AST::DoWhileLoop&) override;
    506504    void visit(AST::ForLoop&) override;
     
    12481246}
    12491247
    1250 void Checker::visit(AST::WhileLoop& whileLoop)
    1251 {
    1252     if (!recurseAndRequireBoolType(whileLoop.conditional()))
    1253         return;
    1254     checkErrorAndVisit(whileLoop.body());
    1255 }
    1256 
    12571248void Checker::visit(AST::DoWhileLoop& doWhileLoop)
    12581249{
     
    12631254void Checker::visit(AST::ForLoop& forLoop)
    12641255{
    1265     WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) {
    1266         checkErrorAndVisit(statement);
    1267     }, [&](UniqueRef<AST::Expression>& expression) {
    1268         checkErrorAndVisit(expression);
    1269     }), forLoop.initialization());
    1270     if (error())
    1271         return;
    1272     if (forLoop.condition()) {
    1273         if (!recurseAndRequireBoolType(*forLoop.condition()))
    1274             return;
    1275     }
    1276     if (forLoop.increment())
    1277         checkErrorAndVisit(*forLoop.increment());
     1256    if (!recurseAndRequireBoolType(forLoop.condition()))
     1257        return;
     1258    checkErrorAndVisit(forLoop.increment());
    12781259    checkErrorAndVisit(forLoop.body());
    12791260}
     
    14351416void Checker::visit(AST::CommaExpression& commaExpression)
    14361417{
    1437     ASSERT(commaExpression.list().size() > 0);
     1418    ASSERT(!commaExpression.list().isEmpty());
    14381419    Visitor::visit(commaExpression);
    14391420    if (error())
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp

    r247419 r247493  
    4444#include "WHLSLVariableDeclaration.h"
    4545#include "WHLSLVariableReference.h"
    46 #include "WHLSLWhileLoop.h"
    4746
    4847namespace WebCore {
     
    121120        return;
    122121
    123     {
    124         NameContext nameContext(&m_nameContext);
    125         NameResolver newNameResolver(*this, nameContext);
    126         newNameResolver.checkErrorAndVisit(ifStatement.body());
    127     }
    128     if (error())
    129         return;
    130 
    131     if (ifStatement.elseBody()) {
    132         NameContext nameContext(&m_nameContext);
    133         NameResolver newNameResolver(*this, nameContext);
    134         newNameResolver.checkErrorAndVisit(*ifStatement.elseBody());
    135     }
    136 }
    137 
    138 void NameResolver::visit(AST::WhileLoop& whileLoop)
    139 {
     122    checkErrorAndVisit(ifStatement.body());
     123    if (error())
     124        return;
     125
     126    if (ifStatement.elseBody())
     127        checkErrorAndVisit(*ifStatement.elseBody());
     128}
     129
     130void NameResolver::visit(AST::DoWhileLoop& whileLoop)
     131{
     132    checkErrorAndVisit(whileLoop.body());
     133    if (error())
     134        return;
     135
    140136    checkErrorAndVisit(whileLoop.conditional());
    141     if (error())
    142         return;
    143 
    144     NameContext nameContext(&m_nameContext);
    145     NameResolver newNameResolver(*this, nameContext);
    146     newNameResolver.checkErrorAndVisit(whileLoop.body());
    147 }
    148 
    149 void NameResolver::visit(AST::DoWhileLoop& whileLoop)
    150 {
    151     {
    152         NameContext nameContext(&m_nameContext);
    153         NameResolver newNameResolver(*this, nameContext);
    154         newNameResolver.checkErrorAndVisit(whileLoop.body());
    155     }
    156 
    157     checkErrorAndVisit(whileLoop.conditional());
    158137}
    159138
    160139void NameResolver::visit(AST::ForLoop& forLoop)
    161140{
    162     NameContext nameContext(&m_nameContext);
    163     NameResolver newNameResolver(*this, nameContext);
    164     newNameResolver.Visitor::visit(forLoop);
     141    checkErrorAndVisit(forLoop.condition());
     142    if (error())
     143        return;
     144    checkErrorAndVisit(forLoop.increment());
     145    if (error())
     146        return;
     147
     148    checkErrorAndVisit(forLoop.body());
    165149}
    166150
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h

    r247419 r247493  
    5151    void visit(AST::Block&) override;
    5252    void visit(AST::IfStatement&) override;
    53     void visit(AST::WhileLoop&) override;
    5453    void visit(AST::DoWhileLoop&) override;
    5554    void visit(AST::ForLoop&) override;
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp

    r247341 r247493  
    10641064    AST::Statements statements;
    10651065    while (!peekTypes<Token::Type::RightCurlyBracket, Token::Type::Case, Token::Type::Default>()) {
    1066         PARSE(statement, Statement);
     1066        bool allowVariableDeclarations = true;
     1067        PARSE(statement, Statement, allowVariableDeclarations);
    10671068        statements.append(WTFMove(*statement));
    10681069    }
     
    11431144}
    11441145
    1145 auto Parser::parseForLoop() -> Expected<AST::ForLoop, Error>
     1146auto Parser::parseForLoop() -> Expected<AST::Block, Error>
    11461147{
    11471148    CONSUME_TYPE(origin, For);
    11481149    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
    11491150
    1150     auto parseRemainder = [&](Variant<UniqueRef<AST::Statement>, UniqueRef<AST::Expression>>&& initialization) -> Expected<AST::ForLoop, Error> {
    1151         CONSUME_TYPE(semicolon, Semicolon);
    1152 
    1153         std::unique_ptr<AST::Expression> condition(nullptr);
    1154         if (!tryType(Token::Type::Semicolon)) {
    1155             if (auto expression = parseExpression())
    1156                 condition = (*expression).moveToUniquePtr();
    1157             else
    1158                 return Unexpected<Error>(expression.error());
    1159             CONSUME_TYPE(secondSemicolon, Semicolon);
    1160         }
    1161 
    1162         std::unique_ptr<AST::Expression> increment(nullptr);
    1163         if (!tryType(Token::Type::RightParenthesis)) {
    1164             if (auto expression = parseExpression())
    1165                 increment = (*expression).moveToUniquePtr();
    1166             else
    1167                 return Unexpected<Error>(expression.error());
    1168             CONSUME_TYPE(rightParenthesis, RightParenthesis);
    1169         }
    1170 
    1171         PARSE(body, Statement);
    1172         AST::CodeLocation location(origin->codeLocation,  (*body)->codeLocation());
    1173         return AST::ForLoop(location, WTFMove(initialization), WTFMove(condition), WTFMove(increment), WTFMove(*body));
    1174     };
    11751151
    11761152    auto variableDeclarations = backtrackingScope<Expected<AST::VariableDeclarationsStatement, Error>>([&]() {
    11771153        return parseVariableDeclarations();
    11781154    });
    1179     if (variableDeclarations) {
    1180         UniqueRef<AST::Statement> declarationStatement = makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations));
    1181         return parseRemainder(WTFMove(declarationStatement));
    1182     }
    1183 
    1184     PARSE(effectfulExpression, EffectfulExpression);
    1185 
    1186     return parseRemainder(WTFMove(*effectfulExpression));
    1187 }
    1188 
    1189 auto Parser::parseWhileLoop() -> Expected<AST::WhileLoop, Error>
     1155    Optional<UniqueRef<AST::Statement>> initialization;
     1156    if (variableDeclarations)
     1157        initialization = static_cast<UniqueRef<AST::Statement>>(makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)));
     1158    else {
     1159        PARSE(effectfulExpression, EffectfulExpression);
     1160        initialization = WTFMove(*effectfulExpression);
     1161    }
     1162
     1163    CONSUME_TYPE(semicolon, Semicolon);
     1164
     1165    Optional<UniqueRef<AST::Expression>> condition;
     1166    auto secondSemicolon = tryType(Token::Type::Semicolon);
     1167    if (!secondSemicolon) {
     1168        PARSE(expression, Expression);
     1169        condition = WTFMove(*expression);
     1170        CONSUME_TYPE(secondSemicolon, Semicolon);
     1171    } else
     1172        condition = static_cast<UniqueRef<AST::Expression>>(makeUniqueRef<AST::BooleanLiteral>(*secondSemicolon, true));
     1173
     1174    Optional<UniqueRef<AST::Expression>> increment;
     1175    auto rightParenthesis = tryType(Token::Type::RightParenthesis);
     1176    if (!rightParenthesis) {
     1177        PARSE(expression, Expression);
     1178        increment = WTFMove(*expression);
     1179        CONSUME_TYPE(rightParenthesis, RightParenthesis);
     1180    } else
     1181        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.
     1182
     1183    PARSE(body, Statement);
     1184    AST::CodeLocation location(origin->codeLocation,  (*body)->codeLocation());
     1185
     1186    auto forLoop = makeUniqueRef<AST::ForLoop>(location, WTFMove(*condition), WTFMove(*increment), WTFMove(*body));
     1187    AST::Statements statements = Vector<UniqueRef<AST::Statement>>::from(WTFMove(*initialization), WTFMove(forLoop));
     1188    return AST::Block(location, WTFMove(statements));
     1189}
     1190
     1191auto Parser::parseWhileLoop() -> Expected<AST::ForLoop, Error>
    11901192{
    11911193    CONSUME_TYPE(origin, While);
     
    11961198
    11971199    AST::CodeLocation location(origin->codeLocation,  (*body)->codeLocation());
    1198     return AST::WhileLoop(location, WTFMove(*conditional), WTFMove(*body));
     1200    auto increment = makeUniqueRef<AST::BooleanLiteral>(*origin, true); // FIXME: NullLiteral would make more sense, but is buggy right now. Anything side-effect free is fine.
     1201    return AST::ForLoop(location, WTFMove(*conditional), WTFMove(increment), WTFMove(*body));
    11991202}
    12001203
     
    12551258}
    12561259
    1257 auto Parser::parseStatement() -> Expected<UniqueRef<AST::Statement>, Error>
     1260auto Parser::parseStatement(bool allowVariableDeclarations) -> Expected<UniqueRef<AST::Statement>, Error>
    12581261{
    12591262    PEEK(token);
     
    12731276    case Token::Type::For: {
    12741277        PARSE(forLoop, ForLoop);
    1275         return { makeUniqueRef<AST::ForLoop>(WTFMove(*forLoop)) };
     1278        return { makeUniqueRef<AST::Block>(WTFMove(*forLoop)) };
    12761279    }
    12771280    case Token::Type::While: {
    12781281        PARSE(whileLoop, WhileLoop);
    1279         return { makeUniqueRef<AST::WhileLoop>(WTFMove(*whileLoop)) };
     1282        return { makeUniqueRef<AST::ForLoop>(WTFMove(*whileLoop)) };
    12801283    }
    12811284    case Token::Type::Do: {
     
    13471350
    13481351    {
    1349         auto effectfulExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> {
     1352        auto effectfulExpressionStatement = backtrackingScope<Expected<UniqueRef<AST::Statement>, Error>>([&]() -> Expected<UniqueRef<AST::Statement>, Error> {
    13501353            PARSE(result, EffectfulExpression);
    13511354            CONSUME_TYPE(semicolon, Semicolon);
    13521355            return result;
    13531356        });
    1354         if (effectfulExpression)
    1355             return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(*effectfulExpression)) };
    1356     }
    1357 
    1358     PARSE(variableDeclarations, VariableDeclarations);
    1359     CONSUME_TYPE(semicolon, Semicolon);
    1360     return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
    1361 }
    1362 
    1363 auto Parser::parseEffectfulExpression() -> Expected<UniqueRef<AST::Expression>, Error>
     1357        if (effectfulExpressionStatement)
     1358            return effectfulExpressionStatement;
     1359    }
     1360
     1361    if (allowVariableDeclarations) {
     1362        PARSE(variableDeclarations, VariableDeclarations);
     1363        CONSUME_TYPE(semicolon, Semicolon);
     1364        return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
     1365    }
     1366
     1367    return Unexpected<Error>("A variable declaration is only valid inside a block");
     1368}
     1369
     1370auto Parser::parseEffectfulExpression() -> Expected<UniqueRef<AST::Statement>, Error>
    13641371{
    13651372    PEEK(origin);
     1373    if (origin->type == Token::Type::Semicolon) {
     1374        AST::Statements statements;
     1375        return { makeUniqueRef<AST::Block>(*origin, WTFMove(statements)) };
     1376    }
     1377
    13661378    Vector<UniqueRef<AST::Expression>> expressions;
    1367     if (origin->type == Token::Type::Semicolon)
    1368         return { makeUniqueRef<AST::CommaExpression>(*origin, WTFMove(expressions)) };
    1369 
    13701379    PARSE(effectfulExpression, EffectfulAssignment);
    13711380    expressions.append(WTFMove(*effectfulExpression));
     
    13771386
    13781387    if (expressions.size() == 1)
    1379         return WTFMove(expressions[0]);
     1388        return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(expressions[0])) };
    13801389    unsigned endOffset = m_lexer.peek().startOffset();
    13811390    AST::CodeLocation location(origin->startOffset(), endOffset);
    1382     return { makeUniqueRef<AST::CommaExpression>(location, WTFMove(expressions)) };
     1391    auto expression = makeUniqueRef<AST::CommaExpression>(location, WTFMove(expressions));
     1392    return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(expression)) };
    13831393}
    13841394
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h

    r247329 r247493  
    9292#include "WHLSLVariableDeclarationsStatement.h"
    9393#include "WHLSLVariableReference.h"
    94 #include "WHLSLWhileLoop.h"
    9594#include <wtf/Expected.h>
    9695#include <wtf/Optional.h>
     
    204203    Expected<AST::SwitchStatement, Error> parseSwitchStatement();
    205204    Expected<AST::SwitchCase, Error> parseSwitchCase();
    206     Expected<AST::ForLoop, Error> parseForLoop();
    207     Expected<AST::WhileLoop, Error> parseWhileLoop();
     205    Expected<AST::Block, Error> parseForLoop();
     206    Expected<AST::ForLoop, Error> parseWhileLoop();
    208207    Expected<AST::DoWhileLoop, Error> parseDoWhileLoop();
    209208    Expected<AST::VariableDeclaration, Error> parseVariableDeclaration(UniqueRef<AST::UnnamedType>&&);
    210209    Expected<AST::VariableDeclarationsStatement, Error> parseVariableDeclarations();
    211     Expected<UniqueRef<AST::Statement>, Error> parseStatement();
    212 
    213     Expected<UniqueRef<AST::Expression>, Error> parseEffectfulExpression();
     210    Expected<UniqueRef<AST::Statement>, Error> parseStatement(bool allowVariableDeclaration = false);
     211
     212    Expected<UniqueRef<AST::Statement>, Error> parseEffectfulExpression();
    214213    Expected<UniqueRef<AST::Expression>, Error> parseEffectfulAssignment();
    215214    struct SuffixExpression {
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp

    r240230 r247493  
    4545#include "WHLSLVariableDeclarationsStatement.h"
    4646#include "WHLSLVisitor.h"
    47 #include "WHLSLWhileLoop.h"
    4847#include <cstdint>
    4948#include <wtf/OptionSet.h>
     
    110109    void visit(AST::ForLoop& forLoop) override
    111110    {
    112         // The initialization always has a behavior of Nothing, which we already add unconditionally below,
    113         // so we can just ignore the initialization.
    114 
    115111        checkErrorAndVisit(forLoop.body());
    116         if (error())
    117             return;
    118         auto b = m_stack.takeLast();
    119         b.remove(Behavior::Break);
    120         b.remove(Behavior::Continue);
    121         b.add(Behavior::Nothing);
    122         m_stack.append(b);
    123     }
    124 
    125     void visit(AST::WhileLoop& whileLoop) override
    126     {
    127         checkErrorAndVisit(whileLoop.body());
    128112        if (error())
    129113            return;
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp

    r246640 r247493  
    332332    else if (is<AST::Trap>(statement))
    333333        checkErrorAndVisit(downcast<AST::Trap>(statement));
    334     else if (is<AST::VariableDeclarationsStatement>(statement))
     334    else {
     335        ASSERT(is<AST::VariableDeclarationsStatement>(statement));
    335336        checkErrorAndVisit(downcast<AST::VariableDeclarationsStatement>(statement));
    336     else
    337         checkErrorAndVisit(downcast<AST::WhileLoop>(statement));
     337    }
    338338}
    339339
     
    428428void Visitor::visit(AST::ForLoop& forLoop)
    429429{
    430     WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) {
    431         checkErrorAndVisit(statement);
    432     }, [&](UniqueRef<AST::Expression>& expression) {
    433         checkErrorAndVisit(expression);
    434     }), forLoop.initialization());
    435     if (forLoop.condition())
    436         checkErrorAndVisit(*forLoop.condition());
    437     if (forLoop.increment())
    438         checkErrorAndVisit(*forLoop.increment());
     430    checkErrorAndVisit(forLoop.condition());
     431    checkErrorAndVisit(forLoop.increment());
    439432    checkErrorAndVisit(forLoop.body());
    440433}
     
    476469    for (auto& variableDeclaration : variableDeclarationsStatement.variableDeclarations())
    477470        checkErrorAndVisit(variableDeclaration.get());
    478 }
    479 
    480 void Visitor::visit(AST::WhileLoop& whileLoop)
    481 {
    482     checkErrorAndVisit(whileLoop.conditional());
    483     checkErrorAndVisit(whileLoop.body());
    484471}
    485472
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h

    r245945 r247493  
    8686class Trap;
    8787class VariableDeclarationsStatement;
    88 class WhileLoop;
    8988class VariableDeclaration;
    9089class AssignmentExpression;
     
    167166    virtual void visit(AST::Trap&);
    168167    virtual void visit(AST::VariableDeclarationsStatement&);
    169     virtual void visit(AST::WhileLoop&);
    170168    virtual void visit(AST::VariableDeclaration&);
    171169    virtual void visit(AST::AssignmentExpression&);
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r247472 r247493  
    1325713257                C21BF70221CD89C400227979 /* WHLSLEnumerationMemberLiteral.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLEnumerationMemberLiteral.h; sourceTree = "<group>"; };
    1325813258                C21BF70321CD89C500227979 /* WHLSLReturn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLReturn.h; sourceTree = "<group>"; };
    13259                 C21BF70421CD89C600227979 /* WHLSLWhileLoop.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLWhileLoop.h; sourceTree = "<group>"; };
    1326013259                C21BF70521CD89C700227979 /* WHLSLFunctionAttribute.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLFunctionAttribute.h; sourceTree = "<group>"; };
    1326113260                C21BF70621CD89C700227979 /* WHLSLCommaExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLCommaExpression.h; sourceTree = "<group>"; };
     
    1713317132                                C21BF71421CD89D300227979 /* WHLSLVariableDeclarationsStatement.h */,
    1713417133                                C21BF71321CD89D200227979 /* WHLSLVariableReference.h */,
    17135                                 C21BF70421CD89C600227979 /* WHLSLWhileLoop.h */,
    1713617134                        );
    1713717135                        path = AST;
Note: See TracChangeset for help on using the changeset viewer.