Skip to content
← Back

src/syntax/process/compile-expressions/loop_result_settler.ghul

1
namespace Syntax.Process is
2
use Logging
3
4
use Semantic.LEAST_UPPER_BOUND_MAP
5
use Semantic.Types.Type
6
7
// Settles a loop expression's result type from its valued-`break`
8
// contributions: the LUB of the contributions — falling back to the
9
// pushed expected type when nothing usable contributes — widened to
10
// the optional form of the element kind. Widening follows the same
11
// per-kind split as if/case arm joins: NULLABLE[T] for a value
12
// type, MAYBE[T] for an unconstrained type parameter where the
13
// runtime assembly is available (the flagged reference optional as
14
// the fallback when it is not), the flagged reference optional for
15
// any other reference kind. An already-optional LUB stands.
16
//
17
// The three optional makers are injected: they depend on reflected
18
// runtime assemblies that unit-test fixtures do not load, and the
19
// contract under test is which maker fires for which element kind,
20
// not how each optional is constructed.
21
class LOOP_RESULT_SETTLER is
22
_make_nullable: (Type) -> Type
23
_make_maybe: (Type) -> Type?
24
_make_reference_optional: (Type) -> Type
25
26
init(
27
make_nullable: (Type) -> Type,
28
make_maybe: (Type) -> Type?,
29
make_reference_optional: (Type) -> Type
30
) is
31
_make_nullable = make_nullable
32
_make_maybe = make_maybe
33
_make_reference_optional = make_reference_optional
34
si
35
36
// Null means "cannot infer" — contributions empty or all-error,
37
// with no expected type — for the caller to report against the
38
// loop's own location.
39
settle(contributions: Collections.Iterable[Type], expected: Type?) -> Type? is
40
let lub = LEAST_UPPER_BOUND_MAP()
41
42
let saw_contribution mut = false
43
44
for t in contributions do
45
if !t.is_error then
46
lub.add(t)
47
48
saw_contribution = true
49
fi
50
od
51
52
if !saw_contribution then
53
return expected
54
fi
55
56
let inner mut = lub.get_result() ?? expected
57
58
if !inner? then
59
return null
60
fi
61
62
if inner.is_optional then
63
return inner
64
fi
65
66
if inner.is_type_variable then
67
return _make_maybe(inner) ?? _make_reference_optional(inner)
68
elif inner.is_value_type then
69
return _make_nullable(inner)
70
fi
71
72
return _make_reference_optional(inner)
73
si
74
si
75
si