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
let body = context.current_srm_body_emitter!
62
let temp = ".coalesce.{id}"
63
64
body.declare_local(temp, receiver.type!)
65
gen(receiver, context)
66
body.stloc(temp)
67
body.ldloca(temp)
68
gen(presence_test, context)
69
body.branch(System.Reflection.Metadata.ILOpCode.BRFALSE, absent_label)
70
body.ldloca(temp)
71
gen(value_extract, context)
72
gen(present_arm, context)
73
body.branch(System.Reflection.Metadata.ILOpCode.BR, end_label)
74
body.mark_label(absent_label)
75
gen(absent_arm, context)
76
body.mark_label(end_label)
77
si
78
79
to_string() -> string =>
80
"null-coalesce-value:[{type}]({receiver},{absent_arm})"
81
si
82
si