From 4e9c3fb436535269947d8edfa0153a1ef4377075 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 18 Jun 2026 13:42:22 +0200 Subject: [PATCH] unified/swift: add literals, names, and operator expression mappings --- .../extractor/src/languages/swift/swift.rs | 68 ++++++++++ .../extractor/tests/corpus/swift/desugar.txt | 16 ++- .../extractor/tests/corpus/swift/literals.txt | 19 +-- .../tests/corpus/swift/operators.txt | 117 ++++++++++++++++-- 4 files changed, 198 insertions(+), 22 deletions(-) diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index bc2f15ebd49..c9f01a9e7ee 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -15,6 +15,74 @@ fn translation_rules() -> Vec { // Declarations may be wrapped in local/global wrapper nodes. rule!((global_declaration _ @inner) => {inner}), rule!((local_declaration _ @inner) => {inner}), + // ---- Literals ---- + rule!((integer_literal) => (int_literal)), + rule!((hex_literal) => (int_literal)), + rule!((bin_literal) => (int_literal)), + rule!((oct_literal) => (int_literal)), + rule!((real_literal) => (float_literal)), + rule!((boolean_literal) => (boolean_literal)), + rule!("nil" => (builtin_expr)), + rule!((special_literal) => (builtin_expr)), + rule!((line_string_literal) => (string_literal)), + rule!((multi_line_string_literal) => (string_literal)), + rule!((raw_string_literal) => (string_literal)), + rule!((regex_literal) => (regex_literal)), + // ---- Names ---- + rule!((simple_identifier) @id => (name_expr identifier: (identifier #{id}))), + // A referenceable_operator (e.g. `+` used as a value, as in `reduce(0, +)`) + // is treated as a name reference to the operator symbol. + rule!((referenceable_operator) @op => (name_expr identifier: (identifier #{op}))), + // ---- Operators ---- + // All binary operators share the lhs/op/rhs shape. + rule!((additive_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((multiplicative_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((comparison_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((equality_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((conjunction_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((disjunction_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((infix_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + // Range expression `a.. (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + // Open-ended ranges `a...` / `...b` + rule!((open_end_range_expression start: @l) => (unary_expr operator: (postfix_operator "...") operand: {l})), + rule!((open_start_range_expression end: @r) => (unary_expr operator: (prefix_operator "...") operand: {r})), + // Custom operator declaration: `[prefix|infix|postfix] operator OP [: PrecedenceGroup]`. + // The fixity keyword is an anonymous child of `operator_declaration`, so we + // dispatch on it with one rule per keyword. + rule!( + (operator_declaration "prefix" (referenceable_operator _ @op) (simple_identifier)? @prec) + => + (operator_syntax_declaration name: (identifier #{op}) fixity: (fixity "prefix") precedence: {..prec}) + ), + rule!( + (operator_declaration "postfix" (referenceable_operator _ @op) (simple_identifier)? @prec) + => + (operator_syntax_declaration name: (identifier #{op}) fixity: (fixity "postfix") precedence: {..prec}) + ), + rule!( + (operator_declaration "infix" (referenceable_operator _ @op) (simple_identifier)? @prec) + => + (operator_syntax_declaration + name: (identifier #{op}) + fixity: (fixity "infix") + precedence: {..prec}) + ), + rule!((bitwise_operation lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((nil_coalescing_expression value: @l if_nil: @r) => (binary_expr left: {l} operator: (infix_operator "??") right: {r})), + // Leading-dot member shorthand (e.g. `.some`, `.foo`) means member access + // on a contextually inferred type. + rule!((prefix_expression operation: "." target: @member) => (member_access_expr base: (inferred_type_expr) member: (identifier #{member}))), + // Prefix unary operators + rule!((prefix_expression operation: @op target: @operand) => (unary_expr operator: (prefix_operator #{op}) operand: {operand})), + // Postfix unary operators + rule!((postfix_expression operation: @op target: @operand) => (unary_expr operator: (postfix_operator #{op}) operand: {operand})), + // Parenthesised single-value tuple is a grouping expression; pass through. + // Multi-value tuples become tuple_expr. + rule!((tuple_expression value: _* @v) => (tuple_expr element: {..v})), + // Blocks contain statement* directly. + rule!((block statement: _+ @stmts) => (block stmt: {..stmts})), + rule!((block) => (block)), // ---- Fallbacks ---- rule!( (_) diff --git a/unified/extractor/tests/corpus/swift/desugar.txt b/unified/extractor/tests/corpus/swift/desugar.txt index c4c486e995b..abf8a23e9ea 100644 --- a/unified/extractor/tests/corpus/swift/desugar.txt +++ b/unified/extractor/tests/corpus/swift/desugar.txt @@ -18,7 +18,11 @@ source_file top_level body: block - stmt: unsupported_node "1 + 2" + stmt: + binary_expr + operator: infix_operator "+" + left: int_literal "1" + right: int_literal "2" === Another additive expression is desugared @@ -40,4 +44,12 @@ source_file top_level body: block - stmt: unsupported_node "foo + bar" + stmt: + binary_expr + operator: infix_operator "+" + left: + name_expr + identifier: identifier "foo" + right: + name_expr + identifier: identifier "bar" diff --git a/unified/extractor/tests/corpus/swift/literals.txt b/unified/extractor/tests/corpus/swift/literals.txt index 53c60b79796..bf0e4aae560 100644 --- a/unified/extractor/tests/corpus/swift/literals.txt +++ b/unified/extractor/tests/corpus/swift/literals.txt @@ -14,7 +14,7 @@ source_file top_level body: block - stmt: unsupported_node "42" + stmt: int_literal "42" === Negative integer literal @@ -35,7 +35,10 @@ source_file top_level body: block - stmt: unsupported_node "-7" + stmt: + unary_expr + operand: int_literal "7" + operator: prefix_operator "-" === Floating-point literal @@ -53,7 +56,7 @@ source_file top_level body: block - stmt: unsupported_node "3.14" + stmt: float_literal "3.14" === Boolean literals @@ -75,8 +78,8 @@ top_level body: block stmt: - unsupported_node "true" - unsupported_node "false" + boolean_literal "true" + boolean_literal "false" === Nil literal @@ -94,7 +97,7 @@ source_file top_level body: block - stmt: unsupported_node "nil" + stmt: builtin_expr "nil" === String literal @@ -114,7 +117,7 @@ source_file top_level body: block - stmt: unsupported_node "\"hello\"" + stmt: string_literal "\"hello\"" === String with interpolation @@ -137,4 +140,4 @@ source_file top_level body: block - stmt: unsupported_node "\"hello \\(name)\"" + stmt: string_literal "\"hello \\(name)\"" diff --git a/unified/extractor/tests/corpus/swift/operators.txt b/unified/extractor/tests/corpus/swift/operators.txt index 30726ad873f..d912a1085dc 100644 --- a/unified/extractor/tests/corpus/swift/operators.txt +++ b/unified/extractor/tests/corpus/swift/operators.txt @@ -18,7 +18,15 @@ source_file top_level body: block - stmt: unsupported_node "a + b" + stmt: + binary_expr + operator: infix_operator "+" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Subtraction @@ -40,7 +48,15 @@ source_file top_level body: block - stmt: unsupported_node "a - b" + stmt: + binary_expr + operator: infix_operator "-" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Multiplication @@ -62,7 +78,15 @@ source_file top_level body: block - stmt: unsupported_node "a * b" + stmt: + binary_expr + operator: infix_operator "*" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Division @@ -84,7 +108,15 @@ source_file top_level body: block - stmt: unsupported_node "a / b" + stmt: + binary_expr + operator: infix_operator "/" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Operator precedence: addition and multiplication @@ -110,7 +142,21 @@ source_file top_level body: block - stmt: unsupported_node "a + b * c" + stmt: + binary_expr + operator: infix_operator "+" + left: + name_expr + identifier: identifier "a" + right: + binary_expr + operator: infix_operator "*" + left: + name_expr + identifier: identifier "b" + right: + name_expr + identifier: identifier "c" === Parenthesised expression @@ -140,7 +186,13 @@ source_file top_level body: block - stmt: unsupported_node "(a + b) * c" + stmt: + binary_expr + operator: infix_operator "*" + left: tuple_expr "(a + b)" + right: + name_expr + identifier: identifier "c" === Comparison @@ -162,7 +214,15 @@ source_file top_level body: block - stmt: unsupported_node "a < b" + stmt: + binary_expr + operator: infix_operator "<" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Equality @@ -184,7 +244,15 @@ source_file top_level body: block - stmt: unsupported_node "a == b" + stmt: + binary_expr + operator: infix_operator "==" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Logical and @@ -206,7 +274,15 @@ source_file top_level body: block - stmt: unsupported_node "a && b" + stmt: + binary_expr + operator: infix_operator "&&" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Logical or @@ -228,7 +304,15 @@ source_file top_level body: block - stmt: unsupported_node "a || b" + stmt: + binary_expr + operator: infix_operator "||" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Logical not @@ -249,7 +333,12 @@ source_file top_level body: block - stmt: unsupported_node "!a" + stmt: + unary_expr + operand: + name_expr + identifier: identifier "a" + operator: prefix_operator "!" === Range operator @@ -271,4 +360,8 @@ source_file top_level body: block - stmt: unsupported_node "1...10" + stmt: + binary_expr + operator: infix_operator "..." + left: int_literal "1" + right: int_literal "10"