Skip to content
← Back

src/semantic/symbols/method_override_map.ghul

1
namespace Semantic is
2
use IO.Std
3
4
use System.Text.StringBuilder
5
6
use Collections.Iterable
7
use Ghul.Pipes
8
use Collections.Iterator
9
10
use Collections.MAP
11
use Collections.SET
12
13
use Symbols.Symbol
14
use Symbols.Function
15
16
class METHOD_OVERRIDE_MAP(name: string): Iterable[METHOD_OVERRIDE_SET] is
17
_symbols: SET[SYMBOL_WRAPPER]
18
_symbols_list: Collections.LIST[Symbol]?
19
20
methods: MAP[METHOD_OVERRIDE_CLASS,METHOD_OVERRIDE_SET]
21
22
// Read several times per class during override resolution, so the
23
// projected list is built once and reused; `add` resets it.
24
symbols: Iterable[Symbol] is
25
if _symbols_list? then
26
return _symbols_list
27
fi
28
29
let list = Collections.LIST[Symbol]()
30
31
for w in _symbols do
32
list.add(w.symbol)
33
od
34
35
_symbols_list = list
36
37
return list
38
si
39
40
// Avoids building and piping `symbols` when only the first element
41
// is wanted.
42
first_symbol: Symbol? is
43
for w in _symbols do
44
return w.symbol
45
od
46
47
return null
48
si
49
50
iterator: Iterator[METHOD_OVERRIDE_SET] => methods.values.iterator
51
52
contains_any_methods: bool => methods.count > 0
53
contains_any_symbols: bool => _symbols.count > 0
54
55
_empty: METHOD_OVERRIDE_MAP? static
56
57
// Shared, read-only empty map for the common case where a class
58
// declares no member of a given name. Only ever read, never added to.
59
empty: METHOD_OVERRIDE_MAP static is
60
if _empty? then
61
return _empty
62
fi
63
64
let empty = METHOD_OVERRIDE_MAP("")
65
66
_empty = empty
67
68
return empty
69
si
70
71
[method_class: METHOD_OVERRIDE_CLASS]: METHOD_OVERRIDE_SET? is
72
let result: METHOD_OVERRIDE_SET mut
73
74
if methods.try_get_value(method_class, result ref) then
75
return result
76
fi
77
78
return null
79
si
80
81
init(..) is
82
methods = MAP()
83
_symbols = SET()
84
si
85
86
contains(override_class: METHOD_OVERRIDE_CLASS) -> bool => methods.contains_key(override_class)
87
88
add(symbol: Symbol) is
89
if isa Function(symbol) then
90
add(symbol)
91
92
return
93
fi
94
95
let wrapper = SYMBOL_WRAPPER(symbol)
96
97
if !_symbols.contains(wrapper) then
98
_symbols.add(wrapper)
99
_symbols_list = null
100
fi
101
si
102
103
add(group: Symbols.FUNCTION_GROUP) is
104
for f in group.functions do
105
add(f)
106
od
107
si
108
109
add(functions: Iterable[Function]) is
110
for f in functions do
111
add(f)
112
od
113
si
114
115
add(method: Function) is
116
let c = method.override_class
117
118
let method_set: METHOD_OVERRIDE_SET mut
119
120
if !methods.try_get_value(c, method_set ref) then
121
method_set = METHOD_OVERRIDE_SET(c)
122
methods[c] = method_set
123
fi
124
125
assert method_set? else "no method set for {method.qualified_name}"
126
127
method_set.add(method)
128
si
129
130
to_string() -> string is
131
let result = StringBuilder()
132
133
for s in methods do
134
result.append("{name}: [{s.key}: {s.value}]")
135
od
136
137
result.append(" others: ").append(symbols |> join(", "))
138
139
return result.to_string()
140
si
141
si
142
si