Remove conditional break/continue.

This CL removes the conditional forms of the break and continue
statements as they are no longer in the WGSL spec.

Change-Id: I46224d6cb5ce706cfc95d35ab0a4eea46abf62a9
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/22580
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
This commit is contained in:
dan sinclair 2020-06-03 16:11:28 +00:00
parent 27d42ede4e
commit 6bd7061a2e
24 changed files with 22 additions and 701 deletions

View File

@ -278,8 +278,6 @@ source_set("libtint_core_src") {
"src/ast/sint_literal.h", "src/ast/sint_literal.h",
"src/ast/statement.cc", "src/ast/statement.cc",
"src/ast/statement.h", "src/ast/statement.h",
"src/ast/statement_condition.cc",
"src/ast/statement_condition.h",
"src/ast/storage_class.cc", "src/ast/storage_class.cc",
"src/ast/storage_class.h", "src/ast/storage_class.h",
"src/ast/struct.cc", "src/ast/struct.cc",

View File

@ -115,8 +115,6 @@ set(TINT_LIB_SRCS
ast/sint_literal.h ast/sint_literal.h
ast/statement.cc ast/statement.cc
ast/statement.h ast/statement.h
ast/statement_condition.cc
ast/statement_condition.h
ast/storage_class.cc ast/storage_class.cc
ast/storage_class.h ast/storage_class.h
ast/struct_decoration.cc ast/struct_decoration.cc

View File

@ -21,19 +21,6 @@ BreakStatement::BreakStatement() : Statement() {}
BreakStatement::BreakStatement(const Source& source) : Statement(source) {} BreakStatement::BreakStatement(const Source& source) : Statement(source) {}
BreakStatement::BreakStatement(StatementCondition condition,
std::unique_ptr<Expression> conditional)
: Statement(),
condition_(condition),
conditional_(std::move(conditional)) {}
BreakStatement::BreakStatement(const Source& source,
StatementCondition condition,
std::unique_ptr<Expression> conditional)
: Statement(source),
condition_(condition),
conditional_(std::move(conditional)) {}
BreakStatement::BreakStatement(BreakStatement&&) = default; BreakStatement::BreakStatement(BreakStatement&&) = default;
BreakStatement::~BreakStatement() = default; BreakStatement::~BreakStatement() = default;
@ -43,26 +30,12 @@ bool BreakStatement::IsBreak() const {
} }
bool BreakStatement::IsValid() const { bool BreakStatement::IsValid() const {
if (condition_ == StatementCondition::kNone) return true;
return conditional_ == nullptr;
return conditional_ != nullptr && conditional_->IsValid();
} }
void BreakStatement::to_str(std::ostream& out, size_t indent) const { void BreakStatement::to_str(std::ostream& out, size_t indent) const {
make_indent(out, indent); make_indent(out, indent);
out << "Break{"; out << "Break{}" << std::endl;
if (condition_ != StatementCondition::kNone) {
out << std::endl;
make_indent(out, indent + 2);
out << condition_ << std::endl;
conditional_->to_str(out, indent + 2);
make_indent(out, indent);
}
out << "}" << std::endl;
} }
} // namespace ast } // namespace ast

View File

@ -15,12 +15,7 @@
#ifndef SRC_AST_BREAK_STATEMENT_H_ #ifndef SRC_AST_BREAK_STATEMENT_H_
#define SRC_AST_BREAK_STATEMENT_H_ #define SRC_AST_BREAK_STATEMENT_H_
#include <memory>
#include <utility>
#include "src/ast/expression.h"
#include "src/ast/statement.h" #include "src/ast/statement.h"
#include "src/ast/statement_condition.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
@ -33,36 +28,10 @@ class BreakStatement : public Statement {
/// Constructor /// Constructor
/// @param source the break statement source /// @param source the break statement source
explicit BreakStatement(const Source& source); explicit BreakStatement(const Source& source);
/// Constructor
/// @param condition the condition type
/// @param conditional the condition expression
BreakStatement(StatementCondition condition,
std::unique_ptr<Expression> conditional);
/// Constructor
/// @param source the break statement source
/// @param condition the condition type
/// @param conditional the condition expression
BreakStatement(const Source& source,
StatementCondition condition,
std::unique_ptr<Expression> conditional);
/// Move constructor /// Move constructor
BreakStatement(BreakStatement&&); BreakStatement(BreakStatement&&);
~BreakStatement() override; ~BreakStatement() override;
/// Sets the condition type
/// @param condition the condition type
void set_condition(StatementCondition condition) { condition_ = condition; }
/// @returns the condition type
StatementCondition condition() const { return condition_; }
/// Sets the conditional expression
/// @param conditional the conditional expression
void set_conditional(std::unique_ptr<Expression> conditional) {
conditional_ = std::move(conditional);
}
/// @returns the conditional expression
Expression* conditional() const { return conditional_.get(); }
/// @returns true if this is an break statement /// @returns true if this is an break statement
bool IsBreak() const override; bool IsBreak() const override;
@ -76,9 +45,6 @@ class BreakStatement : public Statement {
private: private:
BreakStatement(const BreakStatement&) = delete; BreakStatement(const BreakStatement&) = delete;
StatementCondition condition_ = StatementCondition::kNone;
std::unique_ptr<Expression> conditional_;
}; };
} // namespace ast } // namespace ast

