unified: Emit structured generic type arguments

Map a generic type applied with explicit arguments (`Set<Int>`,
`Dictionary<String, Array<Int>>`) to a `generic_type_expr` whose `base`
is the type name and whose `type_argument`s are the structured,
recursively-mapped arguments — the same shape the sugared `?`/`[]`/`[:]`
types already desugar to.

Previously the whole application was kept opaquely as a
`named_type_expr` whose name was the raw source text, matching the
tree-sitter path for corpus parity.

Adds a focused `generic-type-arguments` corpus case (multiple and nested
arguments) and updates `set-literal` to witness the structured
arguments.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Taus
2026-07-23 13:09:51 +00:00
parent 3f56bc7d5e
commit 08024d8f4a
4 changed files with 102 additions and 8 deletions

View File

@@ -944,14 +944,19 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
// an ordinary `declReferenceExpr`, already mapped to a `name_expr`.)
rule!((superExpr) => (super_expr)),
// Type expressions. A generic type applied with explicit arguments
// (`Set<Int>`) is represented opaquely, using the whole source text as
// the name (PARITY(tree-sitter): the generic arguments are not
// structured `type_argument`s). Matched before the plain `identifierType`
// rule, which would otherwise drop the arguments.
// (`Set<Int>`) becomes a `generic_type_expr` whose `base` is the type
// name and whose `type_argument`s are the (structured) arguments — the
// same shape the sugared `?`/`[]`/`[:]` types desugar to. Matched before
// the plain `identifierType` rule, which would otherwise drop the
// arguments.
rule!(
(identifierType genericArgumentClause: (genericArgumentClause)) @@ty
(identifierType
name: @@name
genericArgumentClause: (genericArgumentClause arguments: (genericArgument argument: @args)*))
=>
(named_type_expr name: (identifier #{ty}))
(generic_type_expr
base: (named_type_expr name: (identifier #{name}))
type_argument: {args})
),
// A named type (`Int`). `identifierType.name` is the type-name token.
rule!((identifierType name: @@n) => (named_type_expr name: (identifier #{n}))),

View File

@@ -66,8 +66,13 @@ top_level
name_pattern
identifier: identifier "s"
type:
named_type_expr
name: identifier "Set<Int>"
generic_type_expr
base:
named_type_expr
name: identifier "Set"
type_argument:
named_type_expr
name: identifier "Int"
value:
array_literal
element:

View File

@@ -0,0 +1,83 @@
let cache: Dictionary<String, Array<Int>> = [:]
---
sourceFile
endOfFileToken: endOfFile
statements:
codeBlockItem
item:
variableDecl
attributes:
modifiers:
bindingSpecifier: let
bindings:
patternBinding
initializer:
initializerClause
equal: =
value:
dictionaryExpr
leftSquare: [
rightSquare: ]
content: :
pattern:
identifierPattern
identifier: identifier "cache"
typeAnnotation:
typeAnnotation
colon: :
type:
identifierType
name: identifier "Dictionary"
genericArgumentClause:
genericArgumentClause
arguments:
genericArgument
trailingComma: ,
argument:
identifierType
name: identifier "String"
genericArgument
argument:
identifierType
name: identifier "Array"
genericArgumentClause:
genericArgumentClause
arguments:
genericArgument
argument:
identifierType
name: identifier "Int"
leftAngle: <
rightAngle: >
leftAngle: <
rightAngle: >
---
top_level
body:
block
stmt:
variable_declaration
modifier: modifier "let"
pattern:
name_pattern
identifier: identifier "cache"
type:
generic_type_expr
base:
named_type_expr
name: identifier "Dictionary"
type_argument:
named_type_expr
name: identifier "String"
generic_type_expr
base:
named_type_expr
name: identifier "Array"
type_argument:
named_type_expr
name: identifier "Int"
value: map_literal "[:]"

View File

@@ -0,0 +1 @@
let cache: Dictionary<String, Array<Int>> = [:]