Skip to content
← Back

src/semantic/symbols/signature_part.ghul

1
namespace Semantic.Symbols is
2
use Collections.LIST
3
4
use Semantic.Types.Type
5
6
// The TYPE_REF field's default-equality comparison is correct as
7
// it stands: `Type` values are interned, so reference equality is
8
// type equality, and the operator the fallback report would ask
9
// for has nothing to add.
10
@suppress("synthesized-equality-fallback")
11
union SignaturePart is
12
NIL
13
LITERAL(text: string)
14
NAME(symbol: Symbol)
15
TYPE_REF(type: Type)
16
SEQUENCE(parts: LIST[SignaturePart])
17
// A break point for the layout engine. Flat form: `open` +
18
// items joined by (`separator` + " " when `tight` is false,
19
// `separator` alone when true) + `close`. Broken form: `open`
20
// + newline + 4-space-indented items joined by `separator` +
21
// newline + indent + newline + `close` at the outer indent.
22
// `separator` is punctuation-only (no trailing space); `tight`
23
// controls whether a flat rendering inserts a space after each
24
// one. Argument lists use `separator=","`, `tight=false`;
25
// generic-argument brackets use `separator=","`, `tight=true`.
26
WRAPPABLE(
27
open: string,
28
separator: string,
29
tight: bool,
30
close: string,
31
items: LIST[SignaturePart]
32
)
33
// A forced line break introducing an indented continuation:
34
// a newline, `indent` spaces, the `head` text, then `body`.
35
// `body`'s own break points nest a further `head.length` columns
36
// so a wrappable body's continuation lines hang under the text
37
// after `head` rather than under the break. Used for the narrowed
38
// `► <type>` line beneath a symbol's declared type.
39
HANGING(
40
indent: int,
41
head: string,
42
body: SignaturePart
43
)
44
si
45
46
// Convenience builders that fold the `Collections.LIST[SignaturePart]`
47
// wrapping into a single call so `describe` overrides read as data.
48
class PARTS is
49
literal(text: string) -> SignaturePart static =>
50
SignaturePart.LITERAL(text)
51
52
name(symbol: Symbol) -> SignaturePart static =>
53
SignaturePart.NAME(symbol)
54
55
type_ref(type: Type) -> SignaturePart static =>
56
SignaturePart.TYPE_REF(type)
57
58
nil() -> SignaturePart static =>
59
SignaturePart.NIL()
60
61
sequence(items: SignaturePart[]) -> SignaturePart static =>
62
SignaturePart.SEQUENCE(Collections.LIST[SignaturePart](items))
63
64
wrappable(
65
open: string,
66
separator: string,
67
tight: bool,
68
close: string,
69
items: SignaturePart[]
70
) -> SignaturePart static =>
71
SignaturePart.WRAPPABLE(open, separator, tight, close, Collections.LIST[SignaturePart](items))
72
73
hanging(indent: int, head: string, body: SignaturePart) -> SignaturePart static =>
74
SignaturePart.HANGING(indent, head, body)
75
si
76
77
class DESCRIBE_CONTEXT is
78
_default: DESCRIBE_CONTEXT? static
79
_observed_types: Collections.Map[Symbol, Type]?
80
81
instance: DESCRIBE_CONTEXT static is
82
if !_default? then
83
_default = DESCRIBE_CONTEXT()
84
fi
85
return _default
86
si
87
88
init() is
89
si
90
91
with_observed_types(observed_types: Collections.Map[Symbol, Type]) -> DESCRIBE_CONTEXT static is
92
let result = DESCRIBE_CONTEXT()
93
result._observed_types = observed_types
94
return result
95
si
96
97
observed_type_for(symbol: Symbol) -> Type? is
98
let map = _observed_types
99
if !map? then
100
return null
101
fi
102
if !map.contains_key(symbol) then
103
return null
104
fi
105
return map[symbol]
106
si
107
si
108
109
class TEXT_RENDERER is
110
_context: DESCRIBE_CONTEXT
111
112
init(context: DESCRIBE_CONTEXT) is
113
_context = context
114
si
115
116
render(part: SignaturePart) -> string is
117
let buffer = System.Text.StringBuilder()
118
_emit(buffer, part)
119
return buffer.to_string()
120
si
121
122
_emit(buffer: System.Text.StringBuilder, part: SignaturePart) is
123
if isa SignaturePart.NIL(part) then
124
return
125
fi
126
127
if let literal: SignaturePart.LITERAL = part then
128
buffer.append(literal.text)
129
return
130
fi
131
132
if let name: SignaturePart.NAME = part then
133
buffer.append(IoC.CONTAINER.instance.name_display.name_for(name.symbol))
134
return
135
fi
136
137
if let type_ref: SignaturePart.TYPE_REF = part then
138
buffer.append("{type_ref.type}")
139
return
140
fi
141
142
if let sequence: SignaturePart.SEQUENCE = part then
143
for item in sequence.parts do
144
_emit(buffer, item)
145
od
146
return
147
fi
148
149
if let wrappable: SignaturePart.WRAPPABLE = part then
150
buffer.append(wrappable.open)
151
let first mut = true
152
for item in wrappable.items do
153
if !first then
154
buffer.append(wrappable.separator)
155
if !wrappable.tight then
156
buffer.append(' ')
157
fi
158
fi
159
first = false
160
_emit(buffer, item)
161
od
162
buffer.append(wrappable.close)
163
return
164
fi
165
166
if let hanging: SignaturePart.HANGING = part then
167
buffer.append('\n')
168
let i mut = 0
169
while i < hanging.indent do
170
buffer.append(' ')
171
i = i + 1
172
od
173
buffer.append(hanging.head)
174
_emit(buffer, hanging.body)
175
return
176
fi
177
si
178
si
179
si