View File

@ -15,8 +15,6 @@
#include "src/ast/break_statement.h" #include "src/ast/break_statement.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/statement_condition.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
@ -24,21 +22,6 @@ namespace {
using BreakStatementTest = testing::Test; using BreakStatementTest = testing::Test;
TEST_F(BreakStatementTest, Creation) {
BreakStatement stmt;
EXPECT_EQ(stmt.condition(), StatementCondition::kNone);
EXPECT_EQ(stmt.conditional(), nullptr);
}
TEST_F(BreakStatementTest, CreationWithConditional) {
auto expr = std::make_unique<IdentifierExpression>("expr");
auto* expr_ptr = expr.get();
BreakStatement stmt(StatementCondition::kIf, std::move(expr));
EXPECT_EQ(stmt.condition(), StatementCondition::kIf);
EXPECT_EQ(stmt.conditional(), expr_ptr);
}
TEST_F(BreakStatementTest, Creation_WithSource) { TEST_F(BreakStatementTest, Creation_WithSource) {
BreakStatement stmt(Source{20, 2}); BreakStatement stmt(Source{20, 2});
auto src = stmt.source(); auto src = stmt.source();
@ -46,51 +29,17 @@ TEST_F(BreakStatementTest, Creation_WithSource) {
EXPECT_EQ(src.column, 2u); EXPECT_EQ(src.column, 2u);
} }
TEST_F(BreakStatementTest, Creation_WithSourceAndCondition) {
auto expr = std::make_unique<IdentifierExpression>("expr");
BreakStatement stmt(Source{20, 2}, StatementCondition::kUnless,
std::move(expr));
auto src = stmt.source();
EXPECT_EQ(src.line, 20u);
EXPECT_EQ(src.column, 2u);
}
TEST_F(BreakStatementTest, IsBreak) { TEST_F(BreakStatementTest, IsBreak) {
BreakStatement stmt; BreakStatement stmt;
EXPECT_TRUE(stmt.IsBreak()); EXPECT_TRUE(stmt.IsBreak());
} }
TEST_F(BreakStatementTest, IsValid_WithoutCondition) { TEST_F(BreakStatementTest, IsValid) {
BreakStatement stmt; BreakStatement stmt;
EXPECT_TRUE(stmt.IsValid()); EXPECT_TRUE(stmt.IsValid());
} }
TEST_F(BreakStatementTest, IsValid_WithCondition) { TEST_F(BreakStatementTest, ToStr) {
auto expr = std::make_unique<IdentifierExpression>("expr");
BreakStatement stmt(StatementCondition::kIf, std::move(expr));
EXPECT_TRUE(stmt.IsValid());
}
TEST_F(BreakStatementTest, IsValid_WithConditionAndConditionNone) {
auto expr = std::make_unique<IdentifierExpression>("expr");
BreakStatement stmt(StatementCondition::kNone, std::move(expr));
EXPECT_FALSE(stmt.IsValid());
}
TEST_F(BreakStatementTest, IsValid_WithCondition_MissingConditional) {
BreakStatement stmt;
stmt.set_condition(StatementCondition::kIf);
EXPECT_FALSE(stmt.IsValid());
}
TEST_F(BreakStatementTest, IsValid_InvalidConditional) {
auto expr = std::make_unique<IdentifierExpression>("");
BreakStatement stmt(StatementCondition::kIf, std::move(expr));
EXPECT_FALSE(stmt.IsValid());
}
TEST_F(BreakStatementTest, ToStr_WithoutCondition) {
BreakStatement stmt; BreakStatement stmt;
std::ostringstream out; std::ostringstream out;
stmt.to_str(out, 2); stmt.to_str(out, 2);
@ -98,18 +47,6 @@ TEST_F(BreakStatementTest, ToStr_WithoutCondition) {
)"); )");
} }
TEST_F(BreakStatementTest, ToStr_WithCondition) {
auto expr = std::make_unique<IdentifierExpression>("expr");
BreakStatement stmt(StatementCondition::kUnless, std::move(expr));
std::ostringstream out;
stmt.to_str(out, 2);
EXPECT_EQ(out.str(), R"( Break{
unless
Identifier{expr}
}
)");
}
} // namespace } // namespace
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -22,19 +22,6 @@ ContinueStatement::ContinueStatement() : Statement() {}
ContinueStatement::ContinueStatement(const Source& source) ContinueStatement::ContinueStatement(const Source& source)
: Statement(source) {} : Statement(source) {}
ContinueStatement::ContinueStatement(StatementCondition condition,
std::unique_ptr<Expression> conditional)
: Statement(),
condition_(condition),
conditional_(std::move(conditional)) {}
ContinueStatement::ContinueStatement(const Source& source,
StatementCondition condition,
std::unique_ptr<Expression> conditional)
: Statement(source),
condition_(condition),
conditional_(std::move(conditional)) {}
ContinueStatement::ContinueStatement(ContinueStatement&&) = default; ContinueStatement::ContinueStatement(ContinueStatement&&) = default;
ContinueStatement::~ContinueStatement() = default; ContinueStatement::~ContinueStatement() = default;
@ -44,26 +31,12 @@ bool ContinueStatement::IsContinue() const {
} }
bool ContinueStatement::IsValid() const { bool ContinueStatement::IsValid() const {
if (condition_ == StatementCondition::kNone) return true;
return conditional_ == nullptr;
return conditional_ && conditional_->IsValid();
} }
void ContinueStatement::to_str(std::ostream& out, size_t indent) const { void ContinueStatement::to_str(std::ostream& out, size_t indent) const {
make_indent(out, indent); make_indent(out, indent);
out << "Continue{"; out << "Continue{}" << std::endl;
if (condition_ != StatementCondition::kNone) {
out << std::endl;
make_indent(out, indent + 2);
out << condition_ << std::endl;
conditional_->to_str(out, indent + 2);
make_indent(out, indent);
}
out << "}" << std::endl;
} }
} // namespace ast } // namespace ast

