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
// A name reaches metadata as written. Quoting was once
67
// how a name colliding with an IL keyword was spelled;
68
// now it would just become part of the name.
69
if il_name.index_of('\'') >= 0 then
70
_logger.error(
71
p.arguments.location, "an IL name cannot contain a quote")
72
73
return
74
fi
75
76
let definition mut = pragma.definition
77
78
while isa Definitions.PRAGMA(definition) do
79
definition = cast Definitions.PRAGMA(definition).definition
80
od
81
82
let symbol = symbol_for(definition)
83
84
if symbol? then
85
if isa Semantic.Symbols.Property(symbol) then
86
let property = symbol
87
88
if name =~ "IL.name.read" then
89
property.read_function_il_name_override = il_name
90
elif name =~ "IL.name.assign" then
91
property.assign_function_il_name_override = il_name
92
elif name =~ "IL.name" then
93
property.il_name_override = il_name
94
95
if !property.read_function_il_name_override? then
96
property.read_function_il_name_override = "get_{il_name}"
97
fi
98
99
if !property.assign_function_il_name_override? then
100
property.assign_function_il_name_override = "set_{il_name}"
101
fi
102
fi
103
104
return
105
fi
106
107
if is_primitive then
108
symbol.il_is_primitive_type = true
109
fi
110
111
symbol.il_name_override = il_name
112
fi
113
else
114
_pragma_scope_stack.leave(p)
115
fi
116
si
117
118
pre(`namespace: Definitions.NAMESPACE) -> bool is
119
declare_and_enter_namespace(`namespace, _symbol_definition_listener, `namespace.is_compiler_generated)
120
return false
121
si
122
123
visit(`namespace: Definitions.NAMESPACE) is
124
leave_namespace(`namespace)
125
si
126
127
_pre(
128
classy: Definitions.Classy,
129
declare_symbol: (Semantic.DeclarationContext, LOCATION, LOCATION, string, Collections.List[string], Semantic.Scope, Semantic.SymbolDefinitionListener) -> Semantic.Symbols.Symbol
130
) -> bool is
131
let symbol: Semantic.Scope mut
132
133
let arguments = _generic_argument_declarer.get_generic_arguments(classy.arguments)
134
135
symbol = declare_symbol(
136
current_declaration_context,
137
classy.name.location,
138
classy.location,
139
classy.name.name,
140
arguments,
141
current_scope,
142
_symbol_definition_listener
143
)
144
145
146
associate_and_enter_scope(
147
classy,
148
symbol
149
)
150
151
_generic_argument_declarer.declare_generic_arguments(classy.arguments)
152
return false
153
si
154
155
pre(`class: Definitions.CLASS) -> bool is
156
_pre(
157
`class,
158
(context, name_location, location, name, arguments, scope, listener) =>
159
context.declare_class(name_location, location, name, arguments, scope, listener)
160
)
161
162
let class_symbol = cast Semantic.Symbols.CLASS?(current_scope)
163
164
if class_symbol? then
165
if `class.modifiers.is_open then
166
class_symbol.mark_declared_open()
167
fi
168
169
if `class.modifiers.is_abstract then
170
class_symbol.mark_abstract()
171
fi
172
173
if `class.modifiers.is_pure then
174
class_symbol.mark_pure()
175
fi
176
fi
177
178
// The body holds only members - declared by DECLARE_MEMBERS.
179
return true
180
si
181
182
visit(`class: Definitions.CLASS) is
183
leave_scope(`class)
184
si
185
186
// impl and partial blocks and all other member-level
187
// declarations are handled by DECLARE_MEMBERS, which runs after
188
// resolve-uses; this pass declares only the type-level skeleton.
189
pre(`partial: Definitions.PARTIAL) -> bool => true
190
191
pre(`impl: Definitions.IMPL) -> bool => true
192
193
pre(`trait: Definitions.TRAIT) -> bool is
194
_pre(
195
`trait,
196
(context, name_location, location, name, arguments, scope, listener) =>
197
context.declare_trait(name_location, location, name, arguments, scope, listener)
198
)
199
200
let trait_symbol = cast Semantic.Symbols.TRAIT?(current_scope)
201
202
if trait_symbol? then
203
if `trait.modifiers.is_open then
204
trait_symbol.mark_declared_open()
205
fi
206
207
if `trait.modifiers.is_pure then
208
trait_symbol.mark_pure()
209
fi
210
fi
211
212
return true
213
si
214
215
visit(`trait: Definitions.TRAIT) is
216
leave_scope(`trait)
217
si
218
219
pre(`struct: Definitions.STRUCT) -> bool is
220
_pre(
221
`struct,
222
(context, name_location, location, name, arguments, scope, listener) =>
223
context.declare_struct(name_location, location, name, arguments, scope, listener)
224
)
225
226
let struct_symbol = cast Semantic.Symbols.STRUCT?(current_scope)
227
228
if struct_symbol? /\ `struct.modifiers.is_pure then
229
struct_symbol.mark_pure()
230
fi
231
232
return true
233
si
234
235
visit(`struct: Definitions.STRUCT) is
236
leave_scope(`struct)
237
si
238
239
pre(`union: Definitions.UNION) -> bool is
240
// The body holds the variants - types, declared here; their
241
// fields are members, declared by DECLARE_MEMBERS.
242
let result =
243
_pre(
244
`union,
245
(context, name_location, location, name, arguments, scope, listener) =>
246
context.declare_union(name_location, location, name, arguments, scope, listener)
247
)
248
249
if isa Semantic.Symbols.UNION(current_scope) /\ `union.modifiers.is_pure then
250
_logger.error(
251
`union.name.location,
252
"pure is not supported on a union"
253
)
254
fi
255
256
return result
257
si
258
259
visit(`union: Definitions.UNION) is
260
leave_scope(`union)
261
si
262
263
pre(variant: Definitions.VARIANT) -> bool is
264
let result =
265
_pre(
266
variant,
267
(context, name_location, location, name, arguments, scope, listener) =>
268
context.declare_variant(name_location, location, name, scope, listener)
269
)
270
271
if result then
272
return result
273
fi
274
275
// Propagate the AST's `default` modifier to the variant
276
// symbol so DECLARE_MEMBERS' union visit can pick the
277
// default variant once fields are declared.
278
if isa Semantic.Symbols.VARIANT(current_scope) then
279
let variant_symbol = cast Semantic.Symbols.VARIANT(current_scope)
280
variant_symbol.is_default = variant.is_default
281
fi
282
283
// Fields are members - declared by DECLARE_MEMBERS.
284
return true
285
si
286
287
288
289
pre(`enum: Definitions.ENUM) -> bool is
290
_pre(
291
`enum,
292
(context, name_location, location, name, arguments, scope, listener) =>
293
context.declare_enum(name_location, location, name, scope, listener)
294
)
295
296
return true
297
si
298
299
visit(`enum: Definitions.ENUM) is
300
leave_scope(`enum)
301
si
302
303
pre(enum_member: Definitions.ENUM_MEMBER) -> bool => true
304
305
pre(function: Definitions.FUNCTION) -> bool => true
306
307
pre(property: Definitions.PROPERTY) -> bool => true
308
309
pre(indexer: Definitions.INDEXER) -> bool => true
310
si
311
si