Skip to content
← Back

src/ir/values/narrow_project.ghul

1
namespace IR.Values is
2
use Semantic.Types.Type
3
4
// Project a flow-narrowed value-type optional (`MAYBE[T]` /
5
// `NULLABLE[T]`) to its inner `T`. `underlying` is the original
6
// wrapper load; `projected` is the `.value` access against that
7
// wrapper. The type-system view is `T`, so member access,
8
// operator resolution and slot-boundary coercion all see the
9
// narrowed type. IL gen emits the projection. `visit_has_value`
10
// and `visit_unwrap` peel back to `underlying` so the wrapper-
11
// shaped operations stay sound.
12
class NARROW_PROJECT: Value is
13
underlying: Value
14
projected: Value
15
16
type: Type? pure => projected.type
17
has_symbol: bool => underlying.has_symbol
18
symbol: Semantic.Symbols.Symbol => underlying.symbol
19
is_lightweight_pure: bool => projected.is_lightweight_pure
20
21
init(underlying: Value, projected: Value) is
22
super.init()
23
24
self.underlying = underlying
25
self.projected = projected
26
si
27
28
// Strip a NARROW_PROJECT wrapper back to the underlying
29
// optional-shaped load — for consumers (`?`, `!`, refutable
30
// binding) that want to operate on the wrapper itself. A
31
// no-op when `value` isn't a projection.
32
peel(value: Value?) -> Value? static =>
33
if isa NARROW_PROJECT(value) then
34
(cast NARROW_PROJECT(value)).underlying
35
else
36
value
37
fi
38
39
gen(context: IR.CONTEXT) is
40
gen(projected, context)
41
42
NARROW_GUARD.emit(type, context)
43
si
44
45
to_string() -> string =>
46
"narrow-project:[{type}]({underlying})"
47
si
48
si