Skip to content

Commit fc168e4

Browse files
authored
Merge pull request #27707 from rintaro/syntaxparse-rawnode-moveonly
[SyntaxParse] Re-apply move-only ParsedRawSyntaxNode to master
2 parents 52035c1 + f321486 commit fc168e4

25 files changed

+412
-224
lines changed

include/swift/Parse/ParsedRawSyntaxNode.h

Lines changed: 108 additions & 5 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,47 @@ class ParsedRawSyntaxNode {
115117
assert(getTokenKind() == tokKind && "Token kind with too large value!");
116118
}
117119

120+
#ifndef NDEBUG
121+
bool ensureDataIsNotRecorded() {
122+
if (DK != DataKind::Recorded)
123+
return true;
124+
llvm::dbgs() << "Leaking node: ";
125+
dump(llvm::dbgs());
126+
llvm::dbgs() << "\n";
127+
return false;
128+
}
129+
#endif
130+
131+
ParsedRawSyntaxNode &operator=(ParsedRawSyntaxNode &&other) {
132+
assert(ensureDataIsNotRecorded() &&
133+
"recorded data is being destroyed by assignment");
134+
switch (other.DK) {
135+
case DataKind::Null:
136+
break;
137+
case DataKind::Recorded:
138+
RecordedData = std::move(other.RecordedData);
139+
break;
140+
case DataKind::DeferredLayout:
141+
DeferredLayout = std::move(other.DeferredLayout);
142+
break;
143+
case DataKind::DeferredToken:
144+
DeferredToken = std::move(other.DeferredToken);
145+
break;
146+
}
147+
SynKind = std::move(other.SynKind);
148+
TokKind = std::move(other.TokKind);
149+
DK = std::move(other.DK);
150+
IsMissing = std::move(other.IsMissing);
151+
other.reset();
152+
return *this;
153+
}
154+
ParsedRawSyntaxNode(ParsedRawSyntaxNode &&other) : ParsedRawSyntaxNode() {
155+
*this = std::move(other);
156+
}
157+
~ParsedRawSyntaxNode() {
158+
assert(ensureDataIsNotRecorded() && "recorded data is being destructed");
159+
}
160+
118161
syntax::SyntaxKind getKind() const { return syntax::SyntaxKind(SynKind); }
119162
tok getTokenKind() const { return tok(TokKind); }
120163

