Skip to content
← Back

src/syntax/process/function_pairing.ghul

1
namespace Syntax is
2
use Collections.LIST;
3
4
use Trees;
5
use Trees.Definitions.FUNCTION;
6
7
// Collects a parsed file's `Definitions.FUNCTION` declarations in
8
// declaration order. After `add_accessors_for_properties` (run as part of
9
// rewrite-syntax-trees) this is every method plus the accessor functions
10
// synthesised for properties and indexers. `pre` returns true for a
11
// function, so bodies are not descended into and nested lambdas are not
12
// collected.
13
class FUNCTION_COLLECTOR: Visitor is
14
functions: LIST[FUNCTION] public;
15
16
init() is
17
super.init();
18
functions = LIST[FUNCTION]();
19
si
20
21
pre(function: FUNCTION) -> bool is
22
functions.add(function);
23
return true;
24
si
25
si
26
27
// One retained-to-donor function pairing for the incremental body re-walk.
28
struct FUNCTION_PAIR is
29
retained: FUNCTION public;
30
donor: FUNCTION public;
31
32
init(retained: FUNCTION, donor: FUNCTION) is
33
self.retained = retained;
34
self.donor = donor;
35
si
36
si
37
38
// Pairs the function declarations of two parses of the same file — the
39
// retained AST and a freshly parsed donor — for the incremental body
40
// re-walk. Only interface-preserving edits reach this, so the two parses
41
// have an identical declaration sequence and the pairing is positional;
42
// name and argument count are checked per pair purely as a desync guard.
43
//
44
// `pairs` is null when the two parses do not pair cleanly: the caller must
45
// then fall back to a full rebuild rather than splice.
46
class FUNCTION_PAIRING is
47
pairs: LIST[FUNCTION_PAIR]? public;
48
49
init(retained_root: Node, donor_root: Node) is
50
let retained = collect(retained_root);
51
let donor = collect(donor_root);
52
53
if retained.count != donor.count then
54
pairs = null;
55
return;
56
fi
57
58
let result = LIST[FUNCTION_PAIR]();
59
60
for i in 0..retained.count do
61
let r = retained[i];
62
let d = donor[i];
63
64
if !signatures_match(r, d) then
65
pairs = null;
66
return;
67
fi
68
69
result.add(FUNCTION_PAIR(r, d));
70
od
71
72
pairs = result;
73
si
74
75
collect(root: Node) -> LIST[FUNCTION] static is
76
let collector = FUNCTION_COLLECTOR();
77
root.walk(collector);
78
return collector.functions;
79
si
80
81
signatures_match(a: FUNCTION, b: FUNCTION) -> bool static =>
82
name_of(a) =~ name_of(b) /\
83
a.arguments.variables.count == b.arguments.variables.count;
84
85
name_of(function: FUNCTION) -> string static =>
86
if function.name? then function.name.name else "" fi;
87
si
88
si