View File

@ -18,9 +18,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "src/ast/expression.h"
#include "src/ast/statement.h" #include "src/ast/statement.h"
#include "src/ast/statement_condition.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
@ -33,36 +31,10 @@ class ContinueStatement : public Statement {
/// Constructor /// Constructor
/// @param source the continue statement source /// @param source the continue statement source
explicit ContinueStatement(const Source& source); explicit ContinueStatement(const Source& source);
/// Constructor
/// @param condition the condition type
/// @param conditional the condition expression
ContinueStatement(StatementCondition condition,
std::unique_ptr<Expression> conditional);
/// Constructor
/// @param source the continue statement source
/// @param condition the condition type
/// @param conditional the condition expression
ContinueStatement(const Source& source,
StatementCondition condition,
std::unique_ptr<Expression> conditional);
/// Move constructor /// Move constructor
ContinueStatement(ContinueStatement&&); ContinueStatement(ContinueStatement&&);
~ContinueStatement() override; ~ContinueStatement() override;
/// Sets the condition type
/// @param condition the condition type
void set_condition(StatementCondition condition) { condition_ = condition; }
/// @returns the condition type
StatementCondition condition() const { return condition_; }
/// Sets the conditional expression
/// @param conditional the conditional expression
void set_conditional(std::unique_ptr<Expression> conditional) {
conditional_ = std::move(conditional);
}
/// @returns the conditional expression
Expression* conditional() const { return conditional_.get(); }
/// @returns true if this is an continue statement /// @returns true if this is an continue statement
bool IsContinue() const override; bool IsContinue() const override;
@ -76,9 +48,6 @@ class ContinueStatement : public Statement {
private: private:
ContinueStatement(const ContinueStatement&) = delete; ContinueStatement(const ContinueStatement&) = delete;
StatementCondition condition_ = StatementCondition::kNone;
std::unique_ptr<Expression> conditional_;
}; };
} // namespace ast } // namespace ast

View File

