From 30678b1dad3c5e994bda4f25e8b0c41efbcab987 Mon Sep 17 00:00:00 2001 From: Alastair Robertson Date: Thu, 2 Nov 2023 06:08:08 -0700 Subject: [PATCH] TypeGraph: Create Mutator and RecursiveMutator base classes --- oi/type_graph/Types.cpp | 3 ++ oi/type_graph/Types.h | 76 +++++++++++++++++++++++++++++--------- oi/type_graph/Visitor.h | 81 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 18 deletions(-) diff --git a/oi/type_graph/Types.cpp b/oi/type_graph/Types.cpp index bed5f5d..8be091f 100644 --- a/oi/type_graph/Types.cpp +++ b/oi/type_graph/Types.cpp @@ -23,6 +23,9 @@ namespace oi::detail::type_graph { void OI_TYPE_NAME::accept(Visitor& v) { \ v.visit(*this); \ } \ + Type& OI_TYPE_NAME::accept(Mutator& m) { \ + return m.visit(*this); \ + } \ void OI_TYPE_NAME::accept(ConstVisitor& v) const { \ v.visit(*this); \ } diff --git a/oi/type_graph/Types.h b/oi/type_graph/Types.h index 40f1628..03f8f81 100644 --- a/oi/type_graph/Types.h +++ b/oi/type_graph/Types.h @@ -67,9 +67,11 @@ enum class Qualifier { using QualifierSet = EnumBitset(Qualifier::Max)>; class Visitor; +class Mutator; class ConstVisitor; -#define DECLARE_ACCEPT \ - void accept(Visitor& v) override; \ +#define DECLARE_ACCEPT \ + void accept(Visitor& v) override; \ + Type& accept(Mutator& m) override; \ void accept(ConstVisitor& v) const override; // TODO delete copy and move ctors @@ -83,6 +85,7 @@ class Type { public: virtual ~Type() = default; virtual void accept(Visitor& v) = 0; + virtual Type& accept(Mutator& m) = 0; virtual void accept(ConstVisitor& v) const = 0; virtual const std::string& name() const = 0; @@ -123,6 +126,10 @@ class Member { return type_; } + void setType(Type& type) { + type_ = type; + } + private: std::reference_wrapper type_; @@ -152,6 +159,10 @@ struct Parent { return type_; } + void setType(Type& type) { + type_ = type; + } + // uint64_t offset() const { // return offset_; // } @@ -178,6 +189,10 @@ struct TemplateParam { return type_; } + void setType(Type& type) { + type_ = type; + } + private: std::reference_wrapper type_; @@ -426,6 +441,10 @@ class Container : public Type { return id_; } + void setAlign(uint64_t alignment) { + align_ = alignment; + } + std::vector templateParams; const ContainerInfo& containerInfo_; @@ -433,6 +452,7 @@ class Container : public Type { std::string name_; std::string inputName_; size_t size_; + uint64_t align_ = 0; NodeId id_ = -1; }; @@ -506,7 +526,7 @@ class Array : public Type { } void regenerateName() { - name_ = std::string{"OIArray<"} + elementType_.name() + ", " + + name_ = std::string{"OIArray<"} + elementType_.get().name() + ", " + std::to_string(len_) + ">"; } @@ -519,11 +539,11 @@ class Array : public Type { } virtual size_t size() const override { - return len_ * elementType_.size(); + return len_ * elementType_.get().size(); } virtual uint64_t align() const override { - return elementType_.align(); + return elementType_.get().align(); } virtual NodeId id() const override { @@ -534,12 +554,16 @@ class Array : public Type { return elementType_; } + void setElementType(Type& type) { + elementType_ = type; + } + size_t len() const { return len_; } private: - Type& elementType_; + std::reference_wrapper elementType_; std::string inputName_; size_t len_; NodeId id_ = -1; @@ -623,11 +647,11 @@ class Typedef : public Type { } virtual size_t size() const override { - return underlyingType_.size(); + return underlyingType_.get().size(); } virtual uint64_t align() const override { - return underlyingType_.align(); + return underlyingType_.get().align(); } virtual NodeId id() const override { @@ -638,10 +662,14 @@ class Typedef : public Type { return underlyingType_; } + void setUnderlyingType(Type& type) { + underlyingType_ = type; + } + private: std::string name_; std::string inputName_; - Type& underlyingType_; + std::reference_wrapper underlyingType_; NodeId id_ = -1; }; @@ -661,7 +689,7 @@ class Pointer : public Type { } void regenerateName() { - name_ = pointeeType_.name() + "*"; + name_ = pointeeType_.get().name() + "*"; } virtual std::string_view inputName() const override { @@ -688,8 +716,12 @@ class Pointer : public Type { return pointeeType_; } + void setPointeeType(Type& type) { + pointeeType_ = type; + } + private: - Type& pointeeType_; + std::reference_wrapper pointeeType_; std::string inputName_; NodeId id_ = -1; @@ -772,7 +804,7 @@ class DummyAllocator : public Type { } void regenerateName() { - name_ = std::string{"DummyAllocator<"} + type_.name() + ", " + + name_ = std::string{"DummyAllocator<"} + type_.get().name() + ", " + std::to_string(size_) + ", " + std::to_string(align_) + ", " + std::to_string(id_) + ">"; } @@ -797,8 +829,12 @@ class DummyAllocator : public Type { return type_; } + void setAllocType(Type& type) { + type_ = type; + } + private: - Type& type_; + std::reference_wrapper type_; size_t size_; uint64_t align_; NodeId id_ = -1; @@ -828,19 +864,19 @@ class CaptureKeys : public Type { } virtual std::string_view inputName() const override { - return container_.inputName(); + return container_.get().inputName(); } void regenerateName() { - name_ = "OICaptureKeys<" + container_.name() + ">"; + name_ = "OICaptureKeys<" + container_.get().name() + ">"; } virtual size_t size() const override { - return container_.size(); + return container_.get().size(); } virtual uint64_t align() const override { - return container_.align(); + return container_.get().align(); } virtual NodeId id() const override { @@ -855,8 +891,12 @@ class CaptureKeys : public Type { return container_; } + void setContainer(Container& container) { + container_ = container; + } + private: - Container& container_; + std::reference_wrapper container_; const ContainerInfo& containerInfo_; std::string name_; }; diff --git a/oi/type_graph/Visitor.h b/oi/type_graph/Visitor.h index 9d932c5..7e4395e 100644 --- a/oi/type_graph/Visitor.h +++ b/oi/type_graph/Visitor.h @@ -32,6 +32,7 @@ namespace oi::detail::type_graph { * Visitor * * Abstract visitor base class. + * A visitor simply walks over nodes in a type graph. */ class Visitor { public: @@ -42,6 +43,21 @@ class Visitor { #undef X }; +/* + * Mutator + * + * Abstract mutator base class. + * A mutator replaces nodes in a type graph with the node returned by visit(). + */ +class Mutator { + public: + virtual ~Mutator() = default; + +#define X(OI_TYPE_NAME) virtual Type& visit(OI_TYPE_NAME&) = 0; + OI_TYPE_LIST +#undef X +}; + /* * LazyVisitor * @@ -115,6 +131,71 @@ class RecursiveVisitor : public Visitor { } }; +/* + * RecursiveMutator + * + * Mutator base class which recurses into types by default. + */ +class RecursiveMutator : public Mutator { + public: + virtual ~RecursiveMutator() = default; + virtual Type& mutate(Type&) = 0; + virtual Type& visit(Incomplete& i) { + return i; + } + virtual Type& visit(Class& c) { + for (auto& param : c.templateParams) { + param.setType(mutate(param.type())); + } + for (auto& parent : c.parents) { + parent.setType(mutate(parent.type())); + } + for (auto& mem : c.members) { + mem.setType(mutate(mem.type())); + } + for (auto& child : c.children) { + child = dynamic_cast(mutate(child)); + } + return c; + } + virtual Type& visit(Container& c) { + for (auto& param : c.templateParams) { + param.setType(mutate(param.type())); + } + return c; + } + virtual Type& visit(Primitive& p) { + return p; + } + virtual Type& visit(Enum& e) { + return e; + } + virtual Type& visit(Array& a) { + a.setElementType(mutate(a.elementType())); + return a; + } + virtual Type& visit(Typedef& td) { + td.setUnderlyingType(mutate(td.underlyingType())); + return td; + } + virtual Type& visit(Pointer& p) { + p.setPointeeType(mutate(p.pointeeType())); + return p; + } + virtual Type& visit(Dummy& d) { + return d; + } + virtual Type& visit(DummyAllocator& d) { + d.setAllocType(mutate(d.allocType())); + return d; + } + virtual Type& visit(CaptureKeys& c) { + auto& newContainer = dynamic_cast(mutate(c.container())); + c.setContainer(newContainer); + return c; + } +}; + /* * ConstVisitor *