diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-05-31 17:20:37 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-05-31 17:20:37 -0400 |
| commit | 6cbc3929a54d37bd23cb5efa8e3320ba02f78b2f (patch) | |
| tree | 5a23cb47782e9e2a77762c90dd35da1005eba8d0 /source/slang/source-loc.h | |
| parent | b81ff3ef968d1cc4e954b31a1812b3c391d17b02 (diff) | |
Use slang- prefix on slang compiler and core source (#973)
* Prefixing source files in source/slang with slang-
* Prefix source in source/slang with slang- prefix.
* Rename core source files with slang- prefix.
* Update project files.
* Fix problems from automatic merge.
Diffstat (limited to 'source/slang/source-loc.h')
| -rw-r--r-- | source/slang/source-loc.h | 412 |
1 files changed, 0 insertions, 412 deletions
diff --git a/source/slang/source-loc.h b/source/slang/source-loc.h deleted file mode 100644 index 95db7a50e..000000000 --- a/source/slang/source-loc.h +++ /dev/null @@ -1,412 +0,0 @@ -// source-loc.h -#ifndef SLANG_SOURCE_LOC_H_INCLUDED -#define SLANG_SOURCE_LOC_H_INCLUDED - -#include "../core/basic.h" -#include "../core/slang-memory-arena.h" -#include "../core/slang-string-slice-pool.h" - -#include "../../slang-com-ptr.h" -#include "../../slang.h" - -namespace Slang { - -/** Overview: - -There needs to be a mechanism where we can easily and quickly track a specific locations in any source file used during a compilation. -This is important because that original location is meaningful to the user as it relates to their original source. Thus SourceLoc are -used so we can display meaningful and accurate errors/warnings as well as being able to always map generated code locations back to their origins. - -A 'SourceLoc' along with associated structures (SourceView, SourceFile, SourceMangager) this can pinpoint the location down to the byte across the -compilation. This could be achieved by storing for every token and instruction the file, line and column number came from. The SourceLoc is used in -lots of places - every AST node, every Token from the lexer, every IRInst - so we really want to make it small. So for this reason we actually -encode SourceLoc as a single integer and then use the associated structures when needed to determine what the location actually refers to - -the source file, line and column number, or in effect the byte in the original file. - -Unfortunately there is extra complications. When a source is parsed it's interpretation (in terms of how a piece of source maps to an 'original' file etc) -can be overridden - for example by using #line directives. Moreover a single source file can be parsed multiple times. When it's parsed multiple times the -interpretation of the mapping (#line directives for example) can change. This is the purpose of the SourceView - it holds the interpretation of a source file -for a specific Lex/Parse. - -Another complication is that not all 'source' comes from SourceFiles, a macro expansion, may generate new 'source' we need to handle this, but also be able -to have a SourceLoc map to the expansion unambiguously. This is handled by creating a SourceFile and SourceView that holds only the macro generated -specific information. - -SourceFile - Is the immutable text contents of a file (or perhaps some generated source - say from doing a macro substitution) -SourceView - Tracks a single parse of a SourceFile. Each SourceView defines a range of source locations used. If a SourceFile is parsed twice, two -SourceViews are created, with unique SourceRanges. This is so that it is possible to tell which specific parse a SourceLoc is from - and so know the right -interpretation for that lex/parse. -*/ - -struct PathInfo -{ - /// To be more rigorous about where a path comes from, the type identifies what a paths origin is - enum class Type - { - Unknown, ///< The path is not known - Normal, ///< Normal has both path and uniqueIdentity - FoundPath, ///< Just has a found path (uniqueIdentity is unknown, or even 'unknowable') - FromString, ///< Created from a string (so found path might not be defined and should not be taken as to map to a loaded file) - TokenPaste, ///< No paths, just created to do a macro expansion - TypeParse, ///< No path, just created to do a type parse - CommandLine, ///< A macro constructed from the command line - }; - - /// True if has a canonical path - SLANG_FORCE_INLINE bool hasUniqueIdentity() const { return type == Type::Normal && uniqueIdentity.getLength() > 0; } - /// True if has a regular found path - SLANG_FORCE_INLINE bool hasFoundPath() const { return type == Type::Normal || type == Type::FoundPath || (type == Type::FromString && foundPath.getLength() > 0); } - /// True if has a found path that has originated from a file (as opposed to string or some other origin) - SLANG_FORCE_INLINE bool hasFileFoundPath() const { return (type == Type::Normal || type == Type::FoundPath) && foundPath.getLength() > 0; } - - /// Returns the 'most unique' identity for the path. If has a 'uniqueIdentity' returns that, else the foundPath, else "". - const String getMostUniqueIdentity() const; - - // So simplify construction. In normal usage it's safer to use make methods over constructing directly. - static PathInfo makeUnknown() { return PathInfo { Type::Unknown, "unknown", String() }; } - static PathInfo makeTokenPaste() { return PathInfo{ Type::TokenPaste, "token paste", String()}; } - static PathInfo makeNormal(const String& foundPathIn, const String& uniqueIdentity) { SLANG_ASSERT(uniqueIdentity.getLength() > 0 && foundPathIn.getLength() > 0); return PathInfo { Type::Normal, foundPathIn, uniqueIdentity }; } - static PathInfo makePath(const String& pathIn) { SLANG_ASSERT(pathIn.getLength() > 0); return PathInfo { Type::FoundPath, pathIn, String()}; } - static PathInfo makeTypeParse() { return PathInfo { Type::TypeParse, "type string", String() }; } - static PathInfo makeCommandLine() { return PathInfo { Type::CommandLine, "command line", String() }; } - static PathInfo makeFromString(const String& userPath) { return PathInfo{ Type::FromString, userPath, String() }; } - - Type type; ///< The type of path - String foundPath; ///< The path where the file was found (might contain relative elements) - String uniqueIdentity; ///< The unique identity of the file on the path found -}; - -class SourceLoc -{ -public: - typedef uint32_t RawValue; - -private: - RawValue raw; - -public: - SourceLoc() - : raw(0) - {} - - SourceLoc( - SourceLoc const& loc) - : raw(loc.raw) - {} - - RawValue getRaw() const { return raw; } - void setRaw(RawValue value) { raw = value; } - - static SourceLoc fromRaw(RawValue value) - { - SourceLoc result; - result.setRaw(value); - return result; - } - - bool isValid() const - { - return raw != 0; - } -}; - -inline SourceLoc operator+(SourceLoc loc, Int offset) -{ - return SourceLoc::fromRaw(SourceLoc::RawValue(Int(loc.getRaw()) + offset)); -} - -// A range of locations in the input source -struct SourceRange -{ - /// True if the loc is in the range. Range is inclusive on begin to end. - bool contains(SourceLoc loc) const { const auto rawLoc = loc.getRaw(); return rawLoc >= begin.getRaw() && rawLoc <= end.getRaw(); } - /// Get the total size - UInt getSize() const { return UInt(end.getRaw() - begin.getRaw()); } - - /// Get the offset of a loc in this range - int getOffset(SourceLoc loc) const { SLANG_ASSERT(contains(loc)); return int(loc.getRaw() - begin.getRaw()); } - - SourceRange() - {} - - SourceRange(SourceLoc loc) - : begin(loc) - , end(loc) - {} - - SourceRange(SourceLoc begin, SourceLoc end) - : begin(begin) - , end(end) - {} - - SourceLoc begin; - SourceLoc end; -}; - -// Pre-declare -struct SourceManager; - -// A logical or physical storage object for a range of input code -// that has logically contiguous source locations. -class SourceFile -{ -public: - - /// Returns the line break offsets (in bytes from start of content) - /// Note that this is lazily evaluated - the line breaks are only calculated on the first request - const List<uint32_t>& getLineBreakOffsets(); - - /// Set the line break offsets - void setLineBreakOffsets(const uint32_t* offsets, UInt numOffsets); - - /// Calculate the line based on the offset - int calcLineIndexFromOffset(int offset); - - /// Calculate the offset for a line - int calcColumnIndex(int line, int offset); - - /// Get the content holding blob - ISlangBlob* getContentBlob() const { return m_contentBlob; } - - /// True if has full set content - bool hasContent() const { return m_contentBlob != nullptr; } - - /// Get the content size - size_t getContentSize() const { return m_contentSize; } - - /// Get the content - const UnownedStringSlice& getContent() const { return m_content; } - - /// Get path info - const PathInfo& getPathInfo() const { return m_pathInfo; } - - /// Set the content as a blob - void setContents(ISlangBlob* blob); - /// Set the content as a string - void setContents(const String& content); - - /// Calculate a display path -> can canonicalize if necessary - String calcVerbosePath() const; - - /// Get the source manager this was created on - SourceManager* getSourceManager() const { return m_sourceManager; } - - /// Ctor - SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize); - /// Dtor - ~SourceFile(); - - protected: - - SourceManager* m_sourceManager; ///< The source manager this belongs to - PathInfo m_pathInfo; ///< The path The logical file path to report for locations inside this span. - ComPtr<ISlangBlob> m_contentBlob; ///< A blob that owns the storage for the file contents. If nullptr, there is no contents - UnownedStringSlice m_content; ///< The actual contents of the file. - size_t m_contentSize; ///< The size of the actual contents - - // In order to speed up lookup of line number information, - // we will cache the starting offset of each line break in - // the input file: - List<uint32_t> m_lineBreakOffsets; -}; - -enum class SourceLocType -{ - Nominal, ///< The normal interpretation which takes into account #line directives - Actual, ///< Ignores #line directives - and is the location as seen in the actual file -}; - -// A source location in a format a human might like to see -struct HumaneSourceLoc -{ - PathInfo pathInfo; - Int line = 0; - Int column = 0; -}; - - -/* A SourceView maps to a single span of SourceLoc range and is equivalent to a single include or more precisely use of a source file. -It is distinct from a SourceFile - because a SourceFile may be included multiple times, with different interpretations (depending -on #defines for example). -*/ -class SourceView -{ - public: - - // Each entry represents some contiguous span of locations that - // all map to the same logical file. - struct Entry - { - /// True if this resets the line numbering. It is distinct from a m_lineAdjust being 0, because it also means the path returns to the default. - bool isDefault() const { return m_pathHandle == StringSlicePool::Handle(0); } - - SourceLoc m_startLoc; ///< Where does this entry begin? - StringSlicePool::Handle m_pathHandle; ///< What is the presumed path for this entry. If 0 it means there is no path. - int32_t m_lineAdjust; ///< Adjustment to apply to source line numbers when printing presumed locations. Relative to the line number in the underlying file. - }; - - /// Given a sourceLoc finds the entry associated with it. If returns -1 then no entry is - /// associated with this location, and therefore the location should be interpreted as an offset - /// into the underlying sourceFile. - int findEntryIndex(SourceLoc sourceLoc) const; - - /// Add a line directive for this view. The directiveLoc must of course be in this SourceView - /// The path handle, must have been constructed on the SourceManager associated with the view - /// NOTE! Directives are assumed to be added IN ORDER during parsing such that every directiveLoc > previous - void addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handle pathHandle, int line); - void addLineDirective(SourceLoc directiveLoc, const String& path, int line); - - /// Removes any corrections on line numbers and reverts to the source files path - void addDefaultLineDirective(SourceLoc directiveLoc); - - /// Get the range that this view applies to - const SourceRange& getRange() const { return m_range; } - /// Get the entries - const List<Entry>& getEntries() const { return m_entries; } - /// Set the entries list - void setEntries(const Entry* entries, UInt numEntries) { m_entries.clear(); m_entries.addRange(entries, numEntries); } - - /// Get the source file holds the contents this view - SourceFile* getSourceFile() const { return m_sourceFile; } - /// Get the source manager - SourceManager* getSourceManager() const { return m_sourceFile->getSourceManager(); } - - /// Get the associated 'content' (the source text) - const UnownedStringSlice& getContent() const { return m_sourceFile->getContent(); } - - /// Get the size of the content - size_t getContentSize() const { return m_sourceFile->getContentSize(); } - - /// Get the humane location - /// Type determines if the location wanted is the original, or the 'normal' (which modifys behavior based on #line directives) - HumaneSourceLoc getHumaneLoc(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - - /// Get the path associated with a location - PathInfo getPathInfo(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - - /// Ctor - SourceView(SourceFile* sourceFile, SourceRange range, const String* viewPath): - m_range(range), - m_sourceFile(sourceFile) - { - if (viewPath) - { - m_viewPath = *viewPath; - } - } - - protected: - /// Get the pathInfo from a string handle. If it's 0, it will return the _getPathInfo - PathInfo _getPathInfoFromHandle(StringSlicePool::Handle pathHandle) const; - /// Gets the pathInfo for this view. It may be different from the m_sourceFile's if the path has been - /// overridden by m_viewPath - PathInfo _getPathInfo() const; - - String m_viewPath; ///< Path to this view. If empty the path is the path to the SourceView - - SourceRange m_range; ///< The range that this SourceView applies to - SourceFile* m_sourceFile; ///< The source file. Can hold the line breaks - List<Entry> m_entries; ///< An array entries describing how we should interpret a range, starting from the start location. -}; - -struct SourceManager -{ - // Initialize a source manager, with an optional parent - void initialize(SourceManager* parent, ISlangFileSystemExt* fileSystemExt); - - /// Allocate a range of SourceLoc locations, these can be used to identify a specific location in the source - SourceRange allocateSourceRange(UInt size); - - /// Create a SourceFile defined with the specified path, and content held within a blob - SourceFile* createSourceFileWithSize(const PathInfo& pathInfo, size_t contentSize); - SourceFile* createSourceFileWithString(const PathInfo& pathInfo, const String& contents); - SourceFile* createSourceFileWithBlob(const PathInfo& pathInfo, ISlangBlob* blob); - - /// Get the humane source location - HumaneSourceLoc getHumaneLoc(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - - /// Get the path associated with a location - PathInfo getPathInfo(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - - /// Create a new source view from a file - /// @param sourceFile is the source file that contains the source - /// @param pathInfo is path used to read the file from - SourceView* createSourceView(SourceFile* sourceFile, const PathInfo* pathInfo); - - /// Find a view by a source file location. - /// If not found in this manager will look in the parent SourceManager - /// Returns nullptr if not found. - SourceView* findSourceViewRecursively(SourceLoc loc) const; - - /// Find the SourceView associated with this manager for a specified location - /// Returns nullptr if not found. - SourceView* findSourceView(SourceLoc loc) const; - - /// Searches this manager, and then the parent to see if can find a match for path. - /// If not found returns nullptr. - SourceFile* findSourceFileRecursively(const String& uniqueIdentity) const; - /// Find if the source file is defined on this manager. - SourceFile* findSourceFile(const String& uniqueIdentity) const; - - /// Get the file system associated with this source manager - ISlangFileSystemExt* getFileSystemExt() const { return m_fileSystemExt; } - /// Get the file system associated with this source manager - void setFileSystemExt(ISlangFileSystemExt* fileSystemExt) { m_fileSystemExt = fileSystemExt; } - - /// Add a source file, uniqueIdentity must be unique for this manager AND any parents - void addSourceFile(const String& uniqueIdentity, SourceFile* sourceFile); - - /// Get the slice pool - StringSlicePool& getStringSlicePool() { return m_slicePool; } - - /// Get the source range for just this manager - /// Caution - the range will change if allocations are made to this manager. - SourceRange getSourceRange() const { return SourceRange(m_startLoc, m_nextLoc); } - - /// Get the parent manager to this manager. Returns nullptr if there isn't any. - SourceManager* getParent() const { return m_parent; } - - /// A memory arena to hold allocations that are in scope for the same time as SourceManager - MemoryArena* getMemoryArena() { return &m_memoryArena; } - - /// Allocate a string slice - UnownedStringSlice allocateStringSlice(const UnownedStringSlice& slice); - - SourceManager() : - m_memoryArena(2048) - {} - ~SourceManager(); - - protected: - - // The first location available to this source manager - // (may not be the first location of all, because we might - // have a parent source manager) - SourceLoc m_startLoc; - - // The "parent" source manager that owns locations ahead of `startLoc` - SourceManager* m_parent = nullptr; - - // The location to be used by the next source file to be loaded - SourceLoc m_nextLoc; - - // All of the SourceViews constructed on this SourceManager. These are held in increasing order of range, so can find by doing a binary chop. - List<SourceView*> m_sourceViews; - // All of the SourceFiles constructed on this SourceManager. This owns the SourceFile. - List<SourceFile*> m_sourceFiles; - - StringSlicePool m_slicePool; - - // Memory arena that can be used for holding data to held in scope as long as the Source is - // Can be used for storing the decoded contents of Token. Content for example. - MemoryArena m_memoryArena; - - // Maps uniqueIdentities to source files - Dictionary<String, SourceFile*> m_sourceFileMap; - - ComPtr<ISlangFileSystemExt> m_fileSystemExt; -}; - -} // namespace Slang - -#endif |