@ -15,8 +15,6 @@
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/statement_condition.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
@ -24,21 +22,6 @@ namespace {
using ContinueStatementTest = testing::Test; using ContinueStatementTest = testing::Test;
TEST_F(ContinueStatementTest, Creation) {
ContinueStatement stmt;
EXPECT_EQ(stmt.condition(), StatementCondition::kNone);
EXPECT_EQ(stmt.conditional(), nullptr);
}
TEST_F(ContinueStatementTest, CreationWithConditional) {
auto expr = std::make_unique<IdentifierExpression>("expr");
auto* expr_ptr = expr.get();
ContinueStatement stmt(StatementCondition::kIf, std::move(expr));
EXPECT_EQ(stmt.condition(), StatementCondition::kIf);
EXPECT_EQ(stmt.conditional(), expr_ptr);
}
TEST_F(ContinueStatementTest, Creation_WithSource) { TEST_F(ContinueStatementTest, Creation_WithSource) {
ContinueStatement stmt(Source{20, 2}); ContinueStatement stmt(Source{20, 2});
auto src = stmt.source(); auto src = stmt.source();
@ -46,51 +29,17 @@ TEST_F(ContinueStatementTest, Creation_WithSource) {
EXPECT_EQ(src.column, 2u); EXPECT_EQ(src.column, 2u);
} }
TEST_F(ContinueStatementTest, Creation_WithSourceAndCondition) {
auto expr = std::make_unique<IdentifierExpression>("expr");
ContinueStatement stmt(Source{20, 2}, StatementCondition::kUnless,
std::move(expr));
auto src = stmt.source();
EXPECT_EQ(src.line, 20u);
EXPECT_EQ(src.column, 2u);
}
TEST_F(ContinueStatementTest, IsContinue) { TEST_F(ContinueStatementTest, IsContinue) {
ContinueStatement stmt; ContinueStatement stmt;
EXPECT_TRUE(stmt.IsContinue()); EXPECT_TRUE(stmt.IsContinue());
} }
TEST_F(ContinueStatementTest, IsValid_WithoutCondition) { TEST_F(ContinueStatementTest, IsValid) {
ContinueStatement stmt; ContinueStatement stmt;
EXPECT_TRUE(stmt.IsValid()); EXPECT_TRUE(stmt.IsValid());
} }
TEST_F(ContinueStatementTest, IsValid_WithCondition) { TEST_F(ContinueStatementTest, ToStr) {
auto expr = std::make_unique<IdentifierExpression>("expr");
ContinueStatement stmt(StatementCondition::kIf, std::move(expr));
EXPECT_TRUE(stmt.IsValid());
}
TEST_F(ContinueStatementTest, IsValid_InvalidConditional) {
auto expr = std::make_unique<IdentifierExpression>("");
ContinueStatement stmt(StatementCondition::kIf, std::move(expr));
EXPECT_FALSE(stmt.IsValid());
}
TEST_F(ContinueStatementTest, IsValid_NoneConditionWithConditional) {
auto expr = std::make_unique<IdentifierExpression>("expr");
ContinueStatement stmt(StatementCondition::kNone, std::move(expr));
EXPECT_FALSE(stmt.IsValid());
}
TEST_F(ContinueStatementTest, IsValid_WithCondition_MissingConditional) {
ContinueStatement stmt;
stmt.set_condition(StatementCondition::kIf);
EXPECT_FALSE(stmt.IsValid());
}
TEST_F(ContinueStatementTest, ToStr_WithoutCondition) {
ContinueStatement stmt; ContinueStatement stmt;
std::ostringstream out; std::ostringstream out;
stmt.to_str(out, 2); stmt.to_str(out, 2);
@ -98,18 +47,6 @@ TEST_F(ContinueStatementTest, ToStr_WithoutCondition) {
)"); )");
} }
TEST_F(ContinueStatementTest, ToStr_WithCondition) {
auto expr = std::make_unique<IdentifierExpression>("expr");
ContinueStatement stmt(StatementCondition::kUnless, std::move(expr));
std::ostringstream out;
stmt.to_str(out, 2);
EXPECT_EQ(out.str(), R"( Continue{
unless
Identifier{expr}
}
)");
}
} // namespace } // namespace
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -15,9 +15,7 @@
#ifndef SRC_AST_FALLTHROUGH_STATEMENT_H_ #ifndef SRC_AST_FALLTHROUGH_STATEMENT_H_
#define SRC_AST_FALLTHROUGH_STATEMENT_H_ #define SRC_AST_FALLTHROUGH_STATEMENT_H_
#include "src/ast/expression.h"
#include "src/ast/statement.h" #include "src/ast/statement.h"
#include "src/ast/statement_condition.h"
namespace tint { namespace tint {
namespace ast { namespace ast {

View File

@ -1,37 +0,0 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/ast/statement_condition.h"
namespace tint {
namespace ast {
std::ostream& operator<<(std::ostream& out, StatementCondition condition) {
switch (condition) {
case StatementCondition::kNone:
out << "none";
break;
case StatementCondition::kIf:
out << "if";
break;
case StatementCondition::kUnless:
out << "unless";
break;
}
return out;
}
} // namespace ast
} // namespace tint

View File

@ -1,31 +0,0 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_AST_STATEMENT_CONDITION_H_
#define SRC_AST_STATEMENT_CONDITION_H_
#include <ostream>
namespace tint {
namespace ast {
/// Type of condition attached to a statement
enum class StatementCondition { kNone = 0, kIf, kUnless };
std::ostream& operator<<(std::ostream& out, StatementCondition condition);
} // namespace ast
} // namespace tint
#endif // SRC_AST_STATEMENT_CONDITION_H_

View File

@ -22,7 +22,6 @@
#include "src/ast/expression.h" #include "src/ast/expression.h"
#include "src/ast/literal.h" #include "src/ast/literal.h"
#include "src/ast/statement.h" #include "src/ast/statement.h"
#include "src/ast/statement_condition.h"
namespace tint { namespace tint {
namespace ast { namespace ast {

View File

@ -41,7 +41,6 @@
#include "src/ast/scalar_constructor_expression.h" #include "src/ast/scalar_constructor_expression.h"
#include "src/ast/set_decoration.h" #include "src/ast/set_decoration.h"
#include "src/ast/sint_literal.h" #include "src/ast/sint_literal.h"
#include "src/ast/statement_condition.h"
#include "src/ast/struct_member_offset_decoration.h" #include "src/ast/struct_member_offset_decoration.h"
#include "src/ast/switch_statement.h" #include "src/ast/switch_statement.h"
#include "src/ast/type/alias_type.h" #include "src/ast/type/alias_type.h"
@ -1943,73 +1942,25 @@ std::unique_ptr<ast::LoopStatement> ParserImpl::loop_stmt() {
} }
// break_stmt // break_stmt
// : BREAK ({IF | UNLESS} paren_rhs_stmt)? // : BREAK
std::unique_ptr<ast::BreakStatement> ParserImpl::break_stmt() { std::unique_ptr<ast::BreakStatement> ParserImpl::break_stmt() {
auto t = peek(); auto t = peek();
if (!t.IsBreak()) if (!t.IsBreak())
return nullptr; return nullptr;
auto source = t.source();
next(); // Consume the peek next(); // Consume the peek
return std::make_unique<ast::BreakStatement>(t.source());
ast::StatementCondition condition = ast::StatementCondition::kNone;
std::unique_ptr<ast::Expression> conditional = nullptr;
t = peek();
if (t.IsIf() || t.IsUnless()) {
next(); // Consume the peek
if (t.IsIf())
condition = ast::StatementCondition::kIf;
else
condition = ast::StatementCondition::kUnless;
conditional = paren_rhs_stmt();
if (has_error())
return nullptr;
if (conditional == nullptr) {
set_error(peek(), "unable to parse conditional statement");
return nullptr;
}
}
return std::make_unique<ast::BreakStatement>(source, condition,
std::move(conditional));
} }
// continue_stmt // continue_stmt
// : CONTINUE ({IF | UNLESS} paren_rhs_stmt)? // : CONTINUE
std::unique_ptr<ast::ContinueStatement> ParserImpl::continue_stmt() { std::unique_ptr<ast::ContinueStatement> ParserImpl::continue_stmt() {
auto t = peek(); auto t = peek();
if (!t.IsContinue()) if (!t.IsContinue())
return nullptr; return nullptr;
auto source = t.source();
next(); // Consume the peek next(); // Consume the peek
return std::make_unique<ast::ContinueStatement>(t.source());
ast::StatementCondition condition = ast::StatementCondition::kNone;
std::unique_ptr<ast::Expression> conditional = nullptr;
t = peek();
if (t.IsIf() || t.IsUnless()) {
next(); // Consume the peek
if (t.IsIf())
condition = ast::StatementCondition::kIf;
else
condition = ast::StatementCondition::kUnless;
conditional = paren_rhs_stmt();
if (has_error())
return nullptr;
if (conditional == nullptr) {
set_error(peek(), "unable to parse conditional statement");
return nullptr;
}
}
return std::make_unique<ast::ContinueStatement>(source, condition,
std::move(conditional));
} }
// continuing_stmt // continuing_stmt

View File

@ -14,8 +14,6 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/break_statement.h" #include "src/ast/break_statement.h"
#include "src/ast/return_statement.h"
#include "src/ast/statement.h"
#include "src/reader/wgsl/parser_impl.h" #include "src/reader/wgsl/parser_impl.h"
#include "src/reader/wgsl/parser_impl_test_helper.h" #include "src/reader/wgsl/parser_impl_test_helper.h"
@ -30,46 +28,6 @@ TEST_F(ParserImplTest, BreakStmt) {
ASSERT_FALSE(p->has_error()) << p->error(); ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e, nullptr); ASSERT_NE(e, nullptr);
ASSERT_TRUE(e->IsBreak()); ASSERT_TRUE(e->IsBreak());
EXPECT_EQ(e->condition(), ast::StatementCondition::kNone);
EXPECT_EQ(e->conditional(), nullptr);
}
TEST_F(ParserImplTest, BreakStmt_WithIf) {
auto* p = parser("break if (a == b)");
auto e = p->break_stmt();
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e, nullptr);
ASSERT_TRUE(e->IsBreak());
EXPECT_EQ(e->condition(), ast::StatementCondition::kIf);
ASSERT_NE(e->conditional(), nullptr);
EXPECT_TRUE(e->conditional()->IsBinary());
}
TEST_F(ParserImplTest, BreakStmt_WithUnless) {
auto* p = parser("break unless (a == b)");
auto e = p->break_stmt();
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e, nullptr);
ASSERT_TRUE(e->IsBreak());
EXPECT_EQ(e->condition(), ast::StatementCondition::kUnless);
ASSERT_NE(e->conditional(), nullptr);
EXPECT_TRUE(e->conditional()->IsBinary());
}
TEST_F(ParserImplTest, BreakStmt_InvalidRHS) {
auto* p = parser("break if (a = b)");
auto e = p->break_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:13: expected )");
}
TEST_F(ParserImplTest, BreakStmt_MissingRHS) {
auto* p = parser("break if");
auto e = p->break_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:9: expected (");
} }
} // namespace } // namespace

View File

@ -14,8 +14,6 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/return_statement.h"
#include "src/ast/statement.h"
#include "src/reader/wgsl/parser_impl.h" #include "src/reader/wgsl/parser_impl.h"
#include "src/reader/wgsl/parser_impl_test_helper.h" #include "src/reader/wgsl/parser_impl_test_helper.h"
@ -30,46 +28,6 @@ TEST_F(ParserImplTest, ContinueStmt) {
ASSERT_FALSE(p->has_error()) << p->error(); ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e, nullptr); ASSERT_NE(e, nullptr);
ASSERT_TRUE(e->IsContinue()); ASSERT_TRUE(e->IsContinue());
EXPECT_EQ(e->condition(), ast::StatementCondition::kNone);
EXPECT_EQ(e->conditional(), nullptr);
}
TEST_F(ParserImplTest, ContinueStmt_WithIf) {
auto* p = parser("continue if (a == b)");
auto e = p->continue_stmt();
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e, nullptr);
ASSERT_TRUE(e->IsContinue());
EXPECT_EQ(e->condition(), ast::StatementCondition::kIf);
ASSERT_NE(e->conditional(), nullptr);
EXPECT_TRUE(e->conditional()->IsBinary());
}
TEST_F(ParserImplTest, ContinueStmt_WithUnless) {
auto* p = parser("continue unless (a == b)");
auto e = p->continue_stmt();
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e, nullptr);
ASSERT_TRUE(e->IsContinue());
EXPECT_EQ(e->condition(), ast::StatementCondition::kUnless);
ASSERT_NE(e->conditional(), nullptr);
EXPECT_TRUE(e->conditional()->IsBinary());
}
TEST_F(ParserImplTest, ContinueStmt_InvalidRHS) {
auto* p = parser("continue if (a = b)");
auto e = p->continue_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:16: expected )");
}
TEST_F(ParserImplTest, ContinueStmt_MissingRHS) {
auto* p = parser("continue if");
auto e = p->continue_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:12: expected (");
} }
} // namespace } // namespace

