Skip to content
← Back

src/syntax/trees/expressions/val_block.ghul

1
namespace Syntax.Trees.Expressions is
2
use Source
3
4
// `val ... lav` — a value-producing block.
5
//
6
// The block's value is the LUB of every contributing source: the
7
// tail expression of `body` (if the tail provides a value) and
8
// every `return E` whose target is this block. `return E` inside
9
// a `val ... lav` exits this block (innermost wins on nesting),
10
// not the enclosing function.
11
class VAL_BLOCK: Expression is
12
body: Statements.LIST public
13
14
// True when the block was written in its parenthesised
15
// spelling `(statement; ...; value)` rather than as
16
// `val ... lav`. Semantics are identical; the formatter uses
17
// this to round-trip the spelling the user wrote.
18
is_parenthesised: bool public
19
20
// A block yields a tuple literal when its tail is one and no
21
// return contributes a value of another shape.
22
is_tuple_literal: bool => body.is_tuple_literal /\ !has_targeted_return
23
24
// Set by the wrapping context (compile-expressions). False
25
// when the block is in expression-statement position or in a
26
// void-returning `=>` body — fall-through is allowed to be
27
// void there. True everywhere else.
28
want_value: bool public => block_state.want_value, = value is block_state.want_value = value si
29
30
// True where a value is wanted but a void one is acceptable —
31
// the body of a function literal whose return type is still
32
// being inferred. A body that yields no value there settles
33
// the block, and the literal's return, as void.
34
void_tolerated: bool public => block_state.void_tolerated, = value is block_state.void_tolerated = value si
35
36
// Pushed expected_type from outer context, threaded onto the
37
// tail expression and every return that targets us so they
38
// participate in inference / overload resolution against the
39
// expected type.
40
expected_type: Semantic.Types.Type? public => block_state.expected_type, = value is block_state.expected_type = value si
41
expected_type_error_message: string? public => block_state.expected_type_error_message, = value is block_state.expected_type_error_message = value si
42
43
// Collected at compile-expressions time: the value type of
44
// every return targeting this block. visit() LUBs these with
45
// the tail's value type to settle the block's value type.
46
return_types: Collections.MutableList[Semantic.Types.Type] => block_state.returns()
47
48
// True when any RETURN statement inside the body targets
49
// this block (with or without an expression). `return_types`
50
// alone misses bare `return;`; this flag is set by
51
// compile_bindings.pre_return whenever a return's target is
52
// resolved to this block.
53
has_targeted_return: bool public => block_state.has_targeted_return, = value is block_state.has_targeted_return = value si
54
55
// Label placed at end of block body in generate-il; returns
56
// with this block as target push their value and `br` here.
57
// All paths (every targeted return + the natural fall-
58
// through) converge with the value on the evaluation stack —
59
// the same shape `if`/`case`-in-expression IL uses, so async
60
// and generator state machines work without value-across-
61
// suspend special handling.
62
end_label: IR.LABEL? public => block_state.end_label, = value is block_state.end_label = value si
63
64
block_state: Syntax.Process.VAL_BLOCK_STATE field
65
66
init(location: LOCATION, body: Statements.LIST) is
67
super.init(location)
68
69
70
self.body = body
71
self.want_value = true
72
self.void_tolerated = false
73
si
74
75
clear() is
76
super.clear()
77
block_state.clear()
78
si
79
80
clear_outputs() is
81
super.clear_outputs()
82
block_state.clear_outputs()
83
si
84
85
set_expected_type(expected_type: Semantic.Types.Type?, error_message: string?) is
86
self.expected_type = expected_type
87
self.expected_type_error_message = error_message
88
89
// Push the constraint onto the tail expression so it
90
// participates in inference / overload resolution against
91
// the expected type — same shape as `if`/`case`
92
// expression-position branches. Returns targeting this
93
// block pick the constraint up from `expected_type` via
94
// compile_bindings.pre_return.
95
body.set_expected_type(expected_type, error_message)
96
si
97
98
clear_expected_type() is
99
expected_type = null
100
expected_type_error_message = null
101
body.clear_expected_type()
102
si
103
104
accept(visitor: Visitor) is
105
visitor.visit(self)
106
si
107
108
walk(visitor: Visitor) is
109
if !visitor.pre(self) then
110
body.walk(visitor)
111
fi
112
113
accept(visitor)
114
si
115
si
116
si