mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[AST] Separate the DeclContexts for different pattern binding entries in a pattern binding decl.
This commit is contained in:
@@ -494,16 +494,19 @@ public:
|
||||
/// deserialization.
|
||||
class SerializedLocalDeclContext : public DeclContext {
|
||||
private:
|
||||
const LocalDeclContextKind LocalKind;
|
||||
unsigned LocalKind : 3;
|
||||
|
||||
protected:
|
||||
unsigned SpareBits : 29;
|
||||
|
||||
public:
|
||||
SerializedLocalDeclContext(LocalDeclContextKind LocalKind,
|
||||
DeclContext *Parent)
|
||||
: DeclContext(DeclContextKind::SerializedLocal, Parent),
|
||||
LocalKind(LocalKind) {}
|
||||
LocalKind(static_cast<unsigned>(LocalKind)) {}
|
||||
|
||||
LocalDeclContextKind getLocalDeclContextKind() const {
|
||||
return LocalKind;
|
||||
return static_cast<LocalDeclContextKind>(LocalKind);
|
||||
}
|
||||
|
||||
static bool classof(const DeclContext *DC) {
|
||||
|
||||
@@ -80,16 +80,20 @@ public:
|
||||
explicit PatternBindingInitializer(DeclContext *parent)
|
||||
: Initializer(InitializerKind::PatternBinding, parent),
|
||||
Binding(nullptr) {
|
||||
SpareBits = 0;
|
||||
}
|
||||
|
||||
|
||||
void setBinding(PatternBindingDecl *binding) {
|
||||
void setBinding(PatternBindingDecl *binding, unsigned bindingIndex) {
|
||||
setParent(binding->getDeclContext());
|
||||
Binding = binding;
|
||||
SpareBits = bindingIndex;
|
||||
}
|
||||
|
||||
PatternBindingDecl *getBinding() const { return Binding; }
|
||||
|
||||
unsigned getBindingIndex() const { return SpareBits; }
|
||||
|
||||
static bool classof(const DeclContext *DC) {
|
||||
if (auto init = dyn_cast<Initializer>(DC))
|
||||
return classof(init);
|
||||
@@ -108,15 +112,21 @@ class SerializedPatternBindingInitializer : public SerializedLocalDeclContext {
|
||||
PatternBindingDecl *Binding;
|
||||
|
||||
public:
|
||||
SerializedPatternBindingInitializer(PatternBindingDecl *Binding)
|
||||
SerializedPatternBindingInitializer(PatternBindingDecl *Binding,
|
||||
unsigned bindingIndex)
|
||||
: SerializedLocalDeclContext(LocalDeclContextKind::PatternBindingInitializer,
|
||||
Binding->getDeclContext()),
|
||||
Binding(Binding) {}
|
||||
Binding(Binding) {
|
||||
SpareBits = bindingIndex;
|
||||
}
|
||||
|
||||
PatternBindingDecl *getBinding() const {
|
||||
return Binding;
|
||||
}
|
||||
|
||||
unsigned getBindingIndex() const { return SpareBits; }
|
||||
|
||||
|
||||
static bool classof(const DeclContext *DC) {
|
||||
if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
|
||||
return LDC->getLocalDeclContextKind() ==
|
||||
|
||||
@@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0;
|
||||
/// in source control, you should also update the comment to briefly
|
||||
/// describe what change you made. The content of this comment isn't important;
|
||||
/// it just ensures a conflict if two people change the module format.
|
||||
const uint16_t VERSION_MINOR = 264; // Last change: remove AllArchetypes
|
||||
const uint16_t VERSION_MINOR = 265; // Last change: pattern binding initializer index
|
||||
|
||||
using DeclID = PointerEmbeddedInt<unsigned, 31>;
|
||||
using DeclIDField = BCFixed<31>;
|
||||
@@ -1306,7 +1306,8 @@ namespace decls_block {
|
||||
|
||||
using PatternBindingInitializerLayout = BCRecordLayout<
|
||||
PATTERN_BINDING_INITIALIZER_CONTEXT,
|
||||
DeclIDField // parent pattern binding decl
|
||||
DeclIDField, // parent pattern binding decl
|
||||
BCVBR<3> // binding index in the pattern binding decl
|
||||
>;
|
||||
|
||||
using DefaultArgumentInitializerLayout = BCRecordLayout<
|
||||
|
||||
@@ -722,7 +722,8 @@ unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
|
||||
switch (cast<Initializer>(this)->getInitializerKind()) {
|
||||
case InitializerKind::PatternBinding: {
|
||||
auto init = cast<PatternBindingInitializer>(this);
|
||||
OS << " PatternBinding 0x" << (void*) init->getBinding();
|
||||
OS << " PatternBinding 0x" << (void*) init->getBinding()
|
||||
<< " #" << init->getBindingIndex();
|
||||
break;
|
||||
}
|
||||
case InitializerKind::DefaultArgument: {
|
||||
@@ -748,7 +749,8 @@ unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
|
||||
}
|
||||
case LocalDeclContextKind::PatternBindingInitializer: {
|
||||
auto init = cast<SerializedPatternBindingInitializer>(local);
|
||||
OS << " PatternBinding 0x" << (void*) init->getBinding();
|
||||
OS << " PatternBinding 0x" << (void*) init->getBinding()
|
||||
<< " #" << init->getBindingIndex();
|
||||
break;
|
||||
}
|
||||
case LocalDeclContextKind::TopLevelCodeDecl:
|
||||
|
||||
@@ -3965,12 +3965,6 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
topLevelDecl = new (Context) TopLevelCodeDecl(CurDeclContext);
|
||||
}
|
||||
|
||||
// If we're not in a local context, we'll need a context to parse initializers
|
||||
// into (should we have one). This happens for properties and global
|
||||
// variables in libraries.
|
||||
PatternBindingInitializer *initContext = nullptr;
|
||||
bool usedInitContext = false;
|
||||
|
||||
bool HasAccessors = false; // Syntactically has accessor {}'s.
|
||||
ParserStatus Status;
|
||||
|
||||
@@ -3980,6 +3974,10 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
// so we can build our singular PatternBindingDecl at the end.
|
||||
SmallVector<PatternBindingEntry, 4> PBDEntries;
|
||||
|
||||
// The pattern binding initializer contexts, which have to be set up at the
|
||||
// end.
|
||||
SmallVector<PatternBindingInitializer *, 4> PBDInitContexts;
|
||||
|
||||
// No matter what error path we take, make sure the
|
||||
// PatternBindingDecl/TopLevel code block are added.
|
||||
SWIFT_DEFER {
|
||||
@@ -3993,12 +3991,17 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
auto PBD = PatternBindingDecl::create(Context, StaticLoc, StaticSpelling,
|
||||
VarLoc, PBDEntries, CurDeclContext);
|
||||
|
||||
// Wire up any initializer contexts we needed.
|
||||
assert(PBDInitContexts.size() == PBDEntries.size());
|
||||
for (unsigned i : indices(PBDInitContexts)) {
|
||||
auto initContext = PBDInitContexts[i];
|
||||
if (initContext) initContext->setBinding(PBD, i);
|
||||
}
|
||||
|
||||
// If we're setting up a TopLevelCodeDecl, configure it by setting up the
|
||||
// body that holds PBD and we're done. The TopLevelCodeDecl is already set
|
||||
// up in Decls to be returned to caller.
|
||||
if (topLevelDecl) {
|
||||
assert(!initContext &&
|
||||
"Shouldn't need an initcontext: TopLevelCode is a local context!");
|
||||
PBD->setDeclContext(topLevelDecl);
|
||||
auto range = PBD->getSourceRange();
|
||||
topLevelDecl->setBody(BraceStmt::create(Context, range.Start,
|
||||
@@ -4007,17 +4010,6 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
return;
|
||||
}
|
||||
|
||||
// If we set up an initialization context for a property or module-level
|
||||
// global, check to see if we needed it and wind it down.
|
||||
if (initContext) {
|
||||
// If we didn't need the context, "destroy" it, which recycles it for
|
||||
// the next user.
|
||||
if (!usedInitContext)
|
||||
Context.destroyPatternBindingContext(initContext);
|
||||
else
|
||||
initContext->setBinding(PBD);
|
||||
}
|
||||
|
||||
// Otherwise return the PBD in "Decls" to the caller. We add it at a
|
||||
// specific spot to get it in before any accessors, which SILGen seems to
|
||||
// want.
|
||||
@@ -4050,11 +4042,18 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
// Remember this pattern/init pair for our ultimate PatternBindingDecl. The
|
||||
// Initializer will be added later when/if it is parsed.
|
||||
PBDEntries.push_back({pattern, nullptr});
|
||||
PBDInitContexts.push_back(nullptr);
|
||||
|
||||
Expr *PatternInit = nullptr;
|
||||
|
||||
// Parse an initializer if present.
|
||||
if (Tok.is(tok::equal)) {
|
||||
// If we're not in a local context, we'll need a context to parse initializers
|
||||
// into (should we have one). This happens for properties and global
|
||||
// variables in libraries.
|
||||
PatternBindingInitializer *initContext = nullptr;
|
||||
bool usedInitContext = false;
|
||||
|
||||
// Record the variables that we're trying to initialize. This allows us
|
||||
// to cleanly reject "var x = x" when "x" isn't bound to an enclosing
|
||||
// decl (even though names aren't injected into scope when the initializer
|
||||
@@ -4115,6 +4114,17 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
if (initContext)
|
||||
usedInitContext |= initParser->hasClosures();
|
||||
|
||||
// If we set up an initialization context for a property or module-level
|
||||
// global, check to see if we needed it and wind it down.
|
||||
if (initContext) {
|
||||
// If we didn't need the context, "destroy" it, which recycles it for
|
||||
// the next user.
|
||||
if (!usedInitContext)
|
||||
Context.destroyPatternBindingContext(initContext);
|
||||
else
|
||||
PBDInitContexts.back() = initContext;
|
||||
}
|
||||
|
||||
// If we are doing second pass of code completion, we don't want to
|
||||
// suddenly cut off parsing and throw away the declaration.
|
||||
if (init.hasCodeCompletion() && isCodeCompletionFirstPass()) {
|
||||
@@ -4144,6 +4154,12 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
// FIXME: Handle generalized parameters.
|
||||
Expr *paramExpr = nullptr;
|
||||
if (Tok.is(tok::l_brace)) {
|
||||
// If we're not in a local context, we'll need a context to parse initializers
|
||||
// into (should we have one). This happens for properties and global
|
||||
// variables in libraries.
|
||||
PatternBindingInitializer *initContext = nullptr;
|
||||
bool usedInitContext = false;
|
||||
|
||||
// Record the variables that we're trying to set up. This allows us
|
||||
// to cleanly reject "var x = x" when "x" isn't bound to an enclosing
|
||||
// decl (even though names aren't injected into scope when the parameter
|
||||
@@ -4172,7 +4188,11 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
||||
initParser.emplace(*this, initContext);
|
||||
|
||||
auto closure = parseExprClosure();
|
||||
if (initContext) {
|
||||
usedInitContext = true;
|
||||
PBDInitContexts.back() = initContext;
|
||||
}
|
||||
|
||||
if (closure.isParseError())
|
||||
return makeParserError();
|
||||
if (closure.hasCodeCompletion())
|
||||
|
||||
@@ -1930,7 +1930,7 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
|
||||
// If we didn't find one, create it.
|
||||
if (!initContext) {
|
||||
initContext = Context.createPatternBindingContext(DC);
|
||||
initContext->setBinding(PBD);
|
||||
initContext->setBinding(PBD, patternNumber);
|
||||
initContextIsNew = true;
|
||||
}
|
||||
DC = initContext;
|
||||
|
||||
@@ -1507,13 +1507,15 @@ DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) {
|
||||
|
||||
case decls_block::PATTERN_BINDING_INITIALIZER_CONTEXT: {
|
||||
DeclID bindingID;
|
||||
uint32_t bindingIndex;
|
||||
decls_block::PatternBindingInitializerLayout::readRecord(scratch,
|
||||
bindingID);
|
||||
bindingID,
|
||||
bindingIndex);
|
||||
auto decl = getDecl(bindingID);
|
||||
PatternBindingDecl *binding = cast<PatternBindingDecl>(decl);
|
||||
|
||||
declContextOrOffset = new (ctx)
|
||||
SerializedPatternBindingInitializer(binding);
|
||||
SerializedPatternBindingInitializer(binding, bindingIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1845,11 +1845,13 @@ void Serializer::writeDeclContext(const DeclContext *DC) {
|
||||
declOrDeclContextID, isDecl);
|
||||
}
|
||||
|
||||
void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding) {
|
||||
void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding,
|
||||
unsigned bindingIndex) {
|
||||
using namespace decls_block;
|
||||
auto abbrCode = DeclTypeAbbrCodes[PatternBindingInitializerLayout::Code];
|
||||
PatternBindingInitializerLayout::emitRecord(Out, ScratchRecord,
|
||||
abbrCode, addDeclRef(binding));
|
||||
abbrCode, addDeclRef(binding),
|
||||
bindingIndex);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1896,7 +1898,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) {
|
||||
|
||||
case DeclContextKind::Initializer: {
|
||||
if (auto PBI = dyn_cast<PatternBindingInitializer>(DC)) {
|
||||
writePatternBindingInitializer(PBI->getBinding());
|
||||
writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex());
|
||||
} else if (auto DAI = dyn_cast<DefaultArgumentInitializer>(DC)) {
|
||||
writeDefaultArgumentInitializer(DAI->getParent(), DAI->getIndex());
|
||||
}
|
||||
@@ -1928,7 +1930,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) {
|
||||
}
|
||||
case LocalDeclContextKind::PatternBindingInitializer: {
|
||||
auto PBI = cast<SerializedPatternBindingInitializer>(local);
|
||||
writePatternBindingInitializer(PBI->getBinding());
|
||||
writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex());
|
||||
return;
|
||||
}
|
||||
case LocalDeclContextKind::TopLevelCodeDecl: {
|
||||
|
||||
@@ -293,7 +293,8 @@ private:
|
||||
void writeLocalDeclContext(const DeclContext *DC);
|
||||
|
||||
/// Write the components of a PatternBindingInitializer as a local context.
|
||||
void writePatternBindingInitializer(PatternBindingDecl *binding);
|
||||
void writePatternBindingInitializer(PatternBindingDecl *binding,
|
||||
unsigned bindingIndex);
|
||||
|
||||
/// Write the components of a DefaultArgumentInitializer as a local context.
|
||||
void writeDefaultArgumentInitializer(const DeclContext *parentContext, unsigned index);
|
||||
|
||||
Reference in New Issue
Block a user