Mercurial > projects > dang
view basic/SourceLocation.d @ 182:4e703658eca0
merge
author | Anders Halager <halager@gmail.com> |
---|---|
date | Fri, 25 Jul 2008 01:40:08 +0200 |
parents | 6ec686d9c87d |
children |
line wrap: on
line source
module basic.SourceLocation; import Integer = tango.text.convert.Integer; /// Shorter alias for SourceLocation public alias SourceLocation SLoc; /// SourceLocation points to a place in some buffer struct SourceLocation { /// Returns true, if the location is from a real file bool isReal() { return (val & 0x80_00_00_00) == 0; } /// Returns true, if the location is not from a real file bool isVirtual() { return (val & 0x80_00_00_00) != 0; } /// Check if this location is invalid or not bool isValid() { return val != uint.max; } /// ditto bool isInvalid() { return val == uint.max; } /** Extracts the file id. Warning: In release mode this may return junk, if the loc is not from a file **/ uint fileID() { assert(isValid, "Location is invalid"); assert(isReal, "You can only extract fileID from a real location"); // Here we can rely on two facts, first that the high bit is zero // since its a real position, second that FileOffset is saved in the // high end, so all we need is some shifting return val >> Bits.FileOffset; } /** Extracts the offset into the "file". (actually in to the referenced chunk) Warning: In release mode this may return junk, if the loc is not from a file **/ uint fileOffset() { assert(isValid, "Location is invalid"); assert(isReal, "You can only extract fileOffset from real locations"); // FileOffset is stored in the lower bits, so all that is needed is a // binary and with all ones in the lower bits. return val & (1 << Bits.FileOffset) - 1; } /// Get a new location, placed n bytes after the given location SourceLocation opAdd(int n) { SourceLocation res = *this; res.val += n; return res; } /// Get a new location, placed n bytes before the given location SourceLocation opSub(int n) { SourceLocation res = *this; res.val -= n; return res; } /// Get the length between two location int opSub(SourceLocation loc) { return val - loc.val; } /// Creates a SourceLocation from a File ID static SourceLocation fromFileID(uint fileID) { assert(fileID < Bits.MaxFileID, "To large fileID"); SourceLocation res; res.val = fileID << Bits.FileOffset; return res; } char[] toString() { return Integer.toString(val); } /** Used for invalid/unknown locations. (also the default value, but this is more explicit) **/ static const SourceLocation Invalid = {val: uint.max}; private: /** A SourceLocation consists of 1 bit, indicating real or virtual, meaning if the location points to a file(real), a string mixin or has been affected by #line(virtual). That information is saved in the most significant bit. The rest depends on which type we are dealing with. Real: 13 bits for a file identifier 18 bits for offset into that "file" (one file may be split) Virtual: Unknown for now. Likely skewed toward more ids and some meta data An invalid location is uint.max, this might happen by accident but its unlikely. **/ uint val = uint.max; /** This enum contains some constants that are useful for manipulating SourceLocation's, like the size of various “members” of val. **/ static enum Bits { /// Number of bits used for the offset into file buffers FileOffset = 18, /// Number of bits used to identify which file buffer this is from FileID = 31 - FileOffset, /// Indicates how much can be indexed within one block(2^FileOffset) MaxFileOffset = 1 << FileOffset, MaxFileID = 1 << FileID, } } /// A simple pair used to describe a range in a buffer and not just a point. struct SourceRange { SourceLocation begin, end; static SourceRange opCall(SourceLocation loc) { return SourceRange(loc, loc + 1); } static SourceRange opCall(SourceLocation begin, SourceLocation end) { SourceRange res; res.begin = begin; res.end = end; return res; } bool isValid() { return begin.isValid && end.isValid; } bool isInvalid() { return begin.isInvalid || end.isInvalid; } bool isReal() { return begin.isReal && end.isReal; } /// Get a new range spanning both ranges SourceRange opAdd(SourceRange that) { assert(this.isValid && that.isValid, "Invalid range"); return SourceRange( this.begin.val < that.begin.val? this.begin : that.begin, this.end.val > that.end.val? this.end : that.end); } }