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
super(location);
28
29
set_expected_type(expected_type: Semantic.Types.Type?, error_message: string?) is
30
case_state.set_expected_type(expected_type, error_message);
31
32
for m in matches do
33
m.statements.set_expected_type(expected_type, error_message);
34
od
35
si
36
37
clear() is
38
super.clear();
39
case_state.clear();
40
si
41
42
clear_expected_type() is
43
case_state.expected_type = null;
44
case_state.expected_type_error_message = null;
45
si
46
47
accept(visitor: Visitor) is
48
visitor.visit(self);
49
si
50
51
walk(visitor: Visitor) is
52
if !visitor.pre(self) then
53
expression.walk(visitor);
54
for m in matches do
55
m.walk(visitor);
56
od
57
fi
58
59
accept(visitor);
60
si
61
62
si
63
64
class CASE_MATCH: Statement, ScopeCarrier is
65
scope: Semantic.Scope? public;
66
67
expressions: Expressions.LIST?;
68
pattern: Variables.VARIABLE?;
69
// Trailing `/\ guard` on a pattern arm. Only ever set alongside
70
// `pattern` — the equality-list and `else` arm shapes have no
71
// syntax for one. Walked after the pattern's names are in scope,
72
// mirroring `REFUTABLE_BINDING_CLAUSE.guard`.
73
guard: Expressions.Expression? public;
74
statements: LIST;
75
76
init(location: LOCATION, expressions: Expressions.LIST?, statements: LIST) is
77
init(location, expressions, null, null, statements);
78
si
79
80
init(location: LOCATION, expressions: Expressions.LIST?, pattern: Variables.VARIABLE?, guard: Expressions.Expression?, statements: LIST) is
81
super.init(location);
82
83
self.expressions = expressions;
84
self.pattern = pattern;
85
self.guard = guard;
86
self.statements = statements;
87
si
88
89
accept(visitor: Visitor) is
90
visitor.visit(self);
91
si
92
93
walk(visitor: Visitor) is
94
// enter/leave_node wrap the whole visit so the ambient
95
// location covers Values built by `pre()` overrides that
96
// take control of the walk — `pre_case_match` returns true
97
// for arms with patterns and runs a synthesised walk,
98
// skipping the default recursion below.
99
visitor.enter_node(self);
100
try
101
if !visitor.pre(self) then
102
if let self.expressions? then
103
expressions.walk(visitor);
104
fi
105
106
if let self.pattern? then
107
pattern.walk(visitor);
108
fi
109
110
if let self.guard? then
111
guard.walk(visitor);
112
fi
113
114
statements.walk(visitor);
115
fi
116
117
accept(visitor);
118
finally
119
visitor.leave_node(self);
120
yrt
121
si
122
si
123
si