Skip to content

Commit e4d8f48

Browse files
committed
Simplify AST for string literals to not depend on implicit tuple splat.
String literal expressions, as well as the magic literals #file and tuple value that is then fed into one or two call expressions. For string literals, that tuple value was implicitly splatted, breaking AST invariants. Instead, keep string literals and these magic literals that produce a string as a single expression node, but store the declarations that will be used to transform the raw literal into the complete literal. SILGen will form the appropriate calls. This representation is far simpler---the AST no longer has a bunch of implicit nodes---and doesn't break AST invariants.
1 parent dfc3933 commit e4d8f48

File tree

11 files changed

+646
-238
lines changed

11 files changed

+646
-238
lines changed

include/swift/AST/Expr.h

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -883,13 +883,13 @@ class BooleanLiteralExpr : public LiteralExpr {
883883
}
884884
};
885885

886-
/// StringLiteralExpr - String literal, like '"foo"'. After semantic
887-
/// analysis assigns types, this is guaranteed to only have a
888-
/// BuiltinRawPointerType.
886+
/// StringLiteralExpr - String literal, like '"foo"'.
889887
class StringLiteralExpr : public LiteralExpr {
890888
StringRef Val;
891889
SourceRange Range;
892-
890+
ConcreteDeclRef BuiltinInitializer;
891+
ConcreteDeclRef Initializer;
892+
893893
public:
894894
/// The encoding that should be used for the string literal.
895895
enum Encoding : unsigned {
@@ -926,6 +926,32 @@ class StringLiteralExpr : public LiteralExpr {
926926
return StringLiteralExprBits.IsSingleExtendedGraphemeCluster;
927927
}
928928

929+
/// Retrieve the builtin initializer that will be used to construct the string
930+
/// literal.
931+
///
932+
/// Any type-checked string literal will have a builtin initializer, which is
933+
/// called first to form a concrete Swift type.
934+
ConcreteDeclRef getBuiltinInitializer() const { return BuiltinInitializer; }
935+
936+
/// Set the builtin initializer that will be used to construct the string
937+
/// literal.
938+
void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) {
939+
BuiltinInitializer = builtinInitializer;
940+
}
941+
942+
/// Retrieve the initializer that will be used to construct the string
943+
/// literal from the result of the initializer.
944+
///
945+
/// Only string literals that have no builtin literal conformance will have
946+
/// this initializer, which will be called on the result of the builtin
947+
/// initializer.
948+
ConcreteDeclRef getInitializer() const { return Initializer; }
949+
950+
/// Set the initializer that will be used to construct the string literal.
951+
void setInitializer(ConcreteDeclRef initializer) {
952+
Initializer = initializer;
953+
}
954+
929955
static bool classof(const Expr *E) {
930956
return E->getKind() == ExprKind::StringLiteral;
931957
}
@@ -978,7 +1004,9 @@ class MagicIdentifierLiteralExpr : public LiteralExpr {
9781004
};
9791005
private:
9801006
SourceLoc Loc;
981-
1007+
ConcreteDeclRef BuiltinInitializer;
1008+
ConcreteDeclRef Initializer;
1009+
9821010
public:
9831011
MagicIdentifierLiteralExpr(Kind kind, SourceLoc loc, bool implicit = false)
9841012
: LiteralExpr(ExprKind::MagicIdentifierLiteral, implicit), Loc(loc) {
@@ -1031,6 +1059,40 @@ class MagicIdentifierLiteralExpr : public LiteralExpr {
10311059
= static_cast<unsigned>(encoding);
10321060
}
10331061

1062+
/// Retrieve the builtin initializer that will be used to construct the string
1063+
/// literal.
1064+
///
1065+
/// Any type-checked string literal will have a builtin initializer, which is
1066+
/// called first to form a concrete Swift type.
1067+
ConcreteDeclRef getBuiltinInitializer() const {
1068+
assert(isString() && "Magic identifier literal is not a string");
1069+
return BuiltinInitializer;
1070+
}
1071+
1072+
/// Set the builtin initializer that will be used to construct the string
1073+
/// literal.
1074+
void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) {
1075+
assert(isString() && "Magic identifier literal is not a string");
1076+
BuiltinInitializer = builtinInitializer;
1077+
}
1078+
1079+
/// Retrieve the initializer that will be used to construct the string
1080+
/// literal from the result of the initializer.
1081+
///
1082+
/// Only string literals that have no builtin literal conformance will have
1083+
/// this initializer, which will be called on the result of the builtin
1084+
/// initializer.
1085+
ConcreteDeclRef getInitializer() const {
1086+
assert(isString() && "Magic identifier literal is not a string");
1087+
return Initializer;
1088+
}
1089+
1090+
/// Set the initializer that will be used to construct the string literal.
1091+
void setInitializer(ConcreteDeclRef initializer) {
1092+
assert(isString() && "Magic identifier literal is not a string");
1093+
Initializer = initializer;
1094+
}
1095+
10341096
static bool classof(const Expr *E) {
10351097
return E->getKind() == ExprKind::MagicIdentifierLiteral;
10361098
}

lib/AST/ASTDumper.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1630,7 +1630,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
16301630
printCommon(E, "string_literal_expr")
16311631
<< " encoding=";
16321632
printStringEncoding(E->getEncoding());
1633-
OS << " value=" << QuotedString(E->getValue()) << ')';
1633+
OS << " value=" << QuotedString(E->getValue())
1634+
<< " builtin_initializer=";
1635+
E->getBuiltinInitializer().dump(OS);
1636+
OS << " initializer=";
1637+
E->getInitializer().dump(OS);
1638+
OS << ')';
16341639
}
16351640
void visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E) {
16361641
printCommon(E, "interpolated_string_literal_expr");
@@ -1657,6 +1662,13 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
16571662
case MagicIdentifierLiteralExpr::Column: OS << "#column"; break;
16581663
case MagicIdentifierLiteralExpr::DSOHandle: OS << "#dsohandle"; break;
16591664
}
1665+
1666+
if (E->isString()) {
1667+
OS << " builtin_initializer=";
1668+
E->getBuiltinInitializer().dump(OS);
1669+
OS << " initializer=";
1670+
E->getInitializer().dump(OS);
1671+
}
16601672
OS << ')';
16611673
}
16621674

lib/AST/Expr.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ ConcreteDeclRef Expr::getReferencedDecl() const {
370370
NO_REFERENCE(MagicIdentifierLiteral);
371371
NO_REFERENCE(DiscardAssignment);
372372

373-
SIMPLE_REFERENCE(DeclRef, getDecl);
373+
SIMPLE_REFERENCE(DeclRef, getDeclRef);
374374
SIMPLE_REFERENCE(SuperRef, getSelf);
375375

376376
case ExprKind::Type: {
@@ -381,7 +381,7 @@ ConcreteDeclRef Expr::getReferencedDecl() const {
381381
return ident->getComponentRange().back()->getBoundDecl();
382382
}
383383

384-
SIMPLE_REFERENCE(OtherConstructorDeclRef, getDecl);
384+
SIMPLE_REFERENCE(OtherConstructorDeclRef, getDeclRef);
385385

386386
PASS_THROUGH_REFERENCE(DotSyntaxBaseIgnored, getRHS);
387387

@@ -439,8 +439,8 @@ ConcreteDeclRef Expr::getReferencedDecl() const {
439439
NO_REFERENCE(PostfixUnary);
440440
NO_REFERENCE(Binary);
441441
NO_REFERENCE(DotSyntaxCall);
442-
NO_REFERENCE(ConstructorRefCall);
443442

443+
PASS_THROUGH_REFERENCE(ConstructorRefCall, getFn);
444444
PASS_THROUGH_REFERENCE(Load, getSubExpr);
445445
NO_REFERENCE(TupleShuffle);
446446
NO_REFERENCE(UnresolvedTypeConversion);

0 commit comments

Comments
 (0)