Skip to content

Commit c9ba70f

Browse files
committed
implement parsing of forget statement
Currently staged in as `_forget` until we're ready to greenlight it. The parsing uses one-token lookahead to disambiguate when someone writes `forget(self)` to mean a function call, from `forget self` to mean the actual forget statement. More tests will be in the swift compiler repository.
1 parent 1b8d5e9 commit c9ba70f

File tree

20 files changed

+439
-5
lines changed

20 files changed

+439
-5
lines changed

CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ public let KEYWORDS: [KeywordSpec] = [
133133
KeywordSpec("fileprivate", isLexerClassified: true, requiresTrailingSpace: true),
134134
KeywordSpec("final"),
135135
KeywordSpec("for", isLexerClassified: true, requiresTrailingSpace: true),
136+
KeywordSpec("_forget"),
136137
KeywordSpec("forward"),
137138
KeywordSpec("func", isLexerClassified: true, requiresTrailingSpace: true),
138139
KeywordSpec("get"),

CodeGeneration/Sources/SyntaxSupport/StmtNodes.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# -*- mode: Swift -*-
55
# Ignore the following admonition it applies to the resulting .swift file only
66
}%
7-
//// Automatically Generated From GenericNodes.swift.gyb.
7+
//// Automatically Generated From StmtNodes.swift.gyb.
88
//// Do Not Edit Directly!
99
//===----------------------------------------------------------------------===//
1010
//

CodeGeneration/Sources/SyntaxSupport/gyb_generated/StmtNodes.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//// Automatically Generated From GenericNodes.swift.gyb.
1+
//// Automatically Generated From StmtNodes.swift.gyb.
22
//// Do Not Edit Directly!
33
//===----------------------------------------------------------------------===//
44
//
@@ -211,6 +211,16 @@ public let STMT_NODES: [Node] = [
211211
nameForDiagnostics: "body")
212212
]),
213213

214+
Node(name: "ForgetStmt",
215+
nameForDiagnostics: "'forget' statement",
216+
kind: "Stmt",
217+
children: [
218+
Child(name: "ForgetKeyword",
219+
kind: .token(choices: [.keyword(text: "_forget")])),
220+
Child(name: "Expression",
221+
kind: .node(kind: "Expr"))
222+
]),
223+
214224
Node(name: "GuardStmt",
215225
nameForDiagnostics: "'guard' statement",
216226
kind: "Stmt",

Sources/SwiftParser/Statements.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ extension Parser {
5555
/// statement → control-transfer-statement ';'?
5656
/// statement → defer-statement ';'?
5757
/// statement → do-statement ';'?
58+
/// statement → forget-statement ';'?
5859
///
5960
/// loop-statement → for-in-statement
6061
/// loop-statement → while-statement
@@ -123,6 +124,8 @@ extension Parser {
123124
return label(self.parseContinueStatement(continueHandle: handle), with: optLabel)
124125
case (.fallthroughKeyword, let handle)?:
125126
return label(self.parseFallthroughStatement(fallthroughHandle: handle), with: optLabel)
127+
case (.forgetKeyword, let handle)?:
128+
return label(self.parseForgetStatement(forgetHandle: handle), with: optLabel)
126129
case (.returnKeyword, let handle)?:
127130
return label(self.parseReturnStatement(returnHandle: handle), with: optLabel)
128131
case (.throwKeyword, let handle)?:
@@ -374,6 +377,28 @@ extension Parser {
374377
}
375378
}
376379

380+
// MARK: Forget Statements
381+
382+
extension Parser {
383+
/// Parse a forget statement.
384+
///
385+
/// Grammar
386+
/// =======
387+
///
388+
/// forget-statement → 'forget' expression
389+
@_spi(RawSyntax)
390+
public mutating func parseForgetStatement(forgetHandle: RecoveryConsumptionHandle) -> RawForgetStmtSyntax {
391+
let (unexpectedBeforeForgetKeyword, forgetKeyword) = self.eat(forgetHandle)
392+
let expr = self.parseExpression()
393+
return RawForgetStmtSyntax(
394+
unexpectedBeforeForgetKeyword,
395+
forgetKeyword: forgetKeyword,
396+
expression: expr,
397+
arena: self.arena
398+
)
399+
}
400+
}
401+
377402
// MARK: Defer Statements
378403

379404
extension Parser {
@@ -946,6 +971,19 @@ extension Parser.Lookahead {
946971
// yield statement of some singular expression.
947972
return !self.peek().isAtStartOfLine
948973
}
974+
case .forgetKeyword?:
975+
switch peek().rawTokenKind {
976+
case .identifier, .keyword:
977+
// Since some identifiers like "self" are classified as keywords,
978+
// we want to recognize those too, to handle "forget self". We also
979+
// accept any identifier since we want to emit a nice error message
980+
// later on during type checking.
981+
return true
982+
default:
983+
// any other token following "forget" means it's not the statement.
984+
// For example, could be the function call "forget()".
985+
return false
986+
}
949987
case nil:
950988
return false
951989
}

Sources/SwiftParser/TokenSpecSet.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ enum CanBeStatementStart: TokenSpecSet {
8080
case doKeyword
8181
case fallthroughKeyword
8282
case forKeyword
83+
case forgetKeyword
8384
case guardKeyword
8485
case ifKeyword
8586
case repeatKeyword
@@ -97,6 +98,7 @@ enum CanBeStatementStart: TokenSpecSet {
9798
case TokenSpec(.do): self = .doKeyword
9899
case TokenSpec(.fallthrough): self = .fallthroughKeyword
99100
case TokenSpec(.for): self = .forKeyword
101+
case TokenSpec(._forget): self = .forgetKeyword
100102
case TokenSpec(.guard): self = .guardKeyword
101103
case TokenSpec(.if): self = .ifKeyword
102104
case TokenSpec(.repeat): self = .repeatKeyword
@@ -117,6 +119,7 @@ enum CanBeStatementStart: TokenSpecSet {
117119
case .doKeyword: return .keyword(.do)
118120
case .fallthroughKeyword: return .keyword(.fallthrough)
119121
case .forKeyword: return .keyword(.for)
122+
case .forgetKeyword: return TokenSpec(._forget, recoveryPrecedence: .stmtKeyword)
120123
case .guardKeyword: return .keyword(.guard)
121124
case .ifKeyword: return .keyword(.if)
122125
case .repeatKeyword: return .keyword(.repeat)

Sources/SwiftSyntax/Documentation.docc/gyb_generated/SwiftSyntax.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
9797
- <doc:SwiftSyntax/FallthroughStmtSyntax>
9898
- <doc:SwiftSyntax/BreakStmtSyntax>
9999
- <doc:SwiftSyntax/ThrowStmtSyntax>
100+
- <doc:SwiftSyntax/ForgetStmtSyntax>
100101

101102
### Expressions
102103

Sources/SwiftSyntax/generated/Keyword.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ public enum Keyword: UInt8, Hashable {
117117
case `fileprivate`
118118
case final
119119
case `for`
120+
case _forget
120121
case forward
121122
case `func`
122123
case get
@@ -428,6 +429,8 @@ public enum Keyword: UInt8, Hashable {
428429
self = .`default`
429430
case "dynamic":
430431
self = .dynamic
432+
case "_forget":
433+
self = ._forget
431434
case "forward":
432435
self = .forward
433436
case "message":
@@ -946,6 +949,7 @@ public enum Keyword: UInt8, Hashable {
946949
"fileprivate",
947950
"final",
948951
"for",
952+
"_forget",
949953
"forward",
950954
"func",
951955
"get",

Sources/SwiftSyntax/generated/Misc.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ extension Syntax {
120120
.node(FloatLiteralExprSyntax.self),
121121
.node(ForInStmtSyntax.self),
122122
.node(ForcedValueExprSyntax.self),
123+
.node(ForgetStmtSyntax.self),
123124
.node(FunctionCallExprSyntax.self),
124125
.node(FunctionDeclSyntax.self),
125126
.node(FunctionParameterListSyntax.self),
@@ -493,6 +494,8 @@ extension SyntaxKind {
493494
return ForInStmtSyntax.self
494495
case .forcedValueExpr:
495496
return ForcedValueExprSyntax.self
497+
case .forgetStmt:
498+
return ForgetStmtSyntax.self
496499
case .functionCallExpr:
497500
return FunctionCallExprSyntax.self
498501
case .functionDecl:
@@ -1020,6 +1023,8 @@ extension SyntaxKind {
10201023
return "'for' statement"
10211024
case .forcedValueExpr:
10221025
return "force unwrap"
1026+
case .forgetStmt:
1027+
return "'forget' statement"
10231028
case .functionCallExpr:
10241029
return "function call"
10251030
case .functionDecl:

Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,14 @@ open class SyntaxAnyVisitor: SyntaxVisitor {
885885
visitAnyPost(node._syntaxNode)
886886
}
887887

888+
override open func visit(_ node: ForgetStmtSyntax) -> SyntaxVisitorContinueKind {
889+
return visitAny(node._syntaxNode)
890+
}
891+
892+
override open func visitPost(_ node: ForgetStmtSyntax) {
893+
visitAnyPost(node._syntaxNode)
894+
}
895+
888896
override open func visit(_ node: FunctionCallExprSyntax) -> SyntaxVisitorContinueKind {
889897
return visitAny(node._syntaxNode)
890898
}

Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ public struct StmtSyntax: StmtSyntaxProtocol, SyntaxHashable {
522522

523523
public init?<S: SyntaxProtocol>(_ node: S) {
524524
switch node.raw.kind {
525-
case .breakStmt, .continueStmt, .deferStmt, .doStmt, .expressionStmt, .fallthroughStmt, .forInStmt, .guardStmt, .labeledStmt, .missingStmt, .repeatWhileStmt, .returnStmt, .throwStmt, .whileStmt, .yieldStmt:
525+
case .breakStmt, .continueStmt, .deferStmt, .doStmt, .expressionStmt, .fallthroughStmt, .forInStmt, .forgetStmt, .guardStmt, .labeledStmt, .missingStmt, .repeatWhileStmt, .returnStmt, .throwStmt, .whileStmt, .yieldStmt:
526526
self._syntaxNode = node._syntaxNode
527527
default:
528528
return nil
@@ -535,7 +535,7 @@ public struct StmtSyntax: StmtSyntaxProtocol, SyntaxHashable {
535535
internal init(_ data: SyntaxData) {
536536
#if DEBUG
537537
switch data.raw.kind {
538-
case .breakStmt, .continueStmt, .deferStmt, .doStmt, .expressionStmt, .fallthroughStmt, .forInStmt, .guardStmt, .labeledStmt, .missingStmt, .repeatWhileStmt, .returnStmt, .throwStmt, .whileStmt, .yieldStmt:
538+
case .breakStmt, .continueStmt, .deferStmt, .doStmt, .expressionStmt, .fallthroughStmt, .forInStmt, .forgetStmt, .guardStmt, .labeledStmt, .missingStmt, .repeatWhileStmt, .returnStmt, .throwStmt, .whileStmt, .yieldStmt:
539539
break
540540
default:
541541
fatalError("Unable to create StmtSyntax from \(data.raw.kind)")
@@ -578,6 +578,7 @@ public struct StmtSyntax: StmtSyntaxProtocol, SyntaxHashable {
578578
.node(ExpressionStmtSyntax.self),
579579
.node(FallthroughStmtSyntax.self),
580580
.node(ForInStmtSyntax.self),
581+
.node(ForgetStmtSyntax.self),
581582
.node(GuardStmtSyntax.self),
582583
.node(LabeledStmtSyntax.self),
583584
.node(MissingStmtSyntax.self),

Sources/SwiftSyntax/generated/SyntaxEnum.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public enum SyntaxEnum {
120120
case floatLiteralExpr(FloatLiteralExprSyntax)
121121
case forInStmt(ForInStmtSyntax)
122122
case forcedValueExpr(ForcedValueExprSyntax)
123+
case forgetStmt(ForgetStmtSyntax)
123124
case functionCallExpr(FunctionCallExprSyntax)
124125
case functionDecl(FunctionDeclSyntax)
125126
case functionParameterList(FunctionParameterListSyntax)
@@ -492,6 +493,8 @@ public extension Syntax {
492493
return .forInStmt(ForInStmtSyntax(self)!)
493494
case .forcedValueExpr:
494495
return .forcedValueExpr(ForcedValueExprSyntax(self)!)
496+
case .forgetStmt:
497+
return .forgetStmt(ForgetStmtSyntax(self)!)
495498
case .functionCallExpr:
496499
return .functionCallExpr(FunctionCallExprSyntax(self)!)
497500
case .functionDecl:

Sources/SwiftSyntax/generated/SyntaxKind.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public enum SyntaxKind {
120120
case floatLiteralExpr
121121
case forInStmt
122122
case forcedValueExpr
123+
case forgetStmt
123124
case functionCallExpr
124125
case functionDecl
125126
case functionParameterList

Sources/SwiftSyntax/generated/SyntaxRewriter.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,13 @@ open class SyntaxRewriter {
753753
return ExprSyntax(visitChildren(node))
754754
}
755755

756+
/// Visit a `ForgetStmtSyntax`.
757+
/// - Parameter node: the node that is being visited
758+
/// - Returns: the rewritten node
759+
open func visit(_ node: ForgetStmtSyntax) -> StmtSyntax {
760+
return StmtSyntax(visitChildren(node))
761+
}
762+
756763
/// Visit a `FunctionCallExprSyntax`.
757764
/// - Parameter node: the node that is being visited
758765
/// - Returns: the rewritten node
@@ -3375,6 +3382,20 @@ open class SyntaxRewriter {
33753382
return Syntax(visit(node))
33763383
}
33773384

3385+
/// Implementation detail of visit(_:). Do not call directly.
3386+
private func visitImplForgetStmtSyntax(_ data: SyntaxData) -> Syntax {
3387+
let node = ForgetStmtSyntax(data)
3388+
// Accessing _syntaxNode directly is faster than calling Syntax(node)
3389+
visitPre(node._syntaxNode)
3390+
defer {
3391+
visitPost(node._syntaxNode)
3392+
}
3393+
if let newNode = visitAny(node._syntaxNode) {
3394+
return newNode
3395+
}
3396+
return Syntax(visit(node))
3397+
}
3398+
33783399
/// Implementation detail of visit(_:). Do not call directly.
33793400
private func visitImplFunctionCallExprSyntax(_ data: SyntaxData) -> Syntax {
33803401
let node = FunctionCallExprSyntax(data)
@@ -5809,6 +5830,8 @@ open class SyntaxRewriter {
58095830
return visitImplForInStmtSyntax
58105831
case .forcedValueExpr:
58115832
return visitImplForcedValueExprSyntax
5833+
case .forgetStmt:
5834+
return visitImplForgetStmtSyntax
58125835
case .functionCallExpr:
58135836
return visitImplFunctionCallExprSyntax
58145837
case .functionDecl:
@@ -6339,6 +6362,8 @@ open class SyntaxRewriter {
63396362
return visitImplForInStmtSyntax(data)
63406363
case .forcedValueExpr:
63416364
return visitImplForcedValueExprSyntax(data)
6365+
case .forgetStmt:
6366+
return visitImplForgetStmtSyntax(data)
63426367
case .functionCallExpr:
63436368
return visitImplFunctionCallExprSyntax(data)
63446369
case .functionDecl:

Sources/SwiftSyntax/generated/SyntaxTransform.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,11 @@ public protocol SyntaxTransformVisitor {
539539
/// - Returns: the sum of whatever the child visitors return.
540540
func visit(_ node: ForcedValueExprSyntax) -> ResultType
541541

542+
/// Visiting `ForgetStmtSyntax` specifically.
543+
/// - Parameter node: the node we are visiting.
544+
/// - Returns: the sum of whatever the child visitors return.
545+
func visit(_ node: ForgetStmtSyntax) -> ResultType
546+
542547
/// Visiting `FunctionCallExprSyntax` specifically.
543548
/// - Parameter node: the node we are visiting.
544549
/// - Returns: the sum of whatever the child visitors return.
@@ -2053,6 +2058,13 @@ extension SyntaxTransformVisitor {
20532058
visitAny(Syntax(node))
20542059
}
20552060

2061+
/// Visiting `ForgetStmtSyntax` specifically.
2062+
/// - Parameter node: the node we are visiting.
2063+
/// - Returns: nil by default.
2064+
public func visit(_ node: ForgetStmtSyntax) -> ResultType {
2065+
visitAny(Syntax(node))
2066+
}
2067+
20562068
/// Visiting `FunctionCallExprSyntax` specifically.
20572069
/// - Parameter node: the node we are visiting.
20582070
/// - Returns: nil by default.
@@ -3357,6 +3369,8 @@ extension SyntaxTransformVisitor {
33573369
return visit(derived)
33583370
case .forcedValueExpr(let derived):
33593371
return visit(derived)
3372+
case .forgetStmt(let derived):
3373+
return visit(derived)
33603374
case .functionCallExpr(let derived):
33613375
return visit(derived)
33623376
case .functionDecl(let derived):

Sources/SwiftSyntax/generated/SyntaxVisitor.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,18 @@ open class SyntaxVisitor {
12821282
open func visitPost(_ node: ForcedValueExprSyntax) {
12831283
}
12841284

1285+
/// Visiting `ForgetStmtSyntax` specifically.
1286+
/// - Parameter node: the node we are visiting.
1287+
/// - Returns: how should we continue visiting.
1288+
open func visit(_ node: ForgetStmtSyntax) -> SyntaxVisitorContinueKind {
1289+
return .visitChildren
1290+
}
1291+
1292+
/// The function called after visiting `ForgetStmtSyntax` and its descendents.
1293+
/// - node: the node we just finished visiting.
1294+
open func visitPost(_ node: ForgetStmtSyntax) {
1295+
}
1296+
12851297
/// Visiting `FunctionCallExprSyntax` specifically.
12861298
/// - Parameter node: the node we are visiting.
12871299
/// - Returns: how should we continue visiting.
@@ -4310,6 +4322,17 @@ open class SyntaxVisitor {
43104322
visitPost(node)
43114323
}
43124324

4325+
/// Implementation detail of doVisit(_:_:). Do not call directly.
4326+
private func visitImplForgetStmtSyntax(_ data: SyntaxData) {
4327+
let node = ForgetStmtSyntax(data)
4328+
let needsChildren = (visit(node) == .visitChildren)
4329+
// Avoid calling into visitChildren if possible.
4330+
if needsChildren && !node.raw.layoutView!.children.isEmpty {
4331+
visitChildren(node)
4332+
}
4333+
visitPost(node)
4334+
}
4335+
43134336
/// Implementation detail of doVisit(_:_:). Do not call directly.
43144337
private func visitImplFunctionCallExprSyntax(_ data: SyntaxData) {
43154338
let node = FunctionCallExprSyntax(data)
@@ -6241,6 +6264,8 @@ open class SyntaxVisitor {
62416264
visitImplForInStmtSyntax(data)
62426265
case .forcedValueExpr:
62436266
visitImplForcedValueExprSyntax(data)
6267+
case .forgetStmt:
6268+
visitImplForgetStmtSyntax(data)
62446269
case .functionCallExpr:
62456270
visitImplFunctionCallExprSyntax(data)
62466271
case .functionDecl:

0 commit comments

Comments
 (0)