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_pointer_type(type: Type) -> Type =>
122
_ghul_innate_type_lookup.get_pointer_type(type);
123
124
get_reference_type(type: Type) -> Type =>
125
_ghul_innate_type_lookup.get_reference_type(type);
126
127
get_bool_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Boolean"));
128
get_char_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Char"));
129
get_byte_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.SByte"));
130
get_ubyte_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Byte"));
131
get_short_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Int16"));
132
get_ushort_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.UInt16"));
133
get_int_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Int32"));
134
get_uint_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.UInt32"));
135
get_long_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Int64"));
136
get_ulong_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.UInt64"));
137
get_word_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.IntPtr"));
138
get_uword_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.UIntPtr"));
139
get_single_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Single"));
140
get_double_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Double"));
141
get_decimal_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Decimal"));
142
get_void_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Void"));
143
get_object_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Object"));
144
get_value_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.ValueType"));
145
get_string_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.String"));
146
get_exception_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Exception"));
147
get_type_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Type"));
148
get_unspecialized_iterable_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Collections.Generic.IEnumerable`1"));
149
get_unspecialized_iterator_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Collections.Generic.IEnumerator`1"));
150
// ghūl emits its own generic types without the .NET `N
151
// arity suffix that BCL types carry, so the reflected name is
152
// bare `Ghul.Pipes.Pipe` (an arity-1 generic definition).
153
//
154
// The assembly is absent when the compiler is building
155
// ghul-runtime itself, so the lookup throws. Treat that as "Pipe
156
// unavailable" and return null (mirrors get_maybe_type): pipe
157
// fusion and the other Pipe-typed queries then simply do not
158
// apply while compiling the pipe library.
159
get_unspecialized_pipe_type() -> Type? is
160
try
161
return _type_mapper.get_type(_type_source.get_type("ghul-runtime", "Ghul.Pipes.Pipe"));
162
catch ex: System.Exception
163
return null;
164
yrt
165
si
166
get_unspecialized_task_type() -> Type? => _type_mapper.get_type(_type_source.get_type("System.Threading.Tasks.Task`1"));
167
168
get_interpolated_string_handler_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.DefaultInterpolatedStringHandler"));
169
170
get_idisposable_type() -> Type => _type_mapper.get_type(_type_source.get_type("System.IDisposable"));
171
172
get_box_type(type: Type) -> Type =>
173
// `Ghul.BOX[T]` lives in the ghul-runtime assembly,
174
// not System.Runtime (the default for the single-arg
175
// overload), so name the assembly explicitly. The
176
// assembly's name is derived from its file name —
177
// see `assemblies.ghul`. Note: ghūl-emitted generic
178
// types drop the .NET-style backtick-arity suffix
179
// (per the arity-overloading change), so the .NET
180
// metadata name is plain `Ghul.BOX`, not
181
// `Ghul.BOX`1`.
182
let classy =
183
cast Semantic.Symbols.Classy?(
184
_symbol_table.get_symbol(_type_source.get_type("ghul-runtime", "Ghul.BOX")))!
185
in
186
Types.GENERIC(LOCATION.internal, classy, LIST[Type]([type]));
187
188
get_task_type(type: Type) -> Type? is
189
// Constructed `System.Threading.Tasks.Task[type]` —
190
// reuses the same unspecialized Task symbol identity
191
// that `try_get_task_element_type` (in compile_bindings)
192
// checks against, so a freshly-constructed Task[T] from
193
// here will be recognised as already-a-Task and not
194
// double-wrapped on subsequent return-position passes.
195
let unspec = get_unspecialized_task_type();
196
197
if !unspec? then
198
return null;
199
fi
200
201
let classy = cast Semantic.Symbols.Classy?(unspec.symbol.unspecialized_symbol);
202
203
if !classy? then
204
return null;
205
fi
206
207
return Types.GENERIC(LOCATION.internal, classy, LIST[Type]([type]));
208
si
209
210
get_void_task_type() -> Type? =>
211
// Non-generic `System.Threading.Tasks.Task` — the
212
// type-name map at type_name_map.ghul:174 already
213
// aliases this to ghūl `Tasks.TASK` (the arity-zero
214
// form alongside the arity-one Task`1).
215
_type_mapper.get_type(_type_source.get_type("System.Threading.Tasks.Task"));
216
217
get_async_task_method_builder_type(type: Type) -> Type? is
218
// `System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1`
219
// constructed over the value-async result type.
220
let unspec = _type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1"));
221
222
let classy = cast Semantic.Symbols.Classy?(unspec.symbol.unspecialized_symbol);
223
224
if !classy? then
225
return null;
226
fi
227
228
return Types.GENERIC(LOCATION.internal, classy, LIST[Type]([type]));
229
si
230
231
get_async_task_method_builder_void_type() -> Type? =>
232
_type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.AsyncTaskMethodBuilder"));
233
234
get_async_state_machine_interface_type() -> Type? =>
235
_type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.IAsyncStateMachine"));
236
237
get_task_awaiter_type(type: Type) -> Type? is
238
// `System.Runtime.CompilerServices.TaskAwaiter`1`
239
// constructed over T. Returned by `Task<T>.GetAwaiter()`;
240
// its `GetResult()` returns T.
241
let unspec = _type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.TaskAwaiter`1"));
242
243
let classy = cast Semantic.Symbols.Classy?(unspec.symbol.unspecialized_symbol);
244
245
if !classy? then
246
return null;
247
fi
248
249
return Types.GENERIC(LOCATION.internal, classy, LIST[Type]([type]));
250
si
251
252
get_task_awaiter_void_type() -> Type? =>
253
_type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.TaskAwaiter"));
254
255
get_unspecialized_async_task_method_builder_type() -> Type? =>
256
_type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1"));
257
258
get_unspecialized_task_awaiter_type() -> Type? =>
259
_type_mapper.get_type(_type_source.get_type("System.Runtime.CompilerServices.TaskAwaiter`1"));
260
si
261
si