CloneContext: Add InsertFront()
Inserts a new node at the start of a (potentially empty) list.
Change-Id: Ie2896fa3e1beabeb89f64e69a84091986ffbf7a2
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/51369
Reviewed-by: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/clone_context.h b/src/clone_context.h
index 6e46f8f..c743d3b 100644
--- a/src/clone_context.h
+++ b/src/clone_context.h
@@ -226,6 +226,9 @@
auto list_transform_it = list_transforms_.find(&v);
if (list_transform_it != list_transforms_.end()) {
const auto& transforms = list_transform_it->second;
+ for (auto* o : transforms.insert_front_) {
+ out.emplace_back(CheckedCast<T>(o));
+ }
for (auto& el : v) {
auto insert_before_it = transforms.insert_before_.find(el);
if (insert_before_it != transforms.insert_before_.end()) {
@@ -374,6 +377,20 @@
return *this;
}
+ /// Inserts `object` before 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
+ /// front of the vector
+ /// @returns this CloneContext so calls can be chained
+ template <typename T, typename OBJECT>
+ CloneContext& InsertFront(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_front_;
+ list.emplace_back(object);
+ return *this;
+ }
+
/// Inserts `object` before `before` whenever `vector` is cloned.
/// @param vector the vector in #src
/// @param before a pointer to the object in #src
@@ -481,6 +498,10 @@
/// A map of object in #src to omit when cloned into #dst.
std::unordered_set<const Cloneable*> remove_;
+ /// A list of objects in #dst to insert before any others when the vector is
+ /// cloned.
+ CloneableList insert_front_;
+
/// 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
/// list into the target vector before cloning and inserting the map-key.
diff --git a/src/clone_context_test.cc b/src/clone_context_test.cc
index cd53cb7..ccf18a9 100644
--- a/src/clone_context_test.cc
+++ b/src/clone_context_test.cc
@@ -349,6 +349,58 @@
EXPECT_EQ(cloned_root->vec[1]->name, cloned.Symbols().Get("c"));
}
+TEST_F(CloneContextNodeTest, CloneWithInsertFront) {
+ 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)
+ .InsertFront(original_root->vec, insertion)
+ .Clone(original_root);
+
+ EXPECT_EQ(cloned_root->vec.size(), 4u);
+
+ EXPECT_NE(cloned_root->vec[0], cloned_root->a);
+ EXPECT_NE(cloned_root->vec[1], cloned_root->b);
+ EXPECT_NE(cloned_root->vec[2], cloned_root->c);
+
+ EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
+ EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion"));
+ EXPECT_EQ(cloned_root->vec[1]->name, cloned.Symbols().Get("a"));
+ EXPECT_EQ(cloned_root->vec[2]->name, cloned.Symbols().Get("b"));
+ EXPECT_EQ(cloned_root->vec[3]->name, cloned.Symbols().Get("c"));
+}
+
+TEST_F(CloneContextNodeTest, CloneWithInsertFront_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)
+ .InsertFront(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, CloneWithInsertBefore) {
Allocator a;