Appearance
| 1 | namespace Semantic.DotNet is | |
| 2 | use TYPE = System.Type; | |
| 3 | ||
| 4 | use IO.Std; | |
| 5 | ||
| 6 | use Collections.MAP; | |
| 7 | ||
| 8 | class SYMBOL_STORE is | |
| 9 | _symbols_by_dotnet_type: MAP[TYPE,Symbols.Scoped]; | |
| 10 | _symbols_by_ghul_name: MAP[string,Symbols.Scoped]; | |
| 11 | ||
| 12 | count: int => _symbols_by_ghul_name.count; | |
| 13 | ||
| 14 | init() is | |
| 15 | _symbols_by_dotnet_type = MAP(); | |
| 16 | _symbols_by_ghul_name = MAP(); | |
| 17 | si | |
| 18 | ||
| 19 | get_symbol(dotnet_type: TYPE) -> Symbols.Scoped? is | |
| 20 | let result: Symbols.Scoped mut; | |
| 21 | ||
| 22 | _symbols_by_dotnet_type.try_get_value(dotnet_type, result ref); | |
| 23 | ||
| 24 | return result; | |
| 25 | si | |
| 26 | ||
| 27 | try_get_symbol(ghul_name: string, result: Symbols.Scoped ref) -> bool => | |
| 28 | _symbols_by_ghul_name.try_get_value(ghul_name, result); | |
| 29 | ||
| 30 | // True when the name has a by-name cache entry, including a | |
| 31 | // null no-result marker. Distinct from get_symbol returning | |
| 32 | // null, which conflates "cached no-result" with "never seen". | |
| 33 | has_symbol(ghul_name: string) -> bool => | |
| 34 | _symbols_by_ghul_name.contains_key(ghul_name); | |
| 35 | ||
| 36 | get_symbol(ghul_name: string) -> Symbols.Scoped? is | |
| 37 | let result: Symbols.Scoped mut; | |
| 38 | ||
| 39 | _symbols_by_ghul_name.try_get_value(ghul_name, result ref); | |
| 40 | ||
| 41 | return result; | |
| 42 | si | |
| 43 | ||
| 44 | cache_no_result(ghul_name: string) is | |
| 45 | _symbols_by_ghul_name.add(ghul_name, null); | |
| 46 | si | |
| 47 | ||
| 48 | add_symbol(type: TYPE, ghul_name: string, symbol: Symbols.Scoped) is | |
| 49 | // Idempotent: re-adding the same dotnet_type is a no-op. | |
| 50 | // The backtick-suffix fallback path re-enters create_symbol | |
| 51 | // for a .NET type already materialized via direct lookup | |
| 52 | // (e.g. `Lazy\`1` source after `Lazy` was looked up); the | |
| 53 | // earlier entry stays and the redundant add is skipped. | |
| 54 | if !_symbols_by_dotnet_type.contains_key(type) then | |
| 55 | _symbols_by_dotnet_type.add(type, symbol); | |
| 56 | fi | |
| 57 | ||
| 58 | // Argument-count overloading: when two reflected types share | |
| 59 | // a ghul name (their `\`N` suffix was stripped on import), | |
| 60 | // the first member to be materialized wins the bare-name | |
| 61 | // cache slot. The caller | |
| 62 | // (`symbol_table.materialize_type_group`) is responsible for | |
| 63 | // then overwriting the entry with the assembled TYPE_GROUP | |
| 64 | // via `set_name_symbol`. | |
| 65 | if !_symbols_by_ghul_name.contains_key(ghul_name) then | |
| 66 | _symbols_by_ghul_name.add(ghul_name, symbol); | |
| 67 | fi | |
| 68 | si | |
| 69 | ||
| 70 | set_name_symbol(ghul_name: string, symbol: Symbols.Scoped) is | |
| 71 | _symbols_by_ghul_name[ghul_name] = symbol; | |
| 72 | si | |
| 73 | si | |
| 74 | si |