Appearance
| 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 |