Skip to content
← Back

src/ir/values/null_coalesce_value.ghul

1
namespace IR.Values is
2
use Semantic.Types.Type;
3
4
// The result of `a ?? b` for a value-type optional `a` —
5
// NULLABLE[T] or MAYBE[T]. The receiver is spilled to a local so
6
// its address can feed the has_value / value accessor calls: the
7
// left operand can be any expression, not just an addressable
8
// slot. `b` is evaluated only on the absent path.
9
//
10
// .locals init (<recv type> '.coalesce.N')
11
// <receiver IL> // [..., recv]
12
// stloc '.coalesce.N' // [...]
13
// ldloca '.coalesce.N' // [..., &recv]
14
// <presence_test IL> // [..., bool] (get_has_value on 'this' addr)
15
// brfalse <absent>
16
// ldloca '.coalesce.N' // [..., &recv]
17
// <value_extract IL> // [..., T] (get_value on 'this' addr)
18
// <present_arm IL> // [..., R] (coercion over the payload, often nothing)
19
// br <end>
20
// <absent>:
21
// <absent_arm IL> // [..., R]
22
// <end>:
23
//
24
// Built by COMPILE_OPERATORS._visit_null_coalesce. Branches use
25
// the long forms — either arm can hold an arbitrarily large
26
// expression.
27
class NULL_COALESCE_VALUE: Value is
28
receiver: Value;
29
presence_test: Value;
30
value_extract: Value;
31
present_arm: Value;
32
absent_arm: Value;
33
_result_type: Type;
34
35
type: Type => _result_type;
36
is_lightweight_pure: bool => false;
37
38
init(
39
receiver: Value,
40
presence_test: Value,
41
value_extract: Value,
42
present_arm: Value,
43
absent_arm: Value,
44
result_type: Type
45
) is
46
super.init();
47
48
self.receiver = receiver;
49
self.presence_test = presence_test;
50
self.value_extract = value_extract;
51
self.present_arm = present_arm;
52
self.absent_arm = absent_arm;
53
self._result_type = result_type;
54
si
55
56
gen(context: IR.CONTEXT) is
57
let id = TEMP.get_next_id();
58
let absent_label = IR.LABEL();
59
let end_label = IR.LABEL();
60
61
context.write_line(".locals init ({receiver.type!.get_il_type()} '.coalesce.{id}')");
62
gen(receiver, context);
63
context.write_line("stloc '.coalesce.{id}'");
64
context.write_line("ldloca '.coalesce.{id}'");
65
gen(presence_test, context);
66
context.write_line("brfalse {absent_label}");
67
context.write_line("ldloca '.coalesce.{id}'");
68
gen(value_extract, context);
69
gen(present_arm, context);
70
context.write_line("br {end_label}");
71
context.write_line("{absent_label}:");
72
gen(absent_arm, context);
73
context.write_line("{end_label}:");
74
si
75
76
to_string() -> string =>
77
"null-coalesce-value:[{type}]({receiver},{absent_arm})";
78
si
79
si