Skip to content
← Back

src/syntax/trees/statements/refutable_binding.ghul

1
namespace Syntax.Trees.Statements is
2
use Source;
3
4
// One clause of an `if let` binding — a single
5
// `pattern[: T] = scrutinee[ /\ guard]` slice. A REFUTABLE_BINDING
6
// holds an ordered list of these; each clause's scrutinee compiles
7
// under the narrowed environment produced by the prior clauses.
8
//
9
// Not visited as an AST node in its own right — the surrounding
10
// REFUTABLE_BINDING walks the clause's pieces (narrow_type_expression
11
// / scrutinee / pattern / guard) directly, and the semantic and IL
12
// passes iterate clauses and drive each clause's work inline.
13
class REFUTABLE_BINDING_CLAUSE: Trees.Node is
14
scrutinee: Expressions.Expression public;
15
narrow_type_expression: TypeExpressions.TypeExpression? public;
16
pattern: Variables.VariableLeft public;
17
guard: Expressions.Expression? public;
18
19
// True for the leaf-name shorthand (`if let x.y.z?` /
20
// `if let x.y: T`), where the pattern's name was inferred
21
// from the path's last member. The formatter prints the
22
// shorthand back rather than the expanded form.
23
is_inferred_name: bool public;
24
25
init(
26
location: LOCATION,
27
scrutinee: Expressions.Expression,
28
narrow_type_expression: TypeExpressions.TypeExpression?,
29
pattern: Variables.VariableLeft,
30
guard: Expressions.Expression?
31
) is
32
super.init(location);
33
34
35
self.scrutinee = scrutinee;
36
self.narrow_type_expression = narrow_type_expression;
37
self.pattern = pattern;
38
self.guard = guard;
39
si
40
si
41
42
// The binding shape of an `if let` arm. Semantically equivalent
43
// to `isa V(scrutinee) /\ <bind pattern from scrutinee>` per clause
44
// when a narrow target is given, and to a `?` (presence) test plus
45
// a bind from the unwrapped value when it is not. A multi-clause
46
// binding short-circuits left-to-right: every clause's test and
47
// optional guard must succeed for the then-arm to fire.
48
//
49
// The semantic and IL passes drive narrowing and binding directly
50
// off this node — the scrutinee remains visible to flow narrowing
51
// and to the destructure's DESTRUCTURE_CONSTRAINT path, which is
52
// what gives `if let` inference parity with the `isa V(t) ... let
53
// p = t` shape for recursive lambdas.
54
class REFUTABLE_BINDING: Trees.Node is
55
clauses: Collections.LIST[REFUTABLE_BINDING_CLAUSE] public;
56
57
init(
58
location: LOCATION,
59
clauses: Collections.Iterable[REFUTABLE_BINDING_CLAUSE]
60
) is
61
super.init(location);
62
63
64
self.clauses = Collections.LIST[REFUTABLE_BINDING_CLAUSE](clauses);
65
66
assert self.clauses.count > 0 else "refutable binding has no clauses";
67
si
68
69
accept(visitor: Visitor) is
70
visitor.visit(self);
71
si
72
73
walk(visitor: Visitor) is
74
if !visitor.pre(self) then
75
for c in clauses do
76
if let c.narrow_type_expression? then
77
narrow_type_expression.walk(visitor);
78
fi
79
80
c.scrutinee.walk(visitor);
81
c.pattern.walk(visitor);
82
83
if let c.guard? then
84
guard.walk(visitor);
85
fi
86
od
87
fi
88
89
accept(visitor);
90
si
91
si
92
si