Skip to content
← Back

src/syntax/trees/statements/if.ghul

1
namespace Syntax.Trees.Statements is
2
use Source
3
4
use Logging
5
6
use Ghul.Pipes
7
8
class IF: Statement is
9
branches: Collections.Iterable[IF_BRANCH]
10
provides_value: bool => true
11
12
// Set by compile-expressions on a value-consuming if with no
13
// unconditional else: the fall-through path contributes absence,
14
// so generate-il pushes the default of the optional result type
15
// before the join label. Compile-expressions clears it at the
16
// start of each visit_if walk and writes it again on every walk
17
// that reaches the join, so a stale value never survives into a
18
// successful walk's output.
19
yields_absence_on_fall_through: bool public => if_state.yields_absence_on_fall_through, = value is if_state.yields_absence_on_fall_through = value si
20
21
if_state: Syntax.Process.IF_STATE field
22
23
// Expected-type constraint pushed down by compile-expressions.
24
branch_state: Syntax.Process.EXPECTED_TYPE_STATE field
25
26
expected_type: Semantic.Types.Type? => branch_state.expected_type
27
expected_type_error_message: string? => branch_state.expected_type_error_message
28
29
is_tuple_literal: bool =>
30
if branches |> all(b => b.body.is_tuple_literal) then
31
true
32
else
33
false
34
fi
35
36
init(location: LOCATION, branches: Collections.Iterable[IF_BRANCH]) is
37
super.init(location)
38
39
self.branches = Collections.LIST(branches)
40
si
41
42
debug_location: LOCATION is
43
for branch in branches do
44
return branch.debug_location
45
od
46
47
return location.start_position
48
si
49
50
set_expected_type(expected_type: Semantic.Types.Type?, error_message: string?) is
51
branch_state.set(expected_type, error_message)
52
53
for b in branches do
54
b.body.set_expected_type(expected_type, error_message)
55
od
56
si
57
58
clear() is
59
super.clear()
60
branch_state.clear()
61
if_state.clear()
62
si
63
64
clear_outputs() is
65
super.clear_outputs()
66
if_state.clear()
67
si
68
69
clear_expected_type() is
70
branch_state.clear()
71
si
72
73
accept(visitor: Visitor) is
74
visitor.visit(self)
75
si
76
77
walk(visitor: Visitor) is
78
if !visitor.pre(self) then
79
for branch in branches do
80
branch.walk(visitor)
81
od
82
fi
83
84
accept(visitor)
85
si
86
si
87
88
class IF_BRANCH: Trees.Node, ScopeCarrier is
89
scope: Semantic.Scope? public
90
91
condition: Expressions.Expression?
92
binding: REFUTABLE_BINDING?
93
body: LIST
94
95
init(
96
location: LOCATION,
97
condition: Expressions.Expression?,
98
body: LIST
99
)
100
is
101
init(location, condition, null, body)
102
si
103
104
init(
105
location: LOCATION,
106
condition: Expressions.Expression?,
107
binding: REFUTABLE_BINDING?,
108
body: LIST
109
)
110
is
111
super.init(location)
112
113
self.condition = condition
114
self.binding = binding
115
self.body = body
116
si
117
118
debug_location: LOCATION is
119
if let self.condition? then
120
return location.start_position :: condition.location
121
elif let self.binding? then
122
return location.start_position :: binding.location
123
fi
124
125
return location.start_position
126
si
127
128
accept(visitor: Visitor) is
129
visitor.visit(self)
130
si
131
132
walk(visitor: Visitor) is
133
if !visitor.pre(self) then
134
if let self.condition? then
135
condition.walk(visitor)
136
fi
137
138
if let self.binding? then
139
binding.walk(visitor)
140
fi
141
142
body.walk(visitor)
143
fi
144
145
accept(visitor)
146
si
147
si
148
si