Skip to content
← Back

src/source/body_spans.ghul

1
namespace Source is
2
use Collections;
3
4
use Ghul.Pipes;
5
6
// The pre-edit spans of the function bodies an incremental EDIT
7
// re-walks. A symbol-use or definition entry inside one of these is
8
// re-recorded fresh by the re-walk, so reconciliation discards it
9
// rather than translating it.
10
//
11
// Function bodies neither nest nor overlap, so the spans sort by start
12
// position and a binary search answers `contains`.
13
class BODY_SPANS is
14
_spans: LIST[LOCATION];
15
_prepared: bool;
16
17
init() is
18
_spans = LIST[LOCATION]();
19
si
20
21
// Internal locations are synthesised — their packed position is
22
// (1,1) by construction and would otherwise drop any real symbol
23
// declared at line 1 column 1 (a top-level namespace, the first
24
// class in the file) when reconciliation calls `contains` with
25
// file_name unchecked.
26
add(span: LOCATION) is
27
if !span.is_internal then
28
_spans.add(span);
29
_prepared = false;
30
fi
31
si
32
33
// Is a (packed) position inside one of the re-walked bodies?
34
contains(position: int) -> bool is
35
_prepare();
36
37
// last span starting at or before `position`
38
let lo mut = 0;
39
let hi mut = _spans.count;
40
41
while lo < hi do
42
let mid = (lo + hi) / 2;
43
44
if _spans[mid].start <= position then
45
lo = mid + 1;
46
else
47
hi = mid;
48
fi
49
od
50
51
return lo > 0 /\ _spans[lo - 1].contains(position);
52
si
53
54
_prepare() is
55
if _prepared then
56
return;
57
fi
58
59
_spans = LIST[LOCATION](_spans |> sort((a, b) => a.start - b.start));
60
_prepared = true;
61
si
62
si
63
si