Skip to content
← Back

src/syntax/process/declare_symbols.ghul

1
namespace Syntax.Process is
2
use Logging;
3
use Source;
4
use Trees;
5
6
class DECLARE_SYMBOLS(
7
_logger: Logger,
8
symbol_table: Semantic.SYMBOL_TABLE,
9
namespaces: Semantic.NAMESPACES,
10
_symbol_definition_listener: Semantic.SymbolDefinitionListener
11
): ScopeVisitorBase is
12
_pragma_scope_stack: PRAGMA_SCOPE_STACK;
13
14
_generic_argument_declarer: GENERIC_ARGUMENT_DECLARER;
15
16
super(symbol_table, namespaces);
17
18
init(..) is
19
_pragma_scope_stack = PRAGMA_SCOPE_STACK();
20
_generic_argument_declarer = GENERIC_ARGUMENT_DECLARER(_logger, symbol_table, _symbol_definition_listener);
21
si
22
23
apply(node: Node) is
24
assert _pragma_scope_stack.is_balanced;
25
26
node.walk(self);
27
28
assert _pragma_scope_stack.is_balanced;
29
si
30
31
32
33
pre(pragma: Definitions.PRAGMA) -> bool is
34
_pragma_scope_stack.enter(pragma.pragma);
35
36
return false;
37
si
38
39
visit(pragma: Definitions.PRAGMA) is
40
let p = pragma.pragma;
41
42
let name = p.name.to_string();
43
44
let is_primitive = name =~ "IL.built_in_type";
45
46
if
47
is_primitive \/
48
name =~ "IL.name" \/
49
name =~ "IL.name.read" \/
50
name =~ "IL.name.assign"
51
then
52
if p.arguments.expressions.count != 1 then
53
_logger.error(p.arguments.location, "expected one argument");
54
return;
55
fi
56
57
let argument = p.arguments.expressions[0];
58
59
if !isa Expressions.Literals.STRING(argument) then
60
_logger.error(p.arguments.location, "expected a string literal argument");
61
return;
62
fi
63
64
let il_name = argument.value_string;
65
66
let definition mut = pragma.definition;
67
68
while isa Definitions.PRAGMA(definition) do
69
definition = cast Definitions.PRAGMA(definition).definition;
70
od
71
72
let symbol = symbol_for(definition);
73
74
if symbol? then
75
if isa Semantic.Symbols.Property(symbol) then
76
let property = symbol;
77
78
if name =~ "IL.name.read" then
79
property.read_function_il_name_override = il_name;
80
elif name =~ "IL.name.assign" then
81
property.assign_function_il_name_override = il_name;
82
elif name =~ "IL.name" then
83
property.il_name_override = il_name;
84
85
if !property.read_function_il_name_override? then
86
property.read_function_il_name_override = "get_{il_name}";
87
fi
88
89
if !property.assign_function_il_name_override? then
90
property.assign_function_il_name_override = "set_{il_name}";
91
fi
92
fi
93
94
return;
95
fi
96
97
if is_primitive then
98
symbol.il_is_primitive_type = true;
99
fi
100
101
symbol.il_name_override = il_name;
102
fi
103
else
104
_pragma_scope_stack.leave(p);
105
fi
106
si
107
108
pre(`namespace: Definitions.NAMESPACE) -> bool is
109
declare_and_enter_namespace(`namespace, _symbol_definition_listener, `namespace.is_compiler_generated);
110
return false;
111
si
112
113
visit(`namespace: Definitions.NAMESPACE) is
114
leave_namespace(`namespace);
115
si
116
117
_pre(
118
classy: Definitions.Classy,
119
declare_symbol: (Semantic.DeclarationContext, LOCATION, LOCATION, string, Collections.List[string], Semantic.Scope, Semantic.SymbolDefinitionListener) -> Semantic.Symbols.Symbol
120
) -> bool is
121
let symbol: Semantic.Scope mut;
122
123
let arguments = _generic_argument_declarer.get_generic_arguments(classy.arguments);
124
125
symbol = declare_symbol(
126
current_declaration_context,
127
classy.name.location,
128
classy.location,
129
classy.name.name,
130
arguments,
131
current_scope,
132
_symbol_definition_listener
133
);
134
135
136
associate_and_enter_scope(
137
classy,
138
symbol
139
);
140
141
_generic_argument_declarer.declare_generic_arguments(classy.arguments);
142
return false;
143
si
144
145
pre(`class: Definitions.CLASS) -> bool is
146
_pre(
147
`class,
148
(context, name_location, location, name, arguments, scope, listener) =>
149
context.declare_class(name_location, location, name, arguments, scope, listener)
150
);
151
152
let class_symbol = cast Semantic.Symbols.CLASS?(current_scope);
153
154
if class_symbol? then
155
if `class.modifiers.is_open then
156
class_symbol.mark_open();
157
fi
158
159
if `class.modifiers.is_abstract then
160
class_symbol.mark_abstract();
161
fi
162
fi
163
164
// The body holds only members - declared by DECLARE_MEMBERS.
165
return true;
166
si
167
168
visit(`class: Definitions.CLASS) is
169
leave_scope(`class);
170
si
171
172
// impl and partial blocks and all other member-level
173
// declarations are handled by DECLARE_MEMBERS, which runs after
174
// resolve-uses; this pass declares only the type-level skeleton.
175
pre(`partial: Definitions.PARTIAL) -> bool => true;
176
177
pre(`impl: Definitions.IMPL) -> bool => true;
178
179
pre(`trait: Definitions.TRAIT) -> bool is
180
_pre(
181
`trait,
182
(context, name_location, location, name, arguments, scope, listener) =>
183
context.declare_trait(name_location, location, name, arguments, scope, listener)
184
);
185
186
return true;
187
si
188
189
visit(`trait: Definitions.TRAIT) is
190
leave_scope(`trait);
191
si
192
193
pre(`struct: Definitions.STRUCT) -> bool is
194
_pre(
195
`struct,
196
(context, name_location, location, name, arguments, scope, listener) =>
197
context.declare_struct(name_location, location, name, arguments, scope, listener)
198
);
199
200
return true;
201
si
202
203
visit(`struct: Definitions.STRUCT) is
204
leave_scope(`struct);
205
si
206
207
pre(`union: Definitions.UNION) -> bool =>
208
// The body holds the variants - types, declared here; their
209
// fields are members, declared by DECLARE_MEMBERS.
210
_pre(
211
`union,
212
(context, name_location, location, name, arguments, scope, listener) =>
213
context.declare_union(name_location, location, name, arguments, scope, listener)
214
);
215
216
visit(`union: Definitions.UNION) is
217
leave_scope(`union);
218
si
219
220
pre(variant: Definitions.VARIANT) -> bool is
221
let result =
222
_pre(
223
variant,
224
(context, name_location, location, name, arguments, scope, listener) =>
225
context.declare_variant(name_location, location, name, scope, listener)
226
);
227
228
if result then
229
return result;
230
fi
231
232
// Propagate the AST's `default` modifier to the variant
233
// symbol so DECLARE_MEMBERS' union visit can pick the
234
// default variant once fields are declared.
235
if isa Semantic.Symbols.VARIANT(current_scope) then
236
let variant_symbol = cast Semantic.Symbols.VARIANT(current_scope);
237
variant_symbol.is_default = variant.is_default;
238
fi
239
240
// Fields are members - declared by DECLARE_MEMBERS.
241
return true;
242
si
243
244
245
246
pre(`enum: Definitions.ENUM) -> bool is
247
_pre(
248
`enum,
249
(context, name_location, location, name, arguments, scope, listener) =>
250
context.declare_enum(name_location, location, name, scope, listener)
251
);
252
253
return true;
254
si
255
256
visit(`enum: Definitions.ENUM) is
257
leave_scope(`enum);
258
si
259
260
pre(enum_member: Definitions.ENUM_MEMBER) -> bool => true;
261
262
pre(function: Definitions.FUNCTION) -> bool => true;
263
264
pre(property: Definitions.PROPERTY) -> bool => true;
265
266
pre(indexer: Definitions.INDEXER) -> bool => true;
267
si
268
si