@@ -136,16 +179,52 @@ class ParsedRawSyntaxNode {
136179
/// Primary used for a deferred missing token.
137180
bool isMissing() const { return IsMissing; }
138181

182+
void reset() {
183+
RecordedData = {};
184+
SynKind = uint16_t(syntax::SyntaxKind::Unknown);
185+
TokKind = uint16_t(tok::unknown);
186+
DK = DataKind::Null;
187+
IsMissing = false;
188+
}
189+
190+
ParsedRawSyntaxNode unsafeCopy() const {
191+
ParsedRawSyntaxNode copy;
192+
switch (DK) {
193+
case DataKind::DeferredLayout:
194+
copy.DeferredLayout = DeferredLayout;
195+
break;
196+
case DataKind::DeferredToken:
197+
copy.DeferredToken = DeferredToken;
198+
break;
199+
case DataKind::Recorded:
200+
copy.RecordedData = RecordedData;
201+
break;
202+
case DataKind::Null:
203+
break;
204+
}
205+
copy.SynKind = SynKind;
206+
copy.TokKind = TokKind;
207+
copy.DK = DK;
208+
copy.IsMissing = IsMissing;
209+
return copy;
210+
}
211+
139212
// Recorded Data ===========================================================//
140213

141214
CharSourceRange getRange() const {
142215
assert(isRecorded());
143216
return RecordedData.Range;
144217
}
145-
OpaqueSyntaxNode getOpaqueNode() const {
218+
const OpaqueSyntaxNode &getOpaqueNode() const {
146219
assert(isRecorded());
147220
return RecordedData.OpaqueNode;
148221
}
222+
OpaqueSyntaxNode takeOpaqueNode() {
223+
assert(isRecorded());
224+
auto opaque = RecordedData.OpaqueNode;
225+
reset();
226+
return opaque;
227+
}
149228

150229
// Deferred Layout Data ====================================================//
151230

@@ -154,6 +233,30 @@ class ParsedRawSyntaxNode {
154233
return DeferredLayout.Children;
155234
}
156235

236+
MutableArrayRef<ParsedRawSyntaxNode> getDeferredChildren() {
237+
assert(DK == DataKind::DeferredLayout);
238+
return DeferredLayout.Children;
239+
}
240+
241+
ParsedRawSyntaxNode copyDeferred() const {
242+
ParsedRawSyntaxNode copy;
243+
switch (DK) {
244+
case DataKind::DeferredLayout:
245+
copy.DeferredLayout = DeferredLayout;
246+
break;
247+
case DataKind::DeferredToken:
248+
copy.DeferredToken = DeferredToken;
249+
break;
250+
default:
251+
llvm_unreachable("node not deferred");
252+
}
253+
copy.SynKind = SynKind;
254+
copy.TokKind = TokKind;
255+
copy.DK = DK;
256+
copy.IsMissing = IsMissing;
257+
return copy;
258+
}
259+
157260
// Deferred Token Data =====================================================//
158261

159262
CharSourceRange getDeferredTokenRange() const {
@@ -176,7 +279,7 @@ class ParsedRawSyntaxNode {
176279

177280
/// Form a deferred syntax layout node.
178281
static ParsedRawSyntaxNode makeDeferred(syntax::SyntaxKind k,
179-
ArrayRef<ParsedRawSyntaxNode> deferredNodes,
282+
MutableArrayRef<ParsedRawSyntaxNode> deferredNodes,
180283
SyntaxParsingContext &ctx);
181284

182285
/// 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: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,15 @@ 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,
@@ -75,18 +75,21 @@ public:
7575
/// optional trailing comma.
7676
static ParsedTupleTypeElementSyntax
7777
makeTupleTypeElement(ParsedTypeSyntax Type,
78-
Optional<ParsedTokenSyntax> TrailingComma,
79-
SyntaxParsingContext &SPCtx);
78+
Optional<ParsedTokenSyntax> TrailingComma,
79+
SyntaxParsingContext &SPCtx);
8080

8181
/// The provided \c elements are in the appropriate order for the syntax
8282
/// \c kind's layout but optional elements are not be included.
8383
/// This function will form the exact layout based on the provided elements,
8484
/// substituting missing parts with a null ParsedRawSyntaxNode object.
8585
///
8686
/// \returns true if the layout could be formed, false otherwise.
87-
static bool formExactLayoutFor(syntax::SyntaxKind kind,
88-
ArrayRef<ParsedRawSyntaxNode> elements,
89-
function_ref<void(syntax::SyntaxKind, ArrayRef<ParsedRawSyntaxNode>)> receiver);
87+
static bool
88+
formExactLayoutFor(syntax::SyntaxKind kind,
89+
MutableArrayRef<ParsedRawSyntaxNode> elements,
90+
function_ref<void(syntax::SyntaxKind,
91+
MutableArrayRef<ParsedRawSyntaxNode>)>
92+
receiver);
9093
};
9194
}
9295

include/swift/Parse/Parser.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,22 @@ class Parser {
358358
};
359359
friend class StructureMarkerRAII;
360360

361+
/// A RAII object that tells the SyntaxParsingContext to defer Syntax nodes.
362+
class DeferringContextRAII {
363+
SyntaxParsingContext &Ctx;
364+
bool WasDeferring;
365+
366+
public:
367+
explicit DeferringContextRAII(SyntaxParsingContext &SPCtx)
368+
: Ctx(SPCtx), WasDeferring(Ctx.shouldDefer()) {
369+
Ctx.setShouldDefer();
370+
}
371+
372+
~DeferringContextRAII() {
373+
Ctx.setShouldDefer(WasDeferring);
374+
}
375+
};
376+
361377
/// The stack of structure markers indicating the locations of
362378
/// structural elements actively being parsed, including the start
363379
/// of declarations, statements, and opening operators of various
@@ -390,7 +406,7 @@ class Parser {
390406

391407
/// Calling this function to finalize libSyntax tree creation without destroying
392408
/// the parser instance.
393-
ParsedRawSyntaxNode finalizeSyntaxTree() {
409+
OpaqueSyntaxNode finalizeSyntaxTree() {
394410
assert(Tok.is(tok::eof) && "not done parsing yet");
395411
return SyntaxContext->finalizeRoot();
396412
}

include/swift/Parse/SyntaxParseActions.h

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

58+
/// Discard raw syntax node.
59+
///
60+
/// FIXME: This breaks invariant that any recorded node will be a part of the
61+
/// result SourceFile syntax. This method is a temporary workaround, and
62+
/// should be removed when we fully migrate to libSyntax parsing.
63+
virtual void discardRecordedNode(OpaqueSyntaxNode node) = 0;
64+
5865
/// Used for incremental re-parsing.
5966
virtual std::pair<size_t, OpaqueSyntaxNode>
6067
lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) {

include/swift/Parse/SyntaxParserResult.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@ template <typename Syntax, typename AST> class SyntaxParserResult {
2929
: SyntaxNode(None), ASTResult(nullptr) {}
3030
SyntaxParserResult(ParserStatus Status)
3131
: SyntaxNode(None), ASTResult(Status) {}
32-
SyntaxParserResult(llvm::Optional<Syntax> SyntaxNode, AST *ASTNode)
33-
: SyntaxNode(SyntaxNode), ASTResult(ASTNode) {}
34-
SyntaxParserResult(ParserStatus Status, llvm::Optional<Syntax> SyntaxNode,
32+
SyntaxParserResult(llvm::Optional<Syntax> &&SyntaxNode, AST *ASTNode)
33+
: SyntaxNode(std::move(SyntaxNode)), ASTResult(ASTNode) {}
34+
SyntaxParserResult(ParserStatus Status, llvm::Optional<Syntax> &&SyntaxNode,
3535
AST *ASTNode)
36-
: SyntaxNode(SyntaxNode), ASTResult(makeParserResult(Status, ASTNode)) {}
36+
: SyntaxNode(std::move(SyntaxNode)), ASTResult(makeParserResult(Status, ASTNode)) {}
3737

3838
/// Convert from a different but compatible parser result.
3939
template <typename U, typename Enabler = typename std::enable_if<
4040
std::is_base_of<AST, U>::value>::type>
41-
SyntaxParserResult(SyntaxParserResult<Syntax, U> Other)
42-
: SyntaxNode(Other.SyntaxNode), ASTResult(Other.ASTResult) {}
41+
SyntaxParserResult(SyntaxParserResult<Syntax, U> &&Other)
42+
: SyntaxNode(std::move(Other.SyntaxNode)), ASTResult(Other.ASTResult) {}
4343

4444

4545
bool isNull() const { return ASTResult.isNull(); }
@@ -58,9 +58,9 @@ template <typename Syntax, typename AST> class SyntaxParserResult {
5858
return SyntaxNode.hasValue();
5959
}
6060

61-
Syntax getSyntax() const {
61+
Syntax getSyntax() {
6262
assert(SyntaxNode.hasValue() && "getSyntax from None value");
63-
return *SyntaxNode;
63+
return std::move(*SyntaxNode);
6464
}
6565

6666
SyntaxParserResult<Syntax, AST> &
@@ -73,16 +73,16 @@ template <typename Syntax, typename AST> class SyntaxParserResult {
7373
/// Create a successful parser result.
7474
template <typename Syntax, typename AST>
7575
static inline SyntaxParserResult<Syntax, AST>
76-
makeSyntaxResult(llvm::Optional<Syntax> SyntaxNode, AST *ASTNode) {
77-
return SyntaxParserResult<Syntax, AST>(SyntaxNode, ASTNode);
76+
makeSyntaxResult(llvm::Optional<Syntax> &&SyntaxNode, AST *ASTNode) {
77+
return SyntaxParserResult<Syntax, AST>(std::move(SyntaxNode), ASTNode);
7878
}
7979

8080
/// Create a result with the specified status.
8181
template <typename Syntax, typename AST>
8282
static inline SyntaxParserResult<Syntax, AST>
83-
makeSyntaxResult(ParserStatus Status, llvm::Optional<Syntax> SyntaxNode,
83+
makeSyntaxResult(ParserStatus Status, llvm::Optional<Syntax> &&SyntaxNode,
8484
AST *ASTNode) {
85-
return SyntaxParserResult<Syntax, AST>(Status, SyntaxNode, ASTNode);
85+
return SyntaxParserResult<Syntax, AST>(Status, std::move(SyntaxNode), ASTNode);
8686
}
8787

8888
/// Create a result (null or non-null) with error and code completion bits set.

0 commit comments

Comments
 (0)