View File

@ -197,20 +197,12 @@ TEST_F(ParserImplTest, Statement_Break) {
EXPECT_TRUE(e->IsBreak()); EXPECT_TRUE(e->IsBreak());
} }
TEST_F(ParserImplTest, Statement_Break_Invalid) {
auto* p = parser("break if (a = b);");
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:13: expected )");
}
TEST_F(ParserImplTest, Statement_Break_MissingSemicolon) { TEST_F(ParserImplTest, Statement_Break_MissingSemicolon) {
auto* p = parser("break if (a == b)"); auto* p = parser("break");
auto e = p->statement(); auto e = p->statement();
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr); ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:18: missing ;"); EXPECT_EQ(p->error(), "1:6: missing ;");
} }
TEST_F(ParserImplTest, Statement_Continue) { TEST_F(ParserImplTest, Statement_Continue) {
@ -221,20 +213,12 @@ TEST_F(ParserImplTest, Statement_Continue) {
EXPECT_TRUE(e->IsContinue()); EXPECT_TRUE(e->IsContinue());
} }
TEST_F(ParserImplTest, Statement_Continue_Invalid) {
auto* p = parser("continue if (a = b);");
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:16: expected )");
}
TEST_F(ParserImplTest, Statement_Continue_MissingSemicolon) { TEST_F(ParserImplTest, Statement_Continue_MissingSemicolon) {
auto* p = parser("continue if (a == b)"); auto* p = parser("continue");
auto e = p->statement(); auto e = p->statement();
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr); ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:21: missing ;"); EXPECT_EQ(p->error(), "1:9: missing ;");
} }
TEST_F(ParserImplTest, Statement_Kill) { TEST_F(ParserImplTest, Statement_Kill) {

View File

@ -159,16 +159,14 @@ bool TypeDeterminer::DetermineResultType(ast::Statement* stmt) {
return DetermineResultType(a->lhs()) && DetermineResultType(a->rhs()); return DetermineResultType(a->lhs()) && DetermineResultType(a->rhs());
} }
if (stmt->IsBreak()) { if (stmt->IsBreak()) {
auto* b = stmt->AsBreak(); return true;
return DetermineResultType(b->conditional());
} }
if (stmt->IsCase()) { if (stmt->IsCase()) {
auto* c = stmt->AsCase(); auto* c = stmt->AsCase();
return DetermineStatements(c->body()); return DetermineStatements(c->body());
} }
if (stmt->IsContinue()) { if (stmt->IsContinue()) {
auto* c = stmt->AsContinue(); return true;
return DetermineResultType(c->conditional());
} }
if (stmt->IsElse()) { if (stmt->IsElse()) {
auto* e = stmt->AsElse(); auto* e = stmt->AsElse();

View File

@ -129,26 +129,6 @@ TEST_F(TypeDeterminerTest, Stmt_Assign) {
EXPECT_TRUE(rhs_ptr->result_type()->IsF32()); EXPECT_TRUE(rhs_ptr->result_type()->IsF32());
} }
TEST_F(TypeDeterminerTest, Stmt_Break) {
ast::type::I32Type i32;
auto cond = std::make_unique<ast::ScalarConstructorExpression>(
std::make_unique<ast::SintLiteral>(&i32, 2));
auto* cond_ptr = cond.get();
ast::BreakStatement brk(ast::StatementCondition::kIf, std::move(cond));
EXPECT_TRUE(td()->DetermineResultType(&brk));
ASSERT_NE(cond_ptr->result_type(), nullptr);
EXPECT_TRUE(cond_ptr->result_type()->IsI32());
}
TEST_F(TypeDeterminerTest, Stmt_Break_WithoutCondition) {
ast::type::I32Type i32;
ast::BreakStatement brk;
EXPECT_TRUE(td()->DetermineResultType(&brk));
}
TEST_F(TypeDeterminerTest, Stmt_Case) { TEST_F(TypeDeterminerTest, Stmt_Case) {
ast::type::I32Type i32; ast::type::I32Type i32;
ast::type::F32Type f32; ast::type::F32Type f32;
@ -176,26 +156,6 @@ TEST_F(TypeDeterminerTest, Stmt_Case) {
EXPECT_TRUE(rhs_ptr->result_type()->IsF32()); EXPECT_TRUE(rhs_ptr->result_type()->IsF32());
} }
TEST_F(TypeDeterminerTest, Stmt_Continue) {
ast::type::I32Type i32;
auto cond = std::make_unique<ast::ScalarConstructorExpression>(
std::make_unique<ast::SintLiteral>(&i32, 2));
auto* cond_ptr = cond.get();
ast::ContinueStatement stmt(ast::StatementCondition::kIf, std::move(cond));
EXPECT_TRUE(td()->DetermineResultType(&stmt));
ASSERT_NE(cond_ptr->result_type(), nullptr);
EXPECT_TRUE(cond_ptr->result_type()->IsI32());
}
TEST_F(TypeDeterminerTest, Stmt_Continue_WithoutStatement) {
ast::type::I32Type i32;
ast::ContinueStatement stmt;
EXPECT_TRUE(td()->DetermineResultType(&stmt));
}
TEST_F(TypeDeterminerTest, Stmt_Else) { TEST_F(TypeDeterminerTest, Stmt_Else) {
ast::type::I32Type i32; ast::type::I32Type i32;
ast::type::F32Type f32; ast::type::F32Type f32;

View File

@ -26,7 +26,6 @@
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/scalar_constructor_expression.h" #include "src/ast/scalar_constructor_expression.h"
#include "src/ast/sint_literal.h" #include "src/ast/sint_literal.h"
#include "src/ast/statement_condition.h"
#include "src/ast/type/bool_type.h" #include "src/ast/type/bool_type.h"
#include "src/ast/type/i32_type.h" #include "src/ast/type/i32_type.h"
#include "src/context.h" #include "src/context.h"
@ -488,67 +487,6 @@ OpBranch %1
)"); )");
} }
// This is blocked on implementing conditional break
TEST_F(BuilderTest, DISABLED_If_WithConditionalBreak) {
ast::type::BoolType bool_type;
// loop {
// if (true) {
// break if (false);
// }
// }
auto cond_true = std::make_unique<ast::ScalarConstructorExpression>(
std::make_unique<ast::BoolLiteral>(&bool_type, true));
auto cond_false = std::make_unique<ast::ScalarConstructorExpression>(
std::make_unique<ast::BoolLiteral>(&bool_type, false));
ast::StatementList if_body;
if_body.push_back(std::make_unique<ast::BreakStatement>(
ast::StatementCondition::kIf, std::move(cond_false)));
auto if_stmt = std::make_unique<ast::IfStatement>(std::move(cond_true),
std::move(if_body));
ast::StatementList loop_body;
loop_body.push_back(std::move(if_stmt));
ast::LoopStatement expr(std::move(loop_body), {});
Context ctx;
ast::Module mod;
TypeDeterminer td(&ctx, &mod);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
Builder b(&mod);
b.push_function(Function{});
EXPECT_TRUE(b.GenerateLoopStatement(&expr)) << b.error();
EXPECT_EQ(DumpInstructions(b.types()), R"(%5 = OpTypeBool
%6 = OpConstantTrue %5
%7 = OpConstantFalse %5
)");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
R"(OpBranch %1
%1 = OpLabel
OpLoopMerge %2 %3 None
OpBranch %4
%4 = OpLabel
OpSelectionMerge %8 None
OpBranchConditional %6 %9 %8
%9 = OpLabel
OpBranchConditional %7 %2 %8
%8 = OpLabel
OpBranch %3
%3 = OpLabel
OpBranch %1
%2 = OpLabel
)");
}
TEST_F(BuilderTest, DISABLED_If_WithElseConditionalBreak) {
FAIL();
}
TEST_F(BuilderTest, If_WithContinue) { TEST_F(BuilderTest, If_WithContinue) {
ast::type::BoolType bool_type; ast::type::BoolType bool_type;
// loop { // loop {
@ -601,10 +539,6 @@ OpBranch %1
)"); )");
} }
TEST_F(BuilderTest, DISABLED_If_WithConditionalContinue) {
FAIL();
}
TEST_F(BuilderTest, If_WithElseContinue) { TEST_F(BuilderTest, If_WithElseContinue) {
ast::type::BoolType bool_type; ast::type::BoolType bool_type;
// loop { // loop {
@ -666,10 +600,6 @@ OpBranch %1
)"); )");
} }
TEST_F(BuilderTest, DISABLED_If_WithElseConditionalContinue) {
FAIL();
}
TEST_F(BuilderTest, If_WithReturn) { TEST_F(BuilderTest, If_WithReturn) {
ast::type::BoolType bool_type; ast::type::BoolType bool_type;
// if (true) { // if (true) {

View File

@ -202,8 +202,6 @@ OpBranch %1
)"); )");
} }
TEST_F(BuilderTest, DISABLED_Loop_WithConditionalContinue) {}
TEST_F(BuilderTest, Loop_WithBreak) { TEST_F(BuilderTest, Loop_WithBreak) {
// loop { // loop {
// break; // break;
@ -236,8 +234,6 @@ OpBranch %1
)"); )");
} }
TEST_F(BuilderTest, DISABLED_Loop_WithConditionalBreak) {}
} // namespace } // namespace
} // namespace spirv } // namespace spirv
} // namespace writer } // namespace writer

