ast: Add an IncrementDecrementStatement node
Bug: tint:1488
Change-Id: I9b307a7b53348055af873c137ad6eebbe1dbe5b0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/86001
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 1a4ae17..79beb3d 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -248,6 +248,8 @@
"ast/identifier_expression.h",
"ast/if_statement.cc",
"ast/if_statement.h",
+ "ast/increment_decrement_statement.cc",
+ "ast/increment_decrement_statement.h",
"ast/index_accessor_expression.cc",
"ast/index_accessor_expression.h",
"ast/int_literal_expression.cc",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 138dfde..ae9ef18 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -136,6 +136,8 @@
ast/identifier_expression.h
ast/if_statement.cc
ast/if_statement.h
+ ast/increment_decrement_statement.cc
+ ast/increment_decrement_statement.h
ast/int_literal_expression.cc
ast/int_literal_expression.h
ast/internal_attribute.cc
@@ -681,6 +683,7 @@
ast/id_attribute_test.cc
ast/identifier_expression_test.cc
ast/if_statement_test.cc
+ ast/increment_decrement_statement_test.cc
ast/index_accessor_expression_test.cc
ast/int_literal_expression_test.cc
ast/interpolate_attribute_test.cc
diff --git a/src/tint/ast/increment_decrement_statement.cc b/src/tint/ast/increment_decrement_statement.cc
new file mode 100644
index 0000000..4ec7f87
--- /dev/null
+++ b/src/tint/ast/increment_decrement_statement.cc
@@ -0,0 +1,44 @@
+// Copyright 2022 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/tint/ast/increment_decrement_statement.h"
+
+#include "src/tint/program_builder.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ast::IncrementDecrementStatement);
+
+namespace tint::ast {
+
+IncrementDecrementStatement::IncrementDecrementStatement(ProgramID pid,
+ const Source& src,
+ const Expression* l,
+ bool inc)
+ : Base(pid, src), lhs(l), increment(inc) {
+ TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id);
+}
+
+IncrementDecrementStatement::IncrementDecrementStatement(
+ IncrementDecrementStatement&&) = default;
+
+IncrementDecrementStatement::~IncrementDecrementStatement() = default;
+
+const IncrementDecrementStatement* IncrementDecrementStatement::Clone(
+ CloneContext* ctx) const {
+ // Clone arguments outside of create() call to have deterministic ordering
+ auto src = ctx->Clone(source);
+ auto* l = ctx->Clone(lhs);
+ return ctx->dst->create<IncrementDecrementStatement>(src, l, increment);
+}
+
+} // namespace tint::ast
diff --git a/src/tint/ast/increment_decrement_statement.h b/src/tint/ast/increment_decrement_statement.h
new file mode 100644
index 0000000..f7882da
--- /dev/null
+++ b/src/tint/ast/increment_decrement_statement.h
@@ -0,0 +1,55 @@
+// Copyright 2022 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_TINT_AST_INCREMENT_DECREMENT_STATEMENT_H_
+#define SRC_TINT_AST_INCREMENT_DECREMENT_STATEMENT_H_
+
+#include "src/tint/ast/expression.h"
+#include "src/tint/ast/statement.h"
+
+namespace tint::ast {
+
+/// An increment or decrement statement
+class IncrementDecrementStatement final
+ : public Castable<IncrementDecrementStatement, Statement> {
+ public:
+ /// Constructor
+ /// @param pid the identifier of the program that owns this node
+ /// @param src the source of this node
+ /// @param lhs the LHS expression
+ /// @param inc `true` for increment, `false` for decrement
+ IncrementDecrementStatement(ProgramID pid,
+ const Source& src,
+ const Expression* lhs,
+ bool inc);
+ /// Move constructor
+ IncrementDecrementStatement(IncrementDecrementStatement&&);
+ ~IncrementDecrementStatement() override;
+
+ /// Clones this node and all transitive child nodes using the `CloneContext`
+ /// `ctx`.
+ /// @param ctx the clone context
+ /// @return the newly cloned node
+ const IncrementDecrementStatement* Clone(CloneContext* ctx) const override;
+
+ /// The LHS expression.
+ const Expression* const lhs;
+
+ /// `true` for increment, `false` for decrement.
+ bool increment;
+};
+
+} // namespace tint::ast
+
+#endif // SRC_TINT_AST_INCREMENT_DECREMENT_STATEMENT_H_
diff --git a/src/tint/ast/increment_decrement_statement_test.cc b/src/tint/ast/increment_decrement_statement_test.cc
new file mode 100644
index 0000000..ccb5f07
--- /dev/null
+++ b/src/tint/ast/increment_decrement_statement_test.cc
@@ -0,0 +1,68 @@
+// Copyright 2022 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/tint/ast/increment_decrement_statement.h"
+
+#include "gtest/gtest-spi.h"
+#include "src/tint/ast/test_helper.h"
+
+namespace tint::ast {
+namespace {
+
+using IncrementDecrementStatementTest = TestHelper;
+
+TEST_F(IncrementDecrementStatementTest, Creation) {
+ auto* expr = Expr("expr");
+
+ auto* i = create<IncrementDecrementStatement>(expr, true);
+ EXPECT_EQ(i->lhs, expr);
+ EXPECT_TRUE(i->increment);
+}
+
+TEST_F(IncrementDecrementStatementTest, Creation_WithSource) {
+ auto* expr = Expr("expr");
+ auto* i = create<IncrementDecrementStatement>(Source{Source::Location{20, 2}},
+ expr, true);
+ auto src = i->source;
+ EXPECT_EQ(i->lhs, expr);
+ EXPECT_TRUE(i->increment);
+ EXPECT_EQ(src.range.begin.line, 20u);
+ EXPECT_EQ(src.range.begin.column, 2u);
+}
+
+TEST_F(IncrementDecrementStatementTest, IsIncrementDecrement) {
+ auto* expr = Expr("expr");
+ auto* i = create<IncrementDecrementStatement>(expr, true);
+ EXPECT_TRUE(i->Is<IncrementDecrementStatement>());
+}
+
+TEST_F(IncrementDecrementStatementTest, Decrement) {
+ auto* expr = Expr("expr");
+ auto* i = create<IncrementDecrementStatement>(expr, false);
+ EXPECT_EQ(i->lhs, expr);
+ EXPECT_FALSE(i->increment);
+}
+
+TEST_F(IncrementDecrementStatementTest, Assert_DifferentProgramID_Expr) {
+ EXPECT_FATAL_FAILURE(
+ {
+ ProgramBuilder b1;
+ ProgramBuilder b2;
+ b1.create<IncrementDecrementStatement>(b2.Expr(true), true);
+ },
+ "internal compiler error");
+}
+
+} // namespace
+} // namespace tint::ast
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index eb87d3e..8365ad9 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -46,6 +46,7 @@
#include "src/tint/ast/i32.h"
#include "src/tint/ast/id_attribute.h"
#include "src/tint/ast/if_statement.h"
+#include "src/tint/ast/increment_decrement_statement.h"
#include "src/tint/ast/index_accessor_expression.h"
#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/invariant_attribute.h"
@@ -2300,6 +2301,46 @@
Expr(std::forward<RhsExpressionInit>(rhs)), op);
}
+ /// Creates an ast::IncrementDecrementStatement with input lhs.
+ /// @param source the source information
+ /// @param lhs the left hand side expression initializer
+ /// @returns the increment decrement statement pointer
+ template <typename LhsExpressionInit>
+ const ast::IncrementDecrementStatement* Increment(const Source& source,
+ LhsExpressionInit&& lhs) {
+ return create<ast::IncrementDecrementStatement>(
+ source, Expr(std::forward<LhsExpressionInit>(lhs)), true);
+ }
+
+ /// Creates a ast::IncrementDecrementStatement with input lhs.
+ /// @param lhs the left hand side expression initializer
+ /// @returns the increment decrement statement pointer
+ template <typename LhsExpressionInit>
+ const ast::IncrementDecrementStatement* Increment(LhsExpressionInit&& lhs) {
+ return create<ast::IncrementDecrementStatement>(
+ Expr(std::forward<LhsExpressionInit>(lhs)), true);
+ }
+
+ /// Creates an ast::IncrementDecrementStatement with input lhs.
+ /// @param source the source information
+ /// @param lhs the left hand side expression initializer
+ /// @returns the increment decrement statement pointer
+ template <typename LhsExpressionInit>
+ const ast::IncrementDecrementStatement* Decrement(const Source& source,
+ LhsExpressionInit&& lhs) {
+ return create<ast::IncrementDecrementStatement>(
+ source, Expr(std::forward<LhsExpressionInit>(lhs)), false);
+ }
+
+ /// Creates a ast::IncrementDecrementStatement with input lhs.
+ /// @param lhs the left hand side expression initializer
+ /// @returns the increment decrement statement pointer
+ template <typename LhsExpressionInit>
+ const ast::IncrementDecrementStatement* Decrement(LhsExpressionInit&& lhs) {
+ return create<ast::IncrementDecrementStatement>(
+ Expr(std::forward<LhsExpressionInit>(lhs)), false);
+ }
+
/// Creates a ast::LoopStatement with input body and optional continuing
/// @param source the source information
/// @param body the loop body
diff --git a/test/tint/BUILD.gn b/test/tint/BUILD.gn
index c5e8048..7cbdff7 100644
--- a/test/tint/BUILD.gn
+++ b/test/tint/BUILD.gn
@@ -175,6 +175,7 @@
"../../src/tint/ast/id_attribute_test.cc",
"../../src/tint/ast/identifier_expression_test.cc",
"../../src/tint/ast/if_statement_test.cc",
+ "../../src/tint/ast/increment_decrement_statement_test.cc",
"../../src/tint/ast/index_accessor_expression_test.cc",
"../../src/tint/ast/int_literal_expression_test.cc",
"../../src/tint/ast/interpolate_attribute_test.cc",