Appearance
| 1 | namespace IR.Values.Load is | |
| 2 | use TypeTyped = Semantic.Types.Typed | |
| 3 | use Semantic.Types.Type | |
| 4 | use SymbolBase = Semantic.Symbols.Symbol | |
| 5 | ||
| 6 | class SYMBOL: Value, TypeTyped is | |
| 7 | symbol: SymbolBase | |
| 8 | has_symbol: bool => true | |
| 9 | has_address: bool => true | |
| 10 | is_consumable: bool => false | |
| 11 | ||
| 12 | // A load of a symbol with no value form. A namespace never has | |
| 13 | // one; a function group reaches here when several overloads | |
| 14 | // were in scope and nothing said which was wanted, or when a | |
| 15 | // single generic one had nothing to take its type arguments | |
| 16 | // from. Naming which of those it is saves the reader working | |
| 17 | // out what about the expression was rejected. | |
| 18 | non_consumable_message: string is | |
| 19 | if isa Semantic.Symbols.NAMESPACE(symbol) then | |
| 20 | return "cannot use a namespace as a value" | |
| 21 | fi | |
| 22 | ||
| 23 | let group = cast Semantic.Symbols.FUNCTION_GROUP?(symbol) | |
| 24 | ||
| 25 | if group? /\ group.count > 1 then | |
| 26 | return "cannot tell which overload of {symbol.name} is meant here: give the expected function type" | |
| 27 | fi | |
| 28 | ||
| 29 | if group? /\ group.count == 1 /\ group.functions[0].is_generic then | |
| 30 | return "cannot infer the type arguments of {symbol.name} here: give the expected function type" | |
| 31 | fi | |
| 32 | ||
| 33 | return "cannot use this here" | |
| 34 | si | |
| 35 | ||
| 36 | // Concrete type at construction time. Snapshotted so later | |
| 37 | // mutation of `symbol.type` (e.g. type-narrowing release | |
| 38 | // restoring a Variable's declared type) doesn't change the | |
| 39 | // type observed by IR consumers — the load *was* of a value | |
| 40 | // of `_snapshot_type`, regardless of where the symbol's | |
| 41 | // type ends up later. Null when the symbol's type was an | |
| 42 | // inference placeholder at load time; that case stays lazy | |
| 43 | // so iterative-inference resolution still flows through, and | |
| 44 | // may still be null when this is read: the caller-facing | |
| 45 | // contract is `Value.type: Type?`, and a caller reading this | |
| 46 | // before the placeholder resolves is expected to see absence | |
| 47 | // rather than a settled type. | |
| 48 | _snapshot_type: Type? | |
| 49 | ||
| 50 | type: Type? pure => | |
| 51 | if _snapshot_type? then | |
| 52 | _snapshot_type | |
| 53 | else | |
| 54 | cast TypeTyped?(symbol)?.type | |
| 55 | fi | |
| 56 | ||
| 57 | // Pin the snapshotted type to a flow-narrowed form. Used | |
| 58 | // when optional-narrowing establishes the loaded variable is | |
| 59 | // non-null at this use site: the load *is* of the | |
| 60 | // non-optional type, even though the symbol's declared type | |
| 61 | // still carries `?`. Mirrors how `isa`-narrowing reaches the | |
| 62 | // snapshot via a mutated `symbol.type` at construction time. | |
| 63 | narrow_snapshot_type(narrowed: Type) is | |
| 64 | _snapshot_type = narrowed | |
| 65 | si | |
| 66 | ||
| 67 | // The guard a complement-narrowed load needs; see NARROW_GUARD. | |
| 68 | guard_complement_narrow(context: IR.CONTEXT) is | |
| 69 | NARROW_GUARD.emit(_snapshot_type, context) | |
| 70 | si | |
| 71 | ||
| 72 | from: Value? | |
| 73 | ||
| 74 | init(from: Value?, symbol: SymbolBase) is | |
| 75 | super.init() | |
| 76 | ||
| 77 | self.from = from | |
| 78 | self.symbol = symbol | |
| 79 | ||
| 80 | let typed = cast TypeTyped?(symbol) | |
| 81 | ||
| 82 | if typed? then | |
| 83 | let typed_type = typed.type | |
| 84 | ||
| 85 | if typed_type? /\ !typed_type.is_sentinel then | |
| 86 | _snapshot_type = typed_type | |
| 87 | fi | |
| 88 | fi | |
| 89 | si | |
| 90 | ||
| 91 | gen(context: IR.CONTEXT) is | |
| 92 | gen(from, context) | |
| 93 | context.fixme("load member {symbol.qualified_name}") | |
| 94 | si | |
| 95 | ||
| 96 | gen_address(context: IR.CONTEXT) is | |
| 97 | gen(from, context) | |
| 98 | context.fixme("load member address {symbol.qualified_name}") | |
| 99 | si | |
| 100 | ||
| 101 | to_string() -> string => | |
| 102 | "load:[{type}]({from},\"{symbol.name}\")" | |
| 103 | si | |
| 104 | si |