Skip to content
← Back

src/ir/values/wrap_maybe.ghul

1
namespace IR.Values is
2
use Semantic.Types.Type
3
4
// Coerce a reference-typed `T?` into the unconstrained-T optional
5
// carrier `Ghul.MAYBE[T]`. A reference optional carries absence as
6
// a null reference and MAYBE as a zeroed struct, so the two are
7
// bridged by a null test: the present path wraps the reference
8
// with MAYBE<T>::.ctor(T), the absent path yields the empty MAYBE.
9
//
10
// <value IL> // [..., a]
11
// dup // [..., a, a]
12
// brtrue <present> // pops one a
13
// pop // [...]
14
// <absent IL> // [..., empty MAYBE]
15
// br <end>
16
// <present>:
17
// newobj MAYBE<T>::.ctor(T)
18
// <end>:
19
//
20
// Built by VALUE_BOXER.wrap_if_needed. The value-type optional
21
// sources (NULLABLE[T], another MAYBE instantiation) go through
22
// NULL_COALESCE_VALUE instead, since presence there is a member
23
// read off the struct's address rather than a null test.
24
class WRAP_MAYBE: Value is
25
value: Value
26
_maybe_type: Type
27
_absent: Value
28
29
type: Type => _maybe_type
30
is_value_type: bool => true
31
is_lightweight_pure: bool => false
32
33
init(
34
maybe_type: Type,
35
value: Value
36
) is
37
super.init()
38
39
self._maybe_type = maybe_type
40
self.value = value
41
self._absent = Values.DEFAULT(maybe_type)
42
si
43
44
gen(context: IR.CONTEXT) is
45
let present_label = IR.LABEL()
46
let end_label = IR.LABEL()
47
48
gen(value, context)
49
50
let body = context.current_srm_body_emitter!
51
body.op(System.Reflection.Metadata.ILOpCode.DUP)
52
body.branch(System.Reflection.Metadata.ILOpCode.BRTRUE, present_label)
53
body.op(System.Reflection.Metadata.ILOpCode.POP)
54
gen(_absent, context)
55
body.branch(System.Reflection.Metadata.ILOpCode.BR, end_label)
56
body.mark_label(present_label)
57
body.new_object(context.resolve_generic_constructor(_maybe_type, 1))
58
body.mark_label(end_label)
59
si
60
61
to_string() -> string =>
62
"wrap-maybe:[{_maybe_type}]({value})"
63
si
64
si