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