Skip to content

Commit

Permalink
implement support for let declarations.
Browse files Browse the repository at this point in the history
Swift SVN r11195
  • Loading branch information
lattner committed Dec 12, 2013
1 parent 0c4baac commit 65aa09d
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 15 deletions.
31 changes: 28 additions & 3 deletions docs/LangRef.html
Expand Up @@ -611,6 +611,7 @@ <h2 id="decl">Declarations</h2>
decl ::= <a href="#decl-protocol">decl-protocol</a>
decl ::= <a href="#decl-struct">decl-struct</a>
decl ::= <a href="#decl-typealias">decl-typealias</a>
decl ::= <a href="#decl-let">decl-let</a>
decl ::= <a href="#decl-var">decl-var</a>
decl ::= <a href="#decl-subscript">decl-subscript</a>
</pre>
Expand Down Expand Up @@ -741,7 +742,33 @@ <h4 id="decl-extension-enum-struct"><a href="#decl-enum">enum</a>, <a

<p>FIXME: Write this section.</p>


<!-- ===================================================================== -->
<h3 id="decl-let">let Declarations</h3>
<!-- ===================================================================== -->

<pre class="grammar">
decl-let ::= <a href="#attribute-list">attribute-list</a> 'let' <a href="#pattern">pattern</a> initializer? (',' pattern initializer?)*
initializer ::= '=' <a href="#expr">expr</a>
</pre>


<p>'let' declarations define an immutable binding between an initializer value
and a name.</p>

<p>Here are some examples of 'let' declarations:</p>

<pre class="example">
<i>// Simple examples.</i>
let a = 4
let c : Int = 42

<i>// This decodes the tuple return value into independently named parts</i>
<i>// and both 'val' and 'err' are in scope after this line.</i>
let (val, err) = foo()

let b : Int <i>// error: let requires an initializer</i>
</pre>

<!-- ===================================================================== -->
<h3 id="decl-var">var Declarations</h3>
<!-- ===================================================================== -->
Expand All @@ -752,8 +779,6 @@ <h3 id="decl-var">var Declarations</h3>
decl-var ::= <a href="#attribute-list">attribute-list</a> 'var' <a href="#identifier">identifier</a> ':' <a href="#type">type-annotation</a> <a href="#brace-item-list">brace-item-list</a>

decl-var ::= <a href="#attribute-list">attribute-list</a> 'var' <a href="#identifier">identifier</a> ':' <a href="#type">type-annotation</a> '{' get-set '}'

initializer ::= '=' <a href="#expr">expr</a>

