diff options
| -rw-r--r-- | source/core/slang-string.cpp | 47 | ||||
| -rw-r--r-- | source/core/slang-string.h | 17 | ||||
| -rw-r--r-- | source/slang/slang-compiler.cpp | 26 | ||||
| -rw-r--r-- | source/slang/slang-compiler.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-diagnostics.cpp | 69 | ||||
| -rw-r--r-- | source/slang/slang-diagnostics.h | 29 | ||||
| -rw-r--r-- | source/slang/slang-file-system.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 9 | ||||
| -rw-r--r-- | source/slang/slang-ir.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-lexer.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-source-loc.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-syntax.cpp | 44 | ||||
| -rw-r--r-- | source/slang/slang-syntax.h | 16 | ||||
| -rw-r--r-- | tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp | 622 |
14 files changed, 613 insertions, 276 deletions
diff --git a/source/core/slang-string.cpp b/source/core/slang-string.cpp index df711218c..bcf5853d5 100644 --- a/source/core/slang-string.cpp +++ b/source/core/slang-string.cpp @@ -439,4 +439,51 @@ namespace Slang sprintf_s(data, kCount, format, val); m_buffer->length += strnlen_s(data, kCount); } + + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnownedStringSlice !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + Index UnownedStringSlice::indexOf(char c) const + { + const Index size = Index(m_end - m_begin); + for (Index i = 0; i < size; ++i) + { + if (m_begin[i] == c) + { + return i; + } + } + return -1; + } + + Index UnownedStringSlice::indexOf(const UnownedStringSlice& in) const + { + const Index len = getLength(); + const Index inLen = in.getLength(); + if (inLen > len) + { + return -1; + } + + const char* inChars = in.m_begin; + switch (inLen) + { + case 0: return 0; + case 1: return indexOf(inChars[0]); + default: break; + } + + const char* chars = m_begin; + const char firstChar = inChars[0]; + + for (Int i = 0; i < len - inLen; ++i) + { + if (chars[i] == firstChar && in == UnownedStringSlice(chars + i, inLen)) + { + return i; + } + } + + return -1; + } + } diff --git a/source/core/slang-string.h b/source/core/slang-string.h index 10bc76048..5eb113dc1 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -104,18 +104,11 @@ namespace Slang return Index(m_end - m_begin); } - Index indexOf(char c) const - { - const Index size = int(m_end - m_begin); - for (Index i = 0; i < size; ++i) - { - if (m_begin[i] == c) - { - return i; - } - } - return -1; - } + /// Finds first index of char 'c'. If not found returns -1. + Index indexOf(char c) const; + /// Find first index of slice. If not found returns -1 + Index indexOf(const UnownedStringSlice& slice) const; + Index lastIndexOf(char c) const { const Index size = Index(m_end - m_begin); diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index f81a63275..8a8017ef3 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -80,6 +80,32 @@ namespace Slang { + + // !!!!!!!!!!!!!!!!!!!!!! free functions for DiagnosicSink !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val) + { + switch (val) + { + default: + sb << "<unknown>"; + break; + + #define CASE(TAG, STR) case CodeGenTarget::TAG: sb << STR; break + CASE(GLSL, "glsl"); + CASE(HLSL, "hlsl"); + CASE(SPIRV, "spirv"); + CASE(SPIRVAssembly, "spriv-assembly"); + CASE(DXBytecode, "dxbc"); + CASE(DXBytecodeAssembly, "dxbc-assembly"); + CASE(DXIL, "dxil"); + CASE(DXILAssembly, "dxil-assembly"); + #undef CASE + } + } + + // !!!!!!!!!!!!!!!!!!!!!!!!!!!! CompileResult !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + SlangResult CompileResult::getSharedLibrary(ComPtr<ISlangSharedLibrary>& outSharedLibrary) { if (downstreamResult) diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 89da498ac..fb13ab146 100644 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -72,6 +72,8 @@ namespace Slang CountOf = SLANG_TARGET_COUNT_OF, }; + void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val); + enum class ContainerFormat : SlangContainerFormat { None = SLANG_CONTAINER_FORMAT_NONE, diff --git a/source/slang/slang-diagnostics.cpp b/source/slang/slang-diagnostics.cpp index bb8b63540..615312661 100644 --- a/source/slang/slang-diagnostics.cpp +++ b/source/slang/slang-diagnostics.cpp @@ -1,9 +1,7 @@ // slang-diagnostics.cpp #include "slang-diagnostics.h" -#include "slang-compiler.h" #include "slang-name.h" -#include "slang-syntax.h" #include <assert.h> @@ -65,34 +63,6 @@ void printDiagnosticArg(StringBuilder& sb, Name* name) } -void printDiagnosticArg(StringBuilder& sb, Decl* decl) -{ - sb << getText(decl->getName()); -} - -void printDiagnosticArg(StringBuilder& sb, Type* type) -{ - sb << type->ToString(); -} - -void printDiagnosticArg(StringBuilder& sb, Val* val) -{ - sb << val->ToString(); -} - -void printDiagnosticArg(StringBuilder& sb, TypeExp const& type) -{ - sb << type.type->ToString(); -} - -void printDiagnosticArg(StringBuilder& sb, QualType const& type) -{ - if (type.type) - sb << type.type->ToString(); - else - sb << "<null>"; -} - void printDiagnosticArg(StringBuilder& sb, TokenType tokenType) { sb << TokenTypeToString(tokenType); @@ -103,50 +73,11 @@ void printDiagnosticArg(StringBuilder& sb, Token const& token) sb << token.Content; } -void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val) -{ - switch( val ) - { - default: - sb << "<unknown>"; - break; - -#define CASE(TAG, STR) case CodeGenTarget::TAG: sb << STR; break - CASE(GLSL, "glsl"); - CASE(HLSL, "hlsl"); - CASE(SPIRV, "spirv"); - CASE(SPIRVAssembly, "spriv-assembly"); - CASE(DXBytecode, "dxbc"); - CASE(DXBytecodeAssembly, "dxbc-assembly"); - CASE(DXIL, "dxil"); - CASE(DXILAssembly, "dxil-assembly"); -#undef CASE - } -} - - - -SourceLoc const& getDiagnosticPos(SyntaxNode const* syntax) -{ - return syntax->loc; -} - SourceLoc const& getDiagnosticPos(Token const& token) { return token.loc; } -SourceLoc const& getDiagnosticPos(TypeExp const& typeExp) -{ - return typeExp.exp->loc; -} - -SourceLoc const& getDiagnosticPos(IRInst* inst) -{ - return inst->sourceLoc; -} - - // Take the format string for a diagnostic message, along with its arguments, and turn it into a static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int argCount, DiagnosticArg const* const* args) { diff --git a/source/slang/slang-diagnostics.h b/source/slang/slang-diagnostics.h index 8ab860708..80e14d1c1 100644 --- a/source/slang/slang-diagnostics.h +++ b/source/slang/slang-diagnostics.h @@ -69,15 +69,11 @@ namespace Slang }; class Name; - class Decl; - struct QualType; - class Type; - struct TypeExp; - class Val; - enum class CodeGenTarget; - enum class Stage : SlangStage; - enum class ProfileVersion; + //enum class CodeGenTarget; + + //enum class Stage : SlangStage; + //enum class ProfileVersion; void printDiagnosticArg(StringBuilder& sb, char const* str); @@ -92,15 +88,11 @@ namespace Slang void printDiagnosticArg(StringBuilder& sb, Slang::String const& str); void printDiagnosticArg(StringBuilder& sb, Slang::UnownedStringSlice const& str); void printDiagnosticArg(StringBuilder& sb, Name* name); - void printDiagnosticArg(StringBuilder& sb, Decl* decl); - void printDiagnosticArg(StringBuilder& sb, Type* type); - void printDiagnosticArg(StringBuilder& sb, TypeExp const& type); - void printDiagnosticArg(StringBuilder& sb, QualType const& type); + void printDiagnosticArg(StringBuilder& sb, TokenType tokenType); void printDiagnosticArg(StringBuilder& sb, Token const& token); - void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val); - void printDiagnosticArg(StringBuilder& sb, Val* val); - + + template<typename T> void printDiagnosticArg(StringBuilder& sb, RefPtr<T> ptr) { @@ -109,13 +101,8 @@ namespace Slang inline SourceLoc const& getDiagnosticPos(SourceLoc const& pos) { return pos; } - class SyntaxNode; - SourceLoc const& getDiagnosticPos(SyntaxNode const* syntax); SourceLoc const& getDiagnosticPos(Token const& token); - SourceLoc const& getDiagnosticPos(TypeExp const& typeExp); - - struct IRInst; - SourceLoc const& getDiagnosticPos(IRInst* inst); + template<typename T> SourceLoc getDiagnosticPos(RefPtr<T> const& ptr) diff --git a/source/slang/slang-file-system.cpp b/source/slang/slang-file-system.cpp index c6bee28e1..29db71459 100644 --- a/source/slang/slang-file-system.cpp +++ b/source/slang/slang-file-system.cpp @@ -4,8 +4,6 @@ #include "../core/slang-io.h" #include "../core/slang-string-util.h" -#include "slang-compiler.h" - namespace Slang { diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 9a44787ff..9fb966eba 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -10,6 +10,15 @@ namespace Slang { struct IRSpecContext; + // !!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticSink Impls !!!!!!!!!!!!!!!!!!!!! + + SourceLoc const& getDiagnosticPos(IRInst* inst) + { + return inst->sourceLoc; + } + + // !!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticSink Impls !!!!!!!!!!!!!!!!!!!!! + IRInst* cloneGlobalValueWithLinkage( IRSpecContext* context, IRInst* originalVal, diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h index 0ca0093f2..d9d09975d 100644 --- a/source/slang/slang-ir.h +++ b/source/slang/slang-ir.h @@ -565,6 +565,8 @@ T* cast(IRInst* inst, T* /* */ = nullptr) return (T*)inst; } +SourceLoc const& getDiagnosticPos(IRInst* inst); + // Now that `IRInst` is defined we can back-fill the definitions that need to access it. template<typename T> diff --git a/source/slang/slang-lexer.cpp b/source/slang/slang-lexer.cpp index 9b3bed88e..e091de735 100644 --- a/source/slang/slang-lexer.cpp +++ b/source/slang/slang-lexer.cpp @@ -5,7 +5,7 @@ // input bytes and turning it into semantically useful tokens. // -#include "slang-compiler.h" +#include "slang-name.h" #include "slang-source-loc.h" #include <assert.h> diff --git a/source/slang/slang-source-loc.cpp b/source/slang/slang-source-loc.cpp index ef45c42b0..eb2ea6b1b 100644 --- a/source/slang/slang-source-loc.cpp +++ b/source/slang/slang-source-loc.cpp @@ -1,8 +1,6 @@ // slang-source-loc.cpp #include "slang-source-loc.h" -#include "slang-compiler.h" - #include "../core/slang-string-util.h" namespace Slang { diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp index 334273870..2055c2422 100644 --- a/source/slang/slang-syntax.cpp +++ b/source/slang/slang-syntax.cpp @@ -74,6 +74,7 @@ ABSTRACT_SYNTAX_CLASS(GlobalGenericParamSubstitution, Substitutions); #include "slang-val-defs.h" #include "slang-object-meta-end.h" + SyntaxClassBase::ClassInfo::ClassInfo(const char* name, CreateFunc createFunc, const ClassInfo* superClass): m_name(name), m_createFunc(createFunc), @@ -184,7 +185,48 @@ static bool _checkSubClassRange() return SLANG_OK; } - // Free functions +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticSink impls !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +void printDiagnosticArg(StringBuilder& sb, Decl* decl) +{ + sb << getText(decl->getName()); +} + +void printDiagnosticArg(StringBuilder& sb, Type* type) +{ + sb << type->ToString(); +} + +void printDiagnosticArg(StringBuilder& sb, Val* val) +{ + sb << val->ToString(); +} + +void printDiagnosticArg(StringBuilder& sb, TypeExp const& type) +{ + sb << type.type->ToString(); +} + +void printDiagnosticArg(StringBuilder& sb, QualType const& type) +{ + if (type.type) + sb << type.type->ToString(); + else + sb << "<null>"; +} + +SourceLoc const& getDiagnosticPos(SyntaxNode const* syntax) +{ + return syntax->loc; +} + +SourceLoc const& getDiagnosticPos(TypeExp const& typeExp) +{ + return typeExp.exp->loc; +} + + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! Free functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! const RefPtr<Decl>* adjustFilterCursorImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end) { diff --git a/source/slang/slang-syntax.h b/source/slang/slang-syntax.h index ff5da913f..5e1f057e4 100644 --- a/source/slang/slang-syntax.h +++ b/source/slang/slang-syntax.h @@ -33,6 +33,22 @@ namespace Slang class Parser; class SyntaxNode; + class Decl; + struct QualType; + class Type; + struct TypeExp; + class Val; + + void printDiagnosticArg(StringBuilder& sb, Decl* decl); + void printDiagnosticArg(StringBuilder& sb, Type* type); + void printDiagnosticArg(StringBuilder& sb, TypeExp const& type); + void printDiagnosticArg(StringBuilder& sb, QualType const& type); + void printDiagnosticArg(StringBuilder& sb, Val* val); + + class SyntaxNode; + SourceLoc const& getDiagnosticPos(SyntaxNode const* syntax); + SourceLoc const& getDiagnosticPos(TypeExp const& typeExp); + typedef RefPtr<RefObject> (*SyntaxParseCallback)(Parser* parser, void* userData); typedef unsigned int ConversionCost; diff --git a/tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp b/tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp index 389bc976a..f5724b7b6 100644 --- a/tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp +++ b/tools/slang-cpp-extractor/slang-cpp-extractor-main.cpp @@ -128,6 +128,8 @@ protected: StringSlicePool m_pool; }; +class SourceOrigin; + class Node : public RefObject { public: @@ -193,6 +195,10 @@ public: /// True if has a derived type that is reflected bool hasReflectedDerivedType() const; + /// Stores in out any reflected derived types + void getReflectedDerivedTypes(List<Node*>& out) const; + + static void filterReflectedClassLike(List<Node*>& io); static void calcScopePath(Node* node, List<Node*>& outPath); @@ -201,7 +207,8 @@ public: m_parentScope(nullptr), m_isReflected(false), m_superNode(nullptr), - m_baseType(BaseType::None) + m_baseType(BaseType::None), + m_origin(nullptr) { m_anonymousNamespace = nullptr; } @@ -224,6 +231,9 @@ public: /// There can only be one anonymousNamespace for a scope. If there is one it's held here Node* m_anonymousNamespace; + /// Defines where this was uniquely defined. For namespaces if it straddles multiple source files will be the first instance. + SourceOrigin* m_origin; + /// Classes can be traversed, but not reflected. To be reflected they have to contain the marker bool m_isReflected; /// The base type of this @@ -237,6 +247,124 @@ public: Node* m_superNode; ///< If this is a class/struct, the type it is derived from (or nullptr if base) }; +class SourceOrigin : public RefObject +{ +public: + + void addNode(Node* node) + { + if (node->isClassLike()) + { + SLANG_ASSERT(node->m_origin == nullptr); + node->m_origin = this; + } + else + { + if (node->m_origin == nullptr) + { + node->m_origin = this; + } + } + m_nodes.add(node); + } + + SourceOrigin(SourceFile* sourceFile, const String& macroOrigin) : + m_sourceFile(sourceFile), + m_macroOrigin(macroOrigin) + {} + + ///< The macro text is inserted into the macro to identify the origin. It is based on the filename + String m_macroOrigin; + /// The source file - also holds the path information + SourceFile* m_sourceFile; + + /// All of the nodes defined in this file in the order they were defined + /// Note that the same namespace may be listed multiple times. + List<RefPtr<Node> > m_nodes; +}; + +struct Options; + +class CPPExtractor +{ +public: + + SlangResult expect(TokenType type, Token* outToken = nullptr); + + bool advanceIfMarker(Token* outToken = nullptr); + bool advanceIfToken(TokenType type, Token* outToken = nullptr); + bool advanceIfStyle(IdentifierStyle style, Token* outToken = nullptr); + + SlangResult pushAnonymousNamespace(); + SlangResult pushNode(Node* node); + SlangResult consumeToClosingBrace(const Token* openBraceToken = nullptr); + SlangResult popBrace(); + + /// Parse the contents of the source file + SlangResult parse(SourceFile* sourceFile, const Options* options); + + /// When parsing we don't lookup all up super types/add derived types. This is because + /// we allow files to be processed in any order, so we have to do the type lookup as a separate operation + SlangResult calcDerivedTypes(); + + /// Only valid after calcDerivedTypes has been executed + const List<Node*>& getBaseTypes() const { return m_baseTypes; } + + /// Get all of the parsed source origins + const List<RefPtr<SourceOrigin> >& getSourceOrigins() const { return m_origins; } + + /// Get the root node + Node* getRootNode() const { return m_rootNode; } + + CPPExtractor(StringSlicePool* typePool, NamePool* namePool, DiagnosticSink* sink, IdentifierLookup* identifierLookup); + +protected: + static Node::Type _toNodeType(IdentifierStyle style); + + bool _isMarker(const UnownedStringSlice& name); + + SlangResult _maybeParseNode(Node::Type type); + SlangResult _maybeParseField(); + + SlangResult _maybeParseType(UnownedStringSlice& outType); + + SlangResult _maybeParseType(UnownedStringSlice& outType, Index& ioTemplateDepth); + SlangResult _maybeParseTemplateArgs(Index& ioTemplateDepth); + SlangResult _maybeParseTemplateArg(Index& ioTemplateDepth); + + SlangResult _calcDerivedTypesRec(Node* node); + static String _calcMacroOrigin(const String& filePath, const Options& options); + + void _consumeTypeModifiers(); + + SlangResult _consumeToSync(); + + TokenList m_tokenList; + TokenReader m_reader; + + Node* m_currentNode; ///< The current scope being processed + + RefPtr<Node> m_rootNode; ///< The root scope + + List<Node*> m_baseTypes; ///< All of the types which are base. Only set after calcDerivedTypes + + SourceOrigin* m_origin; + + DiagnosticSink* m_sink; + + NamePool* m_namePool; + + List<RefPtr<SourceOrigin>> m_origins; + + const Options* m_options; + + IdentifierLookup* m_identifierLookup; + StringSlicePool* m_typePool; +}; + + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Node Impl !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + Node* Node::getAnonymousNamespace() { @@ -466,6 +594,36 @@ bool Node::hasReflectedDerivedType() const return false; } +void Node::getReflectedDerivedTypes(List<Node*>& out) const +{ + out.clear(); + for (Node* type : m_derivedTypes) + { + if (type->m_isReflected) + { + out.add(type); + } + } +} + +/* static */void Node::filterReflectedClassLike(List<Node*>& ioNodes) +{ + // Filter out all the unreflected nodes + Index count = ioNodes.getCount(); + for (Index j = 0; j < count; ) + { + Node* node = ioNodes[j]; + if (!node->isClassLike() || !node->m_isReflected) + { + ioNodes.removeAt(j); + count--; + } + else + { + j++; + } + } +} // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Options !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -473,21 +631,26 @@ struct Options { void reset() { - m_inputPaths.clear(); - m_outputPath = String(); - m_dump = false; + *this = Options(); + } + Options() + { m_prefixMark = "SLANG_"; m_postfixMark = "_CLASS"; } - bool m_dump = false; - List<String> m_inputPaths; - String m_outputPath; - String m_inputDirectory; + bool m_defs = false; ///< If set will output a '-defs.h' file for each of the input files, that corresponds to previous defs files (although doesn't have fields/RAW) + bool m_dump = false; ///< If true will dump to stderr the types/fields and hierarchy it extracted + + List<String> m_inputPaths; ///< The input paths to the files to be processed + + String m_outputPath; ///< The ouput path. Note that the extractor can generate multiple output files, and this will actually be the 'stem' of several files + String m_inputDirectory; ///< The input directory that is by default used for reading m_inputPaths from. String m_reflectType; ///< The typename used for output - String m_prefixMark; - String m_postfixMark; + String m_prefixMark; ///< The prefix of the 'marker' used to identify a reflected type + String m_postfixMark; ///< The postfix of the 'marker' used to identify a reflected type + String m_stripFilePrefix; ///< Used for the 'origin' information, this is stripped from the source filename, and the remainder of the filename (without extension) is 'macroized' }; struct OptionsParser @@ -592,6 +755,16 @@ SlangResult OptionsParser::parse(int argc, const char*const* argv, DiagnosticSin SLANG_RETURN_ON_FAIL(_parseArgReplaceValue("-postfix-mark", outOptions.m_postfixMark)); continue; } + else if (arg == "-defs") + { + outOptions.m_defs = true; + continue; + } + else if (arg == "-strip-prefix") + { + SLANG_RETURN_ON_FAIL(_parseArgWithValue("-strip-prefix", outOptions.m_stripFilePrefix)); + continue; + } m_sink->diagnose(SourceLoc(), CPPDiagnostics::unknownOption, arg); return SLANG_FAIL; @@ -621,78 +794,6 @@ SlangResult OptionsParser::parse(int argc, const char*const* argv, DiagnosticSin // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPExtractor !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -class CPPExtractor -{ -public: - - SlangResult expect(TokenType type, Token* outToken = nullptr); - - bool advanceIfMarker(Token* outToken = nullptr); - bool advanceIfToken(TokenType type, Token* outToken = nullptr); - bool advanceIfStyle(IdentifierStyle style, Token* outToken = nullptr); - - SlangResult pushAnonymousNamespace(); - SlangResult pushNode(Node* node); - SlangResult consumeToClosingBrace(const Token* openBraceToken = nullptr); - SlangResult popBrace(); - - /// Parse the contents of the source file - SlangResult parse(SourceFile* sourceFile, const Options* options); - - /// When parsing we don't lookup all up super types/add derived types. This is because - /// we allow files to be processed in any order, so we have to do the type lookup as a separate operation - SlangResult calcDerivedTypes(); - - /// Only valid after calcDerivedTypes has been executed - const List<Node*>& getBaseTypes() const { return m_baseTypes; } - - /// Get the root node - Node* getRootNode() const { return m_rootNode; } - - CPPExtractor(StringSlicePool* typePool, NamePool* namePool, DiagnosticSink* sink, IdentifierLookup* identifierLookup); - -protected: - static Node::Type _toNodeType(IdentifierStyle style); - - bool _isMarker(const UnownedStringSlice& name) - { - return name.startsWith(m_options->m_prefixMark.getUnownedSlice()) && name.endsWith(m_options->m_postfixMark.getUnownedSlice()); - } - - SlangResult _maybeParseNode(Node::Type type); - SlangResult _maybeParseField(); - - SlangResult _maybeParseType(UnownedStringSlice& outType); - - SlangResult _maybeParseType(UnownedStringSlice& outType, Index& ioTemplateDepth); - SlangResult _maybeParseTemplateArgs(Index& ioTemplateDepth); - SlangResult _maybeParseTemplateArg(Index& ioTemplateDepth); - - SlangResult _calcDerivedTypesRec(Node* node); - - void _consumeTypeModifiers(); - - SlangResult _consumeToSync(); - - TokenList m_tokenList; - TokenReader m_reader; - - Node* m_currentNode; ///< The current scope being processed - - RefPtr<Node> m_rootNode; ///< The root scope - - List<Node*> m_baseTypes; ///< All of the types which are base. Only set after calcDerivedTypes - - DiagnosticSink* m_sink; - - NamePool* m_namePool; - - const Options* m_options; - - IdentifierLookup* m_identifierLookup; - StringSlicePool* m_typePool; -}; - CPPExtractor::CPPExtractor(StringSlicePool* typePool, NamePool* namePool, DiagnosticSink* sink, IdentifierLookup* identifierLookup): m_typePool(typePool), m_sink(sink), @@ -702,6 +803,11 @@ CPPExtractor::CPPExtractor(StringSlicePool* typePool, NamePool* namePool, Diagno m_rootNode = new Node(Node::Type::Namespace); } +bool CPPExtractor::_isMarker(const UnownedStringSlice& name) +{ + return name.startsWith(m_options->m_prefixMark.getUnownedSlice()) && name.endsWith(m_options->m_postfixMark.getUnownedSlice()); +} + SlangResult CPPExtractor::expect(TokenType type, Token* outToken) { if (m_reader.peekTokenType() != type) @@ -772,11 +878,22 @@ bool CPPExtractor::advanceIfStyle(IdentifierStyle style, Token* outToken) SlangResult CPPExtractor::pushAnonymousNamespace() { m_currentNode = m_currentNode->getAnonymousNamespace(); + + if (m_origin) + { + m_origin->addNode(m_currentNode); + } + return SLANG_OK; } SlangResult CPPExtractor::pushNode(Node* node) { + if (m_origin) + { + m_origin->addNode(node); + } + if (node->m_name.Content.getLength()) { // For anonymous namespace, we should look if we already have one and just reopen that. Doing so will mean will @@ -1270,8 +1387,18 @@ SlangResult CPPExtractor::_maybeParseField() SlangResult CPPExtractor::parse(SourceFile* sourceFile, const Options* options) { + SLANG_ASSERT(options); m_options = options; + // Calculate from the path, a 'macro origin' name. + const String macroOrigin = _calcMacroOrigin(sourceFile->getPathInfo().foundPath, *options); + + RefPtr<SourceOrigin> origin = new SourceOrigin(sourceFile, macroOrigin); + m_origins.add(origin); + + // Set the current origin + m_origin = origin; + SourceManager* manager = sourceFile->getSourceManager(); SourceView* sourceView = manager->createSourceView(sourceFile, nullptr); @@ -1462,6 +1589,45 @@ SlangResult CPPExtractor::calcDerivedTypes() return _calcDerivedTypesRec(m_rootNode); } + +/* static */String CPPExtractor::_calcMacroOrigin(const String& filePath, const Options& options) +{ + String fileName = Path::getFileNameWithoutExt(filePath); + + if (options.m_stripFilePrefix.getLength() && fileName.startsWith(options.m_stripFilePrefix)) + { + const Index len = options.m_stripFilePrefix.getLength(); + fileName = UnownedStringSlice(fileName.begin() + len, fileName.end()); + } + + const char* start = fileName.begin(); + const char* end = fileName.end(); + + // Trim any - + while (start < end && *start == '-') ++start; + while (end - 1 > start && end[-1] == '-') --end; + + StringBuilder out; + + // Make into macro like name + for (; start < end; ++start) + { + char c = *start; + + if (c == '-') + { + c = '_'; + } + else if (c >= 'a' && c <= 'z') + { + c = c - 'a' + 'A'; + } + out.append(c); + } + + return out; +} + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPExtractorApp !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! class CPPExtractorApp @@ -1479,9 +1645,14 @@ public: /// Write output SlangResult writeOutput(CPPExtractor& extractor); + /// Write def files + SlangResult writeDefs(CPPExtractor& extractor); + /// Calculate the header SlangResult calcHeader(CPPExtractor& extractor, StringBuilder& out); - SlangResult calcMacroHeader(CPPExtractor& exctractor, StringBuilder& out); + SlangResult calcChildrenHeader(CPPExtractor& exctractor, StringBuilder& out); + + SlangResult calcDef(CPPExtractor& extractor, SourceOrigin* origin, StringBuilder& out); CPPExtractorApp(DiagnosticSink* sink, SourceManager* sourceManager, RootNamePool* rootNamePool): m_sink(sink), @@ -1522,8 +1693,8 @@ public: } } - protected: + NamePool m_namePool; Options m_options; @@ -1531,6 +1702,7 @@ protected: SourceManager* m_sourceManager; IdentifierLookup m_identifierLookup; + StringSlicePool m_slicePool; }; @@ -1571,7 +1743,29 @@ SlangResult CPPExtractorApp::writeAllText(const Slang::String& fileName, const U return SLANG_OK; } -SlangResult CPPExtractorApp::calcMacroHeader(CPPExtractor& extractor, StringBuilder& out) +SlangResult CPPExtractorApp::calcDef(CPPExtractor& extractor, SourceOrigin* origin, StringBuilder& out) +{ + Node* currentScope = nullptr; + + for (Node* node : origin->m_nodes) + { + if (node->isClassLike() && node->m_isReflected) + { + if (node->m_marker.Content.indexOf(UnownedStringSlice::fromLiteral("ABSTRACT")) >= 0) + { + out << "ABSTRACT_"; + } + + out << "SYNTAX_CLASS(" << node->m_name.Content << ", " << node->m_super.Content << ")\n"; + out << "END_SYNTAX_CLASS()\n\n"; + } + } + return SLANG_OK; +} + + + +SlangResult CPPExtractorApp::calcChildrenHeader(CPPExtractor& extractor, StringBuilder& out) { const List<Node*>& baseTypes = extractor.getBaseTypes(); @@ -1590,68 +1784,54 @@ SlangResult CPPExtractorApp::calcMacroHeader(CPPExtractor& extractor, StringBuil List<Node*> nodes; baseType->calcDerivedDepthFirst(nodes); + Node::filterReflectedClassLike(nodes); - for (Index j = 0; j < nodes.getCount(); j++) - { - Node* node = nodes[j]; + List<Node*> derivedTypes; - if (!node->isClassLike() || !node->m_isReflected) - { - continue; - } + out << "\n\n /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! CHILDREN !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ \n\n"; + + // Now the children + for (Node* node : nodes) + { + node->getReflectedDerivedTypes(derivedTypes); // Define the derived types - out << "#define " << m_options.m_prefixMark << "DERIVED_" << reflectTypeName << "_" << node->m_name.Content << "(x, param) \\\n"; - for (Node* derivedType : node->m_derivedTypes) + out << "#define " << m_options.m_prefixMark << "CHILDREN_" << reflectTypeName << "_" << node->m_name.Content << "(x, param)"; + + if (derivedTypes.getCount()) { - if (!derivedType->m_isReflected) + out << " \\\n"; + for (Index j = 0; j < derivedTypes.getCount(); ++j) { - continue; - } - _indent(1, out); - out << "SLANG_" << reflectTypeName << "_" << derivedType->m_name.Content << "(x, param) \\\n"; + Node* derivedType = derivedTypes[j]; + _indent(1, out); + out << m_options.m_prefixMark << "ALL_" << reflectTypeName << "_" << derivedType->m_name.Content << "(x, param)"; + if (j < derivedTypes.getCount() - 1) + { + out << "\\\n"; + } + } } - out << "/* */\n"; + out << "\n\n"; + } + out << "\n\n /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ALL !!!!!!!!!!!!!!!!!!!!!!!!!!!! */\n\n"; - out << "#define SLANG_" << reflectTypeName << "_" << node->m_name.Content << "(x, param) \\\n"; - - // Output the X macro part + for (Node* node : nodes) + { + // Define the derived types + out << "#define " << m_options.m_prefixMark << "ALL_" << reflectTypeName << "_" << node->m_name.Content << "(x, param) \\\n"; _indent(1, out); - out << "x(" << node->m_name.Content << ", "; - - UnownedStringSlice marker = node->m_marker.Content; - // Need to extract the name - if (marker.getLength() > m_options.m_prefixMark.getLength() + m_options.m_postfixMark.getLength()) - { - marker = UnownedStringSlice(marker.begin() + m_options.m_prefixMark.getLength(), marker.end() - m_options.m_postfixMark.getLength()); - } - else - { - marker = UnownedStringSlice::fromLiteral("NORMAL"); - } - out << marker << ", "; + out << m_options.m_prefixMark << reflectTypeName << "_" << node->m_name.Content << "(x, param)"; - if (node->m_baseType != Node::BaseType::None || node->m_superNode && node->m_superNode->m_isReflected == false) + // If has derived types output them + if (node->hasReflectedDerivedType()) { - out << "BASE, "; - } - else if (node->hasReflectedDerivedType()) - { - out << "INNER, "; - } - else - { - out << "LEAF, "; + out << " \\\n"; + _indent(1, out); + out << m_options.m_prefixMark << "CHILDREN_" << reflectTypeName << "_" << node->m_name.Content << "(x, param)"; } - - out << "param) \\\n"; - - // Reference the derived types - _indent(1, out); - out << m_options.m_prefixMark << "DERIVED_" << reflectTypeName << "_" << node->m_name.Content << "(x, param) \n"; - - out << "\n"; + out << "\n\n"; } } @@ -1691,34 +1871,28 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder& List<Node*> nodes; baseType->calcDerivedDepthFirst(nodes); + Node::filterReflectedClassLike(nodes); - out << "\n"; - out << "enum class " << reflectTypeName << "Type\n"; - out << "{\n"; - - - Index typeIndex = 0; - - for (Node* node : nodes) + // Write out the types { - SLANG_ASSERT(node->isClassLike()); - // If it's not reflected we don't output, in the enum list - if (!node->m_isReflected) + out << "\n"; + out << "enum class " << reflectTypeName << "Type\n"; + out << "{\n"; + + Index typeIndex = 0; + for (Node* node : nodes) { - continue; + // Okay first we are going to output the enum values + const Index depth = node->calcDerivedDepth() - 1; + _indent(depth, out); + out << node->m_name.Content << " = " << typeIndex << ",\n"; + typeIndex++; } - // Okay first we are going to output the enum values - const Index depth = node->calcDerivedDepth() - 1; - _indent(depth, out); - - out << node->m_name.Content << " = " << typeIndex << ",\n"; - - typeIndex++; + out << "};\n\n"; } - out << "};\n\n"; - +#if 0 out << "\n"; out << "enum class " << reflectTypeName << "Last\n"; out << "{\n"; @@ -1743,21 +1917,24 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder& } out << "};\n\n"; +#endif - // Predeclare - - out << "// Predeclare\n\n"; - for (Node* node : nodes) + // Predeclare the classes { - SLANG_ASSERT(node->isClassLike()); - // If it's not reflected we don't output, in the enum list - if (node->m_isReflected) + out << "// Predeclare\n\n"; + for (Node* node : nodes) { - const char* type = (node->m_type == Node::Type::ClassType) ? "class" : "struct"; - out << type << " " << node->m_name.Content << ";\n"; + SLANG_ASSERT(node->isClassLike()); + // If it's not reflected we don't output, in the enum list + if (node->m_isReflected) + { + const char* type = (node->m_type == Node::Type::ClassType) ? "class" : "struct"; + out << type << " " << node->m_name.Content << ";\n"; + } } } +#if 0 out << "struct " << reflectTypeName << "Super\n"; out << "{\n"; @@ -1773,6 +1950,82 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder& } out << "};\n"; +#endif + + // Do the macros for each of the types + + { + out << "// Type macros\n\n"; + + out << "// Order is (NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \n"; + out << "// NAME - is the class name\n"; + out << "// SUPER - is the super class name (or NO_SUPER)\n"; + out << "// LAST - is the class name for the last in the range (or NO_LAST)\n"; + out << "// MARKER - is the text inbetween in the prefix/postix (like ABSTRACT). If no inbetween text is is 'NONE'\n"; + out << "// TYPE - Can be BASE, INNER or LEAF for the overall base class, an INNER class, or a LEAF class\n"; + out << "// param is a user defined parameter that can be parsed to the invoked x macro\n\n"; + + // Output all of the definitions for each type + for (Node* node : nodes) + { + out << "#define SLANG_" << reflectTypeName << "_" << node->m_name.Content << "(x, param) "; + + // Output the X macro part + _indent(1, out); + out << "x(" << node->m_name.Content << ", "; + + if (node->m_superNode) + { + out << node->m_superNode->m_name.Content << ", "; + } + else + { + out << "NO_SUPER, "; + } + + // Output the (file origin) + out << node->m_origin->m_macroOrigin; + out << ", "; + + // The last type + Node* lastDerived = node->findLastDerived(); + if (lastDerived) + { + out << lastDerived->m_name.Content << ", "; + } + else + { + out << "NO_LAST, "; + } + + // Output any specifics of the markup + UnownedStringSlice marker = node->m_marker.Content; + // Need to extract the name + if (marker.getLength() > m_options.m_prefixMark.getLength() + m_options.m_postfixMark.getLength()) + { + marker = UnownedStringSlice(marker.begin() + m_options.m_prefixMark.getLength(), marker.end() - m_options.m_postfixMark.getLength()); + } + else + { + marker = UnownedStringSlice::fromLiteral("NONE"); + } + out << marker << ", "; + + if (node->m_baseType != Node::BaseType::None || node->m_superNode && node->m_superNode->m_isReflected == false) + { + out << "BASE, "; + } + else if (node->hasReflectedDerivedType()) + { + out << "INNER, "; + } + else + { + out << "LEAF, "; + } + out << "param)\n"; + } + } // Now pop the scope in revers for (Index j = baseScopePath.getCount() - 1; j >= 0; j--) @@ -1785,6 +2038,34 @@ SlangResult CPPExtractorApp::calcHeader(CPPExtractor& extractor, StringBuilder& return SLANG_OK; } +SlangResult CPPExtractorApp::writeDefs(CPPExtractor& extractor) +{ + const auto& origins = extractor.getSourceOrigins(); + + for (SourceOrigin* origin : origins) + { + const String path = origin->m_sourceFile->getPathInfo().foundPath; + + // We need to work out the name of the def file + + String ext = Path::getPathExt(path); + String pathWithoutExt = Path::getPathWithoutExt(path); + + // The output path + + StringBuilder outPath; + outPath << pathWithoutExt << "-defs." << ext; + + StringBuilder content; + SLANG_RETURN_ON_FAIL(calcDef(extractor, origin, content)); + + // Write the defs file + SLANG_RETURN_ON_FAIL(writeAllText(outPath, content.getUnownedSlice())); + } + + return SLANG_OK; +} + SlangResult CPPExtractorApp::writeOutput(CPPExtractor& extractor) { @@ -1822,13 +2103,12 @@ SlangResult CPPExtractorApp::writeOutput(CPPExtractor& extractor) } { - StringBuilder macroHeader; - - SLANG_RETURN_ON_FAIL(calcMacroHeader(extractor, macroHeader)); + StringBuilder childrenHeader; + SLANG_RETURN_ON_FAIL(calcChildrenHeader(extractor, childrenHeader)); StringBuilder headerPath; headerPath << path << "-macro." + ext; - SLANG_RETURN_ON_FAIL(writeAllText(headerPath, macroHeader.getUnownedSlice())); + SLANG_RETURN_ON_FAIL(writeAllText(headerPath, childrenHeader.getUnownedSlice())); } // Write to output @@ -1842,6 +2122,7 @@ SlangResult CPPExtractorApp::execute(const Options& options) { m_options = options; + CPPExtractor extractor(&m_slicePool, &m_namePool, m_sink, &m_identifierLookup); // Read in each of the input files @@ -1892,6 +2173,11 @@ SlangResult CPPExtractorApp::execute(const Options& options) } } + if (options.m_defs) + { + SLANG_RETURN_ON_FAIL(writeDefs(extractor)); + } + if (options.m_outputPath.getLength()) { SLANG_RETURN_ON_FAIL(writeOutput(extractor)); |
