Appearance
| 1 | namespace Semantic.Symbols is | |
| 2 | use IO.Std | |
| 3 | ||
| 4 | use System.Text.StringBuilder | |
| 5 | ||
| 6 | use Collections.List | |
| 7 | use Collections.Map | |
| 8 | ||
| 9 | use IoC | |
| 10 | use Logging | |
| 11 | use Source | |
| 12 | ||
| 13 | use IR.Values.Value | |
| 14 | use Types.Type | |
| 15 | ||
| 16 | use Ghul.Pipes | |
| 17 | ||
| 18 | // A GENERIC represents a particular specialization of a generic class, trait or struct - i.e. a version of that symbol | |
| 19 | // with actual type arguments specified for its formal type parameters, and all its member symbols' signatures rewritten | |
| 20 | // with all instances of each formal type parameter replaced with the corresponding actual type argument | |
| 21 | class GENERIC: Symbol, Types.Typed is | |
| 22 | _symbol: Classy | |
| 23 | _type_map: Collections.Map[Symbol,Type] | |
| 24 | ||
| 25 | type_map: Collections.Map[Symbol,Type] => _type_map | |
| 26 | arguments: Collections.List[Type] | |
| 27 | ancestors: Collections.List[Type] => symbol.ancestors | |
| 28 | ||
| 29 | implementors: Collections.Iterable[Symbol]? => symbol.implementors | |
| 30 | ||
| 31 | symbol: Classy => _symbol | |
| 32 | ||
| 33 | symbols: Collections.Iterable[Symbol] is | |
| 34 | let result = Collections.LIST[Symbol]() | |
| 35 | ||
| 36 | for s in symbol.symbols do | |
| 37 | if let specialized = _specialize(s) then | |
| 38 | result.add(specialized) | |
| 39 | fi | |
| 40 | od | |
| 41 | ||
| 42 | return result | |
| 43 | si | |
| 44 | ||
| 45 | owner: Scope? public => symbol.owner, = value is si | |
| 46 | ||
| 47 | unspecialized_symbol: Symbols.Symbol => symbol | |
| 48 | root_unspecialized_symbol: Symbols.Symbol => symbol.root_unspecialized_symbol | |
| 49 | ||
| 50 | location: LOCATION => symbol.location | |
| 51 | name: string => symbol.name | |
| 52 | ||
| 53 | access: ACCESS => symbol.access | |
| 54 | ||
| 55 | is_type: bool => symbol.is_type | |
| 56 | is_generic_type_specialization: bool => true | |
| 57 | is_value_type: bool => symbol.is_value_type | |
| 58 | is_inheritable: bool => symbol.is_inheritable | |
| 59 | is_class: bool => symbol.is_class | |
| 60 | is_trait: bool => symbol.is_trait | |
| 61 | is_union: bool => symbol.is_union | |
| 62 | is_variant: bool => symbol.is_variant | |
| 63 | is_unit_variant: bool => symbol.is_unit_variant | |
| 64 | is_closed_root: bool => symbol.is_closed_root | |
| 65 | is_specializable: bool => false // type parameters already applied | |
| 66 | ||
| 67 | qualified_name: string => "{symbol.qualified_name}[{arguments_string}]" | |
| 68 | ||
| 69 | // Only the head shortens; the type arguments stay. (Type rendering | |
| 70 | // reaches the head directly and adds the arguments itself, so this | |
| 71 | // is only used when a constructed generic is named on its own - as | |
| 72 | // the owner of a member, say.) | |
| 73 | render_name(scope: Scope?) -> string => | |
| 74 | if !scope? then | |
| 75 | qualified_name | |
| 76 | else | |
| 77 | "{symbol._render_scope_relative_name(scope)}[{arguments_string}]" | |
| 78 | fi | |
| 79 | ||
| 80 | arguments_string: string is | |
| 81 | let result = System.Text.StringBuilder() | |
| 82 | ||
| 83 | let seen_any mut = false | |
| 84 | ||
| 85 | for a in arguments do | |
| 86 | if seen_any then | |
| 87 | result.append(',') | |
| 88 | fi | |
| 89 | ||
| 90 | result.append(a) | |
| 91 | ||
| 92 | seen_any = true | |
| 93 | od | |
| 94 | ||
| 95 | return result.to_string() | |
| 96 | si | |
| 97 | ||
| 98 | short_description: string is | |
| 99 | let result = System.Text.StringBuilder() | |
| 100 | ||
| 101 | result | |
| 102 | .append(name) | |
| 103 | .append('[') | |
| 104 | ||
| 105 | let seen_any mut = false | |
| 106 | ||
| 107 | for a in arguments do | |
| 108 | if seen_any then | |
| 109 | result.append(',') | |
| 110 | fi | |
| 111 | ||
| 112 | result.append(a.short_description) | |
| 113 | ||
| 114 | seen_any = true | |
| 115 | od | |
| 116 | ||
| 117 | result | |
| 118 | .append(']') | |
| 119 | ||
| 120 | return result.to_string() | |
| 121 | si | |
| 122 | ||
| 123 | symbol_kind: SymbolKind => symbol.symbol_kind | |
| 124 | completion_kind: CompletionKind => symbol.completion_kind | |
| 125 | ||
| 126 | // TODO we could probably cache this rather than creating | |
| 127 | // a new one every time | |
| 128 | type: Type => Types.GENERIC(location, symbol, arguments) | |
| 129 | ||
| 130 | depth: int => symbol.depth | |
| 131 | ||
| 132 | init(location: LOCATION, symbol: Classy, arguments: Collections.List[Type]) is | |
| 133 | assert arguments |> all(a => a?) else "type argument is null for {symbol.name}" | |
| 134 | ||
| 135 | super.init( | |
| 136 | symbol.location, | |
| 137 | symbol, | |
| 138 | symbol.name) | |
| 139 | ||
| 140 | _symbol = symbol | |
| 141 | ||
| 142 | assert arguments.count > 0 else "generic has 0 arguments" | |
| 143 | assert arguments |> all(a => a?) else "at least one null argument" | |
| 144 | assert symbol.is_generic else "symbol is not generic" | |
| 145 | ||
| 146 | let length mut = arguments.count | |
| 147 | ||
| 148 | if arguments.count != symbol.argument_names.count then | |
| 149 | if length > symbol.argument_names.count then | |
| 150 | length = symbol.argument_names.count | |
| 151 | fi | |
| 152 | ||
| 153 | IoC.CONTAINER.instance.logger.error(location, "expected {symbol.argument_names.count} type arguments") | |
| 154 | fi | |
| 155 | ||
| 156 | self.arguments = arguments | |
| 157 | let tm = Collections.MAP[Symbol,Type]() | |
| 158 | ||
| 159 | for i in 0..length do | |
| 160 | if let parameter = cast GenericArgument?(symbol.type_parameter_at(i)) then | |
| 161 | tm[parameter] = arguments[i] | |
| 162 | fi | |
| 163 | od | |
| 164 | ||
| 165 | _type_map = tm | |
| 166 | ||
| 167 | is_unsafe_constraints = symbol.is_unsafe_constraints | |
| 168 | si | |
| 169 | ||
| 170 | try_create_from(location: LOCATION, symbol: Classy, type_map: Collections.Map[Symbol,Type]) -> GENERIC? static is | |
| 171 | let arguments = Collections.LIST[Type]() | |
| 172 | ||
| 173 | for i in 0..symbol.argument_names.count do | |
| 174 | let parameter = cast GenericArgument?(symbol.type_parameter_at(i)) | |
| 175 | ||
| 176 | if !parameter? then | |
| 177 | return null | |
| 178 | fi | |
| 179 | ||
| 180 | let t: Type mut | |
| 181 | ||
| 182 | if !type_map.try_get_value(parameter, t ref) then | |
| 183 | return null | |
| 184 | fi | |
| 185 | ||
| 186 | arguments.add(t) | |
| 187 | od | |
| 188 | ||
| 189 | return GENERIC(location, symbol, arguments) | |
| 190 | si | |
| 191 | ||
| 192 | add_member(symbol: Symbol) -> bool is | |
| 193 | IoC.CONTAINER.instance.logger.warn(location, "inherit-into-specialized-generic", "cannot inherit {symbol} into specialized generic {self}") | |
| 194 | return true | |
| 195 | si | |
| 196 | ||
| 197 | add_implementor(implementor: Symbol) is | |
| 198 | symbol.add_implementor(implementor) | |
| 199 | si | |
| 200 | ||
| 201 | assert_symbols_pulled_down() is | |
| 202 | symbol.assert_symbols_pulled_down() | |
| 203 | si | |
| 204 | ||
| 205 | pull_down_super_symbols() is | |
| 206 | symbol.pull_down_super_symbols() | |
| 207 | si | |
| 208 | ||
| 209 | get_ancestor(i: int) -> Type | |
| 210 | => ancestors[i].specialize(type_map) | |
| 211 | ||
| 212 | // Declared: the loop over each argument's `matches` is | |
| 213 | // genuinely store-free, but the store-free walk disqualifies | |
| 214 | // any function containing a `for` loop unconditionally rather | |
| 215 | // than reasoning about the loop body. | |
| 216 | =~(other: Symbol) -> bool pure is | |
| 217 | if !isa GENERIC(other) then | |
| 218 | return false | |
| 219 | fi | |
| 220 | ||
| 221 | let other_generic = other | |
| 222 | ||
| 223 | if other_generic.symbol != symbol then | |
| 224 | return false | |
| 225 | fi | |
| 226 | ||
| 227 | assert | |
| 228 | other_generic.arguments.count == arguments.count | |
| 229 | else | |
| 230 | "generics with the same symbol should have same number of arguments" | |
| 231 | ||
| 232 | for i in 0..arguments.count do | |
| 233 | if !arguments[i].matches(other_generic.arguments[i]) then | |
| 234 | return false | |
| 235 | fi | |
| 236 | od | |
| 237 | ||
| 238 | return true | |
| 239 | si | |
| 240 | ||
| 241 | load(location: LOCATION, from: Value?, loader: SYMBOL_LOADER) -> Value => symbol.load(location, from, loader) | |
| 242 | store(location: LOCATION, from: Value?, value: Value, loader: SYMBOL_LOADER, is_initialize: bool) -> Value => symbol.store(location, from, value, loader, is_initialize) | |
| 243 | call(location: Source.LOCATION, from: Value?, arguments: Collections.List[Value], type: Type?, caller: FUNCTION_CALLER) -> Value => symbol.call(location, from, arguments, type, caller) | |
| 244 | // given a member of the class, trait or struct that this generic wraps, we want to get a copy of it | |
| 245 | // with all references to formal type parameters replaced with the corresponding actual type arguments | |
| 246 | _specialize(member: Symbols.Symbol?) -> Symbols.Symbol? => | |
| 247 | if !member? then | |
| 248 | null | |
| 249 | elif !member.is_specializable then | |
| 250 | member | |
| 251 | elif member.can_accept_actual_type_arguments then | |
| 252 | member.specialize(arguments) | |
| 253 | else | |
| 254 | member.specialize(type_map, self) | |
| 255 | fi | |
| 256 | ||
| 257 | find_direct(name: string) -> Symbol? is | |
| 258 | assert_symbols_pulled_down() | |
| 259 | ||
| 260 | return _specialize(symbol.find_direct(name)) | |
| 261 | si | |
| 262 | ||
| 263 | find_member(name: string) -> Symbol? => | |
| 264 | let result = symbol.find_member(name) in | |
| 265 | if result? then | |
| 266 | _specialize(result) | |
| 267 | else | |
| 268 | null | |
| 269 | fi | |
| 270 | ||
| 271 | find_specialized_function(function: Symbol) -> Function? is | |
| 272 | let result = find_member(function.name) | |
| 273 | ||
| 274 | if !result? then | |
| 275 | let results = Collections.MAP[string, Symbols.Symbol]() | |
| 276 | ||
| 277 | symbol.find_member_matches("", results) | |
| 278 | ||
| 279 | return null | |
| 280 | fi | |
| 281 | ||
| 282 | let function_result = cast Function?(result) | |
| 283 | ||
| 284 | if function_result? /\ function_result.specialized_from == function then | |
| 285 | return function_result | |
| 286 | fi | |
| 287 | ||
| 288 | let function_group_result = cast FUNCTION_GROUP?(result) | |
| 289 | ||
| 290 | if !function_group_result? then | |
| 291 | return null | |
| 292 | fi | |
| 293 | ||
| 294 | for f in function_group_result.functions do | |
| 295 | if f.specialized_from == function then | |
| 296 | return f | |
| 297 | fi | |
| 298 | od | |
| 299 | ||
| 300 | return null | |
| 301 | si | |
| 302 | ||
| 303 | get_destructure_member_name(index: int) -> string? => | |
| 304 | symbol.get_destructure_member_name(index) | |
| 305 | ||
| 306 | find_enclosing(name: string) -> Symbol? => | |
| 307 | let unspecialized = symbol.find_enclosing(name) in | |
| 308 | ||
| 309 | if unspecialized? /\ unspecialized.owner == symbol then | |
| 310 | _specialize(unspecialized) | |
| 311 | else | |
| 312 | unspecialized | |
| 313 | fi | |
| 314 | ||
| 315 | find_direct_matches(prefix: string, matches: Collections.MutableMap[string, Symbols.Symbol]) is | |
| 316 | let m = Collections.MAP[string, Symbols.Symbol]() | |
| 317 | ||
| 318 | symbol.find_direct_matches(prefix, m) | |
| 319 | ||
| 320 | for p in m.iterator do | |
| 321 | if !matches.contains_key(p.key) then | |
| 322 | if let specialized = _specialize(p.value) then | |
| 323 | matches[p.key] = specialized.collapse_group_if_single_member() | |
| 324 | fi | |
| 325 | fi | |
| 326 | od | |
| 327 | si | |
| 328 | ||
| 329 | find_member_matches(prefix: string, matches: Collections.MutableMap[string, Symbols.Symbol]) is | |
| 330 | find_direct_matches(prefix, matches) | |
| 331 | symbol.find_ancestor_matches(prefix, matches) | |
| 332 | si | |
| 333 | ||
| 334 | find_enclosing_matches(prefix: string, matches: Collections.MutableMap[string, Symbols.Symbol]) is | |
| 335 | si | |
| 336 | ||
| 337 | get_hash_code() -> int is | |
| 338 | let result mut = symbol.get_hash_code() | |
| 339 | ||
| 340 | for a in arguments do | |
| 341 | result = result + a.get_hash_code() | |
| 342 | od | |
| 343 | ||
| 344 | return result | |
| 345 | si | |
| 346 | ||
| 347 | to_string() -> string => "{IoC.CONTAINER.instance.name_display.bare_name_for(symbol)}[{arguments_string}]" | |
| 348 | si | |
| 349 | si |