Skip to content

Commit 1f1eab6

Browse files
committed
[Parse/Syntax] Replace ParsedSyntaxRecorder::record* calls from the parser with ParsedSyntaxRecorder::make*
Doing a "direct ParsedSyntaxRecorder::record[some syntax]" call from the parser is not a good idea due to possibility of being in a backtracking context when the call is made. Replace them with "ParsedSyntaxRecorder::make[some syntax]" which will implicitly check for backtracking and create a recorded or deferred node accordingly.
1 parent 48f6a21 commit 1f1eab6

File tree

9 files changed

+115
-71
lines changed

9 files changed

+115
-71
lines changed

include/swift/Parse/ParsedSyntaxBuilders.h.gyb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,28 @@
2323

2424
#include "swift/Parse/ParsedRawSyntaxNode.h"
2525
#include "swift/Parse/ParsedSyntaxNodes.h"
26+
#include "swift/Parse/SyntaxParsingContext.h"
2627

2728
namespace swift {
2829

2930
class ParsedRawSyntaxRecorder;
31+
class SyntaxParsingContext;
3032

3133
% for node in SYNTAX_NODES:
3234
% if node.is_buildable():
3335
% child_count = len(node.children)
3436
class Parsed${node.name}Builder {
3537
ParsedRawSyntaxRecorder &Rec;
38+
bool IsBacktracking;
3639
ParsedRawSyntaxNode Layout[${child_count}] = {
3740
% for child in node.children:
3841
ParsedRawSyntaxNode::null(),
3942
% end
4043
};
4144

4245
public:
43-
explicit Parsed${node.name}Builder(ParsedRawSyntaxRecorder &rec) : Rec(rec) {}
46+
explicit Parsed${node.name}Builder(SyntaxParsingContext &SPCtx)
47+
: Rec(SPCtx.getRecorder()), IsBacktracking(SPCtx.isBacktracking()) {}
4448

4549
% for child in node.children:
4650
Parsed${node.name}Builder &use${child.name}(Parsed${child.type_name} ${child.name});
@@ -52,10 +56,11 @@ public:
5256
% end
5357
% end
5458

55-
Parsed${node.name} record();
59+
Parsed${node.name} build();
5660
Parsed${node.name} makeDeferred();
5761

5862
private:
63+
Parsed${node.name} record();
5964
void finishLayout();
6065
};
6166

include/swift/Parse/ParsedSyntaxRecorder.h.gyb

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
namespace swift {
2828

2929
class ParsedRawSyntaxRecorder;
30+
class SyntaxParsingContext;
3031

3132
struct ParsedSyntaxRecorder {
3233

@@ -41,19 +42,28 @@ struct ParsedSyntaxRecorder {
4142
% child_params.append("%s %s" % (param_type, child.name))
4243
% end
4344
% child_params = ', '.join(child_params)
45+
private:
4446
static Parsed${node.name} record${node.syntax_kind}(${child_params},
4547
ParsedRawSyntaxRecorder &rec);
46-
48+
public:
4749
static Parsed${node.name} defer${node.syntax_kind}(${child_params});
50+
static Parsed${node.name} make${node.syntax_kind}(${child_params},
51+
SyntaxParsingContext &SPCtx);
4852
% elif node.is_syntax_collection():
53+
private:
4954
static Parsed${node.name} record${node.syntax_kind}(
50-
ArrayRef<Parsed${node.collection_element_type}> &elts,
55+
ArrayRef<Parsed${node.collection_element_type}> elts,
5156
ParsedRawSyntaxRecorder &rec);
5257

58+
public:
5359
static Parsed${node.name} defer${node.syntax_kind}(
54-
ArrayRef<Parsed${node.collection_element_type}> &elts);
60+
ArrayRef<Parsed${node.collection_element_type}> elts);
61+
static Parsed${node.name} make${node.syntax_kind}(
62+
ArrayRef<Parsed${node.collection_element_type}> elts,
63+
SyntaxParsingContext &SPCtx);
5564

56-
static Parsed${node.name} recordBlank${node.syntax_kind}(SourceLoc loc, ParsedRawSyntaxRecorder &rec);
65+
static Parsed${node.name} makeBlank${node.syntax_kind}(SourceLoc loc,
66+
SyntaxParsingContext &SPCtx);
5767
% end
5868
% end
5969

@@ -62,9 +72,9 @@ struct ParsedSyntaxRecorder {
6272
/// Records an unlabelled TupleTypeElementSyntax with the provided type and
6373
/// optional trailing comma.
6474
static ParsedTupleTypeElementSyntax
65-
recordTupleTypeElement(ParsedTypeSyntax Type,
75+
makeTupleTypeElement(ParsedTypeSyntax Type,
6676
Optional<ParsedTokenSyntax> TrailingComma,
67-
ParsedRawSyntaxRecorder &rec);
77+
SyntaxParsingContext &SPCtx);
6878

6979
/// The provided \c elements are in the appropriate order for the syntax
7080
/// \c kind's layout but optional elements are not be included.

include/swift/Parse/SyntaxParsingContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,8 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
302302
IsBacktracking = true;
303303
}
304304

305+
bool isBacktracking() const { return IsBacktracking; }
306+
305307
/// Explicitly finalizing syntax tree creation.
306308
/// This function will be called during the destroying of a root syntax
307309
/// parsing context. However, we can explicitly call this function to get

lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4419,8 +4419,7 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags,
44194419
if (SyntaxContext->isEnabled()) {
44204420
SourceLoc listLoc = accessors.LBLoc.getAdvancedLoc(1);
44214421
SyntaxContext->addSyntax(
4422-
ParsedSyntaxRecorder::recordBlankAccessorList(listLoc,
4423-
SyntaxContext->getRecorder()));
4422+
ParsedSyntaxRecorder::makeBlankAccessorList(listLoc, *SyntaxContext));
44244423
}
44254424
accessors.RBLoc = consumeToken(tok::r_brace);
44264425

lib/Parse/ParseExpr.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,8 +1266,8 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
12661266
if (SyntaxContext->isEnabled()) {
12671267
// Add dummy blank argument list to the call expression syntax.
12681268
SyntaxContext->addSyntax(
1269-
ParsedSyntaxRecorder::recordBlankFunctionCallArgumentList(
1270-
Tok.getLoc(), SyntaxContext->getRecorder()));
1269+
ParsedSyntaxRecorder::makeBlankFunctionCallArgumentList(
1270+
Tok.getLoc(), *SyntaxContext));
12711271
}
12721272

12731273
ParserResult<Expr> closure =
@@ -1556,10 +1556,9 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
15561556
: VarDecl::Specifier::Var;
15571557
auto pattern = createBindingFromPattern(loc, name, specifier);
15581558
if (SyntaxContext->isEnabled()) {
1559-
auto &rec = SyntaxContext->getRecorder();
15601559
ParsedPatternSyntax PatternNode =
1561-
ParsedSyntaxRecorder::recordIdentifierPattern(
1562-
SyntaxContext->popToken(), rec);
1560+
ParsedSyntaxRecorder::makeIdentifierPattern(
1561+
SyntaxContext->popToken(), *SyntaxContext);
15631562
ParsedExprSyntax ExprNode =
15641563
ParsedSyntaxRecorder::deferUnresolvedPatternExpr(PatternNode);
15651564
SyntaxContext->addSyntax(ExprNode);
@@ -1669,8 +1668,8 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
16691668
if (SyntaxContext->isEnabled()) {
16701669
// Add dummy blank argument list to the call expression syntax.
16711670
SyntaxContext->addSyntax(
1672-
ParsedSyntaxRecorder::recordBlankFunctionCallArgumentList(
1673-
Tok.getLoc(), SyntaxContext->getRecorder()));
1671+
ParsedSyntaxRecorder::makeBlankFunctionCallArgumentList(
1672+
Tok.getLoc(), *SyntaxContext));
16741673
}
16751674

16761675
ParserResult<Expr> closure =
@@ -2170,8 +2169,8 @@ DeclName Parser::parseUnqualifiedDeclName(bool afterDot,
21702169
consumeToken(tok::l_paren);
21712170
if (SyntaxContext->isEnabled())
21722171
SyntaxContext->addSyntax(
2173-
ParsedSyntaxRecorder::recordBlankDeclNameArgumentList(
2174-
Tok.getLoc(), SyntaxContext->getRecorder()));
2172+
ParsedSyntaxRecorder::makeBlankDeclNameArgumentList(
2173+
Tok.getLoc(), *SyntaxContext));
21752174
consumeToken(tok::r_paren);
21762175
loc = DeclNameLoc(baseNameLoc);
21772176
SmallVector<Identifier, 2> argumentLabels;
@@ -3366,8 +3365,8 @@ ParserResult<Expr> Parser::parseExprCollection() {
33663365
if (Tok.is(tok::r_square)) {
33673366
if (SyntaxContext->isEnabled())
33683367
SyntaxContext->addSyntax(
3369-
ParsedSyntaxRecorder::recordBlankArrayElementList(
3370-
Tok.getLoc(), SyntaxContext->getRecorder()));
3368+
ParsedSyntaxRecorder::makeBlankArrayElementList(
3369+
Tok.getLoc(), *SyntaxContext));
33713370
RSquareLoc = consumeToken(tok::r_square);
33723371
ArrayOrDictContext.setCreateSyntax(SyntaxKind::ArrayExpr);
33733372
return makeParserResult(

lib/Parse/ParseType.cpp

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,15 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(Diag<> MessageID,
216216
auto makeMetatypeTypeSyntax = [&]() {
217217
if (!SyntaxContext->isEnabled())
218218
return;
219-
ParsedMetatypeTypeSyntaxBuilder Builder(SyntaxContext->getRecorder());
219+
ParsedMetatypeTypeSyntaxBuilder Builder(*SyntaxContext);
220220
auto TypeOrProtocol = SyntaxContext->popToken();
221221
auto Period = SyntaxContext->popToken();
222222
auto BaseType = SyntaxContext->popIf<ParsedTypeSyntax>().getValue();
223223
Builder
224224
.useTypeOrProtocol(TypeOrProtocol)
225225
.usePeriod(Period)
226226
.useBaseType(BaseType);
227-
SyntaxContext->addSyntax(Builder.record());
227+
SyntaxContext->addSyntax(Builder.build());
228228
};
229229

230230
// '.Type', '.Protocol', '?', '!', and '[]' still leave us with type-simple.
@@ -425,7 +425,7 @@ ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
425425
return nullptr;
426426

427427
if (SyntaxContext->isEnabled()) {
428-
ParsedFunctionTypeSyntaxBuilder Builder(SyntaxContext->getRecorder());
428+
ParsedFunctionTypeSyntaxBuilder Builder(*SyntaxContext);
429429
Builder.useReturnType(SyntaxContext->popIf<ParsedTypeSyntax>().getValue());
430430
Builder.useArrow(SyntaxContext->popToken());
431431
if (throwsLoc.isValid())
@@ -442,10 +442,10 @@ ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
442442
.useArguments(Arguments)
443443
.useRightParen(RightParen);
444444
} else {
445-
Builder.addTupleTypeElement(ParsedSyntaxRecorder::recordTupleTypeElement(
446-
InputNode, /*TrailingComma=*/None, SyntaxContext->getRecorder()));
445+
Builder.addTupleTypeElement(ParsedSyntaxRecorder::makeTupleTypeElement(
446+
InputNode, /*TrailingComma=*/None, *SyntaxContext));
447447
}
448-
SyntaxContext->addSyntax(Builder.record());
448+
SyntaxContext->addSyntax(Builder.build());
449449
}
450450

451451
TupleTypeRepr *argsTyR = nullptr;
@@ -708,13 +708,13 @@ Parser::parseTypeSimpleOrComposition(Diag<> MessageID,
708708
consumeToken(); // consume '&'
709709

710710
if (SyntaxContext->isEnabled() && Status.isSuccess()) {
711-
ParsedCompositionTypeElementSyntaxBuilder Builder(SyntaxContext->getRecorder());
711+
ParsedCompositionTypeElementSyntaxBuilder Builder(*SyntaxContext);
712712
auto Ampersand = SyntaxContext->popToken();
713713
auto Type = SyntaxContext->popIf<ParsedTypeSyntax>().getValue();
714714
Builder
715715
.useAmpersand(Ampersand)
716716
.useType(Type);
717-
SyntaxContext->addSyntax(Builder.record());
717+
SyntaxContext->addSyntax(Builder.build());
718718
}
719719

720720
// Parse next type.
@@ -727,9 +727,9 @@ Parser::parseTypeSimpleOrComposition(Diag<> MessageID,
727727
} while (Tok.isContextualPunctuator("&"));
728728

729729
if (SyntaxContext->isEnabled() && Status.isSuccess()) {
730-
auto LastNode = ParsedSyntaxRecorder::recordCompositionTypeElement(
730+
auto LastNode = ParsedSyntaxRecorder::makeCompositionTypeElement(
731731
SyntaxContext->popIf<ParsedTypeSyntax>().getValue(), None,
732-
SyntaxContext->getRecorder());
732+
*SyntaxContext);
733733
SyntaxContext->addSyntax(LastNode);
734734
}
735735
SyntaxContext->collectNodesInPlace(SyntaxKind::CompositionTypeElementList);
@@ -1122,7 +1122,7 @@ SyntaxParserResult<ParsedTypeSyntax, TypeRepr> Parser::parseTypeCollection() {
11221122
TyR = new (Context)
11231123
DictionaryTypeRepr(firstTy.get(), secondTy.get(), colonLoc, brackets);
11241124
if (SyntaxContext->isEnabled()) {
1125-
ParsedDictionaryTypeSyntaxBuilder Builder(SyntaxContext->getRecorder());
1125+
ParsedDictionaryTypeSyntaxBuilder Builder(*SyntaxContext);
11261126
auto RightSquareBracket = SyntaxContext->popToken();
11271127
auto ValueType = SyntaxContext->popIf<ParsedTypeSyntax>().getValue();
11281128
auto Colon = SyntaxContext->popToken();
@@ -1134,21 +1134,21 @@ SyntaxParserResult<ParsedTypeSyntax, TypeRepr> Parser::parseTypeCollection() {
11341134
.useColon(Colon)
11351135
.useKeyType(KeyType)
11361136
.useLeftSquareBracket(LeftSquareBracket);
1137-
SyntaxNode.emplace(Builder.record());
1137+
SyntaxNode.emplace(Builder.build());
11381138
}
11391139
} else {
11401140
// Form the array type.
11411141
TyR = new (Context) ArrayTypeRepr(firstTy.get(), brackets);
11421142
if (SyntaxContext->isEnabled()) {
1143-
ParsedArrayTypeSyntaxBuilder Builder(SyntaxContext->getRecorder());
1143+
ParsedArrayTypeSyntaxBuilder Builder(*SyntaxContext);
11441144
auto RightSquareBracket = SyntaxContext->popToken();
11451145
auto ElementType = SyntaxContext->popIf<ParsedTypeSyntax>().getValue();
11461146
auto LeftSquareBracket = SyntaxContext->popToken();
11471147
Builder
11481148
.useRightSquareBracket(RightSquareBracket)
11491149
.useElementType(ElementType)
11501150
.useLeftSquareBracket(LeftSquareBracket);
1151-
SyntaxNode.emplace(Builder.record());
1151+
SyntaxNode.emplace(Builder.build());
11521152
}
11531153
}
11541154

@@ -1205,11 +1205,11 @@ Parser::parseTypeOptional(TypeRepr *base) {
12051205
if (SyntaxContext->isEnabled()) {
12061206
auto QuestionMark = SyntaxContext->popToken();
12071207
if (auto WrappedType = SyntaxContext->popIf<ParsedTypeSyntax>()) {
1208-
ParsedOptionalTypeSyntaxBuilder Builder(SyntaxContext->getRecorder());
1208+
ParsedOptionalTypeSyntaxBuilder Builder(*SyntaxContext);
12091209
Builder
12101210
.useQuestionMark(QuestionMark)
12111211
.useWrappedType(WrappedType.getValue());
1212-
SyntaxNode.emplace(Builder.record());
1212+
SyntaxNode.emplace(Builder.build());
12131213
} else {
12141214
// Undo the popping of the question mark
12151215
SyntaxContext->addSyntax(QuestionMark);
@@ -1227,14 +1227,13 @@ Parser::parseTypeImplicitlyUnwrappedOptional(TypeRepr *base) {
12271227
new (Context) ImplicitlyUnwrappedOptionalTypeRepr(base, exclamationLoc);
12281228
llvm::Optional<ParsedTypeSyntax> SyntaxNode;
12291229
if (SyntaxContext->isEnabled()) {
1230-
ParsedImplicitlyUnwrappedOptionalTypeSyntaxBuilder Builder(
1231-
SyntaxContext->getRecorder());
1230+
ParsedImplicitlyUnwrappedOptionalTypeSyntaxBuilder Builder(*SyntaxContext);
12321231
auto ExclamationMark = SyntaxContext->popToken();
12331232
auto WrappedType = SyntaxContext->popIf<ParsedTypeSyntax>().getValue();
12341233
Builder
12351234
.useExclamationMark(ExclamationMark)
12361235
.useWrappedType(WrappedType);
1237-
SyntaxNode.emplace(Builder.record());
1236+
SyntaxNode.emplace(Builder.build());
12381237
}
12391238
return makeSyntaxResult(SyntaxNode, TyR);
12401239
}

lib/Parse/ParsedSyntaxBuilders.cpp.gyb

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "swift/Parse/ParsedSyntaxBuilders.h"
2222
#include "swift/Parse/ParsedRawSyntaxRecorder.h"
23+
#include "swift/Parse/SyntaxParsingContext.h"
2324
#include "swift/Syntax/SyntaxNodes.h"
2425

2526
using namespace swift;
@@ -56,27 +57,41 @@ Parsed${node.name}Builder::record() {
5657
finishLayout();
5758
auto raw = Rec.recordExactRawSyntax(SyntaxKind::${node.syntax_kind},
5859
Layout);
59-
return Parsed${node.name}(raw);
60+
return Parsed${node.name}(std::move(raw));
6061
}
6162

6263
Parsed${node.name}
6364
Parsed${node.name}Builder::makeDeferred() {
6465
finishLayout();
6566
auto raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind},
6667
Layout);
67-
return Parsed${node.name}(raw);
68+
return Parsed${node.name}(std::move(raw));
69+
}
70+
71+
Parsed${node.name}
72+
Parsed${node.name}Builder::build() {
73+
if (IsBacktracking)
74+
return makeDeferred();
75+
return record();
6876
}
6977

7078
void Parsed${node.name}Builder::finishLayout() {
7179
% if node.children:
7280
% for (idx, child) in enumerate(node.children):
7381
% if not child.is_optional:
74-
if (Layout[${idx}].isNull())
82+
if (Layout[${idx}].isNull()) {
7583
% if child.is_token():
76-
Layout[${idx}] = ${make_missing_parsed_child(child)};
84+
% token = child.main_token()
85+
% tok_kind = token.kind if token else "unknown"
86+
if (IsBacktracking) {
87+
Layout[${idx}] = ParsedRawSyntaxNode::makeDeferredMissing(tok::${tok_kind}, SourceLoc());
88+
} else {
89+
Layout[${idx}] = Rec.recordMissingToken(tok::${tok_kind}, SourceLoc());
90+
}
7791
% else:
7892
llvm_unreachable("need missing non-token nodes ?");
7993
% end
94+
}
8095
% end
8196
% end
8297
% end

0 commit comments

Comments
 (0)