FE 0.15.0
A C++23 toolkit for writing compiler/interpreter frontends.
Loading...
Searching...
No Matches
loc.h
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4#include <cstdint>
5
6#include <algorithm>
7#include <iosfwd>
8
9namespace fe {
10
11class Src;
12
13/// Byte offset into a Src; pass around as value.
14/// A Pos%ition is just an index - fe::Src turns it back into the row/column a human wants to read.
15/// @warning Files beyond 4GiB wrap around, and the largest offset doubles as the "invalid" sentinel.
16struct Pos {
17 static constexpr uint32_t Invalid = uint32_t(-1);
18
19 constexpr Pos() noexcept = default; ///< Creates an invalid Pos%ition.
20 constexpr explicit Pos(uint32_t off) noexcept
21 : off(off) {}
22
23 constexpr explicit operator bool() const noexcept { return off != Invalid; } ///< Is a valid Pos%ition?
24 constexpr auto operator<=>(const Pos&) const noexcept = default;
25 constexpr Pos operator+(uint32_t n) const noexcept {
26 assert(*this && (uint64_t)off + n < Invalid);
27 return Pos(off + n);
28 }
29 void dump() const;
30
31 uint32_t off = Invalid;
32
33 friend std::ostream& operator<<(std::ostream& os, Pos pos);
34};
35
36/// Loc%ation within a Src: the half-open byte range `[Loc::begin, Loc::end)`.
37/// It's only two machine words on a 64 bit arch, so pass around as value.
38/// An *empty* range is a Loc%ation *between* two characters - what you want to point at
39/// when something is missing rather than wrong; see Loc::anew_end.
40/// @warning Loc::src is only a pointer and it is your job to guarantee that the underlying
41/// fe::Src outlives this Loc%ation; fe::SrcMap owns one for you.
42struct Loc {
43 /// How much of a Loc a diagnostic spells out; see Diag::loc_style.
44 enum class Style {
45 Full, ///< `path:row:col-row:col` - the whole range.
46 RowCol, ///< `path:row:col`
47 Row, ///< `path:row`
48 MSVC, ///< `path(row,col)`
49 };
50
51 constexpr Loc() noexcept = default; ///< Creates an invalid Loc%ation.
52 constexpr Loc(const Src* src, Pos begin, Pos end) noexcept
53 : src(src)
54 , begin(begin)
55 , end(end) {}
56 constexpr Loc(const Src* src, Pos pos) noexcept
57 : Loc(src, pos, pos) {} ///< The empty Loc%ation at @p pos.
58 constexpr Loc(Pos begin, Pos end) noexcept
59 : Loc(nullptr, begin, end) {}
60 constexpr Loc(Pos pos) noexcept
61 : Loc(nullptr, pos, pos) {}
62
63 constexpr Loc anew_begin() const noexcept { return {src, begin, begin}; }
64 constexpr Loc anew_end() const noexcept { return {src, end, end}; }
65 constexpr uint32_t size() const noexcept {
66 assert((bool)begin == (bool)end && begin <= end);
67 return end.off - begin.off;
68 }
69 constexpr Loc operator+(Pos pos) const noexcept { return {src, begin, pos}; }
70 constexpr Loc operator+(Loc loc) const noexcept { return {src, begin, loc.end}; } ///< The hull of both Loc%ations.
71
72 /// The overlap of both Loc%ations - invalid if they are disjoint or sit in different files.
73 /// Dual to operator+; since an invalid Loc is falsy, `if (a & b)` also reads as "do they overlap?".
74 /// An empty Loc overlaps nothing, not even itself.
75 /// @note Loc::src is only compared via pointer equality - which is all it takes, as fe::SrcMap
76 /// interns paths and hands out exactly one Src per file.
77 constexpr Loc operator&(Loc loc) const noexcept {
78 auto b = std::max(begin, loc.begin);
79 auto e = std::min(end, loc.end);
80 if (src != loc.src || b >= e) return {};
81 return {src, b, e};
82 }
83
84 constexpr explicit operator bool() const noexcept { return (bool)begin; } ///< Is a valid Loc%ation?
85 /// @note Loc::src is only checked via pointer equality.
86 constexpr bool operator==(Loc other) const noexcept {
87 return begin == other.begin && end == other.end && src == other.src;
88 }
89 void dump() const;
90
91 const Src* src = {};
92 Pos begin = {};
93 Pos end = {};
94 ///< It's called `end` because - just like an STL iterator - it refers to the byte
95 /// one **past** the last one within this Loc%ation.
96
97 /// Streams as `path:row:col-row:col`, resolved through Loc::src - or as raw offsets if it has none.
98 friend std::ostream& operator<<(std::ostream& os, Loc loc);
99};
100
101// Keep Loc at two machine words so it is passed/returned in registers.
102static_assert(sizeof(void*) != 8 || sizeof(Loc) == 16, "Loc should stay two machine words");
103
104} // namespace fe
The content of one source file together with the offsets its rows start at.
Definition src.h:40
Definition algo.h:17
Location within a Src: the half-open byte range [Loc::begin, Loc::end).
Definition loc.h:42
void dump() const
constexpr bool operator==(Loc other) const noexcept
Definition loc.h:86
constexpr Loc anew_end() const noexcept
Definition loc.h:64
constexpr Loc(const Src *src, Pos pos) noexcept
The empty Location at pos.
Definition loc.h:56
constexpr Loc() noexcept=default
Creates an invalid Location.
constexpr Loc operator&(Loc loc) const noexcept
The overlap of both Locations - invalid if they are disjoint or sit in different files.
Definition loc.h:77
friend std::ostream & operator<<(std::ostream &os, Loc loc)
Streams as path:row:col-row:col, resolved through Loc::src - or as raw offsets if it has none.
Pos begin
Definition loc.h:92
constexpr Loc operator+(Loc loc) const noexcept
The hull of both Locations.
Definition loc.h:70
constexpr Loc operator+(Pos pos) const noexcept
Definition loc.h:69
Style
How much of a Loc a diagnostic spells out; see Diag::loc_style.
Definition loc.h:44
constexpr Loc anew_begin() const noexcept
Definition loc.h:63
const Src * src
Definition loc.h:91
constexpr Loc(Pos pos) noexcept
Definition loc.h:60
Pos end
It's called end because - just like an STL iterator - it refers to the byte one past the last one wit...
Definition loc.h:93
constexpr Loc(Pos begin, Pos end) noexcept
Definition loc.h:58
constexpr uint32_t size() const noexcept
Definition loc.h:65
Byte offset into a Src; pass around as value.
Definition loc.h:16
uint32_t off
Definition loc.h:31
static constexpr uint32_t Invalid
Definition loc.h:17
constexpr Pos operator+(uint32_t n) const noexcept
Definition loc.h:25
friend std::ostream & operator<<(std::ostream &os, Pos pos)
constexpr auto operator<=>(const Pos &) const noexcept=default
constexpr Pos() noexcept=default
Creates an invalid Position.
void dump() const