Skip to content

Commit

Permalink
Enable borrowingSwitch syntax.
Browse files Browse the repository at this point in the history
  • Loading branch information
jckarter committed Apr 11, 2024
1 parent d722cfc commit aee7a84
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public enum ExperimentalFeature: String, CaseIterable {
case doExpressions
case nonescapableTypes
case transferringArgsAndResults
case borrowingSwitch

/// The name of the feature, which is used in the doc comment.
public var featureName: String {
Expand All @@ -33,8 +32,6 @@ public enum ExperimentalFeature: String, CaseIterable {
return "NonEscableTypes"
case .transferringArgsAndResults:
return "TransferringArgsAndResults"
case .borrowingSwitch:
return "borrowing pattern matching"
}
}

Expand Down
23 changes: 1 addition & 22 deletions CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public struct KeywordSpec {
/// The experimental feature the keyword is part of, or `nil` if this isn't
/// for an experimental feature.
public let experimentalFeature: ExperimentalFeature?
public let experimentalFeature2: ExperimentalFeature?

/// Indicates if the token kind is switched from being an identifier to a keyword in the lexer.
public let isLexerClassified: Bool
Expand Down Expand Up @@ -69,26 +68,6 @@ public struct KeywordSpec {
) {
self.name = name
self.experimentalFeature = experimentalFeature
self.experimentalFeature2 = nil
self.isLexerClassified = isLexerClassified
}

/// Initializes a new `KeywordSpec` instance.
///
/// - Parameters:
/// - name: A name of the keyword.
/// - experimentalFeature: The experimental feature the keyword is part of, or `nil` if this isn't for an experimental feature.
/// - or: A second experimental feature the keyword is also part of, or `nil` if this isn't for an experimental feature.
/// - isLexerClassified: Indicates if the token kind is switched from being an identifier to a keyword in the lexer.
init(
_ name: String,
experimentalFeature: ExperimentalFeature,
or experimentalFeature2: ExperimentalFeature,
isLexerClassified: Bool = false
) {
self.name = name
self.experimentalFeature = experimentalFeature
self.experimentalFeature2 = experimentalFeature2
self.isLexerClassified = isLexerClassified
}
}
Expand Down Expand Up @@ -340,7 +319,7 @@ public enum Keyword: CaseIterable {
case ._borrow:
return KeywordSpec("_borrow")
case ._borrowing:
return KeywordSpec("_borrowing", experimentalFeature: .referenceBindings, or: .borrowingSwitch)
return KeywordSpec("_borrowing", experimentalFeature: .referenceBindings)
case ._BridgeObject:
return KeywordSpec("_BridgeObject")
case ._cdecl:
Expand Down
1 change: 1 addition & 0 deletions CodeGeneration/Sources/SyntaxSupport/PatternNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ public let PATTERN_NODES: [Node] = [
kind: .token(choices: [
.keyword(.let), .keyword(.var), .keyword(.inout),
.keyword(._mutating), .keyword(._borrowing), .keyword(._consuming),
.keyword(.borrowing),
])
),
Child(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,11 @@ import Utils

func tokenCaseMatch(
_ caseName: TokenSyntax,
experimentalFeature: ExperimentalFeature?,
experimentalFeature2: ExperimentalFeature?
experimentalFeature: ExperimentalFeature?
) -> SwitchCaseSyntax {
var whereClause = ""
if let feature = experimentalFeature {
whereClause += "where experimentalFeatures.contains(.\(feature.token))"
if let feature2 = experimentalFeature2 {
whereClause += " || experimentalFeatures.contains(.\(feature2.token))"
}
}
return "case TokenSpec(.\(caseName))\(raw: whereClause): self = .\(caseName)"
}
Expand Down Expand Up @@ -74,14 +70,12 @@ let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
case .keyword(let keyword):
tokenCaseMatch(
keyword.spec.varOrCaseName,
experimentalFeature: keyword.spec.experimentalFeature,
experimentalFeature2: keyword.spec.experimentalFeature2
experimentalFeature: keyword.spec.experimentalFeature
)
case .token(let token):
tokenCaseMatch(
token.spec.varOrCaseName,
experimentalFeature: token.spec.experimentalFeature,
experimentalFeature2: nil
experimentalFeature: token.spec.experimentalFeature
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftParser/Patterns.swift
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ extension Parser.Lookahead {
// TODO: the other ownership modifiers (borrowing/consuming/mutating) more
// than likely need to be made contextual as well before finalizing their
// grammar.
case ._borrowing where experimentalFeatures.contains(.borrowingSwitch):
case ._borrowing, .borrowing:
return peek(isAt: TokenSpec(.identifier, allowAtStartOfLine: false))
default:
// Other keywords can be parsed unconditionally.
Expand Down
3 changes: 0 additions & 3 deletions Sources/SwiftParser/generated/ExperimentalFeatures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,4 @@ extension Parser.ExperimentalFeatures {

/// Whether to enable the parsing of TransferringArgsAndResults.
public static let transferringArgsAndResults = Self (rawValue: 1 << 4)

/// Whether to enable the parsing of borrowing pattern matching.
public static let borrowingSwitch = Self (rawValue: 1 << 5)
}
15 changes: 12 additions & 3 deletions Sources/SwiftParser/generated/Parser+TokenSpecSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2934,7 +2934,7 @@ extension OptionalBindingConditionSyntax {
self = .inout
case TokenSpec(._mutating) where experimentalFeatures.contains(.referenceBindings):
self = ._mutating
case TokenSpec(._borrowing) where experimentalFeatures.contains(.referenceBindings) || experimentalFeatures.contains(.borrowingSwitch):
case TokenSpec(._borrowing) where experimentalFeatures.contains(.referenceBindings):
self = ._borrowing
case TokenSpec(._consuming) where experimentalFeatures.contains(.referenceBindings):
self = ._consuming
Expand Down Expand Up @@ -3905,6 +3905,7 @@ extension ValueBindingPatternSyntax {
@_spi(ExperimentalLanguageFeatures)
#endif
case _consuming
case borrowing

init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) {
switch PrepareForKeywordMatch(lexeme) {
Expand All @@ -3916,10 +3917,12 @@ extension ValueBindingPatternSyntax {
self = .inout
case TokenSpec(._mutating) where experimentalFeatures.contains(.referenceBindings):
self = ._mutating
case TokenSpec(._borrowing) where experimentalFeatures.contains(.referenceBindings) || experimentalFeatures.contains(.borrowingSwitch):
case TokenSpec(._borrowing) where experimentalFeatures.contains(.referenceBindings):
self = ._borrowing
case TokenSpec(._consuming) where experimentalFeatures.contains(.referenceBindings):
self = ._consuming
case TokenSpec(.borrowing):
self = .borrowing
default:
return nil
}
Expand All @@ -3939,6 +3942,8 @@ extension ValueBindingPatternSyntax {
self = ._borrowing
case TokenSpec(._consuming):
self = ._consuming
case TokenSpec(.borrowing):
self = .borrowing
default:
return nil
}
Expand All @@ -3958,6 +3963,8 @@ extension ValueBindingPatternSyntax {
return .keyword(._borrowing)
case ._consuming:
return .keyword(._consuming)
case .borrowing:
return .keyword(.borrowing)
}
}

Expand All @@ -3979,6 +3986,8 @@ extension ValueBindingPatternSyntax {
return .keyword(._borrowing)
case ._consuming:
return .keyword(._consuming)
case .borrowing:
return .keyword(.borrowing)
}
}
}
Expand Down Expand Up @@ -4013,7 +4022,7 @@ extension VariableDeclSyntax {
self = .inout
case TokenSpec(._mutating) where experimentalFeatures.contains(.referenceBindings):
self = ._mutating
case TokenSpec(._borrowing) where experimentalFeatures.contains(.referenceBindings) || experimentalFeatures.contains(.borrowingSwitch):
case TokenSpec(._borrowing) where experimentalFeatures.contains(.referenceBindings):
self = ._borrowing
case TokenSpec(._consuming) where experimentalFeatures.contains(.referenceBindings):
self = ._consuming
Expand Down
3 changes: 2 additions & 1 deletion Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2706,7 +2706,8 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) {
.keyword("inout"),
.keyword("_mutating"),
.keyword("_borrowing"),
.keyword("_consuming")
.keyword("_consuming"),
.keyword("borrowing")
]))
assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self))
assertNoError(kind, 3, verify(layout[3], as: RawPatternSyntax.self))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3256,7 +3256,7 @@ public struct UnresolvedTernaryExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _

/// ### Children
///
/// - `bindingSpecifier`: (`let` | `var` | `inout` | `_mutating` | `_borrowing` | `_consuming`)
/// - `bindingSpecifier`: (`let` | `var` | `inout` | `_mutating` | `_borrowing` | `_consuming` | `borrowing`)
/// - `pattern`: ``PatternSyntax``
public struct ValueBindingPatternSyntax: PatternSyntaxProtocol, SyntaxHashable, _LeafPatternSyntaxNodeProtocol {
public let _syntaxNode: Syntax
Expand Down Expand Up @@ -3327,6 +3327,7 @@ public struct ValueBindingPatternSyntax: PatternSyntaxProtocol, SyntaxHashable,
/// - `_mutating`
/// - `_borrowing`
/// - `_consuming`
/// - `borrowing`
public var bindingSpecifier: TokenSyntax {
get {
return Syntax(self).child(at: 1)!.cast(TokenSyntax.self)
Expand Down
55 changes: 23 additions & 32 deletions Tests/SwiftParserTest/translated/MatchingPatternsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -612,126 +612,117 @@ final class MatchingPatternsTests: ParserTestCase {
assertParse(
"""
switch 42 {
case _borrowing .foo(): // parses as `_borrowing.foo()` as before
case borrowing .foo(): // parses as `borrowing.foo()` as before
break
}
""",
substructure: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_borrowing"))),
experimentalFeatures: .borrowingSwitch
substructure: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("borrowing")))
)

assertParse(
"""
switch 42 {
case _borrowing (): // parses as `_borrowing()` as before
case borrowing (): // parses as `borrowing()` as before
break
}
""",
substructure: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_borrowing"))),
experimentalFeatures: .borrowingSwitch
substructure: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("borrowing")))
)

assertParse(
"""
switch 42 {
case _borrowing x: // parses as binding
case borrowing x: // parses as binding
break
}
""",
substructure: PatternSyntax(
ValueBindingPatternSyntax(
bindingSpecifier: .keyword(._borrowing),
bindingSpecifier: .keyword(.borrowing),
pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier("x")))
)
),
experimentalFeatures: .borrowingSwitch
)
)

