Appearance
| 1 | namespace IR.Values is | |
| 2 | use Semantic.Types.Type; | |
| 3 | ||
| 4 | // Present a flow-narrowed optional reference at its non-optional | |
| 5 | // type without changing its representation. An optional reference | |
| 6 | // (`T?`) and its non-optional form (`T`) share IL, so the view is | |
| 7 | // a pure type-system reinterpretation that gens identically to | |
| 8 | // the underlying load. Used where presence narrowing establishes | |
| 9 | // a member-access path holds a value (`receiver.prop` inside | |
| 10 | // `if receiver.prop? then …`): the use is of `T`, even though the | |
| 11 | // member is declared `T?`. The value-type optionals (`NULLABLE[T]` | |
| 12 | // / `MAYBE[T]`) use NARROW_PROJECT instead, since they must emit a | |
| 13 | // `.value` unwrap. The local-variable path reaches the same effect | |
| 14 | // through Load.SYMBOL.narrow_snapshot_type; a member load is not | |
| 15 | // always a Load.SYMBOL, so the view wraps any value. | |
| 16 | class NARROW_VIEW: Value is | |
| 17 | underlying: Value; | |
| 18 | _type: Type; | |
| 19 | ||
| 20 | type: Type => _type; | |
| 21 | has_symbol: bool => underlying.has_symbol; | |
| 22 | symbol: Semantic.Symbols.Symbol => underlying.symbol; | |
| 23 | is_consumable: bool => underlying.is_consumable; | |
| 24 | has_address: bool => underlying.has_address; | |
| 25 | is_lightweight_pure: bool => underlying.is_lightweight_pure; | |
| 26 | is_state_changing_call: bool => underlying.is_state_changing_call; | |
| 27 | ||
| 28 | init(underlying: Value, narrowed: Type) is | |
| 29 | super.init(); | |
| 30 | ||
| 31 | self.underlying = underlying; | |
| 32 | self._type = narrowed; | |
| 33 | si | |
| 34 | ||
| 35 | gen(context: IR.CONTEXT) is | |
| 36 | gen(underlying, context); | |
| 37 | si | |
| 38 | ||
| 39 | gen_address(context: IR.CONTEXT) is | |
| 40 | underlying.gen_address(context); | |
| 41 | si | |
| 42 | ||
| 43 | to_string() -> string => | |
| 44 | "narrow-view:[{type}]({underlying})"; | |
| 45 | si | |
| 46 | si |