Skip to content
← Back

src/semantic/unit_variant_constructor.ghul

1
namespace Semantic is
2
use Source.LOCATION
3
use Types.Type
4
use IR.Values.Value
5
6
// Lowers a bare reference to a unit variant — `RED`, `COLOR.RED`,
7
// `Option.NONE`, `Many.EMPTY`, `Option.NONE[int]` — to a NEW value
8
// that points at the variant's interned singleton.
9
// `gen_unit_variant_singleton` and `IR.Values.NEW.gen` cooperate to
10
// emit `ldsfld` for that path.
11
//
12
// For a generic union the variant only constructs once every type
13
// parameter is fixed. When the caller has an expected type pushed
14
// in by the parent context — assignment LHS, function-argument
15
// slot, return slot, explicit type arguments via `Option.NONE[int]`
16
// — `try_load` borrows the OWNER_CONSTRAINT_SPECIALIZER to derive
17
// the type arguments from it, the same way `Option.NONE()` does
18
// today via resolve_constructor. When the variant is generic and
19
// the constraint can't fill every owner slot, `try_load` returns
20
// null and the caller falls back to a TYPE_EXPRESSION; any
21
// enclosing `()` then drives the regular constructor-resolution
22
// path.
23
//
24
// A name looked up from inside a generic type's own body arrives
25
// already specialized, wrapped in a GENERIC rather than as the
26
// VARIANT itself. Its type arguments are fixed by the scope that
27
// resolved it, so that shape needs neither the constraint nor the
28
// placeholders — it reads its constructor straight off the
29
// specialization.
30
class UNIT_VARIANT_CONSTRUCTOR is
31
_owner_constraint_specializer: OWNER_CONSTRAINT_SPECIALIZER
32
_type_arg_placeholder_registry: TYPE_ARG_PLACEHOLDER_REGISTRY
33
_function_caller: FUNCTION_CALLER
34
35
init(
36
owner_constraint_specializer: OWNER_CONSTRAINT_SPECIALIZER,
37
type_arg_placeholder_registry: TYPE_ARG_PLACEHOLDER_REGISTRY,
38
function_caller: FUNCTION_CALLER
39
) is
40
super.init()
41
42
_owner_constraint_specializer = owner_constraint_specializer
43
_type_arg_placeholder_registry = type_arg_placeholder_registry
44
_function_caller = function_caller
45
si
46
47
try_load(
48
location: LOCATION,
49
symbol: Symbols.Symbol?,
50
constraint: Type?,
51
cache_key: Syntax.Trees.Node
52
) -> UNIT_VARIANT_LOAD? is
53
if !symbol? \/ !symbol.is_unit_variant then
54
return null
55
fi
56
57
if let specialized: Symbols.GENERIC = symbol then
58
return _load_specialized(specialized)
59
fi
60
61
let variant = cast Symbols.VARIANT?(symbol)
62
63
if !variant? then
64
return null
65
fi
66
67
let init_group = cast Symbols.FUNCTION_GROUP?(variant.find_direct("init"))
68
69
if !init_group? \/ init_group.functions.count == 0 then
70
return null
71
fi
72
73
let init mut = init_group.functions[0]
74
75
if variant.is_generic then
76
if constraint? then
77
init = _owner_constraint_specializer.specialize_from_constraint(location, init, constraint)
78
fi
79
80
// Any owner-generic slot the constraint didn't fix
81
// (or every slot when no constraint reached us) is
82
// covered by a phantom origin keyed off `cache_key`.
83
// The enclosing call's overload resolver back-feeds
84
// each phantom from the argument slot it lands in,
85
// matching the path taken by resolve_constructor for
86
// the parenthesised form.
87
init = _type_arg_placeholder_registry.specialize_with_placeholders(location, init, cache_key)
88
fi
89
90
return _call(init)
91
si
92
93
_load_specialized(specialized: Symbols.GENERIC) -> UNIT_VARIANT_LOAD? is
94
let init_group = cast Symbols.FUNCTION_GROUP?(specialized.find_direct("init"))
95
96
if !init_group? \/ init_group.functions.count == 0 then
97
return null
98
fi
99
100
return _call(init_group.functions[0])
101
si
102
103
_call(init: Symbols.Function) -> UNIT_VARIANT_LOAD? is
104
let owner_type = init.owner!.type
105
assert owner_type? else "variant constructor owner has no type"
106
let value = _function_caller.call_constructor(init, Collections.LIST[Value](), owner_type)
107
108
return UNIT_VARIANT_LOAD(value, init)
109
si
110
si
111
112
class UNIT_VARIANT_LOAD is
113
value: Value
114
constructor: Symbols.Function
115
116
init(value: Value, constructor: Symbols.Function) is
117
super.init()
118
self.value = value
119
self.constructor = constructor
120
si
121
si
122
si