diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn index 0d527043ce..7a5ca93279 100644 --- a/src/tint/BUILD.gn +++ b/src/tint/BUILD.gn @@ -210,6 +210,8 @@ libtint_source_set("libtint_core_all_src") { "ast/call_statement.h", "ast/case_statement.cc", "ast/case_statement.h", + "ast/compound_assignment_statement.cc", + "ast/compound_assignment_statement.h", "ast/continue_statement.cc", "ast/continue_statement.h", "ast/depth_multisampled_texture.cc", diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt index 30e23228bd..4d30266247 100644 --- a/src/tint/CMakeLists.txt +++ b/src/tint/CMakeLists.txt @@ -98,6 +98,8 @@ set(TINT_LIB_SRCS ast/call_statement.h ast/case_statement.cc ast/case_statement.h + ast/compound_assignment_statement.cc + ast/compound_assignment_statement.h ast/continue_statement.cc ast/continue_statement.h ast/depth_multisampled_texture.cc @@ -658,6 +660,7 @@ if(TINT_BUILD_TESTS) ast/call_expression_test.cc ast/call_statement_test.cc ast/case_statement_test.cc + ast/compound_assignment_statement_test.cc ast/continue_statement_test.cc ast/depth_multisampled_texture_test.cc ast/depth_texture_test.cc diff --git a/src/tint/ast/compound_assignment_statement.cc b/src/tint/ast/compound_assignment_statement.cc new file mode 100644 index 0000000000..cc1f07cef0 --- /dev/null +++ b/src/tint/ast/compound_assignment_statement.cc @@ -0,0 +1,51 @@ +// 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/compound_assignment_statement.h" + +#include "src/tint/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::CompoundAssignmentStatement); + +namespace tint { +namespace ast { + +CompoundAssignmentStatement::CompoundAssignmentStatement(ProgramID pid, + const Source& src, + const Expression* l, + const Expression* r, + BinaryOp o) + : Base(pid, src), lhs(l), rhs(r), op(o) { + TINT_ASSERT(AST, lhs); + TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id); + TINT_ASSERT(AST, rhs); + TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs, program_id); +} + +CompoundAssignmentStatement::CompoundAssignmentStatement( + CompoundAssignmentStatement&&) = default; + +CompoundAssignmentStatement::~CompoundAssignmentStatement() = default; + +const CompoundAssignmentStatement* CompoundAssignmentStatement::Clone( + CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source); + auto* l = ctx->Clone(lhs); + auto* r = ctx->Clone(rhs); + return ctx->dst->create(src, l, r, op); +} + +} // namespace ast +} // namespace tint diff --git a/src/tint/ast/compound_assignment_statement.h b/src/tint/ast/compound_assignment_statement.h new file mode 100644 index 0000000000..49a2004a9b --- /dev/null +++ b/src/tint/ast/compound_assignment_statement.h @@ -0,0 +1,63 @@ +// 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_COMPOUND_ASSIGNMENT_STATEMENT_H_ +#define SRC_TINT_AST_COMPOUND_ASSIGNMENT_STATEMENT_H_ + +#include "src/tint/ast/binary_expression.h" +#include "src/tint/ast/expression.h" +#include "src/tint/ast/statement.h" + +namespace tint { +namespace ast { + +/// A compound assignment statement +class CompoundAssignmentStatement final + : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the compound assignment statement source + /// @param lhs the left side of the expression + /// @param rhs the right side of the expression + /// @param op the binary operator + CompoundAssignmentStatement(ProgramID program_id, + const Source& source, + const Expression* lhs, + const Expression* rhs, + BinaryOp op); + /// Move constructor + CompoundAssignmentStatement(CompoundAssignmentStatement&&); + ~CompoundAssignmentStatement() override; + + /// Clones this node and all transitive child nodes using the `CloneContext` + /// `ctx`. + /// @param ctx the clone context + /// @return the newly cloned node + const CompoundAssignmentStatement* Clone(CloneContext* ctx) const override; + + /// left side expression + const Expression* const lhs; + + /// right side expression + const Expression* const rhs; + + /// the binary operator + const BinaryOp op; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_TINT_AST_COMPOUND_ASSIGNMENT_STATEMENT_H_ diff --git a/src/tint/ast/compound_assignment_statement_test.cc b/src/tint/ast/compound_assignment_statement_test.cc new file mode 100644 index 0000000000..c84faf01fe --- /dev/null +++ b/src/tint/ast/compound_assignment_statement_test.cc @@ -0,0 +1,102 @@ +// 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/compound_assignment_statement.h" + +#include "gtest/gtest-spi.h" +#include "src/tint/ast/test_helper.h" + +namespace tint { +namespace ast { +namespace { + +using CompoundAssignmentStatementTest = TestHelper; + +TEST_F(CompoundAssignmentStatementTest, Creation) { + auto* lhs = Expr("lhs"); + auto* rhs = Expr("rhs"); + auto op = BinaryOp::kAdd; + + auto* stmt = create(lhs, rhs, op); + EXPECT_EQ(stmt->lhs, lhs); + EXPECT_EQ(stmt->rhs, rhs); + EXPECT_EQ(stmt->op, op); +} + +TEST_F(CompoundAssignmentStatementTest, CreationWithSource) { + auto* lhs = Expr("lhs"); + auto* rhs = Expr("rhs"); + auto op = BinaryOp::kMultiply; + + auto* stmt = create( + Source{Source::Location{20, 2}}, lhs, rhs, op); + auto src = stmt->source; + EXPECT_EQ(src.range.begin.line, 20u); + EXPECT_EQ(src.range.begin.column, 2u); +} + +TEST_F(CompoundAssignmentStatementTest, IsCompoundAssign) { + auto* lhs = Expr("lhs"); + auto* rhs = Expr("rhs"); + auto op = BinaryOp::kSubtract; + + auto* stmt = create(lhs, rhs, op); + EXPECT_TRUE(stmt->Is()); +} + +TEST_F(CompoundAssignmentStatementTest, Assert_Null_LHS) { + EXPECT_FATAL_FAILURE( + { + ProgramBuilder b; + b.create(nullptr, b.Expr(1), + BinaryOp::kAdd); + }, + "internal compiler error"); +} + +TEST_F(CompoundAssignmentStatementTest, Assert_Null_RHS) { + EXPECT_FATAL_FAILURE( + { + ProgramBuilder b; + b.create(b.Expr(1), nullptr, + BinaryOp::kAdd); + }, + "internal compiler error"); +} + +TEST_F(CompoundAssignmentStatementTest, Assert_DifferentProgramID_LHS) { + EXPECT_FATAL_FAILURE( + { + ProgramBuilder b1; + ProgramBuilder b2; + b1.create(b2.Expr("lhs"), b1.Expr("rhs"), + BinaryOp::kAdd); + }, + "internal compiler error"); +} + +TEST_F(CompoundAssignmentStatementTest, Assert_DifferentProgramID_RHS) { + EXPECT_FATAL_FAILURE( + { + ProgramBuilder b1; + ProgramBuilder b2; + b1.create(b1.Expr("lhs"), b2.Expr("rhs"), + BinaryOp::kAdd); + }, + "internal compiler error"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/test/tint/BUILD.gn b/test/tint/BUILD.gn index 3588b0876c..b0edf0f646 100644 --- a/test/tint/BUILD.gn +++ b/test/tint/BUILD.gn @@ -158,6 +158,7 @@ tint_unittests_source_set("tint_unittests_ast_src") { "../../src/tint/ast/call_expression_test.cc", "../../src/tint/ast/call_statement_test.cc", "../../src/tint/ast/case_statement_test.cc", + "../../src/tint/ast/compound_assignment_statement_test.cc", "../../src/tint/ast/continue_statement_test.cc", "../../src/tint/ast/depth_multisampled_texture_test.cc", "../../src/tint/ast/depth_texture_test.cc",