comparison src/basic/SourceLocation.d @ 206:d3c148ca429b

Major moving of files. all src now goes into src, all docs in docs.
author Anders Johnsen <skabet@gmail.com>
date Tue, 12 Aug 2008 18:14:56 +0200
parents
children e0551773a005
comparison
equal deleted inserted replaced
205:8387cbaa85ab 206:d3c148ca429b
1 module basic.SourceLocation;
2
3 /// Shorter alias for SourceLocation
4 public alias SourceLocation SLoc;
5
6 /// SourceLocation points to a place in some buffer
7 struct SourceLocation
8 {
9 /// Returns true, if the location is from a real file
10 bool isReal() { return (val & 0x80_00_00_00) == 0; }
11 /// Returns true, if the location is not from a real file
12 bool isVirtual() { return (val & 0x80_00_00_00) != 0; }
13
14 /// Check if this location is invalid or not
15 bool isValid() { return val != uint.max; }
16 /// ditto
17 bool isInvalid() { return val == uint.max; }
18
19 /**
20 Extracts the file id.
21
22 Warning: In release mode this may return junk, if the loc is not from a
23 file
24 **/
25 uint fileID() {
26 assert(isValid, "Location is invalid");
27 assert(isReal, "You can only extract fileID from a real location");
28 // Here we can rely on two facts, first that the high bit is zero
29 // since its a real position, second that FileOffset is saved in the
30 // high end, so all we need is some shifting
31 return val >> Bits.FileOffset;
32 }
33
34 /**
35 Extracts the offset into the "file". (actually in to the referenced
36 chunk)
37
38 Warning: In release mode this may return junk, if the loc is not from a
39 file
40 **/
41 uint fileOffset() {
42 assert(isValid, "Location is invalid");
43 assert(isReal, "You can only extract fileOffset from real locations");
44 // FileOffset is stored in the lower bits, so all that is needed is a
45 // binary and with all ones in the lower bits.
46 return val & (1 << Bits.FileOffset) - 1;
47 }
48
49 /// Get a new location, placed n bytes after the given location
50 SourceLocation opAdd(int n)
51 {
52 SourceLocation res = *this;
53 res.val += n;
54 return res;
55 }
56
57 /// Get a new location, placed n bytes before the given location
58 SourceLocation opSub(int n)
59 {
60 SourceLocation res = *this;
61 res.val -= n;
62 return res;
63 }
64
65 /// Creates a SourceLocation from a File ID
66 static SourceLocation fromFileID(uint fileID)
67 {
68 assert(fileID < Bits.MaxFileID, "To large fileID");
69 SourceLocation res;
70 res.val = fileID << Bits.FileOffset;
71 return res;
72 }
73
74 /**
75 Used for invalid/unknown locations. (also the default value, but this is
76 more explicit)
77 **/
78 static const SourceLocation Invalid = {val: uint.max};
79
80 private:
81 /**
82 A SourceLocation consists of 1 bit, indicating real or virtual, meaning
83 if the location points to a file(real), a string mixin or has been
84 affected by #line(virtual). That information is saved in the most
85 significant bit.
86 The rest depends on which type we are dealing with.
87 Real:
88 13 bits for a file identifier
89 18 bits for offset into that "file" (one file may be split)
90 Virtual:
91 Unknown for now. Likely skewed toward more ids and some meta data
92 An invalid location is uint.max, this might happen by accident but its
93 unlikely.
94 **/
95 uint val = uint.max;
96
97 /**
98 This enum contains some constants that are useful for manipulating
99 SourceLocation's, like the size of various “members” of val.
100 **/
101 static enum Bits {
102 /// Number of bits used for the offset into file buffers
103 FileOffset = 18,
104 /// Number of bits used to identify which file buffer this is from
105 FileID = 31 - FileOffset,
106
107 /// Indicates how much can be indexed within one block(2^FileOffset)
108 MaxFileOffset = 1 << FileOffset,
109 MaxFileID = 1 << FileID,
110 }
111 }
112
113 /// A simple pair used to describe a range in a buffer and not just a point.
114 struct SourceRange
115 {
116 SourceLocation begin, end;
117
118 static SourceRange opCall(SourceLocation loc)
119 {
120 return SourceRange(loc, loc + 1);
121 }
122
123 static SourceRange opCall(SourceLocation begin, SourceLocation end)
124 {
125 SourceRange res;
126 res.begin = begin;
127 res.end = end;
128 return res;
129 }
130
131 bool isValid() { return begin.isValid && end.isValid; }
132 bool isInvalid() { return begin.isInvalid || end.isInvalid; }
133
134 bool isReal() { return begin.isReal && end.isReal; }
135
136 /// Get a new range spanning both ranges
137 SourceRange opAdd(SourceRange that)
138 {
139 assert(this.isValid && that.isValid, "Invalid range");
140 return SourceRange(
141 this.begin.val < that.begin.val? this.begin : that.begin,
142 this.end.val > that.end.val? this.end : that.end);
143 }
144 }
145