Skip to content

Commit b09f875

Browse files
authored
Merge pull request swiftlang#27230 from rintaro/syntaxparsse-rdar55421369
[SyntaxParse] Re-apply move-only ParsedRawSyntaxNode
2 parents d0b7eca + 4527711 commit b09f875

27 files changed

+500
-328
lines changed

include/swift/Parse/HiddenLibSyntaxAction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class HiddenLibSyntaxAction : public SyntaxParseActions {
7070
std::pair<size_t, OpaqueSyntaxNode>
7171
lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) override;
7272

73+
void discardRecordedNode(OpaqueSyntaxNode node) override;
74+
7375
OpaqueSyntaxNodeKind getOpaqueKind() override {
7476
return ExplicitAction->getOpaqueKind();
7577
}

include/swift/Parse/LibSyntaxGenerator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class LibSyntaxGenerator {
4444

4545
auto Recorded = Recorder.recordToken(Kind, Range, LeadingTriviaPieces,
4646
TrailingTriviaPieces);
47-
auto Raw = static_cast<RawSyntax *>(Recorded.getOpaqueNode());
47+
auto Raw = static_cast<RawSyntax *>(Recorded.takeOpaqueNode());
4848
return make<TokenSyntax>(Raw);
4949
}
5050

@@ -55,7 +55,7 @@ class LibSyntaxGenerator {
5555
auto Children = Node.getDeferredChildren();
5656

5757
auto Recorded = Recorder.recordRawSyntax(Kind, Children);
58-
RC<RawSyntax> Raw {static_cast<RawSyntax *>(Recorded.getOpaqueNode()) };
58+
RC<RawSyntax> Raw {static_cast<RawSyntax *>(Recorded.takeOpaqueNode()) };
5959
Raw->Release(); // -1 since it's transfer of ownership.
6060
return make<SyntaxNode>(Raw);
6161
}

include/swift/Parse/ParsedRawSyntaxNode.h