View File

@ -472,16 +472,6 @@ TEST_F(BuilderTest, Switch_CaseFallthroughLastStatement) {
EXPECT_EQ(b.error(), "fallthrough of last case statement is disallowed"); EXPECT_EQ(b.error(), "fallthrough of last case statement is disallowed");
} }
// TODO(dsinclair): Implement when parsing is handled for multi-value
// case labels.
TEST_F(BuilderTest, DISABLED_Switch_CaseWithMulitpleLabels) {
// switch (a) {
// case 1, 2, 3:
// v = 1;
// }
FAIL();
}
TEST_F(BuilderTest, Switch_WithNestedBreak) { TEST_F(BuilderTest, Switch_WithNestedBreak) {
ast::type::I32Type i32; ast::type::I32Type i32;
ast::type::BoolType bool_type; ast::type::BoolType bool_type;

View File

@ -691,28 +691,9 @@ bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) {
return true; return true;
} }
bool GeneratorImpl::EmitBreak(ast::BreakStatement* stmt) { bool GeneratorImpl::EmitBreak(ast::BreakStatement*) {
make_indent(); make_indent();
out_ << "break;" << std::endl;
out_ << "break";
if (stmt->condition() != ast::StatementCondition::kNone) {
out_ << " ";
if (stmt->condition() == ast::StatementCondition::kIf) {
out_ << "if";
} else {
out_ << "unless";
}
out_ << " (";
if (!EmitExpression(stmt->conditional())) {
return false;
}
out_ << ")";
}
out_ << ";" << std::endl;
return true; return true;
} }
@ -742,28 +723,9 @@ bool GeneratorImpl::EmitCase(ast::CaseStatement* stmt) {
return EmitStatementBlockAndNewline(stmt->body()); return EmitStatementBlockAndNewline(stmt->body());
} }
bool GeneratorImpl::EmitContinue(ast::ContinueStatement* stmt) { bool GeneratorImpl::EmitContinue(ast::ContinueStatement*) {
make_indent(); make_indent();
out_ << "continue;" << std::endl;
out_ << "continue";
if (stmt->condition() != ast::StatementCondition::kNone) {
out_ << " ";
if (stmt->condition() == ast::StatementCondition::kIf) {
out_ << "if";
} else {
out_ << "unless";
}
out_ << " (";
if (!EmitExpression(stmt->conditional())) {
return false;
}
out_ << ")";
}
out_ << ";" << std::endl;
return true; return true;
} }