assertParse(
"""
switch bar {
case .payload(_borrowing x): // parses as binding
case .payload(borrowing x): // parses as binding
break
}
""",
substructure: PatternSyntax(
ValueBindingPatternSyntax(
bindingSpecifier: .keyword(._borrowing),
bindingSpecifier: .keyword(.borrowing),
pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier("x")))
)
),
experimentalFeatures: .borrowingSwitch
)
)

assertParse(
"""
switch bar {
case _borrowing x.member: // parses as var introducer surrounding postfix expression (which never is valid)
case borrowing x.member: // parses as var introducer surrounding postfix expression (which never is valid)
break
}
""",
substructure: PatternSyntax(
ValueBindingPatternSyntax(
bindingSpecifier: .keyword(._borrowing),
bindingSpecifier: .keyword(.borrowing),
pattern: ExpressionPatternSyntax(
expression: MemberAccessExprSyntax(
base: DeclReferenceExprSyntax(baseName: .identifier("x")),
declName: DeclReferenceExprSyntax(baseName: .identifier("member"))
)
)
)
),
experimentalFeatures: .borrowingSwitch
)
)
assertParse(
"""
switch 42 {
case let _borrowing: // parses as let binding named '_borrowing'
case let borrowing: // parses as let binding named 'borrowing'
break
}
""",
substructure: PatternSyntax(
ValueBindingPatternSyntax(
bindingSpecifier: .keyword(.let),
pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier("_borrowing")))
pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier("borrowing")))
)
),
experimentalFeatures: .borrowingSwitch
)
)
assertParse(
"""
switch 42 {
case _borrowing + _borrowing: // parses as expr pattern
case borrowing + borrowing: // parses as expr pattern
break
}
""",
substructure: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_borrowing"))),
experimentalFeatures: .borrowingSwitch
substructure: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("borrowing")))
)
assertParse(
"""
switch 42 {
case _borrowing(let _borrowing): // parses as let binding named '_borrowing' inside a case pattern named 'borrowing'
case borrowing(let borrowing): // parses as let binding named 'borrowing' inside a case pattern named 'borrowing'
break
}
""",
substructure: PatternSyntax(
ValueBindingPatternSyntax(
bindingSpecifier: .keyword(.let),
pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier("_borrowing")))
pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier("borrowing")))
)
),
experimentalFeatures: .borrowingSwitch
)
)
assertParse(
"""
switch 42 {
case {}(_borrowing + _borrowing): // parses as expr pattern
case {}(borrowing + borrowing): // parses as expr pattern
break
}
""",
substructure: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_borrowing"))),
experimentalFeatures: .borrowingSwitch
substructure: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("borrowing")))
)
}
}

0 comments on commit aee7a84

Please sign in to comment.