Enhance VarPattern to capture a bit indicating whether the pattern was a var or let.

Previously we only used this information in the parser, but Sema needs to know as well.

NFC except in -dump-ast.



Swift SVN r25914
This commit is contained in:
Chris Lattner
2015-03-10 06:07:56 +00:00
parent 6423209466
commit db187f2183
8 changed files with 25 additions and 17 deletions

View File

@@ -757,14 +757,18 @@ public:
/// parsed as expressions referencing existing entities. /// parsed as expressions referencing existing entities.
class VarPattern : public Pattern { class VarPattern : public Pattern {
SourceLoc VarLoc; SourceLoc VarLoc;
bool IsLet; // True if this is a let pattern, false if a var pattern.
Pattern *SubPattern; Pattern *SubPattern;
public: public:
VarPattern(SourceLoc loc, Pattern *sub, Optional<bool> implicit = None) VarPattern(SourceLoc loc, bool isLet, Pattern *sub,
: Pattern(PatternKind::Var), VarLoc(loc), SubPattern(sub) { Optional<bool> implicit = None)
: Pattern(PatternKind::Var), VarLoc(loc), IsLet(isLet), SubPattern(sub) {
if (implicit.hasValue() ? *implicit : !loc.isValid()) if (implicit.hasValue() ? *implicit : !loc.isValid())
setImplicit(); setImplicit();
} }
bool isLet() const { return IsLet; }
SourceLoc getLoc() const { return VarLoc; } SourceLoc getLoc() const { return VarLoc; }
SourceRange getSourceRange() const { SourceRange getSourceRange() const {
SourceLoc EndLoc = SubPattern->getSourceRange().End; SourceLoc EndLoc = SubPattern->getSourceRange().End;

View File

@@ -51,7 +51,7 @@ const uint16_t VERSION_MAJOR = 0;
/// To ensure that two separate changes don't silently get merged into one /// To ensure that two separate changes don't silently get merged into one
/// in source control, you should also update the comment to briefly /// in source control, you should also update the comment to briefly
/// describe what change you made. /// describe what change you made.
const uint16_t VERSION_MINOR = 177; // Last change: Flag for sib const uint16_t VERSION_MINOR = 178; // Last change: VarPattern
using DeclID = Fixnum<31>; using DeclID = Fixnum<31>;
using DeclIDField = BCFixed<31>; using DeclIDField = BCFixed<31>;
@@ -1009,6 +1009,7 @@ namespace decls_block {
using VarPatternLayout = BCRecordLayout< using VarPatternLayout = BCRecordLayout<
VAR_PATTERN, VAR_PATTERN,
BCFixed<1>, // isLet?
BCFixed<1> // implicit? BCFixed<1> // implicit?
// The sub-pattern trails the record. // The sub-pattern trails the record.
>; >;

View File

@@ -259,7 +259,7 @@ namespace {
OS << ')'; OS << ')';
} }
void visitVarPattern(VarPattern *P) { void visitVarPattern(VarPattern *P) {
printCommon(P, "pattern_var"); printCommon(P, P->isLet() ? "pattern_let" : "pattern_var");
OS << '\n'; OS << '\n';
printRec(P->getSubPattern()); printRec(P->getSubPattern());
OS << ')'; OS << ')';

View File

@@ -498,7 +498,7 @@ void PrintAST::printPattern(const Pattern *pattern) {
case PatternKind::Var: case PatternKind::Var:
if (!Options.SkipIntroducerKeywords) if (!Options.SkipIntroducerKeywords)
Printer << "var "; Printer << (cast<VarPattern>(pattern)->isLet() ? "let " : "var ");
printPattern(cast<VarPattern>(pattern)->getSubPattern()); printPattern(cast<VarPattern>(pattern)->getSubPattern());
} }
} }

View File

@@ -390,7 +390,7 @@ Pattern *Pattern::clone(ASTContext &context,
case PatternKind::Var: { case PatternKind::Var: {
auto var = cast<VarPattern>(this); auto var = cast<VarPattern>(this);
result = new(context) VarPattern(var->getLoc(), result = new(context) VarPattern(var->getLoc(), var->isLet(),
var->getSubPattern()->clone( var->getSubPattern()->clone(
context, context,
options|IsVar)); options|IsVar));
@@ -431,7 +431,7 @@ Pattern *Pattern::cloneForwardable(ASTContext &context, DeclContext *DC,
case PatternKind::Var: { case PatternKind::Var: {
auto var = cast<VarPattern>(this); auto var = cast<VarPattern>(this);
result = new(context) VarPattern(var->getLoc(), result = new(context) VarPattern(var->getLoc(), var->isLet(),
var->getSubPattern()->cloneForwardable( var->getSubPattern()->cloneForwardable(
context, DC, options|IsVar)); context, DC, options|IsVar));
break; break;

View File

@@ -391,7 +391,8 @@ mapParsedParameters(Parser &parser,
// If 'var' or 'let' was specified explicitly, create a pattern for it. // If 'var' or 'let' was specified explicitly, create a pattern for it.
if (specifierKind != Parser::ParsedParameter::InOut && if (specifierKind != Parser::ParsedParameter::InOut &&
letVarInOutLoc.isValid()) { letVarInOutLoc.isValid()) {
param = new (ctx) VarPattern(letVarInOutLoc, param); bool isLet = specifierKind == Parser::ParsedParameter::Let;
param = new (ctx) VarPattern(letVarInOutLoc, isLet, param);
} }
if (var) if (var)
@@ -802,7 +803,8 @@ ParserResult<Pattern> Parser::parsePatternVarOrLet() {
return makeParserCodeCompletionResult<Pattern>(); return makeParserCodeCompletionResult<Pattern>();
if (subPattern.isNull()) if (subPattern.isNull())
return nullptr; return nullptr;
return makeParserResult(new (Context) VarPattern(varLoc, subPattern.get())); return makeParserResult(new (Context) VarPattern(varLoc, isLet,
subPattern.get()));
} }
/// \brief Determine whether this token can start a binding name, whether an /// \brief Determine whether this token can start a binding name, whether an
@@ -978,21 +980,22 @@ ParserResult<Pattern> Parser::parseMatchingPattern() {
ParserResult<Pattern> Parser::parseMatchingPatternVarOrVal() { ParserResult<Pattern> Parser::parseMatchingPatternVarOrVal() {
assert((Tok.is(tok::kw_let) || Tok.is(tok::kw_var)) && "expects val or var"); assert((Tok.is(tok::kw_let) || Tok.is(tok::kw_var)) && "expects val or var");
bool isVal = Tok.is(tok::kw_let); bool isLet = Tok.is(tok::kw_let);
SourceLoc varLoc = consumeToken(); SourceLoc varLoc = consumeToken();
// 'var' and 'let' patterns shouldn't nest. // 'var' and 'let' patterns shouldn't nest.
if (InVarOrLetPattern) if (InVarOrLetPattern)
diagnose(varLoc, diag::var_pattern_in_var, unsigned(isVal)); diagnose(varLoc, diag::var_pattern_in_var, unsigned(isLet));
// In our recursive parse, remember that we're in a var/let pattern. // In our recursive parse, remember that we're in a var/let pattern.
llvm::SaveAndRestore<decltype(InVarOrLetPattern)> llvm::SaveAndRestore<decltype(InVarOrLetPattern)>
T(InVarOrLetPattern, isVal ? IVOLP_InLet : IVOLP_InVar); T(InVarOrLetPattern, isLet ? IVOLP_InLet : IVOLP_InVar);
ParserResult<Pattern> subPattern = parseMatchingPattern(); ParserResult<Pattern> subPattern = parseMatchingPattern();
if (subPattern.isNull()) if (subPattern.isNull())
return nullptr; return nullptr;
return makeParserResult(new (Context) VarPattern(varLoc, subPattern.get())); return makeParserResult(new (Context) VarPattern(varLoc, isLet,
subPattern.get()));
} }
// matching-pattern ::= 'is' type // matching-pattern ::= 'is' type

View File

@@ -367,12 +367,12 @@ Pattern *ModuleFile::maybeReadPattern() {
return result; return result;
} }
case decls_block::VAR_PATTERN: { case decls_block::VAR_PATTERN: {
bool isImplicit; bool isImplicit, isLet;
VarPatternLayout::readRecord(scratch, isImplicit); VarPatternLayout::readRecord(scratch, isLet, isImplicit);
Pattern *subPattern = maybeReadPattern(); Pattern *subPattern = maybeReadPattern();
assert(subPattern); assert(subPattern);
auto result = new (getContext()) VarPattern(SourceLoc(), subPattern, auto result = new (getContext()) VarPattern(SourceLoc(), isLet, subPattern,
isImplicit); isImplicit);
result->setType(subPattern->getType()); result->setType(subPattern->getType());
return result; return result;

View File

@@ -842,7 +842,7 @@ void Serializer::writePattern(const Pattern *pattern) {
auto var = cast<VarPattern>(pattern); auto var = cast<VarPattern>(pattern);
unsigned abbrCode = DeclTypeAbbrCodes[VarPatternLayout::Code]; unsigned abbrCode = DeclTypeAbbrCodes[VarPatternLayout::Code];
VarPatternLayout::emitRecord(Out, ScratchRecord, abbrCode, VarPatternLayout::emitRecord(Out, ScratchRecord, abbrCode, var->isLet(),
var->isImplicit()); var->isImplicit());
writePattern(var->getSubPattern()); writePattern(var->getSubPattern());
break; break;