ast: Have all decorations derive from base class This is the first step in unifying the way decorations are parsed - i.e. instead of parsing decorations in different ways based on the predicted grammar that follows, we can parse decorations blocks in a unified way, then later verify what we have is as expected. `StructDecoration` has been transformed from an `enum class` to a proper class so it can derive from `Decoration`. Bug: tint:282 Bug: tint:291 Change-Id: Iaf12d266068d03edf695acdf2cd21e6cc3ea8eb3 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31663 Reviewed-by: dan sinclair <dsinclair@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/BUILD.gn b/BUILD.gn index 2165569..1a1aae1 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -255,6 +255,8 @@ "src/ast/continue_statement.h", "src/ast/decorated_variable.cc", "src/ast/decorated_variable.h", + "src/ast/decoration.cc", + "src/ast/decoration.h", "src/ast/discard_statement.cc", "src/ast/discard_statement.h", "src/ast/else_statement.cc", @@ -311,6 +313,8 @@ "src/ast/stride_decoration.h", "src/ast/struct.cc", "src/ast/struct.h", + "src/ast/struct_block_decoration.cc", + "src/ast/struct_block_decoration.h", "src/ast/struct_decoration.cc", "src/ast/struct_decoration.h", "src/ast/struct_member.cc", @@ -734,6 +738,7 @@ "src/ast/case_statement_test.cc", "src/ast/constant_id_decoration_test.cc", "src/ast/continue_statement_test.cc", + "src/ast/decoration_test.cc", "src/ast/decorated_variable_test.cc", "src/ast/discard_statement_test.cc", "src/ast/else_statement_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0eff8bd..f5e1945 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt
@@ -76,6 +76,8 @@ ast/continue_statement.h ast/decorated_variable.cc ast/decorated_variable.h + ast/decoration.cc + ast/decoration.h ast/discard_statement.cc ast/discard_statement.h ast/else_statement.cc @@ -132,6 +134,8 @@ ast/stride_decoration.h ast/struct.cc ast/struct.h + ast/struct_block_decoration.cc + ast/struct_block_decoration.h ast/struct_decoration.cc ast/struct_decoration.h ast/struct_member.cc @@ -344,6 +348,7 @@ ast/constant_id_decoration_test.cc ast/continue_statement_test.cc ast/discard_statement_test.cc + ast/decoration_test.cc ast/decorated_variable_test.cc ast/else_statement_test.cc ast/expression_test.cc
diff --git a/src/ast/array_decoration.cc b/src/ast/array_decoration.cc index 8402439..96da686 100644 --- a/src/ast/array_decoration.cc +++ b/src/ast/array_decoration.cc
@@ -21,7 +21,7 @@ namespace tint { namespace ast { -ArrayDecoration::ArrayDecoration() = default; +ArrayDecoration::ArrayDecoration() : Decoration(Kind) {} ArrayDecoration::~ArrayDecoration() = default;
diff --git a/src/ast/array_decoration.h b/src/ast/array_decoration.h index 579668b..a86a4df 100644 --- a/src/ast/array_decoration.h +++ b/src/ast/array_decoration.h
@@ -19,15 +19,20 @@ #include <string> #include <vector> +#include "src/ast/decoration.h" + namespace tint { namespace ast { class StrideDecoration; /// A decoration attached to an array -class ArrayDecoration { +class ArrayDecoration : public Decoration { public: - virtual ~ArrayDecoration(); + /// The kind of decoration that this type represents + static constexpr DecorationKind Kind = DecorationKind::kArray; + + ~ArrayDecoration() override; /// @returns true if this is a stride decoration virtual bool IsStride() const; @@ -39,6 +44,7 @@ virtual std::string to_str() const = 0; protected: + /// Constructor ArrayDecoration(); };
diff --git a/src/ast/decoration.cc b/src/ast/decoration.cc new file mode 100644 index 0000000..c4abc90 --- /dev/null +++ b/src/ast/decoration.cc
@@ -0,0 +1,39 @@ +// 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/decoration.h" + +namespace tint { +namespace ast { + +Decoration::~Decoration() = default; + +std::ostream& operator<<(std::ostream& out, DecorationKind data) { + switch (data) { + case DecorationKind::kArray: + return out << "array"; + case DecorationKind::kFunction: + return out << "function"; + case DecorationKind::kStruct: + return out << "struct"; + case DecorationKind::kStructMember: + return out << "struct member"; + case DecorationKind::kVariable: + return out << "variable"; + } + return out << "<unknown>"; +} + +} // namespace ast +} // namespace tint
diff --git a/src/ast/decoration.h b/src/ast/decoration.h new file mode 100644 index 0000000..9c58cca --- /dev/null +++ b/src/ast/decoration.h
@@ -0,0 +1,82 @@ +// 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_DECORATION_H_ +#define SRC_AST_DECORATION_H_ + +#include <memory> +#include <ostream> +#include <vector> + +#include "src/source.h" + +namespace tint { +namespace ast { + +/// The decoration kind enumerator +enum class DecorationKind { + kArray, + kFunction, + kStruct, + kStructMember, + kVariable +}; + +std::ostream& operator<<(std::ostream& out, DecorationKind data); + +/// The base class for all decorations +class Decoration { + public: + virtual ~Decoration(); + + /// @return the decoration kind + DecorationKind GetKind() const { return kind_; } + + /// @return true if this decoration is of (or derives from) type |TO| + template <typename TO> + bool Is() const { + return GetKind() == TO::Kind; + } + + protected: + /// Constructor + /// @param kind represents the derived type + explicit Decoration(DecorationKind kind) : kind_(kind) {} + + private: + DecorationKind const kind_; +}; + +/// As dynamically casts |deco| to the target type |TO|. +/// @return the dynamically cast decoration, or nullptr if |deco| is not of the +/// type |TO|. +template <typename TO> +std::unique_ptr<TO> As(std::unique_ptr<Decoration>&& deco) { + if (deco == nullptr) { + return nullptr; + } + if (deco->Is<TO>()) { + auto ptr = static_cast<TO*>(deco.release()); + return std::unique_ptr<TO>(ptr); + } + return nullptr; +} + +/// A list of unique decorations +using DecorationList = std::vector<std::unique_ptr<Decoration>>; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_DECORATION_H_
diff --git a/src/ast/decoration_test.cc b/src/ast/decoration_test.cc new file mode 100644 index 0000000..a800494 --- /dev/null +++ b/src/ast/decoration_test.cc
@@ -0,0 +1,53 @@ +// 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/decoration.h" + +#include <sstream> +#include <utility> + +#include "gtest/gtest.h" + +#include "src/ast/array_decoration.h" +#include "src/ast/constant_id_decoration.h" + +namespace tint { +namespace ast { +namespace { + +using DecorationTest = testing::Test; + +TEST_F(DecorationTest, AsCorrectType) { + auto* decoration = new ConstantIdDecoration(1); + auto upcast = std::unique_ptr<Decoration>(decoration); + auto downcast = As<VariableDecoration>(std::move(upcast)); + EXPECT_EQ(decoration, downcast.get()); +} + +TEST_F(DecorationTest, AsIncorrectType) { + auto* decoration = new ConstantIdDecoration(1); + auto upcast = std::unique_ptr<Decoration>(decoration); + auto downcast = As<ArrayDecoration>(std::move(upcast)); + EXPECT_EQ(nullptr, downcast.get()); +} + +TEST_F(DecorationTest, Is) { + auto decoration = std::make_unique<ConstantIdDecoration>(1); + EXPECT_TRUE(decoration->Is<VariableDecoration>()); + EXPECT_FALSE(decoration->Is<ArrayDecoration>()); +} + +} // namespace +} // namespace ast +} // namespace tint
diff --git a/src/ast/function_decoration.cc b/src/ast/function_decoration.cc index d94c2c1..15d7eaa 100644 --- a/src/ast/function_decoration.cc +++ b/src/ast/function_decoration.cc
@@ -22,7 +22,7 @@ namespace tint { namespace ast { -FunctionDecoration::FunctionDecoration() = default; +FunctionDecoration::FunctionDecoration() : Decoration(Kind) {} FunctionDecoration::~FunctionDecoration() = default;
diff --git a/src/ast/function_decoration.h b/src/ast/function_decoration.h index d767138..101f3a9 100644 --- a/src/ast/function_decoration.h +++ b/src/ast/function_decoration.h
@@ -19,6 +19,8 @@ #include <ostream> #include <vector> +#include "src/ast/decoration.h" + namespace tint { namespace ast { @@ -26,9 +28,12 @@ class WorkgroupDecoration; /// A decoration attached to a function -class FunctionDecoration { +class FunctionDecoration : public Decoration { public: - virtual ~FunctionDecoration(); + /// The kind of decoration that this type represents + static constexpr DecorationKind Kind = DecorationKind::kFunction; + + ~FunctionDecoration() override; /// @returns true if this is a stage decoration virtual bool IsStage() const; @@ -42,11 +47,10 @@ /// Outputs the function decoration to the given stream /// @param out the stream to output too - //! @cond Doxygen_Suppress virtual void to_str(std::ostream& out) const = 0; - //! @endcond protected: + /// Constructor FunctionDecoration(); };
diff --git a/src/ast/struct.cc b/src/ast/struct.cc index cf3a02c..8f1e23b 100644 --- a/src/ast/struct.cc +++ b/src/ast/struct.cc
@@ -23,7 +23,9 @@ : Node(), members_(std::move(members)) {} Struct::Struct(StructDecorationList decorations, StructMemberList members) - : Node(), decorations_(decorations), members_(std::move(members)) {} + : Node(), + decorations_(std::move(decorations)), + members_(std::move(members)) {} Struct::Struct(const Source& source, StructMemberList members) : Node(source), members_(std::move(members)) {} @@ -31,7 +33,9 @@ Struct::Struct(const Source& source, StructDecorationList decorations, StructMemberList members) - : Node(source), decorations_(decorations), members_(std::move(members)) {} + : Node(source), + decorations_(std::move(decorations)), + members_(std::move(members)) {} Struct::Struct(Struct&&) = default; @@ -47,8 +51,8 @@ } bool Struct::IsBlockDecorated() const { - for (auto deco : decorations_) { - if (deco == StructDecoration::kBlock) { + for (auto& deco : decorations_) { + if (deco->IsBlock()) { return true; } } @@ -56,11 +60,6 @@ } bool Struct::IsValid() const { - for (auto deco : decorations_) { - if (deco == StructDecoration::kNone) { - return false; - } - } for (const auto& mem : members_) { if (mem == nullptr || !mem->IsValid()) { return false; @@ -71,9 +70,11 @@ void Struct::to_str(std::ostream& out, size_t indent) const { out << "Struct{" << std::endl; - for (auto deco : decorations_) { + for (auto& deco : decorations_) { make_indent(out, indent + 2); - out << "[[" << deco << "]]" << std::endl; + out << "[["; + deco->to_str(out); + out << "]]" << std::endl; } for (const auto& member : members_) { member->to_str(out, indent + 2);
diff --git a/src/ast/struct_block_decoration.cc b/src/ast/struct_block_decoration.cc new file mode 100644 index 0000000..aac4c21 --- /dev/null +++ b/src/ast/struct_block_decoration.cc
@@ -0,0 +1,33 @@ +// 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/struct_block_decoration.h" + +namespace tint { +namespace ast { + +StructBlockDecoration::StructBlockDecoration() = default; + +StructBlockDecoration::~StructBlockDecoration() = default; + +bool StructBlockDecoration::IsBlock() const { + return true; +} + +void StructBlockDecoration::to_str(std::ostream& out) const { + out << "block"; +} + +} // namespace ast +} // namespace tint
diff --git a/src/ast/struct_block_decoration.h b/src/ast/struct_block_decoration.h new file mode 100644 index 0000000..e5f4eaf --- /dev/null +++ b/src/ast/struct_block_decoration.h
@@ -0,0 +1,48 @@ +// 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_STRUCT_BLOCK_DECORATION_H_ +#define SRC_AST_STRUCT_BLOCK_DECORATION_H_ + +#include <memory> +#include <ostream> +#include <vector> + +#include "src/ast/struct_decoration.h" + +namespace tint { +namespace ast { + +/// The struct decorations +class StructBlockDecoration : public StructDecoration { + public: + /// constructor + StructBlockDecoration(); + ~StructBlockDecoration() override; + + /// @returns true if this is a block struct + bool IsBlock() const override; + + /// Outputs the decoration to the given stream + /// @param out the stream to output too + void to_str(std::ostream& out) const override; +}; + +/// List of struct decorations +using StructDecorationList = std::vector<std::unique_ptr<StructDecoration>>; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_STRUCT_BLOCK_DECORATION_H_
diff --git a/src/ast/struct_decoration.cc b/src/ast/struct_decoration.cc index 10ee485..f75e16b 100644 --- a/src/ast/struct_decoration.cc +++ b/src/ast/struct_decoration.cc
@@ -17,19 +17,9 @@ namespace tint { namespace ast { -std::ostream& operator<<(std::ostream& out, StructDecoration stage) { - switch (stage) { - case StructDecoration::kNone: { - out << "none"; - break; - } - case StructDecoration::kBlock: { - out << "block"; - break; - } - } - return out; -} +StructDecoration::StructDecoration() : Decoration(Kind) {} + +StructDecoration::~StructDecoration() = default; } // namespace ast } // namespace tint
diff --git a/src/ast/struct_decoration.h b/src/ast/struct_decoration.h index 20139ac..9386e42 100644 --- a/src/ast/struct_decoration.h +++ b/src/ast/struct_decoration.h
@@ -15,19 +15,37 @@ #ifndef SRC_AST_STRUCT_DECORATION_H_ #define SRC_AST_STRUCT_DECORATION_H_ +#include <memory> #include <ostream> #include <vector> +#include "src/ast/decoration.h" + namespace tint { namespace ast { /// The struct decorations -enum class StructDecoration { kNone = -1, kBlock }; +class StructDecoration : public Decoration { + public: + /// The kind of decoration that this type represents + static constexpr DecorationKind Kind = DecorationKind::kStruct; -std::ostream& operator<<(std::ostream& out, StructDecoration stage); + ~StructDecoration() override; + + /// @returns true if this is a block struct + virtual bool IsBlock() const = 0; + + /// Outputs the decoration to the given stream + /// @param out the stream to output too + virtual void to_str(std::ostream& out) const = 0; + + protected: + /// Constructor + StructDecoration(); +}; /// List of struct decorations -using StructDecorationList = std::vector<StructDecoration>; +using StructDecorationList = std::vector<std::unique_ptr<StructDecoration>>; } // namespace ast } // namespace tint
diff --git a/src/ast/struct_member_decoration.cc b/src/ast/struct_member_decoration.cc index 1c4d154..1e35fd4 100644 --- a/src/ast/struct_member_decoration.cc +++ b/src/ast/struct_member_decoration.cc
@@ -21,7 +21,8 @@ namespace tint { namespace ast { -StructMemberDecoration::StructMemberDecoration() = default; +StructMemberDecoration::StructMemberDecoration() + : Decoration(DecorationKind::kStructMember) {} StructMemberDecoration::~StructMemberDecoration() = default;
diff --git a/src/ast/struct_member_decoration.h b/src/ast/struct_member_decoration.h index b54f3eb..b8cbb8a 100644 --- a/src/ast/struct_member_decoration.h +++ b/src/ast/struct_member_decoration.h
@@ -19,15 +19,20 @@ #include <string> #include <vector> +#include "src/ast/decoration.h" + namespace tint { namespace ast { class StructMemberOffsetDecoration; /// A decoration attached to a struct member -class StructMemberDecoration { +class StructMemberDecoration : public Decoration { public: - virtual ~StructMemberDecoration(); + /// The kind of decoration that this type represents + static constexpr DecorationKind Kind = DecorationKind::kStructMember; + + ~StructMemberDecoration() override; /// @returns true if this is an offset decoration virtual bool IsOffset() const; @@ -39,6 +44,7 @@ virtual std::string to_str() const = 0; protected: + /// Constructor StructMemberDecoration(); };
diff --git a/src/ast/struct_test.cc b/src/ast/struct_test.cc index 55abf23..95f8adb 100644 --- a/src/ast/struct_test.cc +++ b/src/ast/struct_test.cc
@@ -19,7 +19,7 @@ #include <utility> #include "gtest/gtest.h" -#include "src/ast/struct_decoration.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/type/i32_type.h" @@ -52,12 +52,12 @@ std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); StructDecorationList decos; - decos.push_back(StructDecoration::kBlock); + decos.push_back(std::make_unique<StructBlockDecoration>()); Struct s{std::move(decos), std::move(members)}; EXPECT_EQ(s.members().size(), 1u); ASSERT_EQ(s.decorations().size(), 1u); - EXPECT_EQ(s.decorations()[0], StructDecoration::kBlock); + EXPECT_TRUE(s.decorations()[0]->IsBlock()); EXPECT_EQ(s.source().range.begin.line, 0u); EXPECT_EQ(s.source().range.begin.column, 0u); EXPECT_EQ(s.source().range.end.line, 0u); @@ -72,14 +72,14 @@ std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); StructDecorationList decos; - decos.push_back(StructDecoration::kBlock); + decos.push_back(std::make_unique<StructBlockDecoration>()); Struct s{ Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}}, std::move(decos), std::move(members)}; EXPECT_EQ(s.members().size(), 1u); ASSERT_EQ(s.decorations().size(), 1u); - EXPECT_EQ(s.decorations()[0], StructDecoration::kBlock); + EXPECT_TRUE(s.decorations()[0]->IsBlock()); EXPECT_EQ(s.source().range.begin.line, 27u); EXPECT_EQ(s.source().range.begin.column, 4u); EXPECT_EQ(s.source().range.end.line, 27u); @@ -114,20 +114,6 @@ EXPECT_FALSE(s.IsValid()); } -TEST_F(StructTest, IsValid_NoneDecoration) { - type::I32Type i32; - - StructMemberList members; - members.push_back( - std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); - - StructDecorationList decos; - decos.push_back(StructDecoration::kNone); - - Struct s{std::move(decos), std::move(members)}; - EXPECT_FALSE(s.IsValid()); -} - TEST_F(StructTest, ToStr) { type::I32Type i32; @@ -136,7 +122,7 @@ std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); StructDecorationList decos; - decos.push_back(StructDecoration::kBlock); + decos.push_back(std::make_unique<StructBlockDecoration>()); Struct s{std::move(decos), std::move(members)};
diff --git a/src/ast/type/access_control_type_test.cc b/src/ast/type/access_control_type_test.cc index cfb3eb0..6dc716e 100644 --- a/src/ast/type/access_control_type_test.cc +++ b/src/ast/type/access_control_type_test.cc
@@ -14,6 +14,9 @@ #include "src/ast/type/access_control_type.h" +#include <memory> +#include <utility> + #include "gtest/gtest.h" #include "src/ast/storage_class.h" #include "src/ast/stride_decoration.h"
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc index 1b5dbc0..6266cfb 100644 --- a/src/ast/type/alias_type_test.cc +++ b/src/ast/type/alias_type_test.cc
@@ -14,6 +14,9 @@ #include "src/ast/type/alias_type.h" +#include <memory> +#include <utility> + #include "gtest/gtest.h" #include "src/ast/storage_class.h" #include "src/ast/stride_decoration.h"
diff --git a/src/ast/variable_decoration.cc b/src/ast/variable_decoration.cc index fff88be..2087e68 100644 --- a/src/ast/variable_decoration.cc +++ b/src/ast/variable_decoration.cc
@@ -25,7 +25,7 @@ namespace tint { namespace ast { -VariableDecoration::VariableDecoration() = default; +VariableDecoration::VariableDecoration() : Decoration(Kind) {} VariableDecoration::~VariableDecoration() = default;
diff --git a/src/ast/variable_decoration.h b/src/ast/variable_decoration.h index 8cc5f70..3a13b68 100644 --- a/src/ast/variable_decoration.h +++ b/src/ast/variable_decoration.h
@@ -20,6 +20,8 @@ #include <string> #include <vector> +#include "src/ast/decoration.h" + namespace tint { namespace ast { @@ -30,9 +32,12 @@ class SetDecoration; /// A decoration attached to a variable -class VariableDecoration { +class VariableDecoration : public Decoration { public: - virtual ~VariableDecoration(); + /// The kind of decoration that this type represents + static constexpr DecorationKind Kind = DecorationKind::kVariable; + + ~VariableDecoration() override; /// @returns true if this is a binding decoration virtual bool IsBinding() const; @@ -58,11 +63,10 @@ /// Outputs the variable decoration to the given stream /// @param out the stream to output too - //! @cond Doxygen_Suppress virtual void to_str(std::ostream& out) const = 0; - //! @endcond protected: + /// Constructor VariableDecoration(); };
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc index f3665e7..97d04f7 100644 --- a/src/inspector/inspector_test.cc +++ b/src/inspector/inspector_test.cc
@@ -34,6 +34,7 @@ #include "src/ast/sint_literal.h" #include "src/ast/stage_decoration.h" #include "src/ast/stride_decoration.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/struct_member_decoration.h" @@ -268,7 +269,7 @@ ast::StructDecorationList decos; if (is_block) { - decos.push_back(ast::StructDecoration::kBlock); + decos.push_back(std::make_unique<ast::StructBlockDecoration>()); } auto str =
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc index d38e96c..ab77baf 100644 --- a/src/reader/spirv/parser_impl.cc +++ b/src/reader/spirv/parser_impl.cc
@@ -48,6 +48,7 @@ #include "src/ast/sint_literal.h" #include "src/ast/stride_decoration.h" #include "src/ast/struct.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/struct_member_decoration.h" @@ -802,9 +803,11 @@ if (struct_decorations.size() == 1) { const auto decoration = struct_decorations[0][0]; if (decoration == SpvDecorationBlock) { - ast_struct_decorations.push_back(ast::StructDecoration::kBlock); + ast_struct_decorations.push_back( + std::make_unique<ast::StructBlockDecoration>()); } else if (decoration == SpvDecorationBufferBlock) { - ast_struct_decorations.push_back(ast::StructDecoration::kBlock); + ast_struct_decorations.push_back( + std::make_unique<ast::StructBlockDecoration>()); remap_buffer_block_type_.insert(type_id); } else { Fail() << "struct with ID " << type_id
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc index eb43221..a938eca 100644 --- a/src/reader/wgsl/parser_impl.cc +++ b/src/reader/wgsl/parser_impl.cc
@@ -42,6 +42,7 @@ #include "src/ast/sint_literal.h" #include "src/ast/stage_decoration.h" #include "src/ast/stride_decoration.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_member_offset_decoration.h" #include "src/ast/switch_statement.h" #include "src/ast/type/alias_type.h" @@ -1524,10 +1525,10 @@ if (has_error()) { return false; } - if (deco == ast::StructDecoration::kNone) { + if (deco == nullptr) { return true; } - decos.push_back(deco); + decos.emplace_back(std::move(deco)); next(); // Consume the peek of [[ next(); // Consume the peek from the struct_decoration @@ -1543,11 +1544,11 @@ // struct_decoration // : BLOCK -ast::StructDecoration ParserImpl::struct_decoration(Token t) { +std::unique_ptr<ast::StructDecoration> ParserImpl::struct_decoration(Token t) { if (t.IsBlock()) { - return ast::StructDecoration::kBlock; + return std::make_unique<ast::StructBlockDecoration>(); } - return ast::StructDecoration::kNone; + return nullptr; } // struct_body_decl
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h index 467b6ee..4133f4b 100644 --- a/src/reader/wgsl/parser_impl.h +++ b/src/reader/wgsl/parser_impl.h
@@ -189,7 +189,7 @@ /// Parses a `struct_decoration` grammar element /// @param t the current token /// @returns the struct decoration or StructDecoraton::kNone if none matched - ast::StructDecoration struct_decoration(Token t); + std::unique_ptr<ast::StructDecoration> struct_decoration(Token t); /// Parses a `struct_body_decl` grammar element /// @returns the struct members ast::StructMemberList struct_body_decl();
diff --git a/src/reader/wgsl/parser_impl_struct_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decl_test.cc index 3222117..c217341 100644 --- a/src/reader/wgsl/parser_impl_struct_decl_test.cc +++ b/src/reader/wgsl/parser_impl_struct_decl_test.cc
@@ -51,7 +51,7 @@ EXPECT_EQ(s->impl()->members()[0]->name(), "a"); EXPECT_EQ(s->impl()->members()[1]->name(), "b"); ASSERT_EQ(s->impl()->decorations().size(), 1u); - EXPECT_EQ(s->impl()->decorations()[0], ast::StructDecoration::kBlock); + EXPECT_TRUE(s->impl()->decorations()[0]->IsBlock()); } TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) { @@ -69,8 +69,8 @@ EXPECT_EQ(s->impl()->members()[0]->name(), "a"); EXPECT_EQ(s->impl()->members()[1]->name(), "b"); ASSERT_EQ(s->impl()->decorations().size(), 2u); - EXPECT_EQ(s->impl()->decorations()[0], ast::StructDecoration::kBlock); - EXPECT_EQ(s->impl()->decorations()[1], ast::StructDecoration::kBlock); + EXPECT_TRUE(s->impl()->decorations()[0]->IsBlock()); + EXPECT_TRUE(s->impl()->decorations()[1]->IsBlock()); } TEST_F(ParserImplTest, StructDecl_EmptyMembers) {
diff --git a/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc index 5c0ef8e..3ff9674 100644 --- a/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc +++ b/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
@@ -27,7 +27,7 @@ ASSERT_TRUE(p->struct_decoration_decl(decos)); ASSERT_FALSE(p->has_error()); EXPECT_EQ(decos.size(), 1u); - EXPECT_EQ(decos[0], ast::StructDecoration::kBlock); + EXPECT_TRUE(decos[0]->IsBlock()); } TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {
diff --git a/src/reader/wgsl/parser_impl_struct_decoration_test.cc b/src/reader/wgsl/parser_impl_struct_decoration_test.cc index 4d07af4..a8da5b2 100644 --- a/src/reader/wgsl/parser_impl_struct_decoration_test.cc +++ b/src/reader/wgsl/parser_impl_struct_decoration_test.cc
@@ -24,7 +24,7 @@ struct StructDecorationData { const char* input; - ast::StructDecoration result; + bool is_block; }; inline std::ostream& operator<<(std::ostream& out, StructDecorationData data) { out << std::string(data.input); @@ -40,17 +40,16 @@ auto deco = p->struct_decoration(p->peek()); ASSERT_FALSE(p->has_error()); - EXPECT_EQ(deco, params.result); + EXPECT_EQ(deco->IsBlock(), params.is_block); } INSTANTIATE_TEST_SUITE_P(ParserImplTest, StructDecorationTest, - testing::Values(StructDecorationData{ - "block", ast::StructDecoration::kBlock})); + testing::Values(StructDecorationData{"block", true})); TEST_F(ParserImplTest, StructDecoration_NoMatch) { auto* p = parser("not-a-stage"); auto deco = p->struct_decoration(p->peek()); - ASSERT_EQ(deco, ast::StructDecoration::kNone); + ASSERT_EQ(deco, nullptr); auto t = p->next(); EXPECT_TRUE(t.IsIdentifier());
diff --git a/src/transform/vertex_pulling_transform.cc b/src/transform/vertex_pulling_transform.cc index 3ab074d..e8390d7 100644 --- a/src/transform/vertex_pulling_transform.cc +++ b/src/transform/vertex_pulling_transform.cc
@@ -25,6 +25,7 @@ #include "src/ast/scalar_constructor_expression.h" #include "src/ast/stride_decoration.h" #include "src/ast/struct.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/struct_member_offset_decoration.h" @@ -234,7 +235,7 @@ kStructBufferName, internal_array_type, std::move(member_dec))); ast::StructDecorationList decos; - decos.push_back(ast::StructDecoration::kBlock); + decos.push_back(std::make_unique<ast::StructBlockDecoration>()); auto* struct_type = ctx_->type_mgr().Get(std::make_unique<ast::type::StructType>(
diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc index 62c7bae..274a6be 100644 --- a/src/writer/hlsl/generator_impl_type_test.cc +++ b/src/writer/hlsl/generator_impl_type_test.cc
@@ -14,6 +14,7 @@ #include "src/ast/module.h" #include "src/ast/struct.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/struct_member_decoration.h" @@ -286,7 +287,7 @@ std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); ast::StructDecorationList decos; - decos.push_back(ast::StructDecoration::kBlock); + decos.push_back(std::make_unique<ast::StructBlockDecoration>()); auto str = std::make_unique<ast::Struct>(std::move(decos), std::move(members));
diff --git a/src/writer/msl/generator_impl_type_test.cc b/src/writer/msl/generator_impl_type_test.cc index d49714e..c3a1205 100644 --- a/src/writer/msl/generator_impl_type_test.cc +++ b/src/writer/msl/generator_impl_type_test.cc
@@ -15,6 +15,7 @@ #include "gtest/gtest.h" #include "src/ast/module.h" #include "src/ast/struct.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/struct_member_decoration.h" @@ -324,7 +325,7 @@ std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); ast::StructDecorationList decos; - decos.push_back(ast::StructDecoration::kBlock); + decos.push_back(std::make_unique<ast::StructBlockDecoration>()); auto str = std::make_unique<ast::Struct>(std::move(decos), std::move(members));
diff --git a/src/writer/spirv/builder_type_test.cc b/src/writer/spirv/builder_type_test.cc index fe8710e..aef87ed 100644 --- a/src/writer/spirv/builder_type_test.cc +++ b/src/writer/spirv/builder_type_test.cc
@@ -18,6 +18,7 @@ #include "src/ast/identifier_expression.h" #include "src/ast/stride_decoration.h" #include "src/ast/struct.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/struct_member_offset_decoration.h" #include "src/ast/type/access_control_type.h" @@ -361,7 +362,7 @@ std::make_unique<ast::StructMember>("a", &f32, std::move(decos))); ast::StructDecorationList struct_decos; - struct_decos.push_back(ast::StructDecoration::kBlock); + struct_decos.push_back(std::make_unique<ast::StructBlockDecoration>()); auto s = std::make_unique<ast::Struct>(std::move(struct_decos), std::move(members));
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc index 205df74..50c378b 100644 --- a/src/writer/wgsl/generator_impl.cc +++ b/src/writer/wgsl/generator_impl.cc
@@ -552,8 +552,10 @@ bool GeneratorImpl::EmitStructType(const ast::type::StructType* str) { auto* impl = str->impl(); - for (auto deco : impl->decorations()) { - out_ << "[[" << deco << "]]" << std::endl; + for (auto& deco : impl->decorations()) { + out_ << "[["; + deco->to_str(out_); + out_ << "]]" << std::endl; } out_ << "struct " << str->name() << " {" << std::endl;
diff --git a/src/writer/wgsl/generator_impl_type_test.cc b/src/writer/wgsl/generator_impl_type_test.cc index a8b5070..2fc6542 100644 --- a/src/writer/wgsl/generator_impl_type_test.cc +++ b/src/writer/wgsl/generator_impl_type_test.cc
@@ -15,6 +15,7 @@ #include "gtest/gtest.h" #include "src/ast/stride_decoration.h" #include "src/ast/struct.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/struct_member_decoration.h" @@ -204,7 +205,7 @@ std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); ast::StructDecorationList decos; - decos.push_back(ast::StructDecoration::kBlock); + decos.push_back(std::make_unique<ast::StructBlockDecoration>()); auto str = std::make_unique<ast::Struct>(std::move(decos), std::move(members));