Skip to content

[libSyntax] Create deferred nodes in SyntaxParseActions #36277

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

Conversation

ahoppen
Copy link
Member

@ahoppen ahoppen commented Mar 4, 2021

Move the creation of deferred nodes from the ParsedRawSyntaxRecorder to SyntaxParseActions. By itself this does not offer any advantage, but from here we will be able to optimize the creation of deferred nodes inside the different SyntaxParseActions implementations.

All implementation that is currently in SyntaxParseActions is transitional. In the next PR these will be pushed to CLibParseActions (which will mostly match what’s currently in SyntaxParseActions) and SyntaxTreeCreator (which can avoid creating deferred nodes altogether by directly constructing RawSyntax nodes).

@ahoppen ahoppen changed the title Pr/deferred nodes in syntax parse actions [libSyntax] Create deferred nodes in SyntaxParseActions Mar 4, 2021
@ahoppen ahoppen force-pushed the pr/deferred-nodes-in-syntax-parse-actions branch 4 times, most recently from 5164eb4 to 5f3abe3 Compare March 8, 2021 21:17
@ahoppen ahoppen requested a review from rintaro March 8, 2021 21:17
@ahoppen ahoppen marked this pull request as ready for review March 8, 2021 21:17
@ahoppen
Copy link
Member Author

ahoppen commented Mar 8, 2021

@swift-ci Please smoke test

Comment on lines 109 to 114
/// Returns the opaque data of this node. This must be interpreted by the
/// \c SyntaxParseAction, which likely also needs the node type to know
/// what type of node the data represents.
OpaqueSyntaxNode getData() const { return Data.getOpaque(); }

RecordedOrDeferredNode getRecordedOrDeferredNode() const { return Data; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These methods (getData() and getRecordedOrDeferredNode()) breaks the "move-only" semantics of ParsedRawSyntaxNode. "Data" should not be extracted without resetting the ParsedRawSyntaxNode.
This is important to ensure not to discard parsed recorded nodes without putting them into the final tree.

Previously, we allowed copying via copyDeferred() method only if it's deferred.

Copy link
Member Author

@ahoppen ahoppen Mar 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need some kind of “get data, but don’t take” method to retrieve the node’s children here.

I’ve renamed the method to getUnsafeOpaqueData and added a comment that the data returned by it should only be used to inspect the node, not to record it. Are you OK with that?

Also, while looking through the uses of this method, I actually found a case where we should have been using takeData instead, so good catch.

I modified getRecordedOrDeferredNode to takeRecordedOrDeferredNode.

case RecordedOrDeferredNode::Kind::Null:
break;
case RecordedOrDeferredNode::Kind::Recorded:
llvm_unreachable("Children of deferred nodes must also be deferred");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any comments why deferred nodes can't contain recorded nodes? If not, could you add some?

Copy link
Member Author

@ahoppen ahoppen Mar 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s because of the way we create the syntax tree. Once we put the SyntaxParsingContext in deferred node all (child) nodes are also deferred. If we chose to record child nodes of deferred nodes, we would also get into trouble should we decide to discard the deferred node, because now we’d also need to discard the recorded child node, which cannot be done. Please correct me if any of the assumptions I’m making here are wrong.

We don’t have a comment about this anywhere. I’ve added one here.

@ahoppen ahoppen force-pushed the pr/deferred-nodes-in-syntax-parse-actions branch 2 times, most recently from 0fa3e7e to 7cca0af Compare March 9, 2021 12:07
@ahoppen ahoppen force-pushed the pr/deferred-nodes-in-syntax-parse-actions branch from 7cca0af to 0c136af Compare March 9, 2021 12:41
@ahoppen
Copy link
Member Author

ahoppen commented Mar 9, 2021

@swift-ci Please smoke test

ahoppen added 5 commits March 9, 2021 14:26
…yntaxRecorder

This is an intermediate step in the effort to push deferred node
handling all the way down to SyntaxParseActions.
By now ParsedRawSyntaxNode does not have any knowledge about deferred
node data anymore, which frees up SyntaxParseActions (and, in
particular its sublass SyntaxTreeCreator) to perform optimisations to
more efficiently create and record deferred nodes.
…e as RecordedOrDeferredNode

This is mostly a clean-up commit. ParsedRawSyntaxNode stores an
OpaqueSyntaxNode and its DataKind so it might as well use a
RecordedOrDeferredNode.
This requires a SyntaxParsingContext to be passed to the dump function
and was thus disabled in an earlier commit
…ParsedRawSyntaxNode

They are superseded by getData/takeData
@ahoppen ahoppen force-pushed the pr/deferred-nodes-in-syntax-parse-actions branch from 0c136af to 1f695c9 Compare March 9, 2021 13:26
@ahoppen
Copy link
Member Author

ahoppen commented Mar 9, 2021

@swift-ci Please smoke test

Parsed${child.type_name} Parsed${node.name}::getDeferred${child.name}() {
return Parsed${child.type_name} {getRaw().getDeferredChildren()[${node.name}::Cursor::${child.name}].copyDeferred()};
Parsed${child.type_name} Parsed${node.name}::getDeferred${child.name}(const SyntaxParsingContext *SyntaxContext) {
return Parsed${child.type_name} {getRaw().getDeferredChild(${node.name}::Cursor::${child.name}, SyntaxContext).copyDeferred()};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copyDeferred() is not needed I believe

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s still used in one place, I’ll remove it in 81f7d1e which is part of #36362

Parsed${node.name}::getDeferred${child.name}() {
auto &RawChild = getRaw().getDeferredChildren()[${node.name}::Cursor::${child.name}];
Parsed${node.name}::getDeferred${child.name}(const SyntaxParsingContext *SyntaxContext) {
auto RawChild = getRaw().getDeferredChild(${node.name}::Cursor::${child.name}, SyntaxContext);
if (RawChild.isNull())
return None;
return Parsed${child.type_name} {RawChild.copyDeferred()};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you remove them, copyDeferred() is not used anymore...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

ahoppen added 2 commits March 9, 2021 19:10
The getData and getRecordedOrDeferredNode methods broke the move-only semantics of ParsedRawSyntaxNode because it allowed retrieving the data without resetting it.

Change most uses to use takeData or takeRecordedOrDeferredNode instead of the get methods.

To retrieve the children of a ParsedRawSyntaxNode, we still need a way to access the OpaqueSyntaxNode for inspection by the SyntaxParseActions without resetting it. For this, we still maintain a method with the semantics of getData, but it’s now called getUnsafeOpaqueData to make sure it’s not accidentally used.
@ahoppen ahoppen force-pushed the pr/deferred-nodes-in-syntax-parse-actions branch from 1f695c9 to bf6aff9 Compare March 9, 2021 18:13
@ahoppen
Copy link
Member Author

ahoppen commented Mar 9, 2021

@swift-ci Please smoke test

@ahoppen
Copy link
Member Author

ahoppen commented Mar 9, 2021

@swift-ci Please smoke test Windows

@ahoppen ahoppen merged commit beadd4a into swiftlang:main Mar 9, 2021
@ahoppen ahoppen deleted the pr/deferred-nodes-in-syntax-parse-actions branch March 9, 2021 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants