Skip to content

Commit e3046d6

Browse files
committed
Parsing for native keypaths.
Use `#keyPath2` as a stand-in for the final syntax.
1 parent a5ca6cc commit e3046d6

File tree

12 files changed

+483
-209
lines changed

12 files changed

+483
-209
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,9 @@ ERROR(string_interpolation_extra,none,
11531153
"extra tokens after interpolated string expression", ())
11541154

11551155
// Keypath expressions.
1156+
ERROR(expr_keypath_invalid_component,PointsToFirstBadToken,
1157+
"key path can only contain property, subscript, optional chaining, or "
1158+
"optional force-unwrapping components", ())
11561159
ERROR(expr_keypath_expected_lparen,PointsToFirstBadToken,
11571160
"expected '(' following '#keyPath'", ())
11581161
ERROR(expr_keypath_expected_property_or_type,PointsToFirstBadToken,

include/swift/AST/Expr.h

Lines changed: 76 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4544,6 +4544,7 @@ class KeyPathExpr : public Expr {
45444544
SourceLoc KeywordLoc;
45454545
SourceLoc LParenLoc;
45464546
SourceLoc RParenLoc;
4547+
TypeRepr *RootType;
45474548
Expr *ObjCStringLiteralExpr = nullptr;
45484549

45494550
public:
@@ -4577,75 +4578,116 @@ class KeyPathExpr : public Expr {
45774578

45784579
llvm::PointerIntPair<Expr *, 3, Kind> SubscriptIndexExprAndKind;
45794580
Type ComponentType;
4581+
SourceLoc Loc;
45804582

45814583
explicit Component(DeclNameOrRef decl,
45824584
Expr *indexExpr,
45834585
Kind kind,
4584-
Type type)
4586+
Type type,
4587+
SourceLoc loc)
45854588
: Decl(decl), SubscriptIndexExprAndKind(indexExpr, kind),
4586-
ComponentType(type)
4589+
ComponentType(type), Loc(loc)
45874590
{}
45884591

45894592
public:
4590-
Component() : Component({}, nullptr, (Kind)0, Type()) {}
4593+
Component() : Component({}, nullptr, (Kind)0, Type(), SourceLoc()) {}
45914594

45924595
/// Create an unresolved component for a property.
4593-
static Component forUnresolvedProperty(DeclName UnresolvedName) {
4596+
static Component forUnresolvedProperty(DeclName UnresolvedName,
4597+
SourceLoc Loc) {
45944598
return Component(UnresolvedName, nullptr,
45954599
Kind::UnresolvedProperty,
4596-
Type());
4600+
Type(),
4601+
Loc);
45974602
}
45984603

45994604
/// Create an unresolved component for a subscript.
4600-
static Component forUnresolvedSubscript(Expr *UnresolvedSubscriptIndex) {
4601-
return Component({}, UnresolvedSubscriptIndex,
4602-
Kind::UnresolvedSubscript,
4603-
Type());
4605+
static Component forUnresolvedSubscript(ASTContext &ctx,
4606+
SourceLoc lSquareLoc,
4607+
ArrayRef<Expr *> indexArgs,
4608+
ArrayRef<Identifier> indexArgLabels,
4609+
ArrayRef<SourceLoc> indexArgLabelLocs,
4610+
SourceLoc rSquareLoc,
4611+
Expr *trailingClosure);
4612+
4613+
/// Create an unresolved component for a subscript.
4614+
///
4615+
/// You shouldn't add new uses of this overload; use the one that takes a
4616+
/// list of index arguments.
4617+
static Component forUnresolvedSubscriptWithPrebuiltIndexExpr(Expr *index,
4618+
SourceLoc loc){
4619+
4620+
return Component({}, index, Kind::UnresolvedSubscript, Type(), loc);
46044621
}
46054622

46064623
/// Create an unresolved optional force `!` component.
4607-
static Component forUnresolvedOptionalForce() {
4624+
static Component forUnresolvedOptionalForce(SourceLoc BangLoc) {
46084625
return Component({}, nullptr,
46094626
Kind::OptionalForce,
4610-
Type());
4627+
Type(),
4628+
BangLoc);
46114629
}
46124630

46134631
/// Create an unresolved optional chain `?` component.
4614-
static Component forUnresolvedOptionalChain() {
4632+
static Component forUnresolvedOptionalChain(SourceLoc QuestionLoc) {
46154633
return Component({}, nullptr,
46164634
Kind::OptionalChain,
4617-
Type());
4635+
Type(),
4636+
QuestionLoc);
46184637
}
46194638

46204639
/// Create a component for a property.
46214640
static Component forProperty(ConcreteDeclRef property,
4622-
Type propertyType) {
4641+
Type propertyType,
4642+
SourceLoc loc) {
46234643
return Component(property, nullptr, Kind::Property,
4624-
propertyType);
4644+
propertyType,
4645+
loc);
46254646
}
46264647

46274648
/// Create a component for a subscript.
4628-
static Component forSubscript(ConcreteDeclRef subscript,
4629-
Expr *indexExpr,
4630-
Type elementType) {
4631-
return Component(subscript, indexExpr, Kind::Subscript, elementType);
4649+
static Component forSubscript(ASTContext &ctx,
4650+
ConcreteDeclRef subscript,
4651+
SourceLoc lSquareLoc,
4652+
ArrayRef<Expr *> indexArgs,
4653+
ArrayRef<Identifier> indexArgLabels,
4654+
ArrayRef<SourceLoc> indexArgLabelLocs,
4655+
SourceLoc rSquareLoc,
4656+
Expr *trailingClosure,
4657+
Type elementType);
4658+
4659+
/// Create a component for a subscript.
4660+
///
4661+
/// You shouldn't add new uses of this overload; use the one that takes a
4662+
/// list of index arguments.
4663+
static Component forSubscriptWithPrebuiltIndexExpr(
4664+
ConcreteDeclRef subscript, Expr *index, Type elementType, SourceLoc loc) {
4665+
return Component(subscript, index, Kind::Subscript, elementType, loc);
46324666
}
46334667

46344668
/// Create an optional-forcing `!` component.
4635-
static Component forOptionalForce(Type forcedType) {
4636-
return Component({}, nullptr, Kind::OptionalForce, forcedType);
4669+
static Component forOptionalForce(Type forcedType, SourceLoc bangLoc) {
4670+
return Component({}, nullptr, Kind::OptionalForce, forcedType,
4671+
bangLoc);
46374672
}
46384673

46394674
/// Create an optional-chaining `?` component.
4640-
static Component forOptionalChain(Type unwrappedType) {
4641-
return Component({}, nullptr, Kind::OptionalChain, unwrappedType);
4675+
static Component forOptionalChain(Type unwrappedType,
4676+
SourceLoc questionLoc) {
4677+
return Component({}, nullptr, Kind::OptionalChain, unwrappedType,
4678+
questionLoc);
46424679
}
46434680

46444681
/// Create an optional-wrapping component. This doesn't have a surface
46454682
/// syntax but may appear when the non-optional result of an optional chain
46464683
/// is implicitly wrapped.
46474684
static Component forOptionalWrap(Type wrappedType) {
4648-
return Component({}, nullptr, Kind::OptionalWrap, wrappedType);
4685+
return Component({}, nullptr, Kind::OptionalWrap, wrappedType,
4686+
SourceLoc());
4687+
}
4688+
4689+
SourceLoc getLoc() const {
4690+
return Loc;
46494691
}
46504692

46514693
Kind getKind() const {
@@ -4702,16 +4744,15 @@ class KeyPathExpr : public Expr {
47024744
}
47034745
};
47044746

4705-
using ComponentAndLoc = std::pair<Component, SourceLoc>;
4706-
47074747
private:
4708-
llvm::MutableArrayRef<ComponentAndLoc> Components;
4748+
llvm::MutableArrayRef<Component> Components;
47094749

47104750
public:
47114751
/// Create a new #keyPath expression.
47124752
KeyPathExpr(ASTContext &C,
47134753
SourceLoc keywordLoc, SourceLoc lParenLoc,
4714-
ArrayRef<ComponentAndLoc> components,
4754+
TypeRepr *root,
4755+
ArrayRef<Component> components,
47154756
SourceLoc rParenLoc,
47164757
bool isObjC,
47174758
bool isImplicit = false);
@@ -4722,7 +4763,7 @@ class KeyPathExpr : public Expr {
47224763
}
47234764

47244765
/// Get the components array.
4725-
ArrayRef<ComponentAndLoc> getComponents() const {
4766+
ArrayRef<Component> getComponents() const {
47264767
return Components;
47274768
}
47284769

@@ -4734,10 +4775,14 @@ class KeyPathExpr : public Expr {
47344775
/// Retrieve the string literal expression, which will be \c NULL prior to
47354776
/// type checking and a string literal after type checking for an
47364777
/// @objc key path.
4737-
Expr *getObjCStringLiteralExpr() const { return ObjCStringLiteralExpr; }
4778+
Expr *getObjCStringLiteralExpr() const {
4779+
return ObjCStringLiteralExpr;
4780+
}
47384781

47394782
/// Set the semantic expression.
4740-
void setObjCStringLiteralExpr(Expr *expr) { ObjCStringLiteralExpr = expr; }
4783+
void setObjCStringLiteralExpr(Expr *expr) {
4784+
ObjCStringLiteralExpr = expr;
4785+
}
47414786

47424787
/// True if this is an ObjC key path expression.
47434788
bool isObjC() const { return KeyPathExprBits.IsObjC; }

include/swift/Parse/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,7 @@ class Parser {
11381138
bool isExprBasic);
11391139
ParserResult<Expr> parseExprPostfix(Diag<> ID, bool isExprBasic);
11401140
ParserResult<Expr> parseExprUnary(Diag<> ID, bool isExprBasic);
1141+
ParserResult<Expr> parseExprKeyPathObjC();
11411142
ParserResult<Expr> parseExprKeyPath();
11421143
ParserResult<Expr> parseExprSelector();
11431144
ParserResult<Expr> parseExprSuper(bool isExprBasic);

include/swift/Syntax/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ POUND_KEYWORD(else)
193193
POUND_KEYWORD(elseif)
194194
POUND_KEYWORD(endif)
195195
POUND_KEYWORD(keyPath)
196+
POUND_KEYWORD(keyPath2) // TODO
196197
POUND_KEYWORD(line)
197198
POUND_KEYWORD(sourceLocation)
198199
POUND_KEYWORD(selector)

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2406,8 +2406,7 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
24062406

24072407
void visitKeyPathExpr(KeyPathExpr *E) {
24082408
printCommon(E, "keypath_expr");
2409-
for (auto &componentAndLoc : E->getComponents()) {
2410-
KeyPathExpr::Component component = componentAndLoc.first;
2409+
for (auto &component : E->getComponents()) {
24112410
OS << '\n';
24122411
OS.indent(Indent + 2);
24132412
OS << "(component=";

lib/AST/ASTWalker.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -907,9 +907,8 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
907907

908908
SmallVector<KeyPathExpr::Component, 4> updatedComponents;
909909
bool didChangeComponents = false;
910-
for (auto &componentAndLoc : E->getComponents()) {
911-
auto component = componentAndLoc.first;
912-
910+
for (auto &origComponent : E->getComponents()) {
911+
auto component = origComponent;
913912
switch (auto kind = component.getKind()) {
914913
case KeyPathExpr::Component::Kind::Subscript:
915914
case KeyPathExpr::Component::Kind::UnresolvedSubscript: {
@@ -919,10 +918,13 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
919918
if (newIndex != origIndex) {
920919
didChangeComponents = true;
921920
component = kind == KeyPathExpr::Component::Kind::Subscript
922-
? KeyPathExpr::Component::forSubscript(component.getDeclRef(),
923-
newIndex,
924-
component.getComponentType())
925-
: KeyPathExpr::Component::forUnresolvedSubscript(newIndex);
921+
? KeyPathExpr::Component::forSubscriptWithPrebuiltIndexExpr(
922+
component.getDeclRef(),
923+
newIndex,
924+
component.getComponentType(),
925+
component.getLoc())
926+
: KeyPathExpr::Component::forUnresolvedSubscriptWithPrebuiltIndexExpr(
927+
newIndex, component.getLoc());
926928
}
927929
break;
928930
}

lib/AST/Expr.cpp

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,13 +1988,15 @@ ArchetypeType *OpenExistentialExpr::getOpenedArchetype() const {
19881988

19891989
KeyPathExpr::KeyPathExpr(ASTContext &C,
19901990
SourceLoc keywordLoc, SourceLoc lParenLoc,
1991-
ArrayRef<ComponentAndLoc> components,
1991+
TypeRepr *root,
1992+
ArrayRef<Component> components,
19921993
SourceLoc rParenLoc,
19931994
bool isObjC,
19941995
bool isImplicit)
19951996
: Expr(ExprKind::KeyPath, isImplicit),
19961997
KeywordLoc(keywordLoc), LParenLoc(lParenLoc), RParenLoc(rParenLoc),
1997-
Components(C.AllocateUninitialized<ComponentAndLoc>(components.size()))
1998+
RootType(root),
1999+
Components(C.AllocateUninitialized<Component>(components.size()))
19982000
{
19992001
// Copy components into the AST context.
20002002
std::uninitialized_copy(components.begin(), components.end(),
@@ -2005,17 +2007,56 @@ KeyPathExpr::KeyPathExpr(ASTContext &C,
20052007

20062008
void
20072009
KeyPathExpr::resolveComponents(ASTContext &C,
2008-
ArrayRef<KeyPathExpr::Component> resolvedComponents){
2010+
ArrayRef<KeyPathExpr::Component> resolvedComponents) {
20092011
// Reallocate the components array if it needs to be.
20102012
if (Components.size() < resolvedComponents.size()) {
2011-
Components = C.Allocate<ComponentAndLoc>(resolvedComponents.size());
2013+
Components = C.Allocate<Component>(resolvedComponents.size());
20122014
for (unsigned i : indices(Components)) {
2013-
new ((void*)&Components[i]) ComponentAndLoc{};
2015+
::new ((void*)&Components[i]) Component{};
20142016
}
20152017
}
20162018

20172019
for (unsigned i : indices(resolvedComponents)) {
2018-
Components[i].first = resolvedComponents[i];
2020+
Components[i] = resolvedComponents[i];
20192021
}
20202022
Components = Components.slice(0, resolvedComponents.size());
20212023
}
2024+
2025+
KeyPathExpr::Component
2026+
KeyPathExpr::Component::forSubscript(ASTContext &ctx,
2027+
ConcreteDeclRef subscript,
2028+
SourceLoc lSquareLoc,
2029+
ArrayRef<Expr *> indexArgs,
2030+
ArrayRef<Identifier> indexArgLabels,
2031+
ArrayRef<SourceLoc> indexArgLabelLocs,
2032+
SourceLoc rSquareLoc,
2033+
Expr *trailingClosure,
2034+
Type elementType) {
2035+
SmallVector<Identifier, 4> indexArgLabelsScratch;
2036+
SmallVector<SourceLoc, 4> indexArgLabelLocsScratch;
2037+
Expr *index = packSingleArgument(ctx, lSquareLoc, indexArgs, indexArgLabels,
2038+
indexArgLabelLocs, rSquareLoc,
2039+
trailingClosure, /*implicit*/ false,
2040+
indexArgLabelsScratch,
2041+
indexArgLabelLocsScratch);
2042+
return forSubscriptWithPrebuiltIndexExpr(subscript, index, elementType,
2043+
lSquareLoc);
2044+
}
2045+
2046+
KeyPathExpr::Component
2047+
KeyPathExpr::Component::forUnresolvedSubscript(ASTContext &ctx,
2048+
SourceLoc lSquareLoc,
2049+
ArrayRef<Expr *> indexArgs,
2050+
ArrayRef<Identifier> indexArgLabels,
2051+
ArrayRef<SourceLoc> indexArgLabelLocs,
2052+
SourceLoc rSquareLoc,
2053+
Expr *trailingClosure) {
2054+
SmallVector<Identifier, 4> indexArgLabelsScratch;
2055+
SmallVector<SourceLoc, 4> indexArgLabelLocsScratch;
2056+
Expr *index = packSingleArgument(ctx, lSquareLoc, indexArgs, indexArgLabels,
2057+
indexArgLabelLocs, rSquareLoc,
2058+
trailingClosure, /*implicit*/ false,
2059+
indexArgLabelsScratch,
2060+
indexArgLabelLocsScratch);
2061+
return forUnresolvedSubscriptWithPrebuiltIndexExpr(index, lSquareLoc);
2062+
}

lib/Parse/Lexer.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,8 +638,11 @@ void Lexer::lexHash() {
638638

639639
// Scan for [a-zA-Z]+ to see what we match.
640640
const char *tmpPtr = CurPtr;
641-
while (clang::isLetter(*tmpPtr))
642-
++tmpPtr;
641+
if (clang::isIdentifierHead(*tmpPtr)) {
642+
do {
643+
++tmpPtr;
644+
} while (clang::isIdentifierBody(*tmpPtr));
645+
}
643646

644647
// Map the character sequence onto
645648
tok Kind = llvm::StringSwitch<tok>(StringRef(CurPtr, tmpPtr-CurPtr))

0 commit comments

Comments
 (0)