Skip to content
← Back

src/syntax/trees/statements/case.ghul

1
namespace Syntax.Trees.Statements is
2
use Source
3
4
class CASE(location: LOCATION, expression: Expressions.Expression, matches: Collections.LIST[CASE_MATCH]): Statement, ScopeCarrier is
5
scope: Semantic.Scope? public
6
7
provides_value: bool => true
8
9
// Expected-type constraint plus exhaustiveness facts recorded
10
// by the compile-expressions pass family.
11
case_state: Syntax.Process.CASE_STATE field
12
13
expected_type: Semantic.Types.Type? => case_state.expected_type
14
expected_type_error_message: string? => case_state.expected_type_error_message
15
// True when the arms cover the scrutinee's closed domain. Lets
16
// the expression-form missing-else gate accept an exhaustive
17
// case without an `else` arm.
18
is_exhaustive: bool => case_state.is_exhaustive
19
20
// True for an expression-form case with no `else` arm over an
21
// open-domain scrutinee whose expected type has a defaultable
22
// value (value type or optional). The IL emitter pushes
23
// default(expected_type) at the no-match fall-through instead
24
// of throwing.
25
requires_default_fallthrough: bool => case_state.requires_default_fallthrough
26
27
// The scrutinee spilled once into a temp in compile-expressions;
28
// see CASE_STATE. generate-il emits the spill and reads the load.
29
scrutinee_spill: IR.Values.Value? => case_state.scrutinee_spill
30
scrutinee_load: IR.Values.Value? => case_state.scrutinee_load
31
32
super(location)
33
34
debug_location: LOCATION =>
35
location.start_position :: expression.location
36
37
set_expected_type(expected_type: Semantic.Types.Type?, error_message: string?) is
38
case_state.set_expected_type(expected_type, error_message)
39
40
for m in matches do
41
m.statements.set_expected_type(expected_type, error_message)
42
od
43
si
44
45
clear() is
46
super.clear()
47
case_state.clear()
48
si
49
50
clear_outputs() is
51
super.clear_outputs()
52
53
case_state.is_exhaustive = false
54
case_state.requires_default_fallthrough = false
55
case_state.scrutinee_spill = null
56
case_state.scrutinee_load = null
57
si
58
59
clear_expected_type() is
60
case_state.expected_type = null
61
case_state.expected_type_error_message = null
62
si
63
64
accept(visitor: Visitor) is
65
visitor.visit(self)
66
si
67
68
walk(visitor: Visitor) is
69
if !visitor.pre(self) then
70
expression.walk(visitor)
71
for m in matches do
72
m.walk(visitor)
73
od
74
fi
75
76
accept(visitor)
77
si
78
79
si
80
81
class CASE_MATCH: Statement, ScopeCarrier is
82
scope: Semantic.Scope? public
83
84
expressions: Expressions.LIST?
85
pattern: Variables.VARIABLE?
86
// Trailing `/\ guard` on a pattern arm. Only ever set alongside
87
// `pattern` — the equality-list and `else` arm shapes have no
88
// syntax for one. Walked after the pattern's names are in scope,
89
// mirroring `REFUTABLE_BINDING_CLAUSE.guard`.
90
guard: Expressions.Expression? public
91
statements: LIST
92
93
// Per-label value-equality test Values, built in
94
// compile-expressions and parallel to `expressions`; see
95
// CASE_MATCH_STATE.
96
match_state: Syntax.Process.CASE_MATCH_STATE field
97
98
tests: Collections.LIST[IR.Values.Value?]? => match_state.tests
99
100
init(location: LOCATION, expressions: Expressions.LIST?, statements: LIST) is
101
init(location, expressions, null, null, statements)
102
si
103
104
init(location: LOCATION, expressions: Expressions.LIST?, pattern: Variables.VARIABLE?, guard: Expressions.Expression?, statements: LIST) is
105
super.init(location)
106
107
self.expressions = expressions
108
self.pattern = pattern
109
self.guard = guard
110
self.statements = statements
111
si
112
113
debug_location: LOCATION is
114
if let self.guard? then
115
return location.start_position :: guard.location
116
elif let self.pattern? then
117
return location.start_position :: pattern.location
118
elif let self.expressions? then
119
return location.start_position :: expressions.location
120
fi
121
122
return location.start_position
123
si
124
125
accept(visitor: Visitor) is
126
visitor.visit(self)
127
si
128
129
walk(visitor: Visitor) is
130
// enter/leave_node wrap the whole visit so the ambient
131
// location covers Values built by `pre()` overrides that
132
// take control of the walk — `pre_case_match` returns true
133
// for arms with patterns and runs a synthesised walk,
134
// skipping the default recursion below.
135
visitor.enter_node(self)
136
try
137
if !visitor.pre(self) then
138
if let self.expressions? then
139
expressions.walk(visitor)
140
fi
141
142
if let self.pattern? then
143
pattern.walk(visitor)
144
fi
145
146
if let self.guard? then
147
guard.walk(visitor)
148
fi
149
150
statements.walk(visitor)
151
fi
152
153
accept(visitor)
154
finally
155
visitor.leave_node(self)
156
yrt
157
si
158
si
159
si