View File

@ -17,7 +17,6 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/break_statement.h" #include "src/ast/break_statement.h"
#include "src/ast/identifier_expression.h"
#include "src/writer/wgsl/generator_impl.h" #include "src/writer/wgsl/generator_impl.h"
namespace tint { namespace tint {
@ -37,28 +36,6 @@ TEST_F(GeneratorImplTest, Emit_Break) {
EXPECT_EQ(g.result(), " break;\n"); EXPECT_EQ(g.result(), " break;\n");
} }
TEST_F(GeneratorImplTest, Emit_BreakWithIf) {
auto expr = std::make_unique<ast::IdentifierExpression>("expr");
ast::BreakStatement b(ast::StatementCondition::kIf, std::move(expr));
GeneratorImpl g;
g.increment_indent();
ASSERT_TRUE(g.EmitStatement(&b)) << g.error();
EXPECT_EQ(g.result(), " break if (expr);\n");
}
TEST_F(GeneratorImplTest, Emit_BreakWithUnless) {
auto expr = std::make_unique<ast::IdentifierExpression>("expr");
ast::BreakStatement b(ast::StatementCondition::kUnless, std::move(expr));
GeneratorImpl g;
g.increment_indent();
ASSERT_TRUE(g.EmitStatement(&b)) << g.error();
EXPECT_EQ(g.result(), " break unless (expr);\n");
}
} // namespace } // namespace
} // namespace wgsl } // namespace wgsl
} // namespace writer } // namespace writer

