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? => 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
si
42
43
to_string() -> string =>
44
"narrow-project:[{type}]({underlying})";
45
si
46
si