<a name="get-set"></a>get-set ::= get set?
get-set ::= set get
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/Diagnostics.def
Expand Up @@ -154,6 +154,8 @@ ERROR(expected_identifier_after_case_comma,decl_parsing,none,
ERROR(decl_redefinition,decl_parsing,none,
"%select{declaration|definition}0 conflicts with previous value",
(bool))
ERROR(let_requires_initializer,decl_parsing,none,
"'let' declarations require an initializer expression", ())
ERROR(disallowed_stored_var_decl,decl_parsing,none,
"'var' declarations without getter/setter not allowed here", ())
ERROR(disallowed_computed_var_decl,decl_parsing,none,
Expand Down
1 change: 1 addition & 0 deletions include/swift/Parse/Tokens.def
Expand Up @@ -38,6 +38,7 @@ KEYWORD(extension)
KEYWORD(func)
KEYWORD(import)
KEYWORD(init)
KEYWORD(let)
KEYWORD(protocol)
KEYWORD(static)
KEYWORD(struct)
Expand Down
26 changes: 21 additions & 5 deletions lib/Parse/ParseDecl.cpp
Expand Up @@ -485,6 +485,7 @@ void Parser::setLocalDiscriminator(ValueDecl *D) {
/// decl:
/// decl-typealias
/// decl-extension
/// decl-let
/// decl-var
/// decl-func
/// decl-enum
Expand Down Expand Up @@ -520,6 +521,9 @@ ParserStatus Parser::parseDecl(SmallVectorImpl<Decl*> &Entries,
DeclResult = parseDeclExtension(Flags, Attributes);
Status = DeclResult;
break;
case tok::kw_let:
Status = parseDeclVar(Flags, Attributes, Entries, SourceLoc());
break;
case tok::kw_var:
// TODO: Static properties are only implemented for non-generic value types.
if (StaticLoc.isValid()) {
Expand Down Expand Up @@ -724,6 +728,7 @@ ParserResult<ImportDecl> Parser::parseDeclImport(unsigned Flags,
Kind = ImportKind::Protocol;
break;
case tok::kw_var:
case tok::kw_let:
Kind = ImportKind::Var;
break;
case tok::kw_func:
Expand Down Expand Up @@ -1321,7 +1326,7 @@ bool Parser::parseGetSet(bool HasContainerType, Pattern *Indices,
void Parser::parseDeclVarGetSet(Pattern &pattern, bool HasContainerType,
SourceLoc StaticLoc) {
bool Invalid = false;

// The grammar syntactically requires a simple identifier for the variable
// name. Complain if that isn't what we got.
VarDecl *PrimaryVar = nullptr;
Expand Down Expand Up @@ -1385,17 +1390,20 @@ void Parser::parseDeclVarGetSet(Pattern &pattern, bool HasContainerType,
PrimaryVar->setComputedAccessors(Context, LBLoc, Get, Set, RBLoc);
}

/// \brief Parse a 'var' declaration, doing no token skipping on error.
/// \brief Parse a 'var' or 'let' declaration, doing no token skipping on error.
///
/// \verbatim
/// decl-var:
/// 'let' attribute-list pattern initializer (',' pattern initializer )*
/// 'var' attribute-list pattern initializer? (',' pattern initializer? )*
/// 'var' attribute-list identifier : type-annotation { get-set }
/// \endverbatim
ParserStatus Parser::parseDeclVar(unsigned Flags, DeclAttributes &Attributes,
SmallVectorImpl<Decl *> &Decls,
SourceLoc StaticLoc) {
SourceLoc VarLoc = consumeToken(tok::kw_var);
bool isLet = Tok.is(tok::kw_let);
assert(Tok.getKind() == tok::kw_let || Tok.getKind() == tok::kw_var);
SourceLoc VarLoc = consumeToken();

struct AllBindings {
Parser &P;
Expand All @@ -1422,12 +1430,19 @@ ParserStatus Parser::parseDeclVar(unsigned Flags, DeclAttributes &Attributes,
ParserStatus Status;

do {
ParserResult<Pattern> pattern = parsePattern(false);
ParserResult<Pattern> pattern = parsePattern(isLet);
if (pattern.hasCodeCompletion())
return makeParserCodeCompletionStatus();
if (pattern.isNull())
return makeParserError();

// 'let' declarations require initializers - get/set specifiers are not
// allowed.
if (isLet && Tok.isNot(tok::equal)) {
diagnose(Tok, diag::let_requires_initializer);
return makeParserError();
}

// If we syntactically match the second decl-var production, with a
// var-get-set clause, parse the var-get-set clause.
if (Tok.is(tok::l_brace)) {
Expand Down Expand Up @@ -1459,6 +1474,7 @@ ParserStatus Parser::parseDeclVar(unsigned Flags, DeclAttributes &Attributes,

Bindings.All.push_back({PBD, topLevelDecl});

// Parse an initializer if present.
if (Tok.is(tok::equal)) {
// Record the variables that we're trying to initialize.
SmallVector<VarDecl *, 4> Vars;
Expand Down Expand Up @@ -1603,7 +1619,7 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,
// that point.
backtrackToPosition(BeginParserPosition);
consumeToken(tok::l_brace);
while (Tok.is(tok::kw_var) ||
while (Tok.is(tok::kw_var) || Tok.is(tok::kw_let) ||
(Tok.isNot(tok::eof) && !isStartOfDecl(Tok, peekToken()))) {
consumeToken();
}
Expand Down
9 changes: 4 additions & 5 deletions lib/Parse/ParsePattern.cpp
Expand Up @@ -682,14 +682,13 @@ ParserResult<Pattern> Parser::parseMatchingPattern() {

// Parse productions that can only be patterns.
// matching-pattern ::= matching-pattern-var
if (Tok.is(tok::kw_var)) {
if (Tok.is(tok::kw_var))
return parseMatchingPatternVar();
}

// matching-pattern ::= 'is' type
if (Tok.is(tok::kw_is)) {
if (Tok.is(tok::kw_is))
return parseMatchingPatternIsa();
}


// matching-pattern ::= expr
// Fall back to expression parsing for ambiguous forms. Name lookup will
// disambiguate.
Expand Down
5 changes: 3 additions & 2 deletions lib/Parse/ParseStmt.cpp
Expand Up @@ -52,6 +52,7 @@ bool Parser::isStartOfDecl(const Token &Tok, const Token &Tok2) {
case tok::at_sign:
case tok::kw_static:
case tok::kw_extension:
case tok::kw_let:
case tok::kw_var:
case tok::kw_typealias:
case tok::kw_enum:
Expand Down Expand Up @@ -659,8 +660,8 @@ ParserResult<Stmt> Parser::parseStmtForCStyle(SourceLoc ForLoc) {
LPLoc = consumeToken();
LPLocConsumed = true;
}
// Parse the first part, either a var, expr, or stmt-assign.
if (Tok.is(tok::kw_var) || Tok.is(tok::at_sign)) {
// Parse the first part, either a var, let, expr, or stmt-assign.
if (Tok.is(tok::kw_var) || Tok.is(tok::kw_let) || Tok.is(tok::at_sign)) {
DeclAttributes Attributes;
parseDeclAttributeList(Attributes);
ParserStatus VarDeclStatus = parseDeclVar(false, Attributes, FirstDecls,
Expand Down

0 comments on commit 65aa09d

Please sign in to comment.