Skip to content

[copy-operator] Add parsing support for copy operator. #1669

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,7 @@ public let EXPR_NODES: [Node] = [
// The move expr
Node(
name: "MoveExpr",
nameForDiagnostics: "'_move' expression",
nameForDiagnostics: "'consume' expression",
kind: "Expr",
children: [
Child(
Expand All @@ -1204,6 +1204,22 @@ public let EXPR_NODES: [Node] = [
]
),

Node(
name: "CopyExpr",
nameForDiagnostics: "'copy' expression",
kind: "Expr",
children: [
Child(
name: "CopyKeyword",
kind: .token(choices: [.keyword(text: "copy")])
),
Child(
name: "Expression",
kind: .node(kind: "Expr")
),
]
),

Node(
name: "MultipleTrailingClosureElementList",
nameForDiagnostics: nil,
Expand Down
1 change: 1 addition & 0 deletions CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public let KEYWORDS: [KeywordSpec] = [
KeywordSpec("class", isLexerClassified: true, requiresTrailingSpace: true),
KeywordSpec("compiler"),
KeywordSpec("consume"),
KeywordSpec("copy"),
KeywordSpec("consuming"),
KeywordSpec("continue", isLexerClassified: true, requiresTrailingSpace: true),
KeywordSpec("convenience"),
Expand Down
55 changes: 43 additions & 12 deletions Sources/SwiftParser/Expressions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ extension Parser {
}
}

switch self.at(anyIn: AwaitTryMove.self) {
EXPR_PREFIX: switch self.at(anyIn: ExpressionModifierKeyword.self) {
case (.awaitKeyword, let handle)?:
let awaitTok = self.eat(handle)
let sub = self.parseSequenceExpressionElement(
Expand Down Expand Up @@ -474,18 +474,48 @@ extension Parser {
)
)

case (.copyKeyword, let handle)?:
// `copy` is only contextually a keyword, if it's followed by an
// identifier or keyword on the same line. We do this to ensure that we do
// not break any copy functions defined by users. This is following with
// what we have done for the consume keyword.
switch self.peek() {
case TokenSpec(.identifier, allowAtStartOfLine: false),
TokenSpec(.dollarIdentifier, allowAtStartOfLine: false),
TokenSpec(.self, allowAtStartOfLine: false):
break
default:
// Break out of `outer switch` on failure.
break EXPR_PREFIX
}

let copyTok = self.eat(handle)
let sub = self.parseSequenceExpressionElement(
flavor,
forDirective: forDirective,
pattern: pattern
)
return RawExprSyntax(
RawCopyExprSyntax(
copyKeyword: copyTok,
expression: sub,
arena: self.arena
)
)

case (.consumeKeyword, let handle)?:
// `consume` is only contextually a keyword, if it's followed by an
// identifier or keyword on the same line.
let next = peek()
if next.isAtStartOfLine {
fallthrough
}
if next.rawTokenKind != .identifier,
next.rawTokenKind != .dollarIdentifier,
next.rawTokenKind != .keyword
{
fallthrough
// identifier or keyword on the same line. We do this to ensure that we do
// not break any copy functions defined by users. This is following with
// what we have done for the consume keyword.
switch self.peek() {
case TokenSpec(.identifier, allowAtStartOfLine: false),
TokenSpec(.dollarIdentifier, allowAtStartOfLine: false),
TokenSpec(.self, allowAtStartOfLine: false):
break
default:
// Break out of the outer `switch`.
break EXPR_PREFIX
}

let consumeTok = self.eat(handle)
Expand All @@ -502,8 +532,9 @@ extension Parser {
)
)
case nil:
return self.parseUnaryExpression(flavor, forDirective: forDirective, pattern: pattern)
break
}
return self.parseUnaryExpression(flavor, forDirective: forDirective, pattern: pattern)
}

/// Parse an optional prefix operator followed by an expression.
Expand Down
11 changes: 7 additions & 4 deletions Sources/SwiftParser/TokenSpecSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -476,12 +476,13 @@ public enum TypeSpecifier: TokenSpecSet {

// MARK: Expression start

enum AwaitTryMove: TokenSpecSet {
enum ExpressionModifierKeyword: TokenSpecSet {
case awaitKeyword
case _moveKeyword
case _borrowKeyword
case tryKeyword
case consumeKeyword
case copyKeyword

init?(lexeme: Lexer.Lexeme) {
switch PrepareForKeywordMatch(lexeme) {
Expand All @@ -490,6 +491,7 @@ enum AwaitTryMove: TokenSpecSet {
case TokenSpec(._borrow): self = ._borrowKeyword
case TokenSpec(.try): self = .tryKeyword
case TokenSpec(.consume): self = .consumeKeyword
case TokenSpec(.copy): self = .copyKeyword
default: return nil
}
}
Expand All @@ -500,6 +502,7 @@ enum AwaitTryMove: TokenSpecSet {
case ._moveKeyword: return .keyword(._move)
case ._borrowKeyword: return .keyword(._borrow)
case .consumeKeyword: return .keyword(.consume)
case .copyKeyword: return .keyword(.copy)
case .tryKeyword: return .keyword(.try)
}
}
Expand Down Expand Up @@ -695,13 +698,13 @@ enum PrimaryExpressionStart: TokenSpecSet {
/// - `MatchingPatternStart`
/// - `PrimaryExpressionStart`
enum ExpressionStart: TokenSpecSet {
case awaitTryMove(AwaitTryMove)
case awaitTryMove(ExpressionModifierKeyword)
case expressionPrefixOperator(ExpressionPrefixOperator)
case primaryExpressionStart(PrimaryExpressionStart)
case ifOrSwitch(IfOrSwitch)

init?(lexeme: Lexer.Lexeme) {
if let subset = AwaitTryMove(lexeme: lexeme) {
if let subset = ExpressionModifierKeyword(lexeme: lexeme) {
self = .awaitTryMove(subset)
} else if let subset = ExpressionPrefixOperator(lexeme: lexeme) {
self = .expressionPrefixOperator(subset)
Expand All @@ -715,7 +718,7 @@ enum ExpressionStart: TokenSpecSet {
}

static var allCases: [ExpressionStart] {
return AwaitTryMove.allCases.map(Self.awaitTryMove)
return ExpressionModifierKeyword.allCases.map(Self.awaitTryMove)
+ ExpressionPrefixOperator.allCases.map(Self.expressionPrefixOperator)
+ PrimaryExpressionStart.allCases.map(Self.primaryExpressionStart)
+ IfOrSwitch.allCases.map(Self.ifOrSwitch)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ extension SyntaxKind {
return "@convention(...) arguments"
case .conventionWitnessMethodAttributeArguments:
return "@convention(...) arguments for witness methods"
case .copyExpr:
return "'copy' expression"
case .declModifier:
return "modifier"
case .declName:
Expand Down Expand Up @@ -272,7 +274,7 @@ extension SyntaxKind {
case .missingType:
return "type"
case .moveExpr:
return "'_move' expression"
return "'consume' expression"
case .multipleTrailingClosureElement:
return "trailing closure"
case .namedOpaqueReturnType:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
- <doc:SwiftSyntax/CanImportExprSyntax>
- <doc:SwiftSyntax/CanImportVersionInfoSyntax>
- <doc:SwiftSyntax/ClosureExprSyntax>
- <doc:SwiftSyntax/CopyExprSyntax>
- <doc:SwiftSyntax/DictionaryExprSyntax>
- <doc:SwiftSyntax/DiscardAssignmentExprSyntax>
- <doc:SwiftSyntax/EditorPlaceholderExprSyntax>
Expand Down
10 changes: 10 additions & 0 deletions Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? {
return "protocolName"
case \ConventionWitnessMethodAttributeArgumentsSyntax.unexpectedAfterProtocolName:
return "unexpectedAfterProtocolName"
case \CopyExprSyntax.unexpectedBeforeCopyKeyword:
return "unexpectedBeforeCopyKeyword"
case \CopyExprSyntax.copyKeyword:
return "copyKeyword"
case \CopyExprSyntax.unexpectedBetweenCopyKeywordAndExpression:
return "unexpectedBetweenCopyKeywordAndExpression"
case \CopyExprSyntax.expression:
return "expression"
case \CopyExprSyntax.unexpectedAfterExpression:
return "unexpectedAfterExpression"
case \DeclModifierDetailSyntax.unexpectedBeforeLeftParen:
return "unexpectedBeforeLeftParen"
case \DeclModifierDetailSyntax.leftParen:
Expand Down
4 changes: 4 additions & 0 deletions Sources/SwiftSyntax/generated/Keyword.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public enum Keyword: UInt8, Hashable {
case `class`
case compiler
case consume
case copy
case consuming
case `continue`
case convenience
Expand Down Expand Up @@ -268,6 +269,8 @@ public enum Keyword: UInt8, Hashable {
self = ._spi
case "case":
self = .`case`
case "copy":
self = .copy
case "each":
self = .each
case "else":
Expand Down Expand Up @@ -826,6 +829,7 @@ public enum Keyword: UInt8, Hashable {
"class",
"compiler",
"consume",
"copy",
"consuming",
"continue",
"convenience",
Expand Down
8 changes: 8 additions & 0 deletions Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,14 @@ open class SyntaxAnyVisitor: SyntaxVisitor {
visitAnyPost(node._syntaxNode)
}

override open func visit(_ node: CopyExprSyntax) -> SyntaxVisitorContinueKind {
return visitAny(node._syntaxNode)
}

override open func visitPost(_ node: CopyExprSyntax) {
visitAnyPost(node._syntaxNode)
}

override open func visit(_ node: DeclModifierDetailSyntax) -> SyntaxVisitorContinueKind {
return visitAny(node._syntaxNode)
}
Expand Down
6 changes: 4 additions & 2 deletions Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {

public init?(_ node: some SyntaxProtocol) {
switch node.raw.kind {
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, .canImportExpr, .canImportVersionInfo, .closureExpr, .dictionaryExpr, .discardAssignmentExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forcedValueExpr, .functionCallExpr, .identifierExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .moveExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .postfixIfConfigExpr, .postfixUnaryExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .specializeExpr, .stringLiteralExpr, .subscriptExpr, .superRefExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedPatternExpr, .unresolvedTernaryExpr:
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, .canImportExpr, .canImportVersionInfo, .closureExpr, .copyExpr, .dictionaryExpr, .discardAssignmentExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forcedValueExpr, .functionCallExpr, .identifierExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .moveExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .postfixIfConfigExpr, .postfixUnaryExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .specializeExpr, .stringLiteralExpr, .subscriptExpr, .superRefExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedPatternExpr, .unresolvedTernaryExpr:
self._syntaxNode = node._syntaxNode
default:
return nil
Expand All @@ -218,7 +218,7 @@ public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
/// is undefined.
internal init(_ data: SyntaxData) {
switch data.raw.kind {
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, .canImportExpr, .canImportVersionInfo, .closureExpr, .dictionaryExpr, .discardAssignmentExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forcedValueExpr, .functionCallExpr, .identifierExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .moveExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .postfixIfConfigExpr, .postfixUnaryExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .specializeExpr, .stringLiteralExpr, .subscriptExpr, .superRefExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedPatternExpr, .unresolvedTernaryExpr:
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, .canImportExpr, .canImportVersionInfo, .closureExpr, .copyExpr, .dictionaryExpr, .discardAssignmentExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forcedValueExpr, .functionCallExpr, .identifierExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .moveExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .postfixIfConfigExpr, .postfixUnaryExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .specializeExpr, .stringLiteralExpr, .subscriptExpr, .superRefExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedPatternExpr, .unresolvedTernaryExpr:
break
default:
preconditionFailure("Unable to create ExprSyntax from \(data.raw.kind)")
Expand Down Expand Up @@ -265,6 +265,7 @@ public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
.node(CanImportExprSyntax.self),
.node(CanImportVersionInfoSyntax.self),
.node(ClosureExprSyntax.self),
.node(CopyExprSyntax.self),
.node(DictionaryExprSyntax.self),
.node(DiscardAssignmentExprSyntax.self),
.node(EditorPlaceholderExprSyntax.self),
Expand Down Expand Up @@ -751,6 +752,7 @@ extension Syntax {
.node(ContinueStmtSyntax.self),
.node(ConventionAttributeArgumentsSyntax.self),
.node(ConventionWitnessMethodAttributeArgumentsSyntax.self),
.node(CopyExprSyntax.self),
.node(DeclModifierDetailSyntax.self),
.node(DeclModifierSyntax.self),
.node(DeclNameArgumentListSyntax.self),
Expand Down
3 changes: 3 additions & 0 deletions Sources/SwiftSyntax/generated/SyntaxEnum.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public enum SyntaxEnum {
case continueStmt(ContinueStmtSyntax)
case conventionAttributeArguments(ConventionAttributeArgumentsSyntax)
case conventionWitnessMethodAttributeArguments(ConventionWitnessMethodAttributeArgumentsSyntax)
case copyExpr(CopyExprSyntax)
case declModifierDetail(DeclModifierDetailSyntax)
case declModifier(DeclModifierSyntax)
case declNameArgumentList(DeclNameArgumentListSyntax)
Expand Down Expand Up @@ -426,6 +427,8 @@ public extension Syntax {
return .conventionAttributeArguments(ConventionAttributeArgumentsSyntax(self)!)
case .conventionWitnessMethodAttributeArguments:
return .conventionWitnessMethodAttributeArguments(ConventionWitnessMethodAttributeArgumentsSyntax(self)!)
case .copyExpr:
return .copyExpr(CopyExprSyntax(self)!)
case .declModifierDetail:
return .declModifierDetail(DeclModifierDetailSyntax(self)!)
case .declModifier:
Expand Down
3 changes: 3 additions & 0 deletions Sources/SwiftSyntax/generated/SyntaxKind.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public enum SyntaxKind {
case continueStmt
case conventionAttributeArguments
case conventionWitnessMethodAttributeArguments
case copyExpr
case declModifierDetail
case declModifier
case declNameArgumentList
Expand Down Expand Up @@ -543,6 +544,8 @@ public enum SyntaxKind {
return ConventionAttributeArgumentsSyntax.self
case .conventionWitnessMethodAttributeArguments:
return ConventionWitnessMethodAttributeArgumentsSyntax.self
case .copyExpr:
return CopyExprSyntax.self
case .declModifierDetail:
return DeclModifierDetailSyntax.self
case .declModifier:
Expand Down
25 changes: 25 additions & 0 deletions Sources/SwiftSyntax/generated/SyntaxRewriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,13 @@ open class SyntaxRewriter {
return Syntax(visitChildren(node)).cast(ConventionWitnessMethodAttributeArgumentsSyntax.self)
}

/// Visit a `CopyExprSyntax`.
/// - Parameter node: the node that is being visited
/// - Returns: the rewritten node
open func visit(_ node: CopyExprSyntax) -> ExprSyntax {
return ExprSyntax(visitChildren(node))
}

/// Visit a `DeclModifierDetailSyntax`.
/// - Parameter node: the node that is being visited
/// - Returns: the rewritten node
Expand Down Expand Up @@ -2920,6 +2927,20 @@ open class SyntaxRewriter {
return Syntax(visit(node))
}

/// Implementation detail of visit(_:). Do not call directly.
private func visitImplCopyExprSyntax(_ data: SyntaxData) -> Syntax {
let node = CopyExprSyntax(data)
// Accessing _syntaxNode directly is faster than calling Syntax(node)
visitPre(node._syntaxNode)
defer {
visitPost(node._syntaxNode)
}
if let newNode = visitAny(node._syntaxNode) {
return newNode
}
return Syntax(visit(node))
}

/// Implementation detail of visit(_:). Do not call directly.
private func visitImplDeclModifierDetailSyntax(_ data: SyntaxData) -> Syntax {
let node = DeclModifierDetailSyntax(data)
Expand Down Expand Up @@ -6004,6 +6025,8 @@ open class SyntaxRewriter {
return visitImplConventionAttributeArgumentsSyntax
case .conventionWitnessMethodAttributeArguments:
return visitImplConventionWitnessMethodAttributeArgumentsSyntax
case .copyExpr:
return visitImplCopyExprSyntax
case .declModifierDetail:
return visitImplDeclModifierDetailSyntax
case .declModifier:
Expand Down Expand Up @@ -6560,6 +6583,8 @@ open class SyntaxRewriter {
return visitImplConventionAttributeArgumentsSyntax(data)
case .conventionWitnessMethodAttributeArguments:
return visitImplConventionWitnessMethodAttributeArgumentsSyntax(data)
case .copyExpr:
return visitImplCopyExprSyntax(data)
case .declModifierDetail:
return visitImplDeclModifierDetailSyntax(data)
case .declModifier:
Expand Down
Loading