View File

@ -17,7 +17,6 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/identifier_expression.h"
#include "src/writer/wgsl/generator_impl.h" #include "src/writer/wgsl/generator_impl.h"
namespace tint { namespace tint {
@ -37,28 +36,6 @@ TEST_F(GeneratorImplTest, Emit_Continue) {
EXPECT_EQ(g.result(), " continue;\n"); EXPECT_EQ(g.result(), " continue;\n");
} }
TEST_F(GeneratorImplTest, Emit_ContinueWithIf) {
auto expr = std::make_unique<ast::IdentifierExpression>("expr");
ast::ContinueStatement c(ast::StatementCondition::kIf, std::move(expr));
GeneratorImpl g;
g.increment_indent();
ASSERT_TRUE(g.EmitStatement(&c)) << g.error();
EXPECT_EQ(g.result(), " continue if (expr);\n");
}
TEST_F(GeneratorImplTest, Emit_ContinueWithUnless) {
auto expr = std::make_unique<ast::IdentifierExpression>("expr");
ast::ContinueStatement c(ast::StatementCondition::kUnless, std::move(expr));
GeneratorImpl g;
g.increment_indent();
ASSERT_TRUE(g.EmitStatement(&c)) << g.error();
EXPECT_EQ(g.result(), " continue unless (expr);\n");
}
} // namespace } // namespace
} // namespace wgsl } // namespace wgsl
} // namespace writer } // namespace writer