yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Lauro OyenMove c++ parsing code from slang-cpp-extractor to static library (#5675)eaa8dcfcc

master
11.7 KiB422 linesraw
1#pragma once
2
3#include "compiler-core/slang-doc-extractor.h"
4#include "diagnostics.h"
5
6namespace CppParse
7{
8using namespace Slang;
9
10enum class ReflectionType : uint8_t
11{
12    NotReflected,
13    Reflected,
14};
15
16// Pre-declare
17class TypeSet;
18class SourceOrigin;
19
20struct ScopeNode;
21
22class Node : public RefObject
23{
24public:
25    enum class Kind : uint8_t
26    {
27        Invalid,
28
29        StructType,
30        ClassType,
31
32        Enum,
33        EnumClass,
34
35        Namespace,
36        AnonymousNamespace,
37
38        Field,
39        EnumCase,
40
41        TypeDef,
42
43        Callable, ///< Functions/methods
44
45        Other,   ///< Used 'other' parsing like for TYPE
46        Unknown, ///< Used for marking tokens consumed but usage is not known
47
48        CountOf,
49    };
50
51    enum class KindRange
52    {
53        ScopeStart = int(Kind::StructType),
54        ScopeEnd = int(Kind::AnonymousNamespace),
55
56        ClassLikeStart = int(Kind::StructType),
57        ClassLikeEnd = int(Kind::ClassType),
58
59        ScopeTypeStart = int(Kind::StructType),
60        ScopeTypeEnd = int(Kind::EnumClass),
61
62        OtherTypeStart = int(Kind::TypeDef),
63        OtherTypeEnd = int(Kind::TypeDef),
64
65        EnumStart = int(Kind::Enum),
66        EnumEnd = int(Kind::EnumClass),
67    };
68
69    /// Returns true if kind can cast to this type
70    /// Used for implementing as<T> casting
71    static bool isOfKind(Kind kind)
72    {
73        SLANG_UNUSED(kind);
74        return true;
75    }
76
77    static bool isKindScope(Kind kind)
78    {
79        return int(kind) >= int(KindRange::ScopeStart) && int(kind) <= int(KindRange::ScopeEnd);
80    }
81    static bool isKindClassLike(Kind kind)
82    {
83        return int(kind) >= int(KindRange::ClassLikeStart) &&
84               int(kind) <= int(KindRange::ClassLikeEnd);
85    }
86    static bool isKindEnumLike(Kind kind)
87    {
88        return int(kind) >= int(KindRange::EnumStart) && int(kind) <= int(KindRange::EnumEnd);
89    }
90
91    /// It a type, but doesn't have a scope
92    static bool isKindOtherType(Kind kind)
93    {
94        return int(kind) >= int(KindRange::OtherTypeStart) &&
95               int(kind) <= int(KindRange::OtherTypeEnd);
96    }
97    /// Is a type and has a scope
98    static bool isKindScopeType(Kind kind)
99    {
100        return int(kind) >= int(KindRange::ScopeTypeStart) &&
101               int(kind) <= int(KindRange::ScopeTypeEnd);
102    }
103
104    /// True if the kind is any type
105    static bool isKindType(Kind kind) { return isKindOtherType(kind) || isKindScopeType(kind); }
106
107    /// True if the kind can accept contained types
108    static bool canKindContainTypes(Kind type)
109    {
110        switch (type)
111        {
112        case Kind::StructType:
113        case Kind::ClassType:
114        case Kind::Namespace:
115        case Kind::AnonymousNamespace:
116            {
117                return true;
118            }
119        default:
120            break;
121        }
122        return false;
123    }
124
125    bool isNamespace() const { return m_kind == Kind::Namespace; }
126    bool isClassLike() const { return isKindClassLike(m_kind); }
127    bool isScope() const { return isKindScope(m_kind); }
128    bool isEnumLike() const { return isKindEnumLike(m_kind); }
129
130    /// These are useful for the filter
131    static bool isClassLikeAndReflected(Node* node)
132    {
133        return node->isClassLike() && node->isReflected();
134    }
135    static bool isClassLike(Node* node) { return isKindClassLike(node->m_kind); }
136
137    virtual void dump(int indent, StringBuilder& out) = 0;
138
139    /// Do depth first traversal of nodes in scopes
140    virtual void calcScopeDepthFirst(List<Node*>& outNodes);
141
142    /// Calculate the absolute name for this namespace/type
143    void calcAbsoluteName(StringBuilder& outName) const;
144
145    /// Get the absolute name
146    String getAbsoluteName() const
147    {
148        StringBuilder buf;
149        calcAbsoluteName(buf);
150        return buf.produceString();
151    }
152
153    /// Calculate the scope path to this node, from the root
154    void calcScopePath(List<Node*>& outPath) { calcScopePath(this, outPath); }
155
156    /// True if reflected
157    bool isReflected() const { return m_reflectionType == ReflectionType::Reflected; }
158
159    SourceLoc getSourceLoc() const { return m_name.getLoc(); }
160
161    ScopeNode* getRootScope();
162
163    typedef bool (*Filter)(Node* node);
164
165    template<typename T>
166    static void filter(Filter filter, List<T*>& io)
167    {
168        const Node* _isNodeDerived = (T*)nullptr;
169        SLANG_UNUSED(_isNodeDerived);
170        filterImpl(filter, reinterpret_cast<List<Node*>&>(io));
171    }
172
173    static void filterImpl(Filter filter, List<Node*>& io);
174
175    static void calcScopePath(Node* node, List<Node*>& outPath);
176
177    /// Lookup a name in just the specified scope
178    /// Handles anonymous namespaces, or name lookups that are in the parents space
179    static Node* lookupNameInScope(ScopeNode* scope, const UnownedStringSlice& name);
180
181    /// Lookup from a path
182    static Node* lookupFromScope(ScopeNode* scope, const UnownedStringSlice* path, Index pathCount);
183    /// Looks up *just* from the specified scope.
184    static Node* lookupFromScope(ScopeNode* scope, const UnownedStringSlice& slice);
185
186    /// Look up name (which can contain ::)
187    static Node* lookup(ScopeNode* scope, const UnownedStringSlice& name);
188
189    static void splitPath(const UnownedStringSlice& slice, List<UnownedStringSlice>& outSplitPath);
190
191    /// If markup is specified dump it
192    void dumpMarkup(int indent, StringBuilder& out);
193
194    Node(Kind type)
195        : m_kind(type), m_parentScope(nullptr), m_reflectionType(ReflectionType::NotReflected)
196    {
197    }
198
199    Kind m_kind;                     ///< The kind of node this is
200    ReflectionType m_reflectionType; ///< Classes can be traversed, but not reflected. To be
201                                     ///< reflected they have to contain the marker
202
203    MarkupVisibility m_markupVisibility =
204        MarkupVisibility::Public; ///< The visibility of the markup
205    String m_markup;              ///< Documentation associated with this node
206
207    Token m_name; ///< The name of this scope/type
208
209    ScopeNode* m_parentScope; ///< The scope this type/scope is defined in
210};
211
212struct ScopeNode : public Node
213{
214    typedef Node Super;
215
216    static bool isOfKind(Kind kind) { return isKindScope(kind); }
217
218    virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
219    virtual void calcScopeDepthFirst(List<Node*>& outNodes) SLANG_OVERRIDE;
220
221    /// True if can contain callable entries
222    bool canContainCallable() const { return isClassLike() || isNamespace(); }
223
224    /// True if can accept fields (class like types can)
225    bool canContainFields() const { return isClassLike(); }
226
227    /// True if the scope can accept types
228    bool canContainTypes() const { return canKindContainTypes(m_kind); }
229
230    /// Gets the reflection for any contained types
231    ReflectionType getContainedReflectionType() const
232    {
233        return m_reflectionType == ReflectionType::NotReflected ? ReflectionType::NotReflected
234                                                                : m_reflectionOverride;
235    }
236
237    /// Add a child node to this nodes scope
238    void addChild(Node* child);
239    /// Adds the child but does not add the name to the map
240    void addChildIgnoringName(Node* child);
241
242    /// Find a child node in this scope with the specified name. Return nullptr if not found
243    Node* findChild(const UnownedStringSlice& name) const;
244
245    /// Gets the anonymous namespace associated with this scope
246    ScopeNode* getAnonymousNamespace();
247
248    ScopeNode(Kind kind)
249        : Super(kind)
250        , m_reflectionOverride(ReflectionType::Reflected)
251        , m_anonymousNamespace(nullptr)
252    {
253    }
254
255    /// For child types, fields, how reflection is handled. If this type is not reflected
256    ReflectionType m_reflectionOverride;
257
258    /// All of the types and namespaces in this *scope*
259    List<RefPtr<Node>> m_children;
260
261    /// Map from a name (in this scope) to the Node
262    Dictionary<UnownedStringSlice, Node*> m_childMap;
263
264    /// There can only be one anonymousNamespace for a scope. If there is one it's held here
265    ScopeNode* m_anonymousNamespace;
266};
267
268struct FieldNode : public Node
269{
270    typedef Node Super;
271
272    static bool isOfKind(Kind kind) { return kind == Kind::Field; }
273
274    virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
275
276    FieldNode()
277        : Super(Kind::Field)
278    {
279    }
280
281    UnownedStringSlice m_fieldType;
282
283    bool m_isStatic = false;
284
285    /// TODO(JS): We may want to add initializer tokens
286};
287
288struct ClassLikeNode : public ScopeNode
289{
290    typedef ScopeNode Super;
291
292    static bool isOfKind(Kind kind) { return isKindClassLike(kind); }
293
294    /// Add a node that is derived from this
295    void addDerived(ClassLikeNode* derived);
296
297    /// Dump all of the derived types
298    void dumpDerived(int indentCount, StringBuilder& out);
299
300    /// Calculates the derived depth
301    Index calcDerivedDepth() const;
302
303    /// Find the last (reflected) derived type
304    ClassLikeNode* findLastDerived();
305
306    /// Traverse the hierarchy of derived nodes, in depth first order
307    void calcDerivedDepthFirst(List<ClassLikeNode*>& outNodes);
308
309    /// True if has a derived type that is reflected
310    bool hasReflectedDerivedType() const;
311
312    /// Stores in out any reflected derived types
313    void getReflectedDerivedTypes(List<ClassLikeNode*>& out) const;
314
315    // Node Impl
316    virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
317
318    ClassLikeNode(Kind kind)
319        : Super(kind), m_origin(nullptr), m_typeSet(nullptr), m_superNode(nullptr)
320    {
321        SLANG_ASSERT(kind == Kind::ClassType || kind == Kind::StructType);
322    }
323
324    SourceOrigin* m_origin; ///< Defines where this was uniquely defined.
325
326    Token m_marker; ///< The marker associated with this scope (typically the marker is SLANG_CLASS
327                    ///< etc, that is used to identify reflectedType)
328
329    List<RefPtr<ClassLikeNode>> m_derivedTypes; ///< All of the types derived from this type
330
331    TypeSet* m_typeSet; ///< The typeset this type belongs to.
332
333    Token m_super;              ///< Super class name
334    ClassLikeNode* m_superNode; ///< If this is a class/struct, the type it is derived from (or
335                                ///< nullptr if base)
336};
337
338struct CallableNode : public Node
339{
340    typedef Node Super;
341
342    static bool isOfKind(Kind kind) { return kind == Kind::Callable; }
343
344    virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
345
346    CallableNode()
347        : Super(Kind::Callable)
348    {
349    }
350
351    struct Param
352    {
353        UnownedStringSlice m_type;
354        Token m_name;
355    };
356
357    UnownedStringSlice m_returnType;
358
359    CallableNode* m_nextOverload = nullptr;
360
361    List<Param> m_params;
362
363    bool m_isStatic = false;
364    bool m_isVirtual = false;
365    bool m_isPure = false;
366};
367
368struct EnumCaseNode : public Node
369{
370    typedef Node Super;
371
372    static bool isOfKind(Kind kind) { return kind == Kind::EnumCase; }
373
374    virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
375
376    EnumCaseNode()
377        : Super(Kind::EnumCase)
378    {
379    }
380
381    // Tokens that make up the value. If not defined will be empty
382    List<Token> m_valueTokens;
383};
384
385struct EnumNode : public ScopeNode
386{
387    typedef ScopeNode Super;
388    static bool isOfKind(Kind kind) { return isKindEnumLike(kind); }
389
390    virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
391
392    EnumNode(Kind kind)
393        : Super(kind)
394    {
395        SLANG_ASSERT(isKindEnumLike(kind));
396    }
397
398    List<Token> m_backingTokens;
399};
400
401struct TypeDefNode : public Node
402{
403    typedef Node Super;
404    static bool isOfKind(Kind kind) { return kind == Kind::TypeDef; }
405
406    virtual void dump(int indent, StringBuilder& out) SLANG_OVERRIDE;
407
408    TypeDefNode()
409        : Super(Kind::TypeDef)
410    {
411    }
412
413    List<Token> m_targetTypeTokens;
414};
415
416template<typename T>
417T* as(Node* node)
418{
419    return (node && T::isOfKind(node->m_kind)) ? static_cast<T*>(node) : nullptr;
420}
421
422} // namespace CppParse