Lines changed: 96 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class ParsedRawSyntaxNode {
5151
CharSourceRange Range;
5252
};
5353
struct DeferredLayoutNode {
54-
ArrayRef<ParsedRawSyntaxNode> Children;
54+
MutableArrayRef<ParsedRawSyntaxNode> Children;
5555
};
5656
struct DeferredTokenNode {
5757
const ParsedTriviaPiece *TriviaPieces;
@@ -73,8 +73,8 @@ class ParsedRawSyntaxNode {
7373
bool IsMissing = false;
7474

7575
ParsedRawSyntaxNode(syntax::SyntaxKind k,
76-
ArrayRef<ParsedRawSyntaxNode> deferredNodes)
77-
: DeferredLayout{deferredNodes},
76+
MutableArrayRef<ParsedRawSyntaxNode> deferredNodes)
77+
: DeferredLayout({deferredNodes}),
7878
SynKind(uint16_t(k)), TokKind(uint16_t(tok::unknown)),
7979
DK(DataKind::DeferredLayout) {
8080
assert(getKind() == k && "Syntax kind with too large value!");
@@ -97,6 +97,8 @@ class ParsedRawSyntaxNode {
9797
assert(DeferredToken.NumTrailingTrivia == numTrailingTrivia &&
9898
"numLeadingTrivia is too large value!");
9999
}
100+
ParsedRawSyntaxNode(ParsedRawSyntaxNode &other) = delete;
101+
ParsedRawSyntaxNode &operator=(ParsedRawSyntaxNode &other) = delete;
100102

101103
public:
102104
ParsedRawSyntaxNode()
@@ -115,6 +117,35 @@ class ParsedRawSyntaxNode {
115117
assert(getTokenKind() == tokKind && "Token kind with too large value!");
116118
}
117119

120+
ParsedRawSyntaxNode &operator=(ParsedRawSyntaxNode &&other) {
121+
assert(DK != DataKind::Recorded);
122+
switch (other.DK) {
123+
case DataKind::Null:
124+
break;
125+
case DataKind::Recorded:
126+
RecordedData = std::move(other.RecordedData);
127+
break;
128+
case DataKind::DeferredLayout:
129+
DeferredLayout = std::move(other.DeferredLayout);
130+
break;
131+
case DataKind::DeferredToken:
132+
DeferredToken = std::move(other.DeferredToken);
133+
break;
134+
}
135+
SynKind = std::move(other.SynKind);
136+
TokKind = std::move(other.TokKind);
137+
DK = std::move(other.DK);
138+
IsMissing = std::move(other.IsMissing);
139+
other.reset();
140+
return *this;
141+
}
142+
ParsedRawSyntaxNode(ParsedRawSyntaxNode &&other) : ParsedRawSyntaxNode() {
143+
*this = std::move(other);
144+
}
145+
~ParsedRawSyntaxNode() {
146+
assert(DK != DataKind::Recorded);
147+
}
148+
118149
syntax::SyntaxKind getKind() const { return syntax::SyntaxKind(SynKind); }
119150
tok getTokenKind() const { return tok(TokKind); }
120151

@@ -136,6 +167,36 @@ class ParsedRawSyntaxNode {
136167
/// Primary used for a deferred missing token.
137168
bool isMissing() const { return IsMissing; }
138169

170+
void reset() {
171+
RecordedData = {};
172+
SynKind = uint16_t(syntax::SyntaxKind::Unknown);
173+
TokKind = uint16_t(tok::unknown);
174+
DK = DataKind::Null;
175+
IsMissing = false;
176+
}
177+
178+
ParsedRawSyntaxNode unsafeCopy() const {
179+
ParsedRawSyntaxNode copy;
180+
switch (DK) {
181+
case DataKind::DeferredLayout:
182+
copy.DeferredLayout = DeferredLayout;
183+
break;
184+
case DataKind::DeferredToken:
185+
copy.DeferredToken = DeferredToken;
186+
break;
187+
case DataKind::Recorded:
188+
copy.RecordedData = RecordedData;
189+
break;
190+
case DataKind::Null:
191+
break;
192+
}
193+
copy.SynKind = SynKind;
194+
copy.TokKind = TokKind;
195+
copy.DK = DK;
196+
copy.IsMissing = IsMissing;
197+
return copy;
198+
}
199+
139200
CharSourceRange getDeferredRange() const {
140201
switch (DK) {
141202
case DataKind::DeferredLayout:
@@ -153,18 +214,24 @@ class ParsedRawSyntaxNode {
153214
assert(isRecorded());
154215
return RecordedData.Range;
155216
}
156-
OpaqueSyntaxNode getOpaqueNode() const {
217+
const OpaqueSyntaxNode &getOpaqueNode() const {
157218
assert(isRecorded());
158219
return RecordedData.OpaqueNode;
159220
}
221+
OpaqueSyntaxNode takeOpaqueNode() {
222+
assert(isRecorded());
223+
auto opaque = RecordedData.OpaqueNode;
224+
reset();
225+
return opaque;
226+
}
160227

161228
// Deferred Layout Data ====================================================//
162229

163230
CharSourceRange getDeferredLayoutRange() const {
164231
assert(DK == DataKind::DeferredLayout);
165232
assert(!DeferredLayout.Children.empty());
166-
auto getLastNonNullChild = [this]() {
167-
for (auto &&Child : llvm::reverse(getDeferredChildren()))
233+
auto getLastNonNullChild = [this]() -> const ParsedRawSyntaxNode & {
234+
for (auto &Child : llvm::reverse(getDeferredChildren()))
168235
if (!Child.isNull())
169236
return Child;
170237
llvm_unreachable("layout node without non-null children");
@@ -178,6 +245,28 @@ class ParsedRawSyntaxNode {
178245
assert(DK == DataKind::DeferredLayout);
179246
return DeferredLayout.Children;
180247
}
248+
MutableArrayRef<ParsedRawSyntaxNode> getDeferredChildren() {
249+
assert(DK == DataKind::DeferredLayout);
250+
return DeferredLayout.Children;
251+
}
252+
ParsedRawSyntaxNode copyDeferred() const {
253+
ParsedRawSyntaxNode copy;
254+
switch (DK) {
255+
case DataKind::DeferredLayout:
256+
copy.DeferredLayout = DeferredLayout;
257+
break;
258+
case DataKind::DeferredToken:
259+
copy.DeferredToken = DeferredToken;
260+
break;
261+
default:
262+
llvm_unreachable("node not deferred");
263+
}
264+
copy.SynKind = SynKind;
265+
copy.TokKind = TokKind;
266+
copy.DK = DK;
267+
copy.IsMissing = IsMissing;
268+
return copy;
269+
}
181270

182271
// Deferred Token Data =====================================================//
183272

@@ -214,7 +303,7 @@ class ParsedRawSyntaxNode {
214303

215304
/// Form a deferred syntax layout node.
216305
static ParsedRawSyntaxNode makeDeferred(syntax::SyntaxKind k,
217-
ArrayRef<ParsedRawSyntaxNode> deferredNodes,
306+
MutableArrayRef<ParsedRawSyntaxNode> deferredNodes,
218307
SyntaxParsingContext &ctx);
219308

220309
/// Form a deferred token node.

include/swift/Parse/ParsedRawSyntaxRecorder.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,16 @@ class ParsedRawSyntaxRecorder {
6060
/// \p kind. Missing optional elements are represented with a null
6161
/// ParsedRawSyntaxNode object.
6262
ParsedRawSyntaxNode recordRawSyntax(syntax::SyntaxKind kind,
63-
ArrayRef<ParsedRawSyntaxNode> elements);
63+
MutableArrayRef<ParsedRawSyntaxNode> elements);
6464

6565
/// Record a raw syntax collecton without eny elements. \p loc can be invalid
6666
/// or an approximate location of where an element of the collection would be
6767
/// if not missing.
6868
ParsedRawSyntaxNode recordEmptyRawSyntaxCollection(syntax::SyntaxKind kind,
6969
SourceLoc loc);
7070

71+
void discardRecordedNode(ParsedRawSyntaxNode &node);
72+
7173
/// Used for incremental re-parsing.
7274
ParsedRawSyntaxNode lookupNode(size_t lexerOffset, SourceLoc loc,
7375
syntax::SyntaxKind kind);

include/swift/Parse/ParsedSyntax.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class ParsedSyntax {
2626
: RawNode(std::move(rawNode)) {}
2727

2828
const ParsedRawSyntaxNode &getRaw() const { return RawNode; }
29+
ParsedRawSyntaxNode takeRaw() { return std::move(RawNode); }
2930
syntax::SyntaxKind getKind() const { return RawNode.getKind(); }
3031

3132
/// Returns true if the syntax node is of the given type.
@@ -39,7 +40,7 @@ class ParsedSyntax {
3940
template <typename T>
4041
T castTo() const {
4142
assert(is<T>() && "castTo<T>() node of incompatible type!");
42-
return T { RawNode };
43+
return T { RawNode.copyDeferred() };
4344
}
4445

4546
/// If this Syntax node is of the right kind, cast and return it,
@@ -52,6 +53,10 @@ class ParsedSyntax {
5253
return llvm::None;
5354
}
5455

56+
ParsedSyntax copyDeferred() const {
57+
return ParsedSyntax { RawNode.copyDeferred() };
58+
}
59+
5560
static bool kindof(syntax::SyntaxKind Kind) {
5661
return true;
5762
}
@@ -65,7 +70,7 @@ class ParsedSyntax {
6570
class ParsedTokenSyntax final : public ParsedSyntax {
6671
public:
6772
explicit ParsedTokenSyntax(ParsedRawSyntaxNode rawNode)
68-
: ParsedSyntax(rawNode) {}
73+
: ParsedSyntax(std::move(rawNode)) {}
6974

7075
tok getTokenKind() const {
7176
return getRaw().getTokenKind();

include/swift/Parse/ParsedSyntaxRecorder.h.gyb

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,32 +53,32 @@ public:
5353
% elif node.is_syntax_collection():
5454
private:
5555
static Parsed${node.name} record${node.syntax_kind}(
56-
ArrayRef<Parsed${node.collection_element_type}> elts,
56+
MutableArrayRef<Parsed${node.collection_element_type}> elts,
5757
ParsedRawSyntaxRecorder &rec);
5858

5959
public:
6060
static Parsed${node.name} defer${node.syntax_kind}(
61-
ArrayRef<Parsed${node.collection_element_type}> elts,
61+
MutableArrayRef<Parsed${node.collection_element_type}> elts,
6262
SyntaxParsingContext &SPCtx);
6363
static Parsed${node.name} make${node.syntax_kind}(
64-
ArrayRef<Parsed${node.collection_element_type}> elts,
64+
MutableArrayRef<Parsed${node.collection_element_type}> elts,
6565
SyntaxParsingContext &SPCtx);
6666

6767
static Parsed${node.name} makeBlank${node.syntax_kind}(SourceLoc loc,
6868
SyntaxParsingContext &SPCtx);
6969
% elif node.is_unknown():
7070
private:
7171
static Parsed${node.name} record${node.syntax_kind}(
72-
ArrayRef<ParsedSyntax> elts,
72+
MutableArrayRef<ParsedSyntax> elts,
7373
ParsedRawSyntaxRecorder &rec);
7474

7575
public:
7676
static Parsed${node.name} defer${node.syntax_kind}(
77-
ArrayRef<ParsedSyntax> elts,
77+
MutableArrayRef<ParsedSyntax> elts,
7878
SyntaxParsingContext &SPCtx);
7979

8080
static Parsed${node.name} make${node.syntax_kind}(
81-
ArrayRef<ParsedSyntax> elts,
81+
MutableArrayRef<ParsedSyntax> elts,
8282
SyntaxParsingContext &SPCtx);
8383
% end
8484
% end
@@ -95,18 +95,21 @@ public:
9595
/// optional trailing comma.
9696
static ParsedTupleTypeElementSyntax
9797
makeTupleTypeElement(ParsedTypeSyntax Type,
98-
Optional<ParsedTokenSyntax> TrailingComma,
99-
SyntaxParsingContext &SPCtx);
98+
Optional<ParsedTokenSyntax> TrailingComma,
99+
SyntaxParsingContext &SPCtx);
100100

101101
/// The provided \c elements are in the appropriate order for the syntax
102102
/// \c kind's layout but optional elements are not be included.
103103
/// This function will form the exact layout based on the provided elements,
104104
/// substituting missing parts with a null ParsedRawSyntaxNode object.
105105
///
106106
/// \returns true if the layout could be formed, false otherwise.
107-
static bool formExactLayoutFor(syntax::SyntaxKind kind,
108-
ArrayRef<ParsedRawSyntaxNode> elements,
109-
function_ref<void(syntax::SyntaxKind, ArrayRef<ParsedRawSyntaxNode>)> receiver);
107+
static bool
108+
formExactLayoutFor(syntax::SyntaxKind kind,
109+
MutableArrayRef<ParsedRawSyntaxNode> elements,
110+
function_ref<void(syntax::SyntaxKind,
111+
MutableArrayRef<ParsedRawSyntaxNode>)>
112+
receiver);
110113
};
111114
}
112115

include/swift/Parse/SyntaxParseActions.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ class SyntaxParseActions {
6161
ArrayRef<OpaqueSyntaxNode> elements,
6262
CharSourceRange range) = 0;
6363

64+
/// Discard raw syntax node.
65+
///
66+
/// FIXME: This breaks invariant that any recorded node will be a part of the
67+
/// result SourceFile syntax. This method is a temporary workaround, and
68+
/// should be removed when we fully migrate to libSyntax parsing.
69+
virtual void discardRecordedNode(OpaqueSyntaxNode node) = 0;
70+
6471
/// Used for incremental re-parsing.
6572
virtual std::pair<size_t, OpaqueSyntaxNode>
6673
lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) {

0 commit comments

Comments
 (0)