wgsl: Replace 'elseif' with 'else if'
Bug: tint:1289
Change-Id: I72432391e60cf5ff173aa51a6d4a2bc8ef58fbf2
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/75240
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/docs/origin-trial-changes.md b/docs/origin-trial-changes.md
index 4acefa6..ef7731a 100644
--- a/docs/origin-trial-changes.md
+++ b/docs/origin-trial-changes.md
@@ -4,7 +4,10 @@
### Deprecated Features
-* The `[[block]]` attribute has been deprecated and will be removed in M102. [tint:1324](https://crbug.com/tint/1324)
+The following features have been deprecated and will be removed in M102:
+
+* The `[[block]]` attribute has been deprecated. [tint:1324](https://crbug.com/tint/1324)
+* `elseif` has been replaced with `else if` [tint:1289](https://crbug.com/tint/1289)
### New Features
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 10aeea6..62fd9fc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -826,7 +826,6 @@
reader/wgsl/parser_impl_continuing_stmt_test.cc
reader/wgsl/parser_impl_depth_texture_type_test.cc
reader/wgsl/parser_impl_external_texture_type_test.cc
- reader/wgsl/parser_impl_else_stmt_test.cc
reader/wgsl/parser_impl_elseif_stmt_test.cc
reader/wgsl/parser_impl_equality_expression_test.cc
reader/wgsl/parser_impl_error_msg_test.cc
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 9112b18..17a5e5f 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -1540,7 +1540,7 @@
}
// body_stmt
-// : BRACKET_LEFT statements BRACKET_RIGHT
+// : BRACE_LEFT statements BRACE_RIGHT
Expect<ast::BlockStatement*> ParserImpl::expect_body_stmt() {
return expect_brace_block("", [&]() -> Expect<ast::BlockStatement*> {
auto stmts = expect_statements();
@@ -1791,7 +1791,7 @@
}
// if_stmt
-// : IF paren_rhs_stmt body_stmt elseif_stmt? else_stmt?
+// : IF paren_rhs_stmt body_stmt ( ELSE else_stmts ) ?
Maybe<const ast::IfStatement*> ParserImpl::if_stmt() {
Source source;
if (!match(Token::Type::kIf, &source))
@@ -1805,59 +1805,52 @@
if (body.errored)
return Failure::kErrored;
- auto elseif = elseif_stmt();
- if (elseif.errored)
+ auto el = else_stmts();
+ if (el.errored) {
return Failure::kErrored;
-
- auto el = else_stmt();
- if (el.errored)
- return Failure::kErrored;
- if (el.matched)
- elseif.value.push_back(el.value);
-
- return create<ast::IfStatement>(source, condition.value, body.value,
- elseif.value);
-}
-
-// elseif_stmt
-// : ELSE_IF paren_rhs_stmt body_stmt elseif_stmt?
-Maybe<ast::ElseStatementList> ParserImpl::elseif_stmt() {
- Source source;
- if (!match(Token::Type::kElseIf, &source))
- return Failure::kNoMatch;
-
- ast::ElseStatementList ret;
- while (continue_parsing()) {
- auto condition = expect_paren_rhs_stmt();
- if (condition.errored)
- return Failure::kErrored;
-
- auto body = expect_body_stmt();
- if (body.errored)
- return Failure::kErrored;
-
- ret.push_back(
- create<ast::ElseStatement>(source, condition.value, body.value));
-
- if (!match(Token::Type::kElseIf, &source))
- break;
}
- return ret;
+ return create<ast::IfStatement>(source, condition.value, body.value,
+ std::move(el.value));
}
-// else_stmt
-// : ELSE body_stmt
-Maybe<const ast::ElseStatement*> ParserImpl::else_stmt() {
- Source source;
- if (!match(Token::Type::kElse, &source))
- return Failure::kNoMatch;
+// else_stmts
+// : body_stmt
+// | if_stmt
+Expect<ast::ElseStatementList> ParserImpl::else_stmts() {
+ ast::ElseStatementList stmts;
+ while (continue_parsing()) {
+ Source start;
- auto body = expect_body_stmt();
- if (body.errored)
- return Failure::kErrored;
+ bool else_if = false;
+ if (match(Token::Type::kElse, &start)) {
+ else_if = match(Token::Type::kIf);
+ } else if (match(Token::Type::kElseIf, &start)) {
+ deprecated(start, "'elseif' is now 'else if'");
+ else_if = true;
+ } else {
+ break;
+ }
- return create<ast::ElseStatement>(source, nullptr, body.value);
+ const ast::Expression* cond = nullptr;
+ if (else_if) {
+ auto condition = expect_paren_rhs_stmt();
+ if (condition.errored) {
+ return Failure::kErrored;
+ }
+ cond = condition.value;
+ }
+
+ auto body = expect_body_stmt();
+ if (body.errored) {
+ return Failure::kErrored;
+ }
+
+ Source source = make_source_range_from(start);
+ stmts.emplace_back(create<ast::ElseStatement>(source, cond, body.value));
+ }
+
+ return stmts;
}
// switch_stmt
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index e059f09..6f51e0e 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -522,12 +522,9 @@
/// Parses a `if_stmt` grammar element
/// @returns the parsed statement or nullptr
Maybe<const ast::IfStatement*> if_stmt();
- /// Parses a `elseif_stmt` grammar element
- /// @returns the parsed elements
- Maybe<ast::ElseStatementList> elseif_stmt();
- /// Parses a `else_stmt` grammar element
+ /// Parses a list of `else_stmt` grammar elements
/// @returns the parsed statement or nullptr
- Maybe<const ast::ElseStatement*> else_stmt();
+ Expect<ast::ElseStatementList> else_stmts();
/// Parses a `switch_stmt` grammar element
/// @returns the parsed statement or nullptr
Maybe<const ast::SwitchStatement*> switch_stmt();
diff --git a/src/reader/wgsl/parser_impl_else_stmt_test.cc b/src/reader/wgsl/parser_impl_else_stmt_test.cc
deleted file mode 100644
index 822602b..0000000
--- a/src/reader/wgsl/parser_impl_else_stmt_test.cc
+++ /dev/null
@@ -1,57 +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/reader/wgsl/parser_impl_test_helper.h"
-
-namespace tint {
-namespace reader {
-namespace wgsl {
-namespace {
-
-TEST_F(ParserImplTest, ElseStmt) {
- auto p = parser("else { a = b; c = d; }");
- auto e = p->else_stmt();
- EXPECT_TRUE(e.matched);
- EXPECT_FALSE(e.errored);
- EXPECT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->Is<ast::ElseStatement>());
- ASSERT_EQ(e->condition, nullptr);
- EXPECT_EQ(e->body->statements.size(), 2u);
-}
-
-TEST_F(ParserImplTest, ElseStmt_InvalidBody) {
- auto p = parser("else { fn main() {}}");
- auto e = p->else_stmt();
- EXPECT_FALSE(e.matched);
- EXPECT_TRUE(e.errored);
- EXPECT_EQ(e.value, nullptr);
- EXPECT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:8: expected '}'");
-}
-
-TEST_F(ParserImplTest, ElseStmt_MissingBody) {
- auto p = parser("else");
- auto e = p->else_stmt();
- EXPECT_FALSE(e.matched);
- EXPECT_TRUE(e.errored);
- EXPECT_EQ(e.value, nullptr);
- EXPECT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:5: expected '{'");
-}
-
-} // namespace
-} // namespace wgsl
-} // namespace reader
-} // namespace tint
diff --git a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
index ade3c99..11099d4 100644
--- a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
@@ -19,11 +19,9 @@
namespace wgsl {
namespace {
-TEST_F(ParserImplTest, ElseIfStmt) {
- auto p = parser("elseif (a == 4) { a = b; c = d; }");
- auto e = p->elseif_stmt();
- EXPECT_TRUE(e.matched);
- EXPECT_FALSE(e.errored);
+TEST_F(ParserImplTest, ElseStmts) {
+ auto p = parser("else if (a == 4) { a = b; c = d; }");
+ auto e = p->else_stmts();
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_EQ(e.value.size(), 1u);
@@ -33,11 +31,9 @@
EXPECT_EQ(e.value[0]->body->statements.size(), 2u);
}
-TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
- auto p = parser("elseif (a == 4) { a = b; c = d; } elseif(c) { d = 2; }");
- auto e = p->elseif_stmt();
- EXPECT_TRUE(e.matched);
- EXPECT_FALSE(e.errored);
+TEST_F(ParserImplTest, ElseStmts_Multiple) {
+ auto p = parser("else if (a == 4) { a = b; c = d; } else if(c) { d = 2; }");
+ auto e = p->else_stmts();
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_EQ(e.value.size(), 2u);
@@ -52,22 +48,82 @@
EXPECT_EQ(e.value[1]->body->statements.size(), 1u);
}
-TEST_F(ParserImplTest, ElseIfStmt_InvalidBody) {
- auto p = parser("elseif (true) { fn main() {}}");
- auto e = p->elseif_stmt();
- EXPECT_FALSE(e.matched);
+TEST_F(ParserImplTest, ElseStmts_InvalidBody) {
+ auto p = parser("else if (true) { fn main() {}}");
+ auto e = p->else_stmts();
EXPECT_TRUE(e.errored);
EXPECT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:17: expected '}'");
+ EXPECT_EQ(p->error(), "1:18: expected '}'");
}
-TEST_F(ParserImplTest, ElseIfStmt_MissingBody) {
- auto p = parser("elseif (true)");
- auto e = p->elseif_stmt();
- EXPECT_FALSE(e.matched);
+TEST_F(ParserImplTest, ElseStmts_MissingBody) {
+ auto p = parser("else if (true)");
+ auto e = p->else_stmts();
EXPECT_TRUE(e.errored);
EXPECT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:14: expected '{'");
+ EXPECT_EQ(p->error(), "1:15: expected '{'");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// The tests below use the deprecated 'elseif' syntax
+////////////////////////////////////////////////////////////////////////////////
+
+TEST_F(ParserImplTest, DEPRECATED_ElseStmts) {
+ auto p = parser("elseif (a == 4) { a = b; c = d; }");
+ auto e = p->else_stmts();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(
+ p->error(),
+ R"(1:1: use of deprecated language feature: 'elseif' is now 'else if')");
+ ASSERT_EQ(e.value.size(), 1u);
+
+ ASSERT_TRUE(e.value[0]->Is<ast::ElseStatement>());
+ ASSERT_NE(e.value[0]->condition, nullptr);
+ ASSERT_TRUE(e.value[0]->condition->Is<ast::BinaryExpression>());
+ EXPECT_EQ(e.value[0]->body->statements.size(), 2u);
+}
+
+TEST_F(ParserImplTest, DEPRECATED_ElseStmts_Multiple) {
+ auto p = parser("elseif (a == 4) { a = b; c = d; } elseif(c) { d = 2; }");
+ auto e = p->else_stmts();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(
+ p->error(),
+ R"(1:1: use of deprecated language feature: 'elseif' is now 'else if'
+1:35: use of deprecated language feature: 'elseif' is now 'else if')");
+ ASSERT_EQ(e.value.size(), 2u);
+
+ ASSERT_TRUE(e.value[0]->Is<ast::ElseStatement>());
+ ASSERT_NE(e.value[0]->condition, nullptr);
+ ASSERT_TRUE(e.value[0]->condition->Is<ast::BinaryExpression>());
+ EXPECT_EQ(e.value[0]->body->statements.size(), 2u);
+
+ ASSERT_TRUE(e.value[1]->Is<ast::ElseStatement>());
+ ASSERT_NE(e.value[1]->condition, nullptr);
+ ASSERT_TRUE(e.value[1]->condition->Is<ast::IdentifierExpression>());
+ EXPECT_EQ(e.value[1]->body->statements.size(), 1u);
+}
+
+TEST_F(ParserImplTest, DEPRECATED_ElseStmts_InvalidBody) {
+ auto p = parser("elseif (true) { fn main() {}}");
+ auto e = p->else_stmts();
+ EXPECT_TRUE(e.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(
+ p->error(),
+ R"(1:1: use of deprecated language feature: 'elseif' is now 'else if'
+1:17: expected '}')");
+}
+
+TEST_F(ParserImplTest, DEPRECATED_ElseStmts_MissingBody) {
+ auto p = parser("elseif (true)");
+ auto e = p->else_stmts();
+ EXPECT_TRUE(e.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(
+ p->error(),
+ R"(1:1: use of deprecated language feature: 'elseif' is now 'else if'
+1:14: expected '{')");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_if_stmt_test.cc b/src/reader/wgsl/parser_impl_if_stmt_test.cc
index 1c93c19..d7d86b2 100644
--- a/src/reader/wgsl/parser_impl_if_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_if_stmt_test.cc
@@ -35,7 +35,8 @@
}
TEST_F(ParserImplTest, IfStmt_WithElse) {
- auto p = parser("if (a == 4) { a = b; c = d; } elseif(c) { d = 2; } else {}");
+ auto p =
+ parser("if (a == 4) { a = b; c = d; } else if(c) { d = 2; } else {}");
auto e = p->if_stmt();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
@@ -98,13 +99,13 @@
}
TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
- auto p = parser("if (a) {} elseif (a) { fn main() -> a{}}");
+ auto p = parser("if (a) {} else if (a) { fn main() -> a{}}");
auto e = p->if_stmt();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
EXPECT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:24: expected '}'");
+ EXPECT_EQ(p->error(), "1:25: expected '}'");
}
TEST_F(ParserImplTest, IfStmt_InvalidElse) {
diff --git a/src/resolver/compound_statement_test.cc b/src/resolver/compound_statement_test.cc
index 7de565c..1eb4f0f 100644
--- a/src/resolver/compound_statement_test.cc
+++ b/src/resolver/compound_statement_test.cc
@@ -221,7 +221,7 @@
// fn F() {
// if (cond_a) {
// stat_a;
- // } elseif (cond_b) {
+ // } else if (cond_b) {
// stat_b;
// } else {
// stat_c;
diff --git a/src/writer/spirv/builder_if_test.cc b/src/writer/spirv/builder_if_test.cc
index 2fda0e1..b67a4aa 100644
--- a/src/writer/spirv/builder_if_test.cc
+++ b/src/writer/spirv/builder_if_test.cc
@@ -150,7 +150,7 @@
TEST_F(BuilderTest, If_WithElseIf) {
// if (true) {
// v = 2;
- // } elseif (true) {
+ // } else if (true) {
// v = 3;
// }
@@ -201,9 +201,9 @@
TEST_F(BuilderTest, If_WithMultiple) {
// if (true) {
// v = 2;
- // } elseif (true) {
+ // } else if (true) {
// v = 3;
- // } elseif (false) {
+ // } else if (false) {
// v = 4;
// } else {
// v = 5;
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index 0140fe7..eef9aaa 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -955,7 +955,7 @@
for (auto* e : stmt->else_statements) {
if (e->condition) {
auto out = line();
- out << "} elseif (";
+ out << "} else if (";
if (!EmitExpression(out, e->condition)) {
return false;
}
diff --git a/src/writer/wgsl/generator_impl_if_test.cc b/src/writer/wgsl/generator_impl_if_test.cc
index a929a69..36fe5d2 100644
--- a/src/writer/wgsl/generator_impl_if_test.cc
+++ b/src/writer/wgsl/generator_impl_if_test.cc
@@ -61,7 +61,7 @@
ASSERT_TRUE(gen.EmitStatement(i)) << gen.error();
EXPECT_EQ(gen.result(), R"( if (cond) {
return;
- } elseif (else_cond) {
+ } else if (else_cond) {
return;
}
)");
@@ -118,7 +118,7 @@
ASSERT_TRUE(gen.EmitStatement(i)) << gen.error();
EXPECT_EQ(gen.result(), R"( if (cond) {
return;
- } elseif (else_cond) {
+ } else if (else_cond) {
return;
} else {
return;
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 4403a24..e85e787 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -462,7 +462,6 @@
"../src/reader/wgsl/parser_impl_continue_stmt_test.cc",
"../src/reader/wgsl/parser_impl_continuing_stmt_test.cc",
"../src/reader/wgsl/parser_impl_depth_texture_type_test.cc",
- "../src/reader/wgsl/parser_impl_else_stmt_test.cc",
"../src/reader/wgsl/parser_impl_elseif_stmt_test.cc",
"../src/reader/wgsl/parser_impl_equality_expression_test.cc",
"../src/reader/wgsl/parser_impl_error_msg_test.cc",
diff --git a/test/bug/tint/1046.wgsl b/test/bug/tint/1046.wgsl
index 1c8ac15..8fdfe17 100644
--- a/test/bug/tint/1046.wgsl
+++ b/test/bug/tint/1046.wgsl
@@ -41,19 +41,19 @@
color = fragment.color;
- }elseif(uniforms.color_source == 1u){
+ } else if(uniforms.color_source == 1u){
// NORMALS
// color = vec4<f32>(0.0, 0.0, 1.0, 1.0);
color = fragment.normal;
color.a = 1.0;
- }elseif(uniforms.color_source == 2u){
+ } else if(uniforms.color_source == 2u){
// uniform color
color = uniforms.color;
- }elseif(uniforms.color_source == 3u){
+ } else if(uniforms.color_source == 3u){
// TEXTURE
color = textureSample(myTexture, mySampler, fragment.uv);
diff --git a/test/bug/tint/1046.wgsl.expected.wgsl b/test/bug/tint/1046.wgsl.expected.wgsl
index 3c654b0..310472c 100644
--- a/test/bug/tint/1046.wgsl.expected.wgsl
+++ b/test/bug/tint/1046.wgsl.expected.wgsl
@@ -44,12 +44,12 @@
var color : vec4<f32>;
if ((uniforms.color_source == 0u)) {
color = fragment.color;
- } elseif ((uniforms.color_source == 1u)) {
+ } else if ((uniforms.color_source == 1u)) {
color = fragment.normal;
color.a = 1.0;
- } elseif ((uniforms.color_source == 2u)) {
+ } else if ((uniforms.color_source == 2u)) {
color = uniforms.color;
- } elseif ((uniforms.color_source == 3u)) {
+ } else if ((uniforms.color_source == 3u)) {
color = textureSample(myTexture, mySampler, fragment.uv);
}
return color;