Skip to content
← Back

src/syntax/trees/expressions/tuple.ghul

1
namespace Syntax.Trees.Expressions is
2
use Source
3
4
use Logging
5
6
class TUPLE: Expression is
7
is_function_arguments: bool public
8
9
// A single-element TUPLE node is a parenthesised expression,
10
// not a 1-tuple — TUPLE.visit collapses its value to the inner
11
// element. Reflect that here so callers driving tuple-shaped
12
// LUB / inference (SEQUENCE elements, IF branches with
13
// uniformly-tupled bodies) don't reach for a non-existent
14
// tuple arity and ICE in get_tuple_type. The parentheses are
15
// transparent: what they hold is a tuple literal when the inner
16
// expression is one - a parenthesised `if` or block whose arms
17
// or tail are tuple literals.
18
is_tuple_literal: bool =>
19
if elements.expressions.count == 1 then
20
elements.expressions[0].is_tuple_literal
21
else
22
true
23
fi
24
25
elements: LIST
26
27
// Type ascription written after the closing paren, as in
28
// `((a, b): (int, int)) => …`. Only ever parsed in a position
29
// that could turn out to be a lambda parameter list, where it
30
// declares the type of the one physical argument the pattern
31
// unpacks. Null everywhere else; if the surrounding syntax
32
// turns out not to be a lambda, `rewrite_as_expression`
33
// reports it rather than dropping it.
34
type_expression: TypeExpressions.TypeExpression? public
35
36
could_be_formal_argument: bool => true
37
38
set_type_expression(type_expression: TypeExpressions.TypeExpression) is
39
self.type_expression = type_expression
40
si
41
42
try_copy_as_variable_left() -> Variables.VariableLeft? is
43
let elements_left = Collections.LIST[Variables.VariableLeft]()
44
45
for e in elements.expressions do
46
let element_left = e.try_copy_as_variable_left()
47
48
if !element_left? then
49
return null
50
fi
51
52
elements_left.add(element_left)
53
od
54
55
return Variables.DESTRUCTURING_VARIABLE_LEFT(location, elements_left)
56
si
57
58
// A lambda parameter written as a parenthesised group is a
59
// destructure pattern over one physical argument. The group's
60
// own name is synthesised - declare-members renames it to a
61
// unique slot, the same way it renames a `_` discard - since
62
// the source only names the leaves.
63
try_copy_as_variable() -> VARIABLE? is
64
let left = try_copy_as_variable_left()
65
66
if !left? then
67
return null
68
fi
69
70
let result =
71
VARIABLE(
72
location,
73
Identifiers.Identifier(location, "$destructured_argument"),
74
type_expression ?? TypeExpressions.INFER(location),
75
null
76
)
77
78
result.mark_synthesized()
79
result.set_left(left)
80
81
return result
82
si
83
84
init(location: LOCATION, elements: LIST, is_function_arguments: bool) is
85
super.init(location)
86
87
self.elements = elements
88
self.is_function_arguments = is_function_arguments
89
si
90
91
// A one-element group is a parenthesised expression rather than
92
// a 1-tuple, so it stands for its element wherever a context
93
// type is offered or asked for. Without this, parenthesising a
94
// `cast(v)` hides that it is still waiting for a type and hands
95
// it the surrounding context's instead.
96
awaits_context_type: bool =>
97
elements.expressions.count == 1 /\ elements.expressions[0].awaits_context_type
98
99
set_expected_type(expected_type: Semantic.Types.Type?, expected_type_error_message: string?) is
100
compile_expressions_state.set_expected_type(expected_type, expected_type_error_message)
101
102
if elements.expressions.count == 1 then
103
elements.expressions[0].set_expected_type(expected_type, expected_type_error_message)
104
fi
105
si
106
107
set_expects_pack(depth: int) is
108
super.set_expects_pack(depth)
109
110
if elements.expressions.count == 1 then
111
elements.expressions[0].set_expects_pack(depth)
112
fi
113
si
114
115
rewrite_as_assignment_left() -> AssignmentLeftExpression is
116
if elements.expressions.count == 1 then
117
return SIMPLE_LEFT_EXPRESSION(location, elements.expressions[0])
118
fi
119
120
let result = Collections.LIST[AssignmentLeftExpression](elements.expressions.count)
121
122
for element in elements.expressions do
123
let expression = element.rewrite_as_expression()
124
if element.is_tuple_literal then
125
result.add(expression.rewrite_as_assignment_left())
126
else
127
result.add(SIMPLE_LEFT_EXPRESSION(element.location, expression))
128
fi
129
od
130
131
return DESTRUCTURING_LEFT_EXPRESSION(location, result)
132
si
133
134
replace_element(index: int, value: Expression) is
135
elements.replace_element(index, value)
136
si
137
138
accept(visitor: Visitor) is
139
visitor.visit(self)
140
si
141
142
walk(visitor: Visitor) is
143
if !visitor.pre(self) then
144
elements.walk(visitor)
145
fi
146
147
accept(visitor)
148
si
149
si
150
si