Add tint::Cloneable base class
The CloneContext was previously dealing with pointers to CastableBase, which has no guarantees that the object was actually cloneable. Add a Cloneable base class that CloneContext can use instead. Improves readability and produces cleaner compiler errors if you try to clone a non-cloneable object. Change-Id: I4352fc5dab3da434e4ab160a54c4c82d50e427b4 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/41722 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
f81df124f6
commit
52296de528
|
@ -19,7 +19,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "src/castable.h"
|
#include "src/clone_context.h"
|
||||||
#include "src/source.h"
|
#include "src/source.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -36,16 +36,10 @@ class Info;
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
/// AST base class node
|
/// AST base class node
|
||||||
class Node : public Castable<Node> {
|
class Node : public Castable<Node, Cloneable> {
|
||||||
public:
|
public:
|
||||||
~Node() override;
|
~Node() override;
|
||||||
|
|
||||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
|
||||||
/// `ctx`.
|
|
||||||
/// @param ctx the clone context
|
|
||||||
/// @return the newly cloned node
|
|
||||||
virtual Node* Clone(CloneContext* ctx) const = 0;
|
|
||||||
|
|
||||||
/// @returns the node source data
|
/// @returns the node source data
|
||||||
const Source& source() const { return source_; }
|
const Source& source() const { return source_; }
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "src/program.h"
|
#include "src/program.h"
|
||||||
#include "src/program_builder.h"
|
#include "src/program_builder.h"
|
||||||
|
|
||||||
|
TINT_INSTANTIATE_CLASS_ID(tint::Cloneable);
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
|
||||||
CloneContext::CloneContext(ProgramBuilder* to, Program const* from)
|
CloneContext::CloneContext(ProgramBuilder* to, Program const* from)
|
||||||
|
|
|
@ -28,15 +28,23 @@
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
|
class CloneContext;
|
||||||
class Program;
|
class Program;
|
||||||
class ProgramBuilder;
|
class ProgramBuilder;
|
||||||
|
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
class FunctionList;
|
class FunctionList;
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
|
||||||
|
/// Cloneable is the base class for all objects that can be cloned
|
||||||
|
class Cloneable : public Castable<Cloneable> {
|
||||||
|
public:
|
||||||
|
/// Performs a deep clone of this object using the CloneContext `ctx`.
|
||||||
|
/// @param ctx the clone context
|
||||||
|
/// @return the newly cloned object
|
||||||
|
virtual Cloneable* Clone(CloneContext* ctx) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
/// CloneContext holds the state used while cloning AST nodes and types.
|
/// CloneContext holds the state used while cloning AST nodes and types.
|
||||||
class CloneContext {
|
class CloneContext {
|
||||||
public:
|
public:
|
||||||
|
@ -186,7 +194,7 @@ class CloneContext {
|
||||||
///
|
///
|
||||||
/// `replacer` must be function-like with the signature:
|
/// `replacer` must be function-like with the signature:
|
||||||
/// `T* (CloneContext*, T*)`
|
/// `T* (CloneContext*, T*)`
|
||||||
/// where `T` is a type deriving from CastableBase.
|
/// where `T` is a type deriving from Cloneable.
|
||||||
///
|
///
|
||||||
/// If `replacer` returns a nullptr then Clone() will attempt the next
|
/// If `replacer` returns a nullptr then Clone() will attempt the next
|
||||||
/// registered replacer function that matches the object type. If no replacers
|
/// registered replacer function that matches the object type. If no replacers
|
||||||
|
@ -210,13 +218,13 @@ class CloneContext {
|
||||||
/// references of the original object. A type mismatch will result in an
|
/// references of the original object. A type mismatch will result in an
|
||||||
/// assertion in debug builds, and undefined behavior in release builds.
|
/// assertion in debug builds, and undefined behavior in release builds.
|
||||||
/// @param replacer a function or function-like object with the signature
|
/// @param replacer a function or function-like object with the signature
|
||||||
/// `T* (CloneContext*, T*)`, where `T` derives from CastableBase
|
/// `T* (CloneContext*, T*)`, where `T` derives from Cloneable
|
||||||
/// @returns this CloneContext so calls can be chained
|
/// @returns this CloneContext so calls can be chained
|
||||||
template <typename F>
|
template <typename F>
|
||||||
CloneContext& ReplaceAll(F replacer) {
|
CloneContext& ReplaceAll(F replacer) {
|
||||||
using TPtr = traits::ParamTypeT<F, 1>;
|
using TPtr = traits::ParamTypeT<F, 1>;
|
||||||
using T = typename std::remove_pointer<TPtr>::type;
|
using T = typename std::remove_pointer<TPtr>::type;
|
||||||
transforms_.emplace_back([=](CastableBase* in) {
|
transforms_.emplace_back([=](Cloneable* in) {
|
||||||
auto* in_as_t = in->As<T>();
|
auto* in_as_t = in->As<T>();
|
||||||
return in_as_t != nullptr ? replacer(this, in_as_t) : nullptr;
|
return in_as_t != nullptr ? replacer(this, in_as_t) : nullptr;
|
||||||
});
|
});
|
||||||
|
@ -264,7 +272,7 @@ class CloneContext {
|
||||||
Program const* const src;
|
Program const* const src;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Transform = std::function<CastableBase*(CastableBase*)>;
|
using Transform = std::function<Cloneable*(Cloneable*)>;
|
||||||
|
|
||||||
CloneContext(const CloneContext&) = delete;
|
CloneContext(const CloneContext&) = delete;
|
||||||
CloneContext& operator=(const CloneContext&) = delete;
|
CloneContext& operator=(const CloneContext&) = delete;
|
||||||
|
@ -272,7 +280,7 @@ class CloneContext {
|
||||||
/// LookupOrTransform is the template-independent logic of Clone().
|
/// LookupOrTransform is the template-independent logic of Clone().
|
||||||
/// This is outside of Clone() to reduce the amount of template-instantiated
|
/// This is outside of Clone() to reduce the amount of template-instantiated
|
||||||
/// code.
|
/// code.
|
||||||
CastableBase* LookupOrTransform(CastableBase* a) {
|
Cloneable* LookupOrTransform(Cloneable* a) {
|
||||||
// Have we seen this object before? If so, return the previously cloned
|
// Have we seen this object before? If so, return the previously cloned
|
||||||
// version instead of making yet another copy.
|
// version instead of making yet another copy.
|
||||||
auto it = cloned_.find(a);
|
auto it = cloned_.find(a);
|
||||||
|
@ -282,7 +290,7 @@ class CloneContext {
|
||||||
|
|
||||||
// Attempt to clone using the registered replacer functions.
|
// Attempt to clone using the registered replacer functions.
|
||||||
for (auto& f : transforms_) {
|
for (auto& f : transforms_) {
|
||||||
if (CastableBase* c = f(a)) {
|
if (Cloneable* c = f(a)) {
|
||||||
cloned_.emplace(a, c);
|
cloned_.emplace(a, c);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -301,16 +309,16 @@ class CloneContext {
|
||||||
return cast;
|
return cast;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A vector of CastableBase*
|
/// A vector of Cloneable*
|
||||||
using CastableList = std::vector<CastableBase*>;
|
using CloneableList = std::vector<Cloneable*>;
|
||||||
|
|
||||||
/// A map of object in #src to their cloned equivalent in #dst
|
/// A map of object in #src to their cloned equivalent in #dst
|
||||||
std::unordered_map<CastableBase*, CastableBase*> cloned_;
|
std::unordered_map<Cloneable*, Cloneable*> cloned_;
|
||||||
|
|
||||||
/// 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 list
|
/// 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.
|
/// into the target vector/ before cloning and inserting the map-key.
|
||||||
std::unordered_map<CastableBase*, CastableList> insert_before_;
|
std::unordered_map<Cloneable*, CloneableList> insert_before_;
|
||||||
|
|
||||||
/// Transform functions registered with ReplaceAll()
|
/// Transform functions registered with ReplaceAll()
|
||||||
std::vector<Transform> transforms_;
|
std::vector<Transform> transforms_;
|
||||||
|
|
|
@ -25,18 +25,17 @@
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct Cloneable : public Castable<Cloneable, ast::Node> {
|
struct Node : public Castable<Node, ast::Node> {
|
||||||
explicit Cloneable(const Source& source, std::string n)
|
explicit Node(const Source& source, std::string n) : Base(source), name(n) {}
|
||||||
: Base(source), name(n) {}
|
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
Cloneable* a = nullptr;
|
Node* a = nullptr;
|
||||||
Cloneable* b = nullptr;
|
Node* b = nullptr;
|
||||||
Cloneable* c = nullptr;
|
Node* c = nullptr;
|
||||||
std::vector<Cloneable*> vec;
|
std::vector<Node*> vec;
|
||||||
|
|
||||||
Cloneable* Clone(CloneContext* ctx) const override {
|
Node* Clone(CloneContext* ctx) const override {
|
||||||
auto* out = ctx->dst->create<Cloneable>(name);
|
auto* out = ctx->dst->create<Node>(name);
|
||||||
out->a = ctx->Clone(a);
|
out->a = ctx->Clone(a);
|
||||||
out->b = ctx->Clone(b);
|
out->b = ctx->Clone(b);
|
||||||
out->c = ctx->Clone(c);
|
out->c = ctx->Clone(c);
|
||||||
|
@ -48,18 +47,18 @@ struct Cloneable : public Castable<Cloneable, ast::Node> {
|
||||||
void to_str(const semantic::Info&, std::ostream&, size_t) const override {}
|
void to_str(const semantic::Info&, std::ostream&, size_t) const override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Replaceable : public Castable<Replaceable, Cloneable> {
|
struct Replaceable : public Castable<Replaceable, Node> {
|
||||||
explicit Replaceable(const Source& source, std::string n) : Base(source, n) {}
|
explicit Replaceable(const Source& source, std::string n) : Base(source, n) {}
|
||||||
};
|
};
|
||||||
struct Replacement : public Castable<Replacement, Replaceable> {
|
struct Replacement : public Castable<Replacement, Replaceable> {
|
||||||
explicit Replacement(const Source& source, std::string n) : Base(source, n) {}
|
explicit Replacement(const Source& source, std::string n) : Base(source, n) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NotACloneable : public Castable<NotACloneable, ast::Node> {
|
struct NotANode : public Castable<NotANode, ast::Node> {
|
||||||
explicit NotACloneable(const Source& source) : Base(source) {}
|
explicit NotANode(const Source& source) : Base(source) {}
|
||||||
|
|
||||||
NotACloneable* Clone(CloneContext* ctx) const override {
|
NotANode* Clone(CloneContext* ctx) const override {
|
||||||
return ctx->dst->create<NotACloneable>();
|
return ctx->dst->create<NotANode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValid() const override { return true; }
|
bool IsValid() const override { return true; }
|
||||||
|
@ -68,24 +67,24 @@ struct NotACloneable : public Castable<NotACloneable, ast::Node> {
|
||||||
|
|
||||||
TEST(CloneContext, Clone) {
|
TEST(CloneContext, Clone) {
|
||||||
ProgramBuilder builder;
|
ProgramBuilder builder;
|
||||||
auto* original_root = builder.create<Cloneable>("root");
|
auto* original_root = builder.create<Node>("root");
|
||||||
original_root->a = builder.create<Cloneable>("a");
|
original_root->a = builder.create<Node>("a");
|
||||||
original_root->a->b = builder.create<Cloneable>("a->b");
|
original_root->a->b = builder.create<Node>("a->b");
|
||||||
original_root->b = builder.create<Cloneable>("b");
|
original_root->b = builder.create<Node>("b");
|
||||||
original_root->b->a = original_root->a; // Aliased
|
original_root->b->a = original_root->a; // Aliased
|
||||||
original_root->b->b = builder.create<Cloneable>("b->b");
|
original_root->b->b = builder.create<Node>("b->b");
|
||||||
original_root->c = original_root->b; // Aliased
|
original_root->c = original_root->b; // Aliased
|
||||||
Program original(std::move(builder));
|
Program original(std::move(builder));
|
||||||
|
|
||||||
// root
|
// root
|
||||||
// ╭──────────────────┼──────────────────╮
|
// ╭──────────────────┼──────────────────╮
|
||||||
// (a) (b) (c)
|
// (a) (b) (c)
|
||||||
// C <──────┐ C <───────────────┘
|
// N <──────┐ N <───────────────┘
|
||||||
// ╭────┼────╮ │ ╭────┼────╮
|
// ╭────┼────╮ │ ╭────┼────╮
|
||||||
// (a) (b) (c) │ (a) (b) (c)
|
// (a) (b) (c) │ (a) (b) (c)
|
||||||
// C └───┘ C
|
// N └───┘ N
|
||||||
//
|
//
|
||||||
// C: Clonable
|
// N: Node
|
||||||
|
|
||||||
ProgramBuilder cloned;
|
ProgramBuilder cloned;
|
||||||
auto* cloned_root = CloneContext(&cloned, &original).Clone(original_root);
|
auto* cloned_root = CloneContext(&cloned, &original).Clone(original_root);
|
||||||
|
@ -119,8 +118,8 @@ TEST(CloneContext, Clone) {
|
||||||
|
|
||||||
TEST(CloneContext, CloneWithReplacements) {
|
TEST(CloneContext, CloneWithReplacements) {
|
||||||
ProgramBuilder builder;
|
ProgramBuilder builder;
|
||||||
auto* original_root = builder.create<Cloneable>("root");
|
auto* original_root = builder.create<Node>("root");
|
||||||
original_root->a = builder.create<Cloneable>("a");
|
original_root->a = builder.create<Node>("a");
|
||||||
original_root->a->b = builder.create<Replaceable>("a->b");
|
original_root->a->b = builder.create<Replaceable>("a->b");
|
||||||
original_root->b = builder.create<Replaceable>("b");
|
original_root->b = builder.create<Replaceable>("b");
|
||||||
original_root->b->a = original_root->a; // Aliased
|
original_root->b->a = original_root->a; // Aliased
|
||||||
|
@ -130,12 +129,12 @@ TEST(CloneContext, CloneWithReplacements) {
|
||||||
// root
|
// root
|
||||||
// ╭──────────────────┼──────────────────╮
|
// ╭──────────────────┼──────────────────╮
|
||||||
// (a) (b) (c)
|
// (a) (b) (c)
|
||||||
// C <──────┐ R <───────────────┘
|
// N <──────┐ R <───────────────┘
|
||||||
// ╭────┼────╮ │ ╭────┼────╮
|
// ╭────┼────╮ │ ╭────┼────╮
|
||||||
// (a) (b) (c) │ (a) (b) (c)
|
// (a) (b) (c) │ (a) (b) (c)
|
||||||
// R └───┘
|
// R └───┘
|
||||||
//
|
//
|
||||||
// C: Clonable
|
// N: Node
|
||||||
// R: Replaceable
|
// R: Replaceable
|
||||||
|
|
||||||
ProgramBuilder cloned;
|
ProgramBuilder cloned;
|
||||||
|
@ -143,7 +142,7 @@ TEST(CloneContext, CloneWithReplacements) {
|
||||||
CloneContext(&cloned, &original)
|
CloneContext(&cloned, &original)
|
||||||
.ReplaceAll([&](CloneContext* ctx, Replaceable* in) {
|
.ReplaceAll([&](CloneContext* ctx, Replaceable* in) {
|
||||||
auto* out = cloned.create<Replacement>("replacement:" + in->name);
|
auto* out = cloned.create<Replacement>("replacement:" + in->name);
|
||||||
out->b = cloned.create<Cloneable>("replacement-child:" + in->name);
|
out->b = cloned.create<Node>("replacement-child:" + in->name);
|
||||||
out->c = ctx->Clone(in->a);
|
out->c = ctx->Clone(in->a);
|
||||||
return out;
|
return out;
|
||||||
})
|
})
|
||||||
|
@ -152,15 +151,15 @@ TEST(CloneContext, CloneWithReplacements) {
|
||||||
// root
|
// root
|
||||||
// ╭─────────────────┼──────────────────╮
|
// ╭─────────────────┼──────────────────╮
|
||||||
// (a) (b) (c)
|
// (a) (b) (c)
|
||||||
// C <──────┐ R <───────────────┘
|
// N <──────┐ R <───────────────┘
|
||||||
// ╭────┼────╮ │ ╭────┼────╮
|
// ╭────┼────╮ │ ╭────┼────╮
|
||||||
// (a) (b) (c) │ (a) (b) (c)
|
// (a) (b) (c) │ (a) (b) (c)
|
||||||
// R │ C |
|
// R │ N |
|
||||||
// ╭────┼────╮ └────────────┘
|
// ╭────┼────╮ └────────────┘
|
||||||
// (a) (b) (c)
|
// (a) (b) (c)
|
||||||
// C
|
// N
|
||||||
//
|
//
|
||||||
// C: Clonable
|
// N: Node
|
||||||
// R: Replacement
|
// R: Replacement
|
||||||
|
|
||||||
EXPECT_NE(cloned_root->a, nullptr);
|
EXPECT_NE(cloned_root->a, nullptr);
|
||||||
|
@ -201,10 +200,10 @@ TEST(CloneContext, CloneWithReplacements) {
|
||||||
|
|
||||||
TEST(CloneContext, CloneWithReplace) {
|
TEST(CloneContext, CloneWithReplace) {
|
||||||
ProgramBuilder builder;
|
ProgramBuilder builder;
|
||||||
auto* original_root = builder.create<Cloneable>("root");
|
auto* original_root = builder.create<Node>("root");
|
||||||
original_root->a = builder.create<Cloneable>("a");
|
original_root->a = builder.create<Node>("a");
|
||||||
original_root->b = builder.create<Cloneable>("b");
|
original_root->b = builder.create<Node>("b");
|
||||||
original_root->c = builder.create<Cloneable>("c");
|
original_root->c = builder.create<Node>("c");
|
||||||
Program original(std::move(builder));
|
Program original(std::move(builder));
|
||||||
|
|
||||||
// root
|
// root
|
||||||
|
@ -213,7 +212,7 @@ TEST(CloneContext, CloneWithReplace) {
|
||||||
// Replaced
|
// Replaced
|
||||||
|
|
||||||
ProgramBuilder cloned;
|
ProgramBuilder cloned;
|
||||||
auto* replacement = cloned.create<Cloneable>("replacement");
|
auto* replacement = cloned.create<Node>("replacement");
|
||||||
|
|
||||||
auto* cloned_root = CloneContext(&cloned, &original)
|
auto* cloned_root = CloneContext(&cloned, &original)
|
||||||
.Replace(original_root->b, replacement)
|
.Replace(original_root->b, replacement)
|
||||||
|
@ -231,15 +230,15 @@ TEST(CloneContext, CloneWithReplace) {
|
||||||
|
|
||||||
TEST(CloneContext, CloneWithInsertBefore) {
|
TEST(CloneContext, CloneWithInsertBefore) {
|
||||||
ProgramBuilder builder;
|
ProgramBuilder builder;
|
||||||
auto* original_root = builder.create<Cloneable>("root");
|
auto* original_root = builder.create<Node>("root");
|
||||||
original_root->a = builder.create<Cloneable>("a");
|
original_root->a = builder.create<Node>("a");
|
||||||
original_root->b = builder.create<Cloneable>("b");
|
original_root->b = builder.create<Node>("b");
|
||||||
original_root->c = builder.create<Cloneable>("c");
|
original_root->c = builder.create<Node>("c");
|
||||||
original_root->vec = {original_root->a, original_root->b, original_root->c};
|
original_root->vec = {original_root->a, original_root->b, original_root->c};
|
||||||
Program original(std::move(builder));
|
Program original(std::move(builder));
|
||||||
|
|
||||||
ProgramBuilder cloned;
|
ProgramBuilder cloned;
|
||||||
auto* insertion = cloned.create<Cloneable>("insertion");
|
auto* insertion = cloned.create<Node>("insertion");
|
||||||
|
|
||||||
auto* cloned_root = CloneContext(&cloned, &original)
|
auto* cloned_root = CloneContext(&cloned, &original)
|
||||||
.InsertBefore(original_root->b, insertion)
|
.InsertBefore(original_root->b, insertion)
|
||||||
|
@ -257,12 +256,12 @@ TEST(CloneContext, CloneWithInsertBefore) {
|
||||||
EXPECT_EQ(cloned_root->vec[3]->name, "c");
|
EXPECT_EQ(cloned_root->vec[3]->name, "c");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CloneContext, CloneWithReplace_WithNotACloneable) {
|
TEST(CloneContext, CloneWithReplace_WithNotANode) {
|
||||||
ProgramBuilder builder;
|
ProgramBuilder builder;
|
||||||
auto* original_root = builder.create<Cloneable>("root");
|
auto* original_root = builder.create<Node>("root");
|
||||||
original_root->a = builder.create<Cloneable>("a");
|
original_root->a = builder.create<Node>("a");
|
||||||
original_root->b = builder.create<Cloneable>("b");
|
original_root->b = builder.create<Node>("b");
|
||||||
original_root->c = builder.create<Cloneable>("c");
|
original_root->c = builder.create<Node>("c");
|
||||||
Program original(std::move(builder));
|
Program original(std::move(builder));
|
||||||
|
|
||||||
// root
|
// root
|
||||||
|
@ -271,7 +270,7 @@ TEST(CloneContext, CloneWithReplace_WithNotACloneable) {
|
||||||
// Replaced
|
// Replaced
|
||||||
|
|
||||||
ProgramBuilder cloned;
|
ProgramBuilder cloned;
|
||||||
auto* replacement = cloned.create<NotACloneable>();
|
auto* replacement = cloned.create<NotANode>();
|
||||||
|
|
||||||
CloneContext ctx(&cloned, &original);
|
CloneContext ctx(&cloned, &original);
|
||||||
ctx.Replace(original_root->b, replacement);
|
ctx.Replace(original_root->b, replacement);
|
||||||
|
@ -289,9 +288,9 @@ TEST(CloneContext, CloneWithReplace_WithNotACloneable) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TINT_INSTANTIATE_CLASS_ID(Cloneable);
|
TINT_INSTANTIATE_CLASS_ID(Node);
|
||||||
TINT_INSTANTIATE_CLASS_ID(Replaceable);
|
TINT_INSTANTIATE_CLASS_ID(Replaceable);
|
||||||
TINT_INSTANTIATE_CLASS_ID(Replacement);
|
TINT_INSTANTIATE_CLASS_ID(Replacement);
|
||||||
TINT_INSTANTIATE_CLASS_ID(NotACloneable);
|
TINT_INSTANTIATE_CLASS_ID(NotANode);
|
||||||
|
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "src/castable.h"
|
|
||||||
#include "src/clone_context.h"
|
#include "src/clone_context.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -32,17 +31,12 @@ namespace type {
|
||||||
enum class MemoryLayout { kUniformBuffer, kStorageBuffer };
|
enum class MemoryLayout { kUniformBuffer, kStorageBuffer };
|
||||||
|
|
||||||
/// Base class for a type in the system
|
/// Base class for a type in the system
|
||||||
class Type : public Castable<Type> {
|
class Type : public Castable<Type, Cloneable> {
|
||||||
public:
|
public:
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Type(Type&&);
|
Type(Type&&);
|
||||||
~Type() override;
|
~Type() override;
|
||||||
|
|
||||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
|
||||||
/// @param ctx the clone context
|
|
||||||
/// @return the newly cloned type
|
|
||||||
virtual Type* Clone(CloneContext* ctx) const = 0;
|
|
||||||
|
|
||||||
/// @returns the name for this type. The type name is unique over all types.
|
/// @returns the name for this type. The type name is unique over all types.
|
||||||
virtual std::string type_name() const = 0;
|
virtual std::string type_name() const = 0;
|
||||||
|
|
||||||
|
@ -114,16 +108,6 @@ class Type : public Castable<Type> {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Type();
|
Type();
|
||||||
|
|
||||||
/// A helper method for cloning the `Type` `t` if it is not null.
|
|
||||||
/// If `t` is null, then `Clone()` returns null.
|
|
||||||
/// @param b the program builder to clone `n` into
|
|
||||||
/// @param t the `Type` to clone (if not null)
|
|
||||||
/// @return the cloned type
|
|
||||||
template <typename T>
|
|
||||||
static T* Clone(ProgramBuilder* b, const T* t) {
|
|
||||||
return (t != nullptr) ? static_cast<T*>(t->Clone(b)) : nullptr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace type
|
} // namespace type
|
||||||
|
|
Loading…
Reference in New Issue