Skip to content
← Back

src/semantic/lookups/reflection_innate_symbol_lookup.ghul

1
namespace Semantic.Lookups is
2
use IO.Std
3
use TYPE = System.Type
4
use System.ValueType
5
use System.Exception
6
7
use Logging
8
9
use Collections.List
10
use Collections.LIST
11
12
use Ghul.Pipes
13
14
use Source.LOCATION
15
16
use Types
17
use ARRAY_TYPE = Types.ARRAY
18
19
class REFLECTION_INNATE_SYMBOL_LOOKUP(
20
_type_mapper: DotNet.TYPE_MAPPER,
21
_symbol_table: DotNet.SYMBOL_TABLE,
22
_ghul_innate_type_lookup: GHUL_INNATE_TYPE_LOOKUP,
23
_type_source: DotNet.TypeSource
24
): InnateSymbolLookup is
25
_tuple_types: List[TYPE]
26
_function_types: List[TYPE]
27
_action_types: List[TYPE]
28
29
init(..) is
30
_tuple_types = _type_source.get_types((1::7) |> map(i => "System.ValueTuple`{i}"))
31
_function_types = _type_source.get_types((1::17) |> map(i => "System.Func`{i}"))
32
_action_types = _type_source.get_types((1::16) |> map(i => "System.Action`{i}"))
33
si
34
35
get_tuple_type(types: Collections.List[Type], names: Collections.List[string?]?) -> Type =>
36
DotNet.HYBRID_TUPLE_TYPE_WRAPPER(_symbol_table, _tuple_types[types.count - 1], types, names)
37
38
get_function_type(types: Collections.List[Type]) -> Type is
39
assert types.count > 0 /\ types.count <= _function_types.count
40
41
let return_type = types[types.count - 1]
42
43
if return_type.is_sentinel \/ return_type.is_type_variable \/ !return_type.matches(get_void_type()) then
44
return
45
DotNet.HYBRID_FUNCTION_TYPE_WRAPPER(_symbol_table, _function_types[types.count - 1], types)
46
elif types.count == 1 then
47
return
48
_type_mapper.get_type(_type_source.get_type("System.Action"))
49
else
50
let without_void_return_type = LIST[Type](types.count - 1)
51
52
for i in 0..types.count - 1 do
53
without_void_return_type.add(types[i])
54
od
55
56
return
57
DotNet.HYBRID_ACTION_TYPE_WRAPPER(_symbol_table, _action_types[types.count - 2], without_void_return_type)
58
fi
59
si
60
61
get_function_type(types: Collections.List[Type], is_pure: bool) -> Type is
62
if !is_pure then
63
return get_function_type(types)
64
fi
65
66
assert types.count > 0 /\ types.count <= _function_types.count
67
68
let return_type = types[types.count - 1]
69
70
if return_type.is_sentinel \/ return_type.is_type_variable \/ !return_type.matches(get_void_type()) then
71
return
72
DotNet.PURE_HYBRID_FUNCTION_TYPE_WRAPPER(_symbol_table, _function_types[types.count - 1], types)
73
elif types.count == 1 then
74
// the zero-argument void form maps to the non-generic
75
// System.Action, which has no pure-marked wrapper —
76
// dropping the marker is conservative: callers get no
77
// purity guarantee and callees keep no facts
78
return
79
_type_mapper.get_type(_type_source.get_type("System.Action"))
80
else
81
let without_void_return_type = LIST[Type](types.count - 1)
82
83
for i in 0..types.count - 1 do
84
without_void_return_type.add(types[i])
85
od
86
87
return
88
DotNet.PURE_HYBRID_ACTION_TYPE_WRAPPER(_symbol_table, _action_types[types.count - 2], without_void_return_type)
89
fi
90
si
91
92
get_enum_type() -> Type =>
93
_type_mapper.get_type(_type_source.get_type("System.Enum"))
94
95
get_array_type(type: Type) -> Type =>
96
_ghul_innate_type_lookup.get_array_type(type)
97
98
get_optional_type(type: Type) -> Type =>
99
let classy =
100
cast Semantic.Symbols.Classy?(
101
_symbol_table.get_symbol(_type_source.get_type("System.Nullable`1")))!
102
in
103
Types.NULLABLE(LOCATION.internal, classy, LIST[Type]([type]))
104
105
get_maybe_type(type: Type) -> Type? is
106
// Mirrors the MAYBE_TYPE_CREATOR registration in
107
// TYPE_MAPPER.start(): the assembly is absent when the
108
// compiler is building ghul-runtime itself, so the
109
// lookup throws. Treat that as "MAYBE unavailable" and
110
// let the caller surface an error appropriate for the
111
// context.
112
try
113
let dotnet_type = _type_source.get_type("ghul-runtime", "Ghul.MAYBE")
114
let classy = cast Semantic.Symbols.Classy?(_symbol_table.get_symbol(dotnet_type))!
115
return Types.MAYBE(LOCATION.internal, classy, LIST[Type]([type]))
116
catch ex: System.Exception
117
return null
118
yrt
119
si
120
121
get_equality_comparer_type(type: Type) -> Type? is
122
try
123
let dotnet_type =
124
_type_source.get_type("System.Collections", "System.Collections.Generic.EqualityComparer`1")
125
126
let classy = cast Semantic.Symbols.Classy?(_symbol_table.get_symbol(dotnet_type))!
127
128
return Types.GENERIC(LOCATION.internal, classy, LIST[Type]([type]))
129
catch ex: System.Exception
130
return null
131
yrt
132
si
133
134
get_pointer_type(type: Type) -> Type =>
135
_ghul_innate_type_lookup.get_pointer_type(type)
136
137
get_reference_type(type: Type) -> Type =>
138
_ghul_innate_type_lookup.get_reference_type(type)
139
140
get_bool_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Boolean"))
141
get_char_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Char"))
142
get_byte_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.SByte"))
143
get_ubyte_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Byte"))
144
get_short_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Int16"))
145
get_ushort_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.UInt16"))
146
get_int_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Int32"))
147
get_uint_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.UInt32"))
148
get_long_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Int64"))
149
get_ulong_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.UInt64"))
150
get_word_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.IntPtr"))
151
get_uword_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.UIntPtr"))
152
get_single_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Single"))
153
get_double_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Double"))
154
get_decimal_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Decimal"))
155
get_bigint_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Runtime.Numerics", "System.Numerics.BigInteger"))
156
get_void_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Void"))
157
get_object_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Object"))
158
get_value_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.ValueType"))
159
get_string_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.String"))
160
get_exception_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Exception"))
161
get_type_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Type"))
162
get_unspecialized_iterable_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Collections.Generic.IEnumerable`1"))
163
164
get_unspecialized_list_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Collections.Generic.IReadOnlyList`1"))
165
get_unspecialized_iterator_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Collections.Generic.IEnumerator`1"))
166
// ghūl emits its own generic types without the .NET `N
167
// arity suffix that BCL types carry, so the reflected name is
168
// bare `Ghul.Pipes.Pipe` (an arity-1 generic definition).
169
//
170
// The assembly is absent when the compiler is building
171
// ghul-runtime itself, so the lookup throws. Treat that as "Pipe
172
// unavailable" and return null (mirrors get_maybe_type): pipe
173
// fusion and the other Pipe-typed queries then simply do not
174
// apply while compiling the pipe library.
175
get_unspecialized_pipe_type() -> Type? is
176
try
177
return _type_mapper.get_type(_type_source.get_type("ghul-runtime", "Ghul.Pipes.Pipe"))
178
catch ex: System.Exception
179
return null
180
yrt
181
si
182
get_unspecialized_task_type() -> Type? => _type_mapper.get_type(_type_source.get_type("System.Threading.Tasks.Task`1"))
183
184
get_interpolated_string_handler_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.DefaultInterpolatedStringHandler"))
185
186
get_idisposable_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.IDisposable"))
187
188
get_multicast_delegate_type() -> Type? => _type_mapper.get_type(_type_source.get_type("System.MulticastDelegate"))
189
190
get_slice_functions() -> Semantic.Symbols.FUNCTION_GROUP? => _ghul_innate_type_lookup.slice_functions
191
192
get_join_functions() -> Semantic.Symbols.FUNCTION_GROUP? => _ghul_innate_type_lookup.join_functions
193
194
get_display_functions() -> Semantic.Symbols.FUNCTION_GROUP? => _ghul_innate_type_lookup.display_functions
195
196
get_render_elements_functions() -> Semantic.Symbols.FUNCTION_GROUP? => _ghul_innate_type_lookup.render_elements_functions
197
198
get_pipes_fusion_functions() -> Collections.MAP[Semantic.Symbols.Symbol, string] => _ghul_innate_type_lookup.fusion_functions
199
200
get_range_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Range"))
201
202
get_int_range_type() -> Type =>
203
_type_mapper.get_type(_type_source.get_type("ghul-runtime", "Ghul.INT_RANGE"))
204
205
get_int_range_inclusive_type() -> Type =>
206
_type_mapper.get_type(_type_source.get_type("ghul-runtime", "Ghul.INT_RANGE_INCLUSIVE"))
207
208
get_box_type(type: Type) -> Type =>
209
// `Ghul.BOX[T]` lives in the ghul-runtime assembly,
210
// not System.Runtime (the default for the single-arg
211
// overload), so name the assembly explicitly. The
212
// assembly's name is derived from its file name —
213
// see `assemblies.ghul`. Note: ghūl-emitted generic
214
// types drop the .NET-style backtick-arity suffix
215
// (per the arity-overloading change), so the .NET
216
// metadata name is plain `Ghul.BOX`, not
217
// `Ghul.BOX`1`.
218
let classy =
219
cast Semantic.Symbols.Classy?(
220
_symbol_table.get_symbol(_type_source.get_type("ghul-runtime", "Ghul.BOX")))!
221
in
222
Types.GENERIC(LOCATION.internal, classy, LIST[Type]([type]))
223
224
get_task_type(type: Type) -> Type? is
225
// Constructed `System.Threading.Tasks.Task[type]` —
226
// reuses the same unspecialized Task symbol identity
227
// that `try_get_task_element_type` (in compile_bindings)
228
// checks against, so a freshly-constructed Task[T] from
229
// here will be recognised as already-a-Task and not
230
// double-wrapped on subsequent return-position passes.
231
let unspec = get_unspecialized_task_type()
232
233
if !unspec? then
234
return null
235
fi
236
237
let classy = cast Semantic.Symbols.Classy?(unspec.symbol.unspecialized_symbol)
238
239
if !classy? then
240
return null
241
fi
242
243
return Types.GENERIC(LOCATION.internal, classy, LIST[Type]([type]))
244
si
245
246
get_void_task_type() -> Type? =>
247
// Non-generic `System.Threading.Tasks.Task` — the
248
// type-name map at type_name_map.ghul:174 already
249
// aliases this to ghūl `Tasks.TASK` (the arity-zero
250
// form alongside the arity-one Task`1).
251
_type_mapper.get_type(_type_source.get_type("System.Threading.Tasks.Task"))
252
253
get_async_task_method_builder_type(type: Type) -> Type? is
254
// `System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1`
255
// constructed over the value-async result type.
256
let unspec = _type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1"))
257
258
let classy = cast Semantic.Symbols.Classy?(unspec.symbol.unspecialized_symbol)
259
260
if !classy? then
261
return null
262
fi
263
264
return Types.GENERIC(LOCATION.internal, classy, LIST[Type]([type]))
265
si
266
267
get_async_task_method_builder_void_type() -> Type? =>
268
_type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.AsyncTaskMethodBuilder"))
269
270
get_async_state_machine_interface_type() -> Type? =>
271
_type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.IAsyncStateMachine"))
272
273
get_notify_completion_type() -> Type? =>
274
_type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.INotifyCompletion"))
275
276
get_critical_notify_completion_type() -> Type? =>
277
_type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.ICriticalNotifyCompletion"))
278
si
279
si