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
5.2 KiB176 linesraw
1#include "node-tree.h"
2
3#include "compiler-core/slang-name-convention-util.h"
4#include "core/slang-io.h"
5#include "identifier-lookup.h"
6#include "options.h"
7
8namespace CppParse
9{
10using namespace Slang;
11
12/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! NodeTree !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
13
14NodeTree::NodeTree(
15    StringSlicePool* typePool,
16    NamePool* namePool,
17    IdentifierLookup* identifierLookup)
18    : m_typePool(typePool)
19    , m_namePool(namePool)
20    , m_identifierLookup(identifierLookup)
21    , m_typeSetPool(StringSlicePool::Style::Empty)
22{
23    m_rootNode = new ScopeNode(Node::Kind::Namespace);
24    m_rootNode->m_reflectionType = ReflectionType::Reflected;
25}
26
27TypeSet* NodeTree::getTypeSet(const UnownedStringSlice& slice)
28{
29    Index index = m_typeSetPool.findIndex(slice);
30    if (index < 0)
31    {
32        return nullptr;
33    }
34    return m_typeSets[index];
35}
36
37TypeSet* NodeTree::getOrAddTypeSet(const UnownedStringSlice& slice)
38{
39    const Index index = Index(m_typeSetPool.add(slice));
40    if (index >= m_typeSets.getCount())
41    {
42        SLANG_ASSERT(m_typeSets.getCount() == index);
43        TypeSet* typeSet = new TypeSet;
44
45        m_typeSets.add(typeSet);
46        typeSet->m_macroName = m_typeSetPool.getSlice(StringSlicePool::Handle(index));
47        return typeSet;
48    }
49    else
50    {
51        return m_typeSets[index];
52    }
53}
54
55SourceOrigin* NodeTree::addSourceOrigin(SourceFile* sourceFile, const Options& options)
56{
57    // Calculate from the path, a 'macro origin' name.
58    const String macroOrigin = calcMacroOrigin(sourceFile->getPathInfo().foundPath, options);
59
60    SourceOrigin* origin = new SourceOrigin(sourceFile, macroOrigin);
61    m_sourceOrigins.add(origin);
62    return origin;
63}
64
65/* static */ String NodeTree::calcMacroOrigin(const String& filePath, const Options& options)
66{
67    // Get the filename without extension
68    String fileName = Path::getFileNameWithoutExt(filePath);
69
70    // We can work on just the slice
71    UnownedStringSlice slice = fileName.getUnownedSlice();
72
73    // Filename prefix
74    if (options.m_stripFilePrefix.getLength() &&
75        slice.startsWith(options.m_stripFilePrefix.getUnownedSlice()))
76    {
77        const Index len = options.m_stripFilePrefix.getLength();
78        slice = UnownedStringSlice(slice.begin() + len, slice.end());
79    }
80
81    // Trim -
82    slice = slice.trim('-');
83
84    StringBuilder out;
85    NameConventionUtil::convert(slice, NameConvention::UpperSnake, out);
86    return out;
87}
88
89SlangResult NodeTree::_calcDerivedTypesRec(ScopeNode* inScopeNode, DiagnosticSink* sink)
90{
91    if (inScopeNode->isClassLike())
92    {
93        ClassLikeNode* classLikeNode = static_cast<ClassLikeNode*>(inScopeNode);
94
95        if (classLikeNode->m_super.hasContent())
96        {
97            ScopeNode* parentScope = classLikeNode->m_parentScope;
98            if (parentScope == nullptr)
99            {
100                sink->diagnoseRaw(
101                    Severity::Error,
102                    UnownedStringSlice::fromLiteral("Can't lookup in scope if there is none!"));
103                return SLANG_FAIL;
104            }
105
106            Node* superNode = Node::lookup(parentScope, classLikeNode->m_super.getContent());
107
108            if (!superNode)
109            {
110                if (classLikeNode->isReflected())
111                {
112                    sink->diagnose(
113                        classLikeNode->m_name,
114                        CPPDiagnostics::superTypeNotFound,
115                        classLikeNode->getAbsoluteName());
116                    return SLANG_FAIL;
117                }
118            }
119            else
120            {
121                ClassLikeNode* superType = as<ClassLikeNode>(superNode);
122
123                if (!superType)
124                {
125                    sink->diagnose(
126                        classLikeNode->m_name,
127                        CPPDiagnostics::superTypeNotAType,
128                        classLikeNode->getAbsoluteName());
129                    return SLANG_FAIL;
130                }
131
132                if (superType->m_typeSet != classLikeNode->m_typeSet)
133                {
134                    sink->diagnose(
135                        classLikeNode->m_name,
136                        CPPDiagnostics::typeInDifferentTypeSet,
137                        classLikeNode->m_name.getContent(),
138                        classLikeNode->m_typeSet->m_macroName,
139                        superType->m_typeSet->m_macroName);
140                    return SLANG_FAIL;
141                }
142
143                // The base class must be defined in same scope (as we didn't allow different scopes
144                // for base classes)
145                superType->addDerived(classLikeNode);
146            }
147        }
148        else
149        {
150            // Add to it's own typeset
151            if (classLikeNode->isReflected() && classLikeNode->m_typeSet)
152            {
153                classLikeNode->m_typeSet->m_baseTypes.add(classLikeNode);
154            }
155        }
156    }
157
158    for (Node* child : inScopeNode->m_children)
159    {
160        ScopeNode* childScope = as<ScopeNode>(child);
161        if (childScope)
162        {
163            SLANG_RETURN_ON_FAIL(_calcDerivedTypesRec(childScope, sink));
164        }
165    }
166
167    return SLANG_OK;
168}
169
170SlangResult NodeTree::calcDerivedTypes(DiagnosticSink* sink)
171{
172    return _calcDerivedTypesRec(m_rootNode, sink);
173}
174
175
176} // namespace CppParse