summaryrefslogtreecommitdiffstats
path: root/tools/slang-cpp-extractor/node.h
diff options
context:
space:
mode:
Diffstat (limited to 'tools/slang-cpp-extractor/node.h')
-rw-r--r--tools/slang-cpp-extractor/node.h221
1 files changed, 221 insertions, 0 deletions
diff --git a/tools/slang-cpp-extractor/node.h b/tools/slang-cpp-extractor/node.h
new file mode 100644
index 000000000..c98a9204d
--- /dev/null
+++ b/tools/slang-cpp-extractor/node.h
@@ -0,0 +1,221 @@
+#ifndef CPP_EXTRACT_NODE_H
+#define CPP_EXTRACT_NODE_H
+
+#include "diagnostics.h"
+
+namespace CppExtract {
+using namespace Slang;
+
+enum class ReflectionType : uint8_t
+{
+ NotReflected,
+ Reflected,
+};
+
+// Pre-declare
+class TypeSet;
+class SourceOrigin;
+
+struct ScopeNode;
+
+class Node : public RefObject
+{
+public:
+ enum class Type : uint8_t
+ {
+ Invalid,
+
+ StructType,
+ ClassType,
+
+ Namespace,
+ AnonymousNamespace,
+
+ Field,
+ };
+
+ enum class TypeRange
+ {
+ ScopeStart = int(Type::StructType),
+ ScopeEnd = int(Type::AnonymousNamespace),
+
+ ClassLikeStart = int(Type::StructType),
+ ClassLikeEnd = int(Type::ClassType),
+ };
+
+ static bool isScopeType(Type type) { return int(type) >= int(TypeRange::ScopeStart) && int(type) <= int(TypeRange::ScopeEnd); }
+ static bool isClassLikeType(Type type) { return int(type) >= int(TypeRange::ClassLikeStart) && int(type) <= int(TypeRange::ClassLikeEnd); }
+
+ static bool isType(Type type) { return true; }
+
+ bool isClassLike() const { return isClassLikeType(m_type); }
+
+ virtual void dump(int indent, StringBuilder& out) = 0;
+
+ /// Do depth first traversal of nodes in scopes
+ virtual void calcScopeDepthFirst(List<Node*>& outNodes);
+
+ /// Calculate the absolute name for this namespace/type
+ void calcAbsoluteName(StringBuilder& outName) const;
+
+ /// Get the absolute name
+ String getAbsoluteName() const { StringBuilder buf; calcAbsoluteName(buf); return buf.ProduceString(); }
+
+ /// Calculate the scope path to this node, from the root
+ void calcScopePath(List<Node*>& outPath) { calcScopePath(this, outPath); }
+
+ /// True if reflected
+ bool isReflected() const { return m_reflectionType == ReflectionType::Reflected; }
+
+ typedef bool(*Filter)(Node* node);
+
+ static bool isClassLikeAndReflected(Node* node) { return node->isClassLike() && node->isReflected(); }
+ static bool isClassLike(Node* node) { return isClassLikeType(node->m_type); }
+
+ template <typename T>
+ static void filter(Filter filter, List<T*>& io) { const Node* _isNodeDerived = (T*)nullptr; SLANG_UNUSED(_isNodeDerived); filterImpl(filter, reinterpret_cast<List<Node*>&>(io)); }
+
+ static void filterImpl(Filter filter, List<Node*>& io);
+
+ static void calcScopePath(Node* node, List<Node*>& outPath);
+
+ /// Find the name starting in specified scope
+ static Node* findNode(ScopeNode* scope, const UnownedStringSlice& name);
+
+ Node(Type type) :
+ m_type(type),
+ m_parentScope(nullptr),
+ m_reflectionType(ReflectionType::NotReflected)
+ {
+ }
+
+ Type m_type; ///< The type of node this is
+ ReflectionType m_reflectionType; /// Classes can be traversed, but not reflected. To be reflected they have to contain the marker
+
+ Token m_name; ///< The name of this scope/type
+
+ ScopeNode* m_parentScope; ///< The scope this type/scope is defined in
+};
+
+struct ScopeNode : public Node
+{
+ typedef Node Super;
+
+ static bool isType(Type type) { return isScopeType(type); }
+
+ virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
+ virtual void calcScopeDepthFirst(List<Node*>& outNodes) SLANG_OVERRIDE;
+
+ /// True if can accept fields (class like types can)
+ bool acceptsFields() const { return isClassLike(); }
+
+ /// Gets the reflection for any contained types
+ ReflectionType getContainedReflectionType() const { return m_reflectionType == ReflectionType::NotReflected ? ReflectionType::NotReflected : m_reflectionOverride; }
+
+ /// Add a child node to this nodes scope
+ void addChild(Node* child);
+
+ /// Find a child node in this scope with the specified name. Return nullptr if not found
+ Node* findChild(const UnownedStringSlice& name) const;
+
+ /// Gets the anonymous namespace associated with this scope
+ ScopeNode* getAnonymousNamespace();
+
+ ScopeNode(Type type) :
+ Super(type),
+ m_reflectionOverride(ReflectionType::Reflected),
+ m_anonymousNamespace(nullptr)
+ {
+ }
+
+ /// For child types, fields, how reflection is handled. If this type is not reflected
+ ReflectionType m_reflectionOverride;
+
+ /// All of the types and namespaces in this *scope*
+ List<RefPtr<Node>> m_children;
+
+ /// Map from a name (in this scope) to the Node
+ Dictionary<UnownedStringSlice, Node*> m_childMap;
+
+ /// There can only be one anonymousNamespace for a scope. If there is one it's held here
+ ScopeNode* m_anonymousNamespace;
+};
+
+struct FieldNode : public Node
+{
+ typedef Node Super;
+
+ static bool isType(Type type) { return type == Type::Field; }
+
+ virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
+
+ FieldNode() :
+ Super(Type::Field)
+ {
+ }
+
+ UnownedStringSlice m_fieldType;
+
+ // We may want to add initializer tokens
+};
+
+struct ClassLikeNode : public ScopeNode
+{
+ typedef ScopeNode Super;
+
+ static bool isType(Type type) { return isClassLikeType(type); }
+
+ /// Add a node that is derived from this
+ void addDerived(ClassLikeNode* derived);
+
+ /// Dump all of the derived types
+ void dumpDerived(int indentCount, StringBuilder& out);
+
+ /// Calculates the derived depth
+ Index calcDerivedDepth() const;
+
+ /// Find the last (reflected) derived type
+ ClassLikeNode* findLastDerived();
+
+ /// Traverse the hierarchy of derived nodes, in depth first order
+ void calcDerivedDepthFirst(List<ClassLikeNode*>& outNodes);
+
+ /// True if has a derived type that is reflected
+ bool hasReflectedDerivedType() const;
+
+ /// Stores in out any reflected derived types
+ void getReflectedDerivedTypes(List<ClassLikeNode*>& out) const;
+
+ // Node Impl
+ virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
+
+ ClassLikeNode(Type type) :
+ Super(type),
+ m_origin(nullptr),
+ m_typeSet(nullptr),
+ m_superNode(nullptr)
+ {
+ SLANG_ASSERT(type == Type::ClassType || type == Type::StructType);
+ }
+
+ SourceOrigin* m_origin; ///< Defines where this was uniquely defined.
+
+ Token m_marker; ///< The marker associated with this scope (typically the marker is SLANG_CLASS etc, that is used to identify reflectedType)
+
+ List<RefPtr<ClassLikeNode>> m_derivedTypes; ///< All of the types derived from this type
+
+ TypeSet* m_typeSet; ///< The typeset this type belongs to.
+
+ Token m_super; ///< Super class name
+ ClassLikeNode* m_superNode; ///< If this is a class/struct, the type it is derived from (or nullptr if base)
+};
+
+template <typename T>
+T* as(Node* node) { return (node && T::isType(node->m_type)) ? static_cast<T*>(node) : nullptr; }
+
+// A macro to define a single indent as a string
+#define CPP_EXTRACT_INDENT_STRING " "
+
+} // CppExtract
+
+#endif