CloneContext: Add InsertBack()

Inserts a new node at the end of a (potentially empty) list.

Change-Id: Ibd487b995aee4a3ae2c3d17b5eb6e8562c43a1c4
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/52320
Commit-Queue: James Price <jrprice@google.com>
Auto-Submit: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2021-05-26 15:12:12 +00:00 committed by Tint LUCI CQ
parent 61fbf13d25
commit 61e573663d
2 changed files with 94 additions and 0 deletions

View File

@ -246,6 +246,9 @@ class CloneContext {
} }
} }
} }
for (auto* o : transforms.insert_back_) {
out.emplace_back(CheckedCast<T>(o));
}
} else { } else {
for (auto& el : v) { for (auto& el : v) {
out.emplace_back(Clone(el)); out.emplace_back(Clone(el));
@ -391,6 +394,20 @@ class CloneContext {
return *this; return *this;
} }
/// Inserts `object` after any other objects of `vector`, when it is cloned.
/// @param vector the vector in #src
/// @param object a pointer to the object in #dst that will be inserted at the
/// end of the vector
/// @returns this CloneContext so calls can be chained
template <typename T, typename OBJECT>
CloneContext& InsertBack(const std::vector<T>& vector, OBJECT* object) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, object);
auto& transforms = list_transforms_[&vector];
auto& list = transforms.insert_back_;
list.emplace_back(object);
return *this;
}
/// Inserts `object` before `before` whenever `vector` is cloned. /// Inserts `object` before `before` whenever `vector` is cloned.
/// @param vector the vector in #src /// @param vector the vector in #src
/// @param before a pointer to the object in #src /// @param before a pointer to the object in #src
@ -502,6 +519,10 @@ class CloneContext {
/// cloned. /// cloned.
CloneableList insert_front_; CloneableList insert_front_;
/// A list of objects in #dst to insert befor after any others when the
/// vector is cloned.
CloneableList insert_back_;
/// A map of object in #src to the list of cloned objects in #dst. /// A map of object in #src to the list of cloned objects in #dst.
/// Clone(const std::vector<T*>& v) will use this to insert the map-value /// Clone(const std::vector<T*>& v) will use this to insert the map-value
/// list into the target vector before cloning and inserting the map-key. /// list into the target vector before cloning and inserting the map-key.

View File

@ -401,6 +401,79 @@ TEST_F(CloneContextNodeTest, CloneWithInsertFront_Empty) {
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion")); EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion"));
} }
TEST_F(CloneContextNodeTest, CloneWithInsertBack) {
Allocator a;
ProgramBuilder builder;
auto* original_root = a.Create<Node>(builder.Symbols().Register("root"));
original_root->a = a.Create<Node>(builder.Symbols().Register("a"));
original_root->b = a.Create<Node>(builder.Symbols().Register("b"));
original_root->c = a.Create<Node>(builder.Symbols().Register("c"));
original_root->vec = {original_root->a, original_root->b, original_root->c};
Program original(std::move(builder));
ProgramBuilder cloned;
auto* insertion = a.Create<Node>(cloned.Symbols().New("insertion"));
auto* cloned_root = CloneContext(&cloned, &original)
.InsertBack(original_root->vec, insertion)
.Clone(original_root);
EXPECT_EQ(cloned_root->vec.size(), 4u);
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
EXPECT_EQ(cloned_root->vec[1]->name, cloned.Symbols().Get("b"));
EXPECT_EQ(cloned_root->vec[2]->name, cloned.Symbols().Get("c"));
EXPECT_EQ(cloned_root->vec[3]->name, cloned.Symbols().Get("insertion"));
}
TEST_F(CloneContextNodeTest, CloneWithInsertBack_Empty) {
Allocator a;
ProgramBuilder builder;
auto* original_root = a.Create<Node>(builder.Symbols().Register("root"));
original_root->vec = {};
Program original(std::move(builder));
ProgramBuilder cloned;
auto* insertion = a.Create<Node>(cloned.Symbols().New("insertion"));
auto* cloned_root = CloneContext(&cloned, &original)
.InsertBack(original_root->vec, insertion)
.Clone(original_root);
EXPECT_EQ(cloned_root->vec.size(), 1u);
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion"));
}
TEST_F(CloneContextNodeTest, CloneWithInsertFrontAndBack_Empty) {
Allocator a;
ProgramBuilder builder;
auto* original_root = a.Create<Node>(builder.Symbols().Register("root"));
original_root->vec = {};
Program original(std::move(builder));
ProgramBuilder cloned;
auto* insertion_front =
a.Create<Node>(cloned.Symbols().New("insertion_front"));
auto* insertion_back = a.Create<Node>(cloned.Symbols().New("insertion_back"));
auto* cloned_root = CloneContext(&cloned, &original)
.InsertBack(original_root->vec, insertion_back)
.InsertFront(original_root->vec, insertion_front)
.Clone(original_root);
EXPECT_EQ(cloned_root->vec.size(), 2u);
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion_front"));
EXPECT_EQ(cloned_root->vec[1]->name, cloned.Symbols().Get("insertion_back"));
}
TEST_F(CloneContextNodeTest, CloneWithInsertBefore) { TEST_F(CloneContextNodeTest, CloneWithInsertBefore) {
Allocator a; Allocator a;