Appearance
| 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 |