-
Notifications
You must be signed in to change notification settings - Fork 439
Port incremental parsing ability to CodeBlockItem
#1685
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
Port incremental parsing ability to CodeBlockItem
#1685
Conversation
69f7cf2
to
7a19dca
Compare
To prevent incremental parse from missing the legal parts of re-used nodes ahead, I made following changes:
This is still WIP but I am open to feedback. |
I think this pr is ready for review. I will squash the commits when there aren't any big problems with the design. |
3ffcc72
to
0055ebe
Compare
70b5a43
to
33f1a29
Compare
fileprivate var edits: ConcurrentEdits? | ||
fileprivate var reusedDelegate: IncrementalParseReusedNodeDelegate? | ||
|
||
public var furthestOffset: Int? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Split IncrementalParseTransition
into two types as discussed offline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I add a IncrementalParseNodeAffectRangeCollector
to collect this and make it as a trigger to enable incremental parse.
func getOffsetToStart(_ token: Lexer.Lexeme) -> Int { | ||
return self.sourceBufferStart.distance(to: token.cursor) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not part of this PR: Can we use getOffsetToStart
instead of offset(of:)
.
Sources/SwiftParser/Lookahead.swift
Outdated
@@ -27,22 +27,30 @@ extension Parser { | |||
/// i.e. how far it looked ahead. | |||
var tokensConsumed: Int = 0 | |||
|
|||
var parseTransition: IncrementalParseTransition? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed offline, we could store furthestOffset
in a standalone struct
and pass that over here as an UnsafeMutablePointer
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have to record the offset in both Parser.peek()
and Lookahead.consumeAnyToken()
, I make this pointer a member of LexemeSequence
.
_ = Parser.parse(source: buf.bindMemory(to: UInt8.self)) | ||
previousTreeDict[file] = Parser.parse(source: buf.bindMemory(to: UInt8.self), parseTransition: parseTransition) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a flag to decide whether we want to do incremental parsing on subsequent iterations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a flag about this, but I'm not quite sure whether the code is still a bit hacky.
b0cf0d5
to
92d7ceb
Compare
92d7ceb
to
accde01
Compare
5edfc14
to
82c73e5
Compare
I add two |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks very close now. I mostly have comments about naming and doc comments.
CodeGeneration/Sources/generate-swiftsyntax/templates/swiftparser/ParserEntryFile.swift
Outdated
Show resolved
Hide resolved
@@ -20,26 +20,39 @@ | |||
/// This is also used for testing purposes to ensure incremental reparsing | |||
/// worked as expected. | |||
public protocol IncrementalParseReusedNodeDelegate { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely not part of this PR but I think we should consider change IncrementalParseReusedNodeDelegate
to just be a callback function on IncrementalParseTransition
, i.e. removing this protocol altogether. That’s more swifty than the Objective-C delegate pattern.
Sources/SwiftParser/Parser.swift
Outdated
@@ -237,6 +262,7 @@ public struct Parser { | |||
extension Parser { | |||
/// Retrieves the token following the current token without consuming it. | |||
func peek() -> Lexer.Lexeme { | |||
lexemes.recordFurthestOffset() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just something that crossed my mind: Can’t we just call recordFurthestOffset
from LexemeSequences.advance
and LexemeSequence.peek
? That way we can’t forget to call it from any Parser
or Lookahead
functions that interact with LexemeSequence
. Or is there a performance regression associated with that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I didn't do that because I was trap into some weird bugs and fail the tests then. And it turned out that it was because I called recordNextTokenInLookaheadTracker
in the wrong time🥹.
Or is there a performance regression associated with that?
About the performance, see my comments below.
bc9be97
to
05ea6d0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even better performance, I love it.
I think the only non-trivial question that remains is who’s responsible for calling recordNextTokenInLookaheadTracker
, everything else is super minor now.
05ea6d0
to
fdcd570
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last comment to make a method private
, otherwise this is looking great now 🕺🏽💃🏽.
Use `LookaheadTracker` to track the furthest offset we reached and use `LookaheadRanges` to record the offset as the source range where might affect the parse of a node. And we could use that information to judge whether a node can be reused
fdcd570
to
1e6406d
Compare
🚀 @swift-ci Please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
swiftlang/swift-stress-tester#242 @swift-ci Please test macOS |
swiftlang/swift-stress-tester#242 @swift-ci Please test Windows |
Oops, the same problem as before. Maybe we need to re-trigger again🥲 |
swiftlang/swift-stress-tester#242 @swift-ci Please test macOS |
1 similar comment
swiftlang/swift-stress-tester#242 @swift-ci Please test macOS |
I want to make this pr as a start effort to port incremental parsing ability to
SwiftParser
.