yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
0c4c63b4a
master
1// slang-source-loc.h 2#ifndef SLANG_SOURCE_LOC_H_INCLUDED 3#define SLANG_SOURCE_LOC_H_INCLUDED 4 5#include "../core/slang-basic.h" 6#include "../core/slang-castable.h" 7#include "../core/slang-crypto.h" 8#include "../core/slang-memory-arena.h" 9#include "../core/slang-string-slice-pool.h" 10#include "slang-com-ptr.h" 11#include "slang-source-map.h" 12#include "slang.h" 13 14namespace Slang 15{ 16 17/** Overview: 18 19There needs to be a mechanism where we can easily and quickly track a specific locations in any 20source file used during a compilation. This is important because that original location is 21meaningful to the user as it relates to their original source. Thus SourceLoc are used so we can 22display meaningful and accurate errors/warnings as well as being able to always map generated code 23locations back to their origins. 24 25A 'SourceLoc' along with associated structures (SourceView, SourceFile, SourceMangager) this can 26pinpoint the location down to the byte across the compilation. This could be achieved by storing for 27every token and instruction the file, line and column number came from. The SourceLoc is used in 28lots of places - every AST node, every Token from the lexer, every IRInst - so we really want to 29make it small. So for this reason we actually encode SourceLoc as a single integer and then use the 30associated structures when needed to determine what the location actually refers to - the source 31file, line and column number, or in effect the byte in the original file. 32 33Unfortunately there is extra complications. When a source is parsed it's interpretation (in terms of 34how a piece of source maps to an 'original' file etc) can be overridden - for example by using #line 35directives. Moreover a single source file can be parsed multiple times. When it's parsed multiple 36times the interpretation of the mapping (#line directives for example) can change. This is the 37purpose of the SourceView - it holds the interpretation of a source file for a specific Lex/Parse. 38 39Another complication is that not all 'source' comes from SourceFiles, a macro expansion, may 40generate new 'source' we need to handle this, but also be able to have a SourceLoc map to the 41expansion unambiguously. This is handled by creating a SourceFile and SourceView that holds only the 42macro generated specific information. 43 44SourceFile - Is the immutable text contents of a file (or perhaps some generated source - say from 45doing a macro substitution) SourceView - Tracks a single parse of a SourceFile. Each SourceView 46defines a range of source locations used. If a SourceFile is parsed twice, two SourceViews are 47created, with unique SourceRanges. This is so that it is possible to tell which specific parse a 48SourceLoc is from - and so know the right interpretation for that lex/parse. 49*/ 50 51struct PathInfo 52{ 53typedef PathInfo ThisType ; 54 55/// To be more rigorous about where a path comes from, the type identifies what a paths origin 56/// is 57enum class Type :uint8_t 58 { 59Unknown ,///< The path is not known 60Normal ,///< Normal has both path and uniqueIdentity 61FoundPath ,///< Just has a found path (uniqueIdentity is unknown, or even 'unknowable') 62FromString ,///< Created from a string (so found path might not be defined and should not be 63///< taken as to map to a loaded file) 64TokenPaste ,///< No paths, just created to do a macro expansion 65TypeParse ,///< No path, just created to do a type parse 66CommandLine ,///< A macro constructed from the command line 67 }; 68 69/// True if has a canonical path 70SLANG_FORCE_INLINE bool hasUniqueIdentity ()const 71 { 72return type == Type ::Normal && uniqueIdentity .getLength ()> 0 ; 73 } 74/// True if has a regular found path 75SLANG_FORCE_INLINE bool hasFoundPath ()const 76 { 77return (type == Type ::Normal || type == Type ::FoundPath || type == Type ::FromString )&& 78foundPath .getLength ()> 0 ; 79 } 80/// True if has a found path that has originated from a file (as opposed to string or some other 81/// origin) 82SLANG_FORCE_INLINE bool hasFileFoundPath ()const 83 { 84return (type == Type ::Normal || type == Type ::FoundPath )&& foundPath .getLength ()> 0 ; 85 } 86/// Get the 'name'/path of the item. Will return an empty string if not applicable or not set. 87String getName ()const ; 88 89bool operator == (const ThisType & rhs )const ; 90bool operator != (const ThisType & rhs )const {return !(* this == rhs ); } 91 92/// Returns the 'most unique' identity for the path. If has a 'uniqueIdentity' returns that, 93/// else the foundPath, else "". 94const String getMostUniqueIdentity ()const ; 95 96/// Append to out, how to display the path 97void appendDisplayName (StringBuilder & out )const ; 98 99// So simplify construction. In normal usage it's safer to use make methods over constructing 100// directly. 101static PathInfo makeUnknown () {return PathInfo {Type ::Unknown ,String (),String ()}; } 102static PathInfo makeTokenPaste () {return PathInfo {Type ::TokenPaste ,"token paste" ,String ()}; } 103static PathInfo makeNormal (const String & foundPathIn ,const String & uniqueIdentity ) 104 { 105SLANG_ASSERT (uniqueIdentity .getLength ()> 0 && foundPathIn .getLength ()> 0 ); 106return PathInfo {Type ::Normal ,foundPathIn ,uniqueIdentity }; 107 } 108static PathInfo makePath (const String & pathIn ) 109 { 110SLANG_ASSERT (pathIn .getLength ()> 0 ); 111return PathInfo {Type ::FoundPath ,pathIn ,String ()}; 112 } 113static PathInfo makeTypeParse () {return PathInfo {Type ::TypeParse ,"type string" ,String ()}; } 114static PathInfo makeCommandLine () 115 { 116return PathInfo {Type ::CommandLine ,"command line" ,String ()}; 117 } 118static PathInfo makeFromString (const String & userPath ) 119 { 120return PathInfo {Type ::FromString ,userPath ,String ()}; 121 } 122 123Type type ;///< The type of path 124String foundPath ;///< The path where the file was found (might contain relative elements) 125String uniqueIdentity ;///< The unique identity of the file on the path found 126}; 127 128class SourceLoc 129{ 130public : 131typedef SourceLoc ThisType ; 132typedef uint32_t RawValue ; 133 134private : 135RawValue raw ; 136 137public : 138SourceLoc () 139 :raw (0 ) 140 { 141 } 142 143SourceLoc (SourceLoc const & loc ) 144 :raw (loc .raw ) 145 { 146 } 147 148SLANG_FORCE_INLINE bool operator == (const ThisType & rhs )const {return raw == rhs .raw ; } 149SLANG_FORCE_INLINE bool operator != (const ThisType & rhs )const {return !(raw == rhs .raw ); } 150SLANG_FORCE_INLINE bool operator < (const ThisType & rhs )const {return raw < rhs .raw ; } 151SLANG_FORCE_INLINE bool operator > (const ThisType & rhs )const {return raw > rhs .raw ; } 152SLANG_FORCE_INLINE bool operator <=(const ThisType & rhs )const {return raw <=rhs .raw ; } 153SLANG_FORCE_INLINE bool operator >=(const ThisType & rhs )const {return raw >=rhs .raw ; } 154 155RawValue getRaw ()const {return raw ; } 156void setRaw (RawValue value ) {raw = value ; } 157 158static SourceLoc fromRaw (RawValue value ) 159 { 160SourceLoc result ; 161result .setRaw (value ); 162return result ; 163 } 164 165bool isValid ()const {return raw != 0 ; } 166SourceLoc & operator = (const ThisType & rhs )= default ; 167}; 168 169inline SourceLoc operator + (SourceLoc loc ,Int offset ) 170{ 171return SourceLoc ::fromRaw (SourceLoc ::RawValue (Int (loc .getRaw ())+ offset )); 172} 173 174// A range of locations in the input source 175struct SourceRange 176{ 177/// True if the loc is in the range. Range is inclusive on begin to end. 178bool contains (SourceLoc loc )const 179 { 180const autorawLoc = loc .getRaw (); 181return rawLoc >=begin .getRaw ()&& rawLoc <=end .getRaw (); 182 } 183/// Get the total size 184SourceLoc ::RawValue getSize ()const {return end .getRaw ()- begin .getRaw (); } 185 186/// Get the offset of a loc in this range 187int getOffset (SourceLoc loc )const 188 { 189SLANG_ASSERT (contains (loc )); 190return int (loc .getRaw ()- begin .getRaw ()); 191 } 192 193/// Convert an offset to a loc 194SourceLoc getSourceLocFromOffset (uint32_t offset )const 195 { 196SLANG_ASSERT (offset <=getSize ()); 197return begin + offset ; 198 } 199 200SourceRange () {} 201 202SourceRange (SourceLoc loc ) 203 :begin (loc ),end (loc ) 204 { 205 } 206 207SourceRange (SourceLoc begin ,SourceLoc end ) 208 :begin (begin ),end (end ) 209 { 210 } 211 212SourceLoc begin ; 213SourceLoc end ; 214}; 215 216/// Source maps associated with files are could be of different uses. We use the SourceMapKind 217/// to indicate the usage. 218/// 219/// If the source map is obfuscated reasonable/desirable to ignore them on emit (if we didn't we 220/// leak information, and we don't emit into the locations in the obfuscated intermediate "file"). 221enum class SourceMapKind 222{ 223Normal ,///< A regular source map 224Obfuscated ,///< Obfuscated source map 225}; 226 227// Pre-declare 228struct SourceManager ; 229 230// A logical or physical storage object for a range of input code 231// that has logically contiguous source locations. 232class SourceFile 233{ 234public : 235struct OffsetRange 236 { 237/// We need a value to indicate an invalid range. We can't use 0 as that is valid for an 238/// offset range We can't use a negative number, and don't want to make signed so we get the 239/// full 32-bits. So we just use the max value as invalid 240static const uint32_t kInvalid = 0xffffffff ; 241 242/// True if the range is valid 243SLANG_FORCE_INLINE bool isValid ()const {return end >=start && start != kInvalid ; } 244/// True if offset is within range (inclusively) 245SLANG_FORCE_INLINE bool containsInclusive (uint32_t offset )const 246 { 247return offset >=start && offset <=end ; 248 } 249 250/// Get the count 251SLANG_FORCE_INLINE uint32_t getCount ()const {return end - start ; } 252 253/// Return an invalid range. 254static OffsetRange makeInvalid () {return OffsetRange {kInvalid ,kInvalid }; } 255 256uint32_t start ; 257uint32_t end ; 258 }; 259 260/// Returns the line break offsets (in bytes from start of content) 261/// Note that this is lazily evaluated - the line breaks are only calculated on the first 262/// request 263const List < uint32_t >& getLineBreakOffsets (); 264 265/// Returns true if the offset is on the specified line 266/// NOTE! If offsets are not fully setup (because we don't have source), will only be correct 267/// for lines that have offsets 268bool isOffsetOnLine (uint32_t offset ,Index lineIndex ); 269 270/// Get the line containing the offset. Requires that content is available, else will return an 271/// empty slice. 272UnownedStringSlice getLineContainingOffset (uint32_t offset ); 273 274/// Get the line at the specified line index. Requires that content is available, else will 275/// return an empty slice. 276UnownedStringSlice getLineAtIndex (Index lineIndex ); 277 278/// Get the offset range at the specified line index. Works without content. 279OffsetRange getOffsetRangeAtLineIndex (Index lineIndex ); 280 281/// Set the line break offsets 282void setLineBreakOffsets (const uint32_t * offsets ,UInt numOffsets ); 283 284/// Calculate the line based on the offset 285int calcLineIndexFromOffset (int offset ); 286 287/// Calculate the offset (in bytes) for a line 288int calcColumnOffset (int line ,int offset ); 289 290/// Given a line and offset (in bytes for the whole file), return the column index, taking into 291/// account tabs and utf8 encoding. Passing tabSize uses the default tab size (currently tab set 292/// to 1) 293int calcColumnIndex (int line ,int offset ,int tabSize = -1 ); 294 295/// Get the content holding blob 296ISlangBlob * getContentBlob ()const {return m_contentBlob ; } 297 298/// True if has full set content 299bool hasContent ()const {return m_contentBlob != nullptr ; } 300 301/// Get the content size 302size_t getContentSize ()const {return m_contentSize ; } 303 304/// Get the content 305const UnownedStringSlice & getContent ()const {return m_content ; } 306 307/// Get path info 308const PathInfo & getPathInfo ()const {return m_pathInfo ; } 309 310/// Set the content as a blob 311void setContents (ISlangBlob * blob ); 312/// Set the content as a string 313void setContents (const String & content ); 314 315/// Calculate a display path -> can canonicalize if necessary 316String calcVerbosePath ()const ; 317 318/// Get the source manager this was created on 319SourceManager * getSourceManager ()const {return m_sourceManager ; } 320 321/// Get the source map associated with this file. If it's set when doing 322/// lookup for source locations, the source map will be used 323IBoxValue < SourceMap >* getSourceMap ()const {return m_sourceMap ; } 324/// Get the source map kind 325SourceMapKind getSourceMapKind ()const {return m_sourceMapKind ; } 326 327/// Set a source map 328void setSourceMap (IBoxValue < SourceMap >* sourceMap ,SourceMapKind sourceMapKind ) 329 { 330m_sourceMap = sourceMap ; 331m_sourceMapKind = sourceMapKind ; 332 } 333 334/// Set the source file as an included file 335void setIncludedFile () {m_included = true; } 336 337/// Check if the source file is an included file 338bool isIncludedFile () {return m_included ; } 339 340/// Ctor 341SourceFile (SourceManager * sourceManager ,const PathInfo & pathInfo ,size_t contentSize ); 342/// Dtor 343 ~SourceFile (); 344 345SHA1 ::Digest getDigest (); 346 347protected : 348SourceManager * m_sourceManager ;///< The source manager this belongs to 349PathInfo 350m_pathInfo ;///< The path The logical file path to report for locations inside this span. 351 352ComPtr < ISlangBlob > m_contentBlob ;///< A blob that owns the storage for the file contents. If 353///< nullptr, there is no contents 354UnownedStringSlice m_content ;///< The actual contents of the file. 355size_t m_contentSize ;///< The size of the actual contents 356 357SHA1 ::Digest m_digest ; 358 359// In order to speed up lookup of line number information, 360// we will cache the starting offset of each line break in 361// the input file: 362List < uint32_t > m_lineBreakOffsets ; 363 364// If set then the locations in this file are really from locations from elsewhere, 365// where the SourceMap specifies that mapping 366ComPtr < IBoxValue < SourceMap >>m_sourceMap ; 367// What kind of source map it is (if there is one) 368SourceMapKind m_sourceMapKind = SourceMapKind ::Normal ; 369 370// Indicate if the source file is an included file 371bool m_included = false; 372}; 373 374enum class SourceLocType 375{ 376Nominal ,///< The normal interpretation which takes into account #line directives and source 377///< maps 378Actual ,///< Ignores #line directives/source maps - and is the location as seen in the actual 379///< file 380Emit ,///< Behaves the same as `Nominal` but ignores source maps. Used for Emit source 381///< locations. 382}; 383 384// A source location in a format a human might like to see 385struct HumaneSourceLoc 386{ 387PathInfo pathInfo = PathInfo ::makeUnknown (); 388Int line = 0 ; 389Int column = 0 ; 390}; 391 392// Same as HumaneSourceLoc but stores the path only as a handle. 393struct HandleSourceLoc 394{ 395StringSlicePool ::Handle pathHandle = StringSlicePool ::Handle (0 ); 396Int line = 0 ; 397Int column = 0 ; 398}; 399 400/* A SourceView maps to a single span of SourceLoc range and is equivalent to a single include or 401more precisely use of a source file. It is distinct from a SourceFile - because a SourceFile may be 402included multiple times, with different interpretations (depending on #defines for example). 403*/ 404class SourceView 405{ 406public : 407// Each entry represents some contiguous span of locations that 408// all map to the same logical file. 409struct Entry 410 { 411/// True if this resets the line numbering. It is distinct from a m_lineAdjust being 0, 412/// because it also means the path returns to the default. 413bool isDefault ()const {return m_pathHandle == StringSlicePool ::Handle (0 ); } 414 415SourceLoc m_startLoc ;///< Where does this entry begin? 416StringSlicePool ::Handle m_pathHandle ;///< What is the presumed path for this entry. If 0 it 417///< means there is no path. 418int32_t m_lineAdjust ;///< Adjustment to apply to source line numbers when printing presumed 419///< locations. Relative to the line number in the underlying file. 420 }; 421 422// Represents a segment of a source. 423// All SourceLoc in segment are linearly mapped relative to absoluteBegin 424struct AbsoluteSegment 425 { 426// SourceLoc in the file range. 427SourceLoc begin = {}; 428// Location in the absolute mapping of locations ordered by includes. 429SourceLoc ::RawValue absoluteBegin = {}; 430 }; 431 432// Set the base of the absolute location mapping for this SourceView. 433void setAbsoluteLocationBase (SourceLoc ::RawValue absLoc ) {m_absoluteLocationBase = absLoc ; } 434 435AbsoluteSegment getLastSegment ()const 436 { 437AbsoluteSegment res ; 438if (m_absSegments .getCount ()) 439 { 440res = m_absSegments .getLast (); 441 } 442else 443 { 444res .begin = m_range .begin ; 445res .absoluteBegin = m_absoluteLocationBase ; 446 } 447return res ; 448 } 449 450// Add a segment of absolute mapping after the previous ones. 451void addAbsoluteSegment (SourceLoc begin ,SourceLoc ::RawValue absoluteBegin ) 452 { 453SLANG_ASSERT (m_range .contains (begin )); 454SLANG_ASSERT (getLastSegment ().begin < begin ); 455AbsoluteSegment seg ; 456seg .begin = begin ; 457seg .absoluteBegin = absoluteBegin ; 458m_absSegments .add (seg ); 459 } 460 461// Maps a SourceLoc inside this SourceView to a unique absolute location ordered by includes. 462SourceLoc ::RawValue getAbsoluteLocation (SourceLoc loc )const ; 463 464/// Given a sourceLoc finds the entry associated with it. If returns -1 then no entry is 465/// associated with this location, and therefore the location should be interpreted as an offset 466/// into the underlying sourceFile. 467int findEntryIndex (SourceLoc sourceLoc )const ; 468 469/// Add a line directive for this view. The directiveLoc must of course be in this SourceView 470/// The path handle, must have been constructed on the SourceManager associated with the view 471/// NOTE! Directives are assumed to be added IN ORDER during parsing such that every 472/// directiveLoc > previous 473void addLineDirective (SourceLoc directiveLoc ,StringSlicePool ::Handle pathHandle ,int line ); 474void addLineDirective (SourceLoc directiveLoc ,const String & path ,int line ); 475 476/// Removes any corrections on line numbers and reverts to the source files path 477void addDefaultLineDirective (SourceLoc directiveLoc ); 478 479/// Get the range that this view applies to 480const SourceRange & getRange ()const {return m_range ; } 481/// Get the entries 482const List < Entry >& getEntries ()const {return m_entries ; } 483/// Set the entries list 484void setEntries (const Entry * entries ,UInt numEntries ) 485 { 486m_entries .clear (); 487m_entries .addRange (entries ,numEntries ); 488 } 489 490/// Get the source file holds the contents this view 491SourceFile * getSourceFile ()const {return m_sourceFile ; } 492/// Get the source manager 493SourceManager * getSourceManager ()const {return m_sourceFile -> getSourceManager (); } 494 495/// Get the associated 'content' (the source text) 496const UnownedStringSlice & getContent ()const {return m_sourceFile -> getContent (); } 497 498/// Get the size of the content 499size_t getContentSize ()const {return m_sourceFile -> getContentSize (); } 500 501/// Get the humane location 502/// Type determines if the location wanted is the original, or the 'normal' (which modifys 503/// behavior based on #line directives) 504HumaneSourceLoc getHumaneLoc (SourceLoc loc ,SourceLocType type = SourceLocType ::Nominal ); 505 506/// Get the humane location, but store the path as a handle 507HandleSourceLoc getHandleLoc (SourceLoc loc ,SourceLocType type = SourceLocType ::Nominal ); 508 509 510/// Get the path associated with a location 511PathInfo getPathInfo (SourceLoc loc ,SourceLocType type = SourceLocType ::Nominal ); 512 513/// Get the initiating source location - that is the source location that caused the this 514/// SourceView to be created Can be SourceLoc(0) if there is no initiating location. For example 515/// for a #include - the view's initiating source loc for the view that is the contents of the 516/// view will be the location of the #include in the source. For the original source file (ie 517/// not an include) - the view will have an initiating source loc of SourceLoc(0) 518SourceLoc getInitiatingSourceLoc ()const {return m_initiatingSourceLoc ; } 519 520/// Gets the pathInfo for this view. It may be different from the m_sourceFile's if the path has 521/// been overridden by m_viewPath 522PathInfo getViewPathInfo ()const ; 523 524/// Ctor 525SourceView ( 526SourceFile * sourceFile , 527SourceRange range , 528const String * viewPath , 529SourceLoc initiatingSourceLoc ) 530 :m_range (range ),m_sourceFile (sourceFile ),m_initiatingSourceLoc (initiatingSourceLoc ) 531 { 532if (viewPath ) 533 { 534m_viewPath = * viewPath ; 535 } 536 } 537 538protected : 539/// Get the pathInfo from a string handle. If it's 0, it will return the _getPathInfo 540PathInfo _getPathInfoFromHandle (StringSlicePool ::Handle pathHandle )const ; 541 542SlangResult _findSourceMapLoc (SourceLoc loc ,SourceLocType type ,HandleSourceLoc & outLoc ); 543 544String m_viewPath ;///< Path to this view. If empty the path is the path to the SourceView 545 546SourceLoc m_initiatingSourceLoc ;///< An optional source loc that defines where this view was 547///< initiated from. SourceLoc(0) if not defined. 548 549SourceRange m_range ;///< The range that this SourceView applies to 550SourceFile * m_sourceFile ;///< The source file. Can hold the line breaks 551List < Entry > m_entries ;///< An array entries describing how we should interpret a range, 552///< starting from the start location. 553SourceLoc ::RawValue m_absoluteLocationBase = 0 ;///< Base of the absolute location mapping. 554List < AbsoluteSegment > m_absSegments ;///< Segments of absolute location mapping. 555}; 556 557struct SourceManager 558{ 559// Initialize a source manager, with an optional parent 560void initialize (SourceManager * parent ,ISlangFileSystemExt * fileSystemExt ); 561 562/// Allocate a range of SourceLoc locations, these can be used to identify a specific location 563/// in the source 564SourceRange allocateSourceRange (UInt size ); 565 566/// Returns the loc for start of next allocation 567SourceLoc getNextRangeStart ()const {return m_nextLoc ; } 568 569/// Create a SourceFile defined with the specified path, and content held within a blob 570SourceFile * createSourceFileWithSize (const PathInfo & pathInfo ,size_t contentSize ); 571SourceFile * createSourceFileWithString (const PathInfo & pathInfo ,const String & contents ); 572SourceFile * createSourceFileWithBlob (const PathInfo & pathInfo ,ISlangBlob * blob ); 573 574/// Get the humane source location 575HumaneSourceLoc getHumaneLoc (SourceLoc loc ,SourceLocType type = SourceLocType ::Nominal ); 576 577/// Get the path associated with a location 578PathInfo getPathInfo (SourceLoc loc ,SourceLocType type = SourceLocType ::Nominal ); 579 580/// Create a new source view from a file 581/// @param sourceFile is the source file that contains the source 582/// @param pathInfo is path used to read the file from 583/// @param initiatingSourceLoc the (optional) location in the source that led the the creation 584/// of this view. If there isn't an initiating source location pass SourceLoc(0)s 585SourceView * createSourceView ( 586SourceFile * sourceFile , 587const PathInfo * pathInfo , 588SourceLoc initiatingSourceLoc ); 589 590/// Find a view by a source file location. 591/// If not found in this manager will look in the parent SourceManager 592/// Returns nullptr if not found. 593SourceView * findSourceViewRecursively (SourceLoc loc )const ; 594 595/// Find the SourceView associated with this manager for a specified location 596/// Returns nullptr if not found. 597SourceView * findSourceView (SourceLoc loc )const ; 598 599/// Searches this manager, and then the parent to see if can find a match for path. 600/// If not found returns nullptr. 601SourceFile * findSourceFileRecursively (const String & uniqueIdentity )const ; 602/// Find if the source file is defined on this manager. 603SourceFile * findSourceFile (const String & uniqueIdentity )const ; 604 605/// Find a source file by path. 606SourceFile * findSourceFileByPath (const String & name )const ; 607/// Find a source file by path recursively. 608SourceFile * findSourceFileByPathRecursively (const String & name )const ; 609 610/// Searches this manager, and then the parent to see if can find a match 611SourceFile * findSourceFileByContentRecursively (const char * text ); 612/// Find the source file that contains *the memory* text points to. 613SourceFile * findSourceFileByContent (const char * text )const ; 614 615/// Get the file system associated with this source manager 616ISlangFileSystemExt * getFileSystemExt ()const {return m_fileSystemExt ; } 617/// Get the file system associated with this source manager 618void setFileSystemExt (ISlangFileSystemExt * fileSystemExt ) {m_fileSystemExt = fileSystemExt ; } 619 620/// Add a source file, uniqueIdentity must be unique for this manager AND any parents 621void addSourceFile (const String & uniqueIdentity ,SourceFile * sourceFile ); 622void addSourceFileIfNotExist (const String & uniqueIdentity ,SourceFile * sourceFile ); 623 624// Maps a SourceLoc to an absolute location 625SourceLoc ::RawValue getAbsoluteLocation (SourceLoc location )const ; 626 627/// Get the slice pool 628StringSlicePool & getStringSlicePool () {return m_slicePool ; } 629 630/// Get the source range for just this manager 631/// Caution - the range will change if allocations are made to this manager. 632SourceRange getSourceRange ()const {return SourceRange (m_startLoc ,m_nextLoc ); } 633 634/// Get the parent manager to this manager. Returns nullptr if there isn't any. 635SourceManager * getParent ()const {return m_parent ; } 636 637/// A memory arena to hold allocations that are in scope for the same time as SourceManager 638MemoryArena * getMemoryArena () {return & m_memoryArena ; } 639 640/// Allocate a string slice 641UnownedStringSlice allocateStringSlice (const UnownedStringSlice & slice ); 642 643/// Get all of the source files 644const List < SourceFile *>& getSourceFiles ()const {return m_sourceFiles ; } 645 646/// Get the source views 647const List < SourceView *>& getSourceViews ()const {return m_sourceViews ; } 648 649/// Resets state. Will release all views/source 650void reset (); 651 652SourceManager () 653 :m_memoryArena (2048 ),m_slicePool (StringSlicePool ::Style ::Default ) 654 { 655 } 656 ~SourceManager (); 657 658protected : 659void _resetLoc (); 660void _resetSource (); 661 662// The first location available to this source manager 663// (may not be the first location of all, because we might 664// have a parent source manager) 665SourceLoc m_startLoc ; 666 667// The "parent" source manager that owns locations ahead of `startLoc` 668SourceManager * m_parent = nullptr ; 669 670// The location to be used by the next source file to be loaded 671SourceLoc m_nextLoc ; 672 673// All of the SourceViews constructed on this SourceManager. These are held in increasing order 674// of range, so can find by doing a binary chop. 675List < SourceView *> m_sourceViews ; 676// All of the SourceFiles constructed on this SourceManager. This owns the SourceFile. 677List < SourceFile *> m_sourceFiles ; 678 679StringSlicePool m_slicePool ; 680 681// Memory arena that can be used for holding data to held in scope as long as the Source is 682// Can be used for storing the decoded contents of Token. Content for example. 683MemoryArena m_memoryArena ; 684 685// Maps uniqueIdentities to source files 686Dictionary < String ,SourceFile *> m_sourceFileMap ; 687 688ComPtr < ISlangFileSystemExt > m_fileSystemExt ; 689}; 690 691}// namespace Slang 692 693#endif