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.
15
is_tuple_literal: bool => elements.expressions.count != 1;
16
17
elements: LIST;
18
19
// Type ascription written after the closing paren, as in
20
// `((a, b): (int, int)) => …`. Only ever parsed in a position
21
// that could turn out to be a lambda parameter list, where it
22
// declares the type of the one physical argument the pattern
23
// unpacks. Null everywhere else; if the surrounding syntax
24
// turns out not to be a lambda, `rewrite_as_expression`
25
// reports it rather than dropping it.
26
type_expression: TypeExpressions.TypeExpression? public;
27
28
could_be_formal_argument: bool => true;
29
30
set_type_expression(type_expression: TypeExpressions.TypeExpression) is
31
self.type_expression = type_expression;
32
si
33
34
try_copy_as_variable_left() -> Variables.VariableLeft? is
35
let elements_left = Collections.LIST[Variables.VariableLeft]();
36
37
for e in elements.expressions do
38
let element_left = e.try_copy_as_variable_left();
39
40
if !element_left? then
41
return null;
42
fi
43
44
elements_left.add(element_left);
45
od
46
47
return Variables.DESTRUCTURING_VARIABLE_LEFT(location, elements_left);
48
si
49
50
// A lambda parameter written as a parenthesised group is a
51
// destructure pattern over one physical argument. The group's
52
// own name is synthesised - declare-members renames it to a
53
// unique slot, the same way it renames a `_` discard - since
54
// the source only names the leaves.
55
try_copy_as_variable() -> VARIABLE? is
56
let left = try_copy_as_variable_left();
57
58
if !left? then
59
return null;
60
fi
61
62
let result =
63
VARIABLE(
64
location,
65
Identifiers.Identifier(location, "$destructured_argument"),
66
type_expression ?? TypeExpressions.INFER(location),
67
null
68
);
69
70
result.set_left(left);
71
72
return result;
73
si
74
75
init(location: LOCATION, elements: LIST, is_function_arguments: bool) is
76
super.init(location);
77
78
self.elements = elements;
79
self.is_function_arguments = is_function_arguments;
80
si
81
82
set_expected_type(expected_type: Semantic.Types.Type?, expected_type_error_message: string?) is
83
compile_expressions_state.set_expected_type(expected_type, expected_type_error_message);
84
si
85
86
rewrite_as_assignment_left() -> AssignmentLeftExpression is
87
if elements.expressions.count == 1 then
88
return SIMPLE_LEFT_EXPRESSION(location, elements.expressions[0]);
89
fi
90
91
let result = Collections.LIST[AssignmentLeftExpression](elements.expressions.count);
92
93
for element in elements.expressions do
94
let expression = element.rewrite_as_expression();
95
if element.is_tuple_literal then
96
result.add(expression.rewrite_as_assignment_left());
97
else
98
result.add(SIMPLE_LEFT_EXPRESSION(element.location, expression));
99
fi
100
od
101
102
return DESTRUCTURING_LEFT_EXPRESSION(location, result);
103
si
104
105
replace_element(index: int, value: Expression) is
106
elements.replace_element(index, value);
107
si
108
109
accept(visitor: Visitor) is
110
visitor.visit(self);
111
si
112
113
walk(visitor: Visitor) is
114
if !visitor.pre(self) then
115
elements.walk(visitor);
116
fi
117
118
accept(visitor);
119
si
120
si
121
si