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