@@ -203,35 +203,98 @@ let tokenKindFile = SourceFileSyntax {
203
203
}
204
204
205
205
EnumDeclSyntax ( """
206
- /// Plain token kind value, without an associated `String` value.
206
+ // Note: It's important that this enum is marked as having a raw base kind
207
+ // because it significantly improves performance when comparing two
208
+ // `RawTokenBaseKind` for equality. With the raw value, it compiles down to
209
+ // a primitive integer compare, without, it calls into `__derived_enum_equals`.
207
210
@frozen // FIXME: Not actually stable, works around a miscompile
208
- public enum RawTokenKind: Equatable, Hashable
211
+ public enum RawTokenBaseKind: UInt8, Equatable, Hashable
209
212
""" ) {
210
213
EnumCaseDeclSyntax ( " case eof " )
211
214
212
215
for token in SYNTAX_TOKENS {
213
- if let associatedValueClass = token. associatedValueClass {
214
- EnumCaseDeclSyntax ( " case \( raw: token. swiftKind) ( \( raw: associatedValueClass) ) " )
215
- } else {
216
- EnumCaseDeclSyntax ( " case \( raw: token. swiftKind) " )
216
+ EnumCaseDeclSyntax ( " case \( raw: token. swiftKind) " )
217
+ }
218
+ }
219
+
220
+ DeclSyntax ( """
221
+ fileprivate extension Keyword {
222
+ static var rawValueZero: Keyword {
223
+ return Keyword(rawValue: 0)!
224
+ }
225
+ }
226
+ """ )
227
+
228
+ StructDeclSyntax ( """
229
+ /// Similar to `TokenKind` but without a `String` associated value.
230
+ /// Technically, this should be an enum like
231
+ /// ```
232
+ /// enum RawTokenKind {
233
+ /// case eof
234
+ /// case associatedtypeKeyword
235
+ /// // remaining case from `RawTokenBaseKind`...
236
+ /// case keyword(Keyword)
237
+ /// }
238
+ /// ```
239
+ ///
240
+ /// But modelling it this way has significant performance implications since
241
+ /// comparing two `RawTokenKind` calls into `__derived_enum_equals`. It's more
242
+ /// effient to model the base kind as an enum with a raw value and store the
243
+ /// keyword separately.
244
+ ///
245
+ /// Whenever `base` is not `keyword`, `keyword` should have a raw value
246
+ /// of `0`.
247
+ @frozen // FIXME: Not actually stable, works around a miscompile
248
+ public struct RawTokenKind: Equatable, Hashable
249
+ """ ) {
250
+ DeclSyntax ( " public let base: RawTokenBaseKind " )
251
+ DeclSyntax ( " public let keyword: Keyword " )
252
+
253
+ DeclSyntax ( """
254
+ public init(base: RawTokenBaseKind, keyword: Keyword) {
255
+ assert(base == .keyword || keyword.rawValue == 0)
256
+ self.base = base
257
+ self.keyword = keyword
217
258
}
259
+ """
260
+ )
261
+
262
+ DeclSyntax ( """
263
+ public static var eof: RawTokenKind {
264
+ return RawTokenKind(base: .eof, keyword: .rawValueZero)
265
+ }
266
+ """ )
267
+ for token in SYNTAX_TOKENS where token. swiftKind != " keyword " {
268
+ VariableDeclSyntax (
269
+ modifiers: [ DeclModifierSyntax ( leadingTrivia: . newline, name: . keyword( . public) ) , DeclModifierSyntax ( name: . keyword( . static) ) ] ,
270
+ name: IdentifierPatternSyntax ( " \( raw: token. swiftKind) " ) ,
271
+ type: TypeAnnotationSyntax ( type: TypeSyntax ( " RawTokenKind " ) )
272
+ ) {
273
+ StmtSyntax ( " return RawTokenKind(base: . \( raw: token. swiftKind) , keyword: .rawValueZero) " )
274
+ }
275
+ }
276
+
277
+ DeclSyntax ( """
278
+ public static func keyword(_ keyword: Keyword) -> RawTokenKind {
279
+ return RawTokenKind(base: .keyword, keyword: keyword)
218
280
}
281
+ """ )
219
282
220
283
VariableDeclSyntax (
221
284
attributes: [ . attribute( AttributeSyntax ( attributeName: TypeSyntax ( " _spi " ) , leftParen: . leftParenToken( ) , argument: . token( . identifier( " RawSyntax " ) ) , rightParen: . rightParenToken( ) ) ) ] ,
222
285
modifiers: [ DeclModifierSyntax ( leadingTrivia: . newline, name: . keyword( . public) ) ] ,
223
286
name: IdentifierPatternSyntax ( " defaultText " ) ,
224
287
type: TypeAnnotationSyntax ( type: OptionalTypeSyntax ( " SyntaxText? " ) )
225
288
) {
226
- SwitchStmtSyntax ( expression: ExprSyntax ( " self " ) ) {
289
+ SwitchStmtSyntax ( expression: ExprSyntax ( " self.base " ) ) {
227
290
SwitchCaseSyntax ( " case .eof: " ) {
228
291
ReturnStmtSyntax ( #"return """# )
229
292
}
230
293
231
294
for token in SYNTAX_TOKENS {
232
- if token. associatedValueClass != nil {
233
- SwitchCaseSyntax ( " case . \( raw: token. swiftKind) (let assoc) :" ) {
234
- ReturnStmtSyntax ( " return assoc .defaultText " )
295
+ if token. swiftKind == " keyword " {
296
+ SwitchCaseSyntax ( " case . \( raw: token. swiftKind) : " ) {
297
+ ReturnStmtSyntax ( " return self.keyword .defaultText " )
235
298
}
236
299
} else if let text = token. text {
237
300
SwitchCaseSyntax ( " case . \( raw: token. swiftKind) : " ) {
@@ -251,7 +314,7 @@ let tokenKindFile = SourceFileSyntax {
251
314
name: IdentifierPatternSyntax ( " nameForDiagnostics " ) ,
252
315
type: TypeAnnotationSyntax ( type: TypeSyntax ( " String " ) )
253
316
) {
254
- SwitchStmtSyntax ( expression: ExprSyntax ( " self " ) ) {
317
+ SwitchStmtSyntax ( expression: ExprSyntax ( " self.base " ) ) {
255
318
SwitchCaseSyntax ( " case .eof: " ) {
256
319
ReturnStmtSyntax ( #"return "end of file""# )
257
320
}
@@ -261,12 +324,12 @@ let tokenKindFile = SourceFileSyntax {
261
324
ReturnStmtSyntax ( " return # \" \( raw: token. nameForDiagnostics) \" # " )
262
325
}
263
326
}
264
- SwitchCaseSyntax ( " case .keyword(let keyword) : " ) {
265
- ReturnStmtSyntax ( " return String(syntaxText: keyword.defaultText) " )
327
+ SwitchCaseSyntax ( " case .keyword: " ) {
328
+ ReturnStmtSyntax ( " return String(syntaxText: self. keyword.defaultText) " )
266
329
}
267
330
}
268
331
}
269
-
332
+
270
333
VariableDeclSyntax (
271
334
leadingTrivia: [
272
335
. docBlockComment( " /// Returns `true` if the token is a Swift keyword. " ) ,
@@ -284,7 +347,7 @@ let tokenKindFile = SourceFileSyntax {
284
347
name: IdentifierPatternSyntax ( " isLexerClassifiedKeyword " ) ,
285
348
type: TypeAnnotationSyntax ( type: TypeSyntax ( " Bool " ) )
286
349
) {
287
- SwitchStmtSyntax ( expression: ExprSyntax ( " self " ) ) {
350
+ SwitchStmtSyntax ( expression: ExprSyntax ( " self.base " ) ) {
288
351
SwitchCaseSyntax ( " case .eof: " ) {
289
352
ReturnStmtSyntax ( " return false " )
290
353
}
@@ -294,8 +357,8 @@ let tokenKindFile = SourceFileSyntax {
294
357
ReturnStmtSyntax ( " return \( raw: token. isKeyword) " )
295
358
}
296
359
}
297
- SwitchCaseSyntax ( " case .keyword(let keyword) : " ) {
298
- ReturnStmtSyntax ( " return keyword.isLexerClassified " )
360
+ SwitchCaseSyntax ( " case .keyword: " ) {
361
+ ReturnStmtSyntax ( " return self. keyword.isLexerClassified " )
299
362
}
300
363
}
301
364
}
@@ -317,7 +380,7 @@ let tokenKindFile = SourceFileSyntax {
317
380
name: IdentifierPatternSyntax ( " isPunctuation " ) ,
318
381
type: TypeAnnotationSyntax ( type: TypeSyntax ( " Bool " ) )
319
382
) {
320
- SwitchStmtSyntax ( expression: ExprSyntax ( " self " ) ) {
383
+ SwitchStmtSyntax ( expression: ExprSyntax ( " self.base " ) ) {
321
384
SwitchCaseSyntax ( " case .eof: " ) {
322
385
ReturnStmtSyntax ( " return false " )
323
386
}
@@ -370,16 +433,16 @@ let tokenKindFile = SourceFileSyntax {
370
433
@_spi(RawSyntax)
371
434
public static func fromRaw(kind rawKind: RawTokenKind, text: String) -> TokenKind
372
435
""" ) {
373
- SwitchStmtSyntax ( expression: ExprSyntax ( " rawKind " ) ) {
436
+ SwitchStmtSyntax ( expression: ExprSyntax ( " rawKind.base " ) ) {
374
437
SwitchCaseSyntax ( " case .eof: " ) {
375
438
ReturnStmtSyntax ( " return .eof " )
376
439
}
377
440
378
441
for token in SYNTAX_TOKENS {
379
- if token. associatedValueClass != nil {
380
- SwitchCaseSyntax ( " case . \( raw: token. swiftKind) (let assoc) :" ) {
381
- FunctionCallExprSyntax ( " assert(text.isEmpty || String(syntaxText: assoc .defaultText) == text) " )
382
- ReturnStmtSyntax ( " return . \( raw : token . swiftKind ) (assoc )" )
442
+ if token. swiftKind == " keyword " {
443
+ SwitchCaseSyntax ( " case . \( raw: token. swiftKind) : " ) {
444
+ FunctionCallExprSyntax ( " assert(text.isEmpty || String(syntaxText: rawKind.keyword .defaultText) == text) " )
445
+ ReturnStmtSyntax ( " return .keyword(rawKind.keyword ) " )
383
446
}
384
447
} else if token. text != nil {
385
448
SwitchCaseSyntax ( " case . \( raw: token. swiftKind) : " ) {
@@ -407,9 +470,9 @@ let tokenKindFile = SourceFileSyntax {
407
470
}
408
471
409
472
for token in SYNTAX_TOKENS {
410
- if token. associatedValueClass != nil {
411
- SwitchCaseSyntax ( " case . \( raw: token. swiftKind) (let assoc ): " ) {
412
- ReturnStmtSyntax ( " return (. \( raw: token. swiftKind) (assoc ), nil) " )
473
+ if token. swiftKind == " keyword " {
474
+ SwitchCaseSyntax ( " case . \( raw: token. swiftKind) (let keyword ): " ) {
475
+ ReturnStmtSyntax ( " return (. \( raw: token. swiftKind) (keyword ), nil) " )
413
476
}
414
477
} else if token. text != nil {
415
478
SwitchCaseSyntax ( " case . \( raw: token. swiftKind) : " ) {
0 commit comments