mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
1554 lines
48 KiB
ReStructuredText
1554 lines
48 KiB
ReStructuredText
:orphan:
|
|
|
|
.. @raise litre.TestsAreMissing
|
|
|
|
===============================
|
|
Swift Language Reference Manual
|
|
===============================
|
|
|
|
.. contents::
|
|
|
|
Introduction
|
|
============
|
|
|
|
.. warning:: This document has not been kept up to date.
|
|
|
|
.. admonition:: Commentary
|
|
|
|
In addition to the main spec, there are lots of open ended questions,
|
|
justification, and ideas of what best practices should be. That random
|
|
discussion is placed in boxes like this one to clarify what is normative and
|
|
what is discussion.
|
|
|
|
This is the language reference manual for the Swift language, which is highly
|
|
volatile and constantly under development. As the prototype evolves, this
|
|
document should be kept up to date with what is actually implemented.
|
|
|
|
The grammar and structure of the language is defined in BNF form in yellow
|
|
boxes. Examples are shown in gray boxes, and assume that the standard library
|
|
is in use (unless otherwise specified).
|
|
|
|
Basic Goals
|
|
-----------
|
|
|
|
.. admonition:: Commentary
|
|
|
|
A non-goal of the Swift project in general is to become some amazing research
|
|
project. We really want to focus on delivering a real product, and having
|
|
the design and spec co-evolve.
|
|
|
|
In no particular order, and not explained well:
|
|
|
|
* Support building great frameworks and applications, with a specific focus on
|
|
permitting rich and powerful APIs.
|
|
* Get the defaults right: this reduces the barrier to entry and increases the
|
|
odds that the right thing happens.
|
|
* Through our support for building great APIs, we aim to provide an expressive
|
|
and productive language that is fun to program in.
|
|
* Support low-level system programming. We should want to write compilers,
|
|
operating system kernels, and media codecs in Swift. This means that being
|
|
able to obtain high performance is really quite important.
|
|
* Provide really great tools, like an IDE, debugger, profiling, etc.
|
|
* Where possible, steal great ideas instead of innovating new things that will
|
|
work out in unpredictable ways. It turns out that there are a lot of good
|
|
ideas already out there.
|
|
* Memory safe by default: array overrun errors, uninitialized values, and other
|
|
problems endemic to C should not occur in Swift, even if it means some amount
|
|
of runtime overhead. Eventually these checks will be disableable for people
|
|
who want ultimate performance in production builds.
|
|
* Efficiently implementable with a static compiler: runtime compilation is
|
|
great technology and Swift may eventually get a runtime optimizer, but it is
|
|
a strong goal to be able to implement swift with just a static compiler.
|
|
* Interoperate as transparently as possible with C, Objective-C, and C++
|
|
without having to write an equivalent of "extern C" for every referenced
|
|
definition.
|
|
* Great support for efficient by-value types.
|
|
* Elegant and natural syntax, aiming to be familiar and easy to transition to
|
|
for "C" people. Differences from the C family should only be done when it
|
|
provides a significant win (e.g. eliminate declarator syntax).
|
|
* Lots of other stuff too.
|
|
|
|
A smaller wishlist goal is to support embedded sub-languages in swift, so that
|
|
we don't get the OpenCL-is-like-C-but-very-different-in-many-details
|
|
problem.
|
|
|
|
Basic Approach
|
|
--------------
|
|
|
|
.. admonition:: Commentary
|
|
|
|
Pushing as much of the language as realistic out of the compiler and into the
|
|
library is generally good for a few reasons: 1) we end up with a smaller core
|
|
language. 2) we force the language that is left to be highly expressive and
|
|
extensible. 3) this highly expressive language core can then be used to
|
|
build a lot of other great libraries, hopefully many we can't even anticipate
|
|
at this point.
|
|
|
|
The basic approach in designing and implementing the Swift prototype was to
|
|
start at the very bottom of the stack (simple expressions and the trivial bits
|
|
of the type system) and incrementally build things up one brick at a time.
|
|
There is a big focus on making things as simple as possible and having a clean
|
|
internal core. Where it makes sense, sugar is added on top to make the core
|
|
more expressive for common situations.
|
|
|
|
One major aspect that dovetails with expressivity, learnability, and focus on
|
|
API development is that much of the language is implemented in a :ref:`standard
|
|
library <langref.stdlib>` (inspired in part by the Haskell Standard Prelude).
|
|
This means that things like ``Int`` and ``Void`` are not part of the language
|
|
itself, but are instead part of the standard library.
|
|
|
|
Phases of Translation
|
|
=====================
|
|
|
|
.. admonition:: Commentary
|
|
|
|
Because Swift doesn't rely on a C-style "lexer hack" to know what is a type
|
|
and what is a value, it is possible to fully parse a file without resolving
|
|
import declarations.
|
|
|
|
Swift has a strict separation between its phases of translation, and the
|
|
compiler follows a conceptually simple design. The phases of translation
|
|
are:
|
|
|
|
* :ref:`Lexing <langref.lexical>`: A source file is broken into tokens
|
|
according to a (nearly, ``/**/`` comments can be nested) regular grammar.
|
|
|
|
* Parsing and AST Building: The tokens are parsed according to the grammar set
|
|
out below. The grammar is context free and does not require any "type
|
|
feedback" from the lexer or later stages. During parsing, name binding for
|
|
references to local variables and other declarations that are not at module
|
|
(and eventually namespace) scope are bound.
|
|
|
|
* :ref:`Name Binding <langref.namebind>`: At this phase, references to
|
|
non-local types and values are bound, and :ref:`import directives
|
|
<langref.decl.import>` are both validated and searched. Name binding can
|
|
cause recursive compilation of modules that are referenced but not yet built.
|
|
|
|
* :ref:`Type Checking <langref.typecheck>`: During this phase all types are
|
|
resolved within value definitions, :ref:`function application
|
|
<langref.expr.call>` and <a href="#expr-infix">binary expressions</a> are
|
|
found and formed, and overloaded functions are resolved.
|
|
|
|
* Code Generation: The AST is converted the LLVM IR, optimizations are
|
|
performed, and machine code generated.
|
|
|
|
* Linking: runtime libraries and referenced modules are linked in.
|
|
|
|
FIXME: "import Swift" implicitly added as the last import in a source file.
|
|
|
|
.. _langref.lexical:
|
|
|
|
Lexical Structure
|
|
=================
|
|
|
|
.. admonition:: Commentary
|
|
|
|
Not all characters are "taken" in the language, this is because it is still
|
|
growing. As there becomes a reason to assign things into the identifier or
|
|
punctuation bucket, we will do so as swift evolves.
|
|
|
|
The lexical structure of a Swift file is very simple: the files are tokenized
|
|
according to the following productions and categories. As is usual with most
|
|
languages, tokenization uses the maximal munch rule and whitespace separates
|
|
tokens. This means that "``a b``" and "``ab``" lex into different token
|
|
streams and are therefore different in the grammar.
|
|
|
|
.. _langref.lexical.whitespace:
|
|
|
|
Whitespace and Comments
|
|
-----------------------
|
|
|
|
.. admonition:: Commentary
|
|
|
|
Nested block comments are important because we don't have the nestable ``#if
|
|
0`` hack from C to rely on.
|
|
|
|
.. code-block:: none
|
|
|
|
whitespace ::= ' '
|
|
whitespace ::= '\n'
|
|
whitespace ::= '\r'
|
|
whitespace ::= '\t'
|
|
whitespace ::= '\0'
|
|
comment ::= //.*[\n\r]
|
|
comment ::= /* .... */
|
|
|
|
Space, newline, tab, and the nul byte are all considered whitespace and are
|
|
discarded, with one exception: a '``(``' or '``[``' which does not follow a
|
|
non-whitespace character is different kind of token (called *spaced*)
|
|
from one which does not (called *unspaced*). A '``(``' or '``[``' at the
|
|
beginning of a file is spaced.
|
|
|
|
Comments may follow the BCPL style, starting with a "``//``" and running to the
|
|
end of the line, or may be recursively nested ``/**/`` style comments. Comments
|
|
are ignored and treated as whitespace.
|
|
|
|
.. _langref.lexical.reserved_punctuation:
|
|
|
|
Reserved Punctuation Tokens
|
|
---------------------------
|
|
|
|
.. admonition:: Commentary
|
|
|
|
Note that ``->`` is used for function types ``() -> Int``, not pointer
|
|
dereferencing.
|
|
|
|
.. code-block:: none
|
|
|
|
punctuation ::= '('
|
|
punctuation ::= ')'
|
|
punctuation ::= '{'
|
|
punctuation ::= '}'
|
|
punctuation ::= '['
|
|
punctuation ::= ']'
|
|
punctuation ::= '.'
|
|
punctuation ::= ','
|
|
punctuation ::= ';'
|
|
punctuation ::= ':'
|
|
punctuation ::= '='
|
|
punctuation ::= '->'
|
|
punctuation ::= '&' // unary prefix operator
|
|
|
|
These are all reserved punctuation that are lexed into tokens. Most other
|
|
non-alphanumeric characters are matched as :ref:`operators
|
|
<langref.lexical.operator>`. Unlike operators, these tokens are not
|
|
overloadable.
|
|
|
|
.. _langref.lexical.keyword:
|
|
|
|
Reserved Keywords
|
|
-----------------
|
|
|
|
.. admonition:: Commentary
|
|
|
|
The number of keywords is reduced by pushing most functionality into the
|
|
library (e.g. "builtin" datatypes like ``Int`` and ``Bool``). This allows us
|
|
to add new stuff to the library in the future without worrying about
|
|
conflicting with the user's namespace.
|
|
|
|
.. code-block:: none
|
|
|
|
// Declarations and Type Keywords
|
|
keyword ::= 'class'
|
|
keyword ::= 'destructor'
|
|
keyword ::= 'extension'
|
|
keyword ::= 'import'
|
|
keyword ::= 'init'
|
|
keyword ::= 'func'
|
|
keyword ::= 'enum'
|
|
keyword ::= 'protocol'
|
|
keyword ::= 'struct'
|
|
keyword ::= 'subscript'
|
|
keyword ::= 'Type'
|
|
keyword ::= 'typealias'
|
|
keyword ::= 'var'
|
|
keyword ::= 'where'
|
|
|
|
// Statements
|
|
keyword ::= 'break'
|
|
keyword ::= 'case'
|
|
keyword ::= 'continue'
|
|
keyword ::= 'default'
|
|
keyword ::= 'do'
|
|
keyword ::= 'else'
|
|
keyword ::= 'if'
|
|
keyword ::= 'in'
|
|
keyword ::= 'for'
|
|
keyword ::= 'return'
|
|
keyword ::= 'switch'
|
|
keyword ::= 'then'
|
|
keyword ::= 'while'
|
|
|
|
// Expressions
|
|
keyword ::= 'as'
|
|
keyword ::= 'is'
|
|
keyword ::= 'new'
|
|
keyword ::= 'super'
|
|
keyword ::= 'self'
|
|
keyword ::= 'Self'
|
|
keyword ::= 'type'
|
|
keyword ::= '__COLUMN__'
|
|
keyword ::= '__FILE__'
|
|
keyword ::= '__LINE__'
|
|
|
|
|
|
These are the builtin keywords. Keywords can still be used as names via
|
|
`escaped identifiers <langref.lexical.escapedident>`.
|
|
|
|
Contextual Keywords
|
|
-------------------
|
|
|
|
Swift uses several contextual keywords at various parts of the language.
|
|
Contextual keywords are not reserved words, meaning that they can be used as
|
|
identifiers. However, in certain contexts, they act as keywords, and are
|
|
represented as such in the grammar below. The following identifiers act as
|
|
contextual keywords within the language:
|
|
|
|
.. code-block:: none
|
|
|
|
get
|
|
infix
|
|
mutating
|
|
nonmutating
|
|
operator
|
|
override
|
|
postfix
|
|
prefix
|
|
set
|
|
|
|
.. _langref.lexical.integer_literal:
|
|
|
|
Integer Literals
|
|
----------------
|
|
|
|
.. code-block:: none
|
|
|
|
integer_literal ::= [0-9][0-9_]*
|
|
integer_literal ::= 0x[0-9a-fA-F][0-9a-fA-F_]*
|
|
integer_literal ::= 0o[0-7][0-7_]*
|
|
integer_literal ::= 0b[01][01_]*
|
|
|
|
Integer literal tokens represent simple integer values of unspecified
|
|
precision. They may be expressed in decimal, binary with the '``0b``' prefix,
|
|
octal with the '``0o``' prefix, or hexadecimal with the '``0x``' prefix.
|
|
Unlike C, a leading zero does not affect the base of the literal.
|
|
|
|
Integer literals may contain underscores at arbitrary positions after the first
|
|
digit. These underscores may be used for human readability and do not affect
|
|
the value of the literal.
|
|
|
|
::
|
|
|
|
789
|
|
0789
|
|
|
|
1000000
|
|
1_000_000
|
|
|
|
0b111_101_101
|
|
0o755
|
|
|
|
0b1111_1011
|
|
0xFB
|
|
|
|
.. _langref.lexical.floating_literal:
|
|
|
|
Floating Point Literals
|
|
-----------------------
|
|
|
|
.. admonition:: Commentary
|
|
|
|
We require a digit on both sides of the dot to allow lexing "``4.km``" as
|
|
"``4 . km``" instead of "``4. km``" and for a series of dots to be an
|
|
operator (for ranges). The regex for decimal literals is same as Java, and
|
|
the one for hex literals is the same as C99, except that we do not allow a
|
|
trailing suffix that specifies a precision.
|
|
|
|
.. code-block:: none
|
|
|
|
floating_literal ::= [0-9][0-9_]*\.[0-9][0-9_]*
|
|
floating_literal ::= [0-9][0-9_]*\.[0-9][0-9_]*[eE][+-]?[0-9][0-9_]*
|
|
floating_literal ::= [0-9][0-9_]*[eE][+-]?[0-9][0-9_]*
|
|
floating_literal ::= 0x[0-9A-Fa-f][0-9A-Fa-f_]*
|
|
(\.[0-9A-Fa-f][0-9A-Fa-f_]*)?[pP][+-]?[0-9][0-9_]*
|
|
|
|
Floating point literal tokens represent floating point values of unspecified
|
|
precision. Decimal and hexadecimal floating-point literals are supported.
|
|
|
|
The integer, fraction, and exponent of a floating point literal may each
|
|
contain underscores at arbitrary positions after their first digits. These
|
|
underscores may be used for human readability and do not affect the value of
|
|
the literal. Each part of the floating point literal must however start with a
|
|
digit; ``1._0`` would be a reference to the ``_0`` member of ``1``.
|
|
|
|
::
|
|
|
|
1.0
|
|
1000000.75
|
|
1_000_000.75
|
|
|
|
0x1.FFFFFFFFFFFFFp1022
|
|
0x1.FFFF_FFFF_FFFF_Fp1_022
|
|
|
|
.. _langref.lexical.character_literal:
|
|
|
|
Character Literals
|
|
------------------
|
|
|
|
.. code-block:: none
|
|
|
|
character_literal ::= '[^'\\\n\r]|character_escape'
|
|
character_escape ::= [\]0 [\][\] | [\]t | [\]n | [\]r | [\]" | [\]'
|
|
character_escape ::= [\]x hex hex
|
|
character_escape ::= [\]u hex hex hex hex
|
|
character_escape ::= [\]U hex hex hex hex hex hex hex hex
|
|
hex ::= [0-9a-fA-F]
|
|
|
|
``character_literal`` tokens represent a single character, and are surrounded
|
|
by single quotes.
|
|
|
|
The ASCII and Unicode character escapes:
|
|
|
|
.. code-block:: none
|
|
|
|
\0 == nul
|
|
\n == new line
|
|
\r == carriage return
|
|
\t == horizontal tab
|
|
\u == small Unicode code points
|
|
\U == large Unicode code points
|
|
\x == raw ASCII byte (less than 0x80)
|
|
|
|
.. _langref.lexical.string_literal:
|
|
|
|
String Literals
|
|
---------------
|
|
|
|
.. admonition:: Commentary
|
|
|
|
FIXME: Forcing ``+`` to concatenate strings is somewhat gross, a proper protocol
|
|
would be better.
|
|
|
|
.. code-block:: none
|
|
|
|
string_literal ::= ["]([^"\\\n\r]|character_escape|escape_expr)*["]
|
|
escape_expr ::= [\]escape_expr_body
|
|
escape_expr_body ::= [(]escape_expr_body[)]
|
|
escape_expr_body ::= [^\n\r"()]
|
|
|
|
``string_literal`` tokens represent a string, and are surrounded by double
|
|
quotes. String literals cannot span multiple lines.
|
|
|
|
String literals may contain embedded expressions in them (known as
|
|
"interpolated expressions") subject to some specific lexical constraints: the
|
|
expression may not contain a double quote ["], newline [\n], or carriage return
|
|
[\r]. All parentheses must be balanced.
|
|
|
|
In addition to these lexical rules, an interpolated expression must satisfy the
|
|
:ref:`expr <langref.expr>` production of the general swift grammar. This
|
|
expression is evaluated, and passed to the constructor for the inferred type of
|
|
the string literal. It is concatenated onto any fixed portions of the string
|
|
literal with a global "``+``" operator that is found through normal name
|
|
lookup.
|
|
|
|
::
|
|
|
|
// Simple string literal.
|
|
"Hello world!"
|
|
|
|
// Interpolated expressions.
|
|
"\(min)...\(max)" + "Result is \((4+i)*j)"
|
|
|
|
.. _langref.lexical.identifier:
|
|
|
|
Identifier Tokens
|
|
-----------------
|
|
|
|
.. code-block:: none
|
|
|
|
identifier ::= id-start id-continue*
|
|
|
|
// An identifier can start with an ASCII letter or underscore...
|
|
id-start ::= [A-Za-z_]
|
|
|
|
// or a Unicode alphanumeric character in the Basic Multilingual Plane...
|
|
// (excluding combining characters, which can't appear initially)
|
|
id-start ::= [\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-00BA]
|
|
id-start ::= [\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]
|
|
id-start ::= [\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]
|
|
id-start ::= [\u1E00-\u1FFF]
|
|
id-start ::= [\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]
|
|
id-start ::= [\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]
|
|
id-start ::= [\u2C00-\u2DFF\u2E80-\u2FFF]
|
|
id-start ::= [\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]
|
|
id-start ::= [\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-FE44]
|
|
id-start ::= [\uFE47-\uFFFD]
|
|
|
|
// or a non-private-use, valid code point outside of the BMP.
|
|
id-start ::= [\u10000-\u1FFFD\u20000-\u2FFFD\u30000-\u3FFFD\u40000-\u4FFFD]
|
|
id-start ::= [\u50000-\u5FFFD\u60000-\u6FFFD\u70000-\u7FFFD\u80000-\u8FFFD]
|
|
id-start ::= [\u90000-\u9FFFD\uA0000-\uAFFFD\uB0000-\uBFFFD\uC0000-\uCFFFD]
|
|
id-start ::= [\uD0000-\uDFFFD\uE0000-\uEFFFD]
|
|
|
|
// After the first code point, an identifier can contain ASCII digits...
|
|
id-continue ::= [0-9]
|
|
|
|
// and/or combining characters...
|
|
id-continue ::= [\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]
|
|
|
|
// in addition to the starting character set.
|
|
id-continue ::= id-start
|
|
|
|
identifier-or-any ::= identifier
|
|
identifier-or-any ::= '_'
|
|
|
|
The set of valid identifier characters is consistent with WG14 N1518,
|
|
"Recommendations for extended identifier characters for C and C++". This
|
|
roughly corresponds to the alphanumeric characters in the Basic Multilingual
|
|
Plane and all non-private-use code points outside of the BMP. It excludes
|
|
mathematical symbols, arrows, line and box drawing characters, and private-use
|
|
and invalid code points. An identifier cannot begin with one of the ASCII
|
|
digits '0' through '9' or with a combining character.
|
|
|
|
The Swift compiler does not normalize Unicode source code, and matches
|
|
identifiers by code points only. Source code must be normalized to a consistent
|
|
normalization form before being submitted to the compiler.
|
|
|
|
::
|
|
|
|
// Valid identifiers
|
|
foo
|
|
_0
|
|
swift
|
|
vernissé
|
|
闪亮
|
|
מבריק
|
|
😄
|
|
|
|
// Invalid identifiers
|
|
☃ // Is a symbol
|
|
0cool // Starts with an ASCII digit
|
|
́foo // Starts with a combining character (U+0301)
|
|
// Is a private-use character (U+F8FF)
|
|
|
|
.. _langref.lexical.operator:
|
|
|
|
Operator Tokens
|
|
---------------
|
|
|
|
.. code-block:: none
|
|
|
|
<a name="operator">operator</a> ::= [/=-+*%<>!&|^~]+
|
|
<a name="operator">operator</a> ::= \.+
|
|
|
|
<a href="#reserved_punctuation">Reserved for punctuation</a>: '.', '=', '->', and unary prefix '&'
|
|
<a href="#whitespace">Reserved for comments</a>: '//', '/*' and '*/'
|
|
|
|
operator-binary ::= operator
|
|
operator-prefix ::= operator
|
|
operator-postfix ::= operator
|
|
|
|
left-binder ::= [ \r\n\t\(\[\{,;:]
|
|
right-binder ::= [ \r\n\t\)\]\},;:]
|
|
|
|
<a name="any-identifier">any-identifier</a> ::= identifier | operator
|
|
|
|
``operator-binary``, ``operator-prefix``, and ``operator-postfix`` are
|
|
distinguished by immediate lexical context. An operator token is called
|
|
*left-bound* if it is immediately preceded by a character matching
|
|
``left-binder``. An operator token is called *right-bound* if it is
|
|
immediately followed by a character matching ``right-binder``. An operator
|
|
token is an ``operator-prefix`` if it is right-bound but not left-bound, an
|
|
``operator-postfix`` if it is left-bound but not right-bound, and an
|
|
``operator-binary`` in either of the other two cases.
|
|
|
|
As an exception, an operator immediately followed by a dot ('``.``') is only
|
|
considered right-bound if not already left-bound. This allows ``a!.prop`` to
|
|
be parsed as ``(a!).prop`` rather than as ``a ! .prop``.
|
|
|
|
The '``!``' operator is postfix if it is left-bound.
|
|
|
|
The '``?``' operator is postfix (and therefore not the ternary operator) if it
|
|
is left-bound. The sugar form for ``Optional`` types must be left-bound.
|
|
|
|
When parsing certain grammatical constructs that involve '``<``' and '``>``'
|
|
(such as <a href="#type-composition">protocol composition types</a>), an
|
|
``operator`` with a leading '``<``' or '``>``' may be split into two or more
|
|
tokens: the leading '``<``' or '``>``' and the remainder of the token, which
|
|
may be an ``operator`` or ``punctuation`` token that may itself be further
|
|
split. This rule allows us to parse nested constructs such as ``A<B<C>>``
|
|
without requiring spaces between the closing '``>``'s.
|
|
|
|
.. _langref.lexical.dollarident:
|
|
|
|
Implementation Identifier Token
|
|
-------------------------------
|
|
|
|
.. code-block:: none
|
|
|
|
dollarident ::= '$' id-continue+
|
|
|
|
Tokens that start with a ``$`` are separate class of identifier, which are
|
|
fixed purpose names that are defined by the implementation.
|
|
|
|
.. _langref.lexical.escapedident:
|
|
|
|
Escaped Identifiers
|
|
-------------------
|
|
|
|
.. code-block:: none
|
|
|
|
identifier ::= '`' id-start id-continue* '`'
|
|
|
|
An identifier that would normally be a `keyword <langref.lexical.keyword>` may
|
|
be used as an identifier by wrapping it in backticks '``\```', for example::
|
|
|
|
func `class`() { /* ... */ }
|
|
let `type` = 0.type
|
|
|
|
Any identifier may be escaped, though only identifiers that would normally be
|
|
parsed as keywords are required to be. The backtick-quoted string must still
|
|
form a valid, non-operator identifier::
|
|
|
|
let `0` = 0 // Error, "0" doesn't start with an alphanumeric
|
|
let `foo-bar` = 0 // Error, '-' isn't an identifier character
|
|
let `+` = 0 // Error, '+' is an operator
|
|
|
|
.. _langref.namebind:
|
|
|
|
Name Binding
|
|
============
|
|
|
|
.. _langref.typecheck:
|
|
|
|
Type Checking
|
|
=============
|
|
|
|
.. _langref.decl:
|
|
|
|
Declarations
|
|
============
|
|
|
|
...
|
|
|
|
.. _langref.decl.import:
|
|
|
|
Import Declarations
|
|
-------------------
|
|
|
|
...
|
|
|
|
.. _langref.decl.var:
|
|
|
|
``var`` Declarations
|
|
--------------------
|
|
|
|
.. code-block:: none
|
|
|
|
decl-var-head-kw ::= ('static' | 'class')? 'override'?
|
|
decl-var-head-kw ::= 'override'? ('static' | 'class')?
|
|
|
|
decl-var-head ::= attribute-list decl-var-head-kw? 'var'
|
|
|
|
decl-var ::= decl-var-head pattern initializer? (',' pattern initializer?)*
|
|
|
|
// 'get' is implicit in this syntax.
|
|
decl-var ::= decl-var-head identifier ':' type brace-item-list
|
|
|
|
decl-var ::= decl-var-head identifier ':' type '{' get-set '}'
|
|
|
|
decl-var ::= decl-var-head identifier ':' type initializer? '{' willset-didset '}'
|
|
|
|
// For use in protocols.
|
|
decl-var ::= decl-var-head identifier ':' type '{' get-set-kw '}'
|
|
|
|
get-set ::= get set?
|
|
get-set ::= set get
|
|
|
|
get ::= attribute-list ( 'mutating' | 'nonmutating' )? 'get' brace-item-list
|
|
set ::= attribute-list ( 'mutating' | 'nonmutating' )? 'set' set-name? brace-item-list
|
|
set-name ::= '(' identifier ')'
|
|
|
|
willset-didset ::= willset didset?
|
|
willset-didset ::= didset willset?
|
|
|
|
willset ::= attribute-list 'willSet' set-name? brace-item-list
|
|
didset ::= attribute-list 'didSet' set-name? brace-item-list
|
|
|
|
get-kw ::= attribute-list ( 'mutating' | 'nonmutating' )? 'get'
|
|
set-kw ::= attribute-list ( 'mutating' | 'nonmutating' )? 'set'
|
|
get-set-kw ::= get-kw set-kw?
|
|
get-set-kw ::= set-kw get-kw
|
|
|
|
``var`` declarations form the backbone of value declarations in Swift. A
|
|
``var`` declaration takes a pattern and an optional initializer, and declares
|
|
all the pattern-identifiers in the pattern as variables. If there is an
|
|
initializer and the pattern is :ref:`fully-typed <langref.types.fully_typed>`,
|
|
the initializer is converted to the type of the pattern. If there is an
|
|
initializer and the pattern is not fully-typed, the type of initializer is
|
|
computed independently of the pattern, and the type of the pattern is derived
|
|
from the initializer. If no initializer is specified, the pattern must be
|
|
fully-typed, and the values are default-initialized.
|
|
|
|
If there is more than one pattern in a ``var`` declaration, they are each
|
|
considered independently, as if there were multiple declarations. The initial
|
|
``attribute-list`` is shared between all the declared variables.
|
|
|
|
A var declaration may contain a getter and (optionally) a setter, which will
|
|
be used when reading or writing the variable, respectively. Such a variable
|
|
does not have any associated storage. A ``var`` declaration with a getter or
|
|
setter must have a type (call it ``T``). The getter function, whose
|
|
body is provided as part of the ``var-get`` clause, has type ``() -> T``.
|
|
Similarly, the setter function, whose body is part of the ``var-set`` clause
|
|
(if provided), has type ``(T) -> ()``.
|
|
|
|
If the ``var-set`` or ``willset`` clause contains a ``set-name`` clause, the
|
|
identifier of that clause is used as the name of the parameter to the setter or
|
|
the observing accessor. Otherwise, the parameter name is ``newValue``. Same
|
|
applies to ``didset`` clause, but the default parameter name is ``oldValue``.
|
|
|
|
FIXME: Should the type of a pattern which isn't fully typed affect the
|
|
type-checking of the expression (i.e. should we compute a structured dependent
|
|
type)?
|
|
|
|
Like all other declarations, ``var``\ s can optionally have a list of
|
|
:ref:`attributes <langref.decl.attribute_list>` applied to them.
|
|
|
|
The type of a variable must be :ref:`materializable
|
|
<langref.types.materializable>`. A variable is an lvalue unless it has a
|
|
``var-get`` clause but not ``var-set`` clause.
|
|
|
|
Here are some examples of ``var`` declarations:
|
|
|
|
::
|
|
|
|
// Simple examples.
|
|
var a = 4
|
|
var b: Int
|
|
var c: Int = 42
|
|
|
|
// This decodes the tuple return value into independently named parts
|
|
// and both 'val' and 'err' are in scope after this line.
|
|
var (val, err) = foo()
|
|
|
|
// Variable getter/setter
|
|
var _x: Int = 0
|
|
var x_modify_count: Int = 0
|
|
var x1: Int {
|
|
return _x
|
|
}
|
|
var x2: Int {
|
|
get {
|
|
return _x
|
|
}
|
|
set {
|
|
x_modify_count = x_modify_count + 1
|
|
_x = value
|
|
}
|
|
}
|
|
|
|
Note that ``get``, ``set``, ``willSet`` and ``didSet`` are context-sensitive
|
|
keywords.
|
|
|
|
``static`` keyword is allowed inside structs and enums, and extensions of
|
|
those.
|
|
|
|
``class`` keyword is allowed inside classes, class extensions, and
|
|
protocols.
|
|
|
|
.. admonition:: Ambiguity 1
|
|
|
|
The production for implicit ``get`` makes this grammar ambiguous. For example:
|
|
|
|
::
|
|
|
|
class A {
|
|
func get(_: () -> Int) {}
|
|
var a: Int {
|
|
get { return 0 } // Getter declaration or call to 'get' with a trailing closure?
|
|
}
|
|
// But if this was intended as a call to 'get' function, then we have a
|
|
// getter without a 'return' statement, so the code is invalid anyway.
|
|
}
|
|
|
|
We disambiguate towards ``get-set`` or ``willset-didset`` production if the
|
|
first token after ``{`` is the corresponding keyword, possibly preceded by
|
|
attributes. Thus, the following code is rejected because we are expecting
|
|
``{`` after ``set``:
|
|
|
|
::
|
|
|
|
class A {
|
|
var set: Foo
|
|
var a: Int {
|
|
set.doFoo()
|
|
return 0
|
|
}
|
|
}
|
|
|
|
.. admonition:: Ambiguity 2
|
|
|
|
The production with ``initializer`` and an accessor block is ambiguous. For
|
|
example:
|
|
|
|
::
|
|
|
|
func takeClosure(_: () -> Int) {}
|
|
struct A {
|
|
var willSet: Int
|
|
var a: Int = takeClosure {
|
|
willSet {} // A 'willSet' declaration or a call to 'takeClosure'?
|
|
}
|
|
}
|
|
|
|
We disambiguate towards ``willget-didset`` production if the first token
|
|
after ``{`` is the keyword ``willSet`` or ``didSet``, possibly preceded by
|
|
attributes.
|
|
|
|
.. admonition:: Rationale
|
|
|
|
Even though it is possible to do further checks and speculatively parse more,
|
|
it introduces unjustified complexity to cover (hopefully rare) corner cases.
|
|
In ambiguous cases users can always opt-out of the trailing closure syntax by
|
|
using explicit parentheses in the function call.
|
|
|
|
.. _langref.decl.func:
|
|
|
|
``func`` Declarations
|
|
---------------------
|
|
|
|
.. code-block:: none
|
|
|
|
// Keywords can be specified in any order.
|
|
decl-func-head-kw ::= ( 'static' | 'class' )? 'override'? ( 'mutating' | 'nonmutating' )?
|
|
|
|
decl-func ::= attribute-list decl-func-head-kw? 'func' any-identifier generic-params? func-signature brace-item-list?
|
|
|
|
``func`` is a declaration for a function. The argument list and optional
|
|
return value are specified by the type production of the function, and the body
|
|
is either a brace expression or elided. Like all other declarations, functions
|
|
are can have attributes.
|
|
|
|
If the type is not syntactically a function type (i.e., has no ``->`` in it at
|
|
top-level), then the return value is implicitly inferred to be ``()``. All of
|
|
the argument and return value names are injected into the <a
|
|
href="#namebind_scope">scope</a> of the function body.</p>
|
|
|
|
A function in an <a href="#decl-extension">extension</a> of some type (or
|
|
in other places that are semantically equivalent to an extension) implicitly
|
|
get a ``self`` argument with these rules ... [todo]
|
|
|
|
``static`` and ``class`` functions are only allowed in an <a
|
|
href="#decl-extension">extension</a> of some type (or in other places that are
|
|
semantically equivalent to an extension). They indicate that the function is
|
|
actually defined on the <a href="#metatype">metatype</a> for the type, not on
|
|
the type itself. Thus its implicit ``self`` argument is actually of
|
|
metatype type.
|
|
|
|
``static`` keyword is allowed inside structs and enums, and extensions of those.
|
|
|
|
``class`` keyword is allowed inside classes, class extensions, and protocols.
|
|
|
|
TODO: Func should be an immutable name binding, it should implicitly add an
|
|
attribute immutable when it exists.
|
|
|
|
TODO: Incoming arguments should be readonly, result should be implicitly
|
|
writeonly when we have these attributes.
|
|
|
|
.. _langref.decl.func.signature:
|
|
|
|
Function signatures
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
...
|
|
|
|
An argument name is a keyword argument if:
|
|
- It is an argument to an initializer, or
|
|
- It is an argument to a method after the first argument, or
|
|
- It is preceded by a back-tick (`), or
|
|
- Both a keyword argument name and an internal parameter name are specified.
|
|
|
|
.. _langref.decl.subscript:
|
|
|
|
``subscript`` Declarations
|
|
---------------------------
|
|
|
|
.. code-block:: none
|
|
|
|
subscript-head ::= attribute-list 'override'? 'subscript' pattern-tuple '->' type
|
|
|
|
decl-subscript ::= subscript-head '{' get-set '}'
|
|
|
|
// 'get' is implicit in this syntax.
|
|
decl-subscript ::= subscript-head brace-item-list
|
|
|
|
// For use in protocols.
|
|
decl-subscript ::= subscript-head '{' get-set-kw '}'
|
|
|
|
A subscript declaration provides support for <a href="#expr-subscript">
|
|
subscripting</a> an object of a particular type via a getter and (optional)
|
|
setter. Therefore, subscript declarations can only appear within a type
|
|
definition or extension.
|
|
|
|
The ``pattern-tuple`` of a subscript declaration provides the indices that
|
|
will be used in the subscript expression, e.g., the ``i`` in ``a[i]``. This
|
|
pattern must be fully-typed. The ``type`` following the arrow provides the
|
|
type of element being accessed, which must be materializable. Subscript
|
|
declarations can be overloaded, so long as either the ``pattern-tuple`` or
|
|
``type`` differs from other declarations.
|
|
|
|
The ``get-set`` clause specifies the getter and setter used for subscripting.
|
|
The getter is a function whose input is the type of the ``pattern-tuple`` and
|
|
whose result is the element type. Similarly, the setter is a function whose
|
|
result type is ``()`` and whose input is the type of the ``pattern-tuple``
|
|
with a parameter of the element type added to the end of the tuple; the name
|
|
of the parameter is the ``set-name``, if provided, or ``value`` otherwise.
|
|
|
|
::
|
|
|
|
// Simple bit vector with storage for 64 boolean values
|
|
struct BitVector64 {
|
|
var bits: Int64
|
|
|
|
// Allow subscripting with integer subscripts and a boolean result.
|
|
subscript (bit : Int) -> Bool {
|
|
// Getter tests the given bit
|
|
get {
|
|
return bits & (1 << bit)) != 0
|
|
}
|
|
|
|
// Setter sets the given bit to the provided value.
|
|
set {
|
|
var mask = 1 << bit
|
|
if value {
|
|
bits = bits | mask
|
|
} else {
|
|
bits = bits & ~mask
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var vec = BitVector64()
|
|
vec[2] = true
|
|
if vec[3] {
|
|
print("third bit is set")
|
|
}
|
|
|
|
.. _langref.decl.attribute_list:
|
|
|
|
Attribute Lists
|
|
---------------
|
|
|
|
...
|
|
|
|
.. _langref.types:
|
|
|
|
Types
|
|
=====
|
|
|
|
...
|
|
|
|
.. _langref.types.fully_typed:
|
|
|
|
Fully-Typed Types
|
|
-----------------
|
|
|
|
...
|
|
|
|
.. _langref.types.materializable:
|
|
|
|
Materializable Types
|
|
--------------------
|
|
|
|
...
|
|
|
|
.. _langref.pattern:
|
|
|
|
Patterns
|
|
========
|
|
|
|
.. admonition:: Commentary
|
|
|
|
The pattern grammar mirrors the expression grammar, or to be more specific,
|
|
the grammar of literals. This is because the conceptual algorithm for
|
|
matching a value against a pattern is to try to find an assignment of values
|
|
to variables which makes the pattern equal the value. So every expression
|
|
form which can be used to build a value directly should generally have a
|
|
corresponding pattern form.
|
|
|
|
.. code-block:: none
|
|
|
|
pattern-atom ::= pattern-var
|
|
pattern-atom ::= pattern-any
|
|
pattern-atom ::= pattern-tuple
|
|
pattern-atom ::= pattern-is
|
|
pattern-atom ::= pattern-enum-element
|
|
pattern-atom ::= expr
|
|
|
|
pattern ::= pattern-atom
|
|
pattern ::= pattern-typed
|
|
|
|
A pattern represents the structure of a composite value. Parts of a value can
|
|
be extracted and bound to variables or compared against other values by
|
|
*pattern matching*. Among other places, pattern matching occurs on the
|
|
left-hand side of :ref:`var bindings <langref.decl.var>`, in the arguments of
|
|
:ref:`func declarations <langref.decl.func>`, and in the <tt>case</tt> labels
|
|
of :ref:`switch statements <langref.stmt.switch>`. Some examples::
|
|
|
|
var point = (1, 0, 0)
|
|
|
|
// Extract the elements of the "point" tuple and bind them to
|
|
// variables x, y, and z.
|
|
var (x, y, z) = point
|
|
print("x=\(x) y=\(y) z=\(z)")
|
|
|
|
// Dispatch on the elements of a tuple in a "switch" statement.
|
|
switch point {
|
|
case (0, 0, 0):
|
|
print("origin")
|
|
// The pattern "_" matches any value.
|
|
case (_, 0, 0):
|
|
print("on the x axis")
|
|
case (0, _, 0):
|
|
print("on the y axis")
|
|
case (0, 0, _):
|
|
print("on the z axis")
|
|
case (var x, var y, var z):
|
|
print("x=\(x) y=\(y) z=\(z)")
|
|
}
|
|
|
|
|
|
A pattern may be "irrefutable", meaning informally that it matches all values
|
|
of its type. Patterns in declarations, such as :ref:`var <langref.decl.var>`
|
|
and :ref:`func <langref.decl.func>`, are required to be irrefutable. Patterns
|
|
in the ``case`` labels of :ref:`switch statements <langref.stmt.switch>`,
|
|
however, are not.
|
|
|
|
The basic pattern grammar is a literal "atom" followed by an optional type
|
|
annotation. Type annotations are useful for documentation, as well as for
|
|
coercing a matched expression to a particular kind. They are also required
|
|
when patterns are used in a :ref:`function signature
|
|
<langref.decl.func.signature>`. Type annotations are currently not allowed in
|
|
switch statements.
|
|
|
|
A pattern has a type. A pattern may be "fully-typed", meaning informally that
|
|
its type is fully determined by the type annotations it contains. Some
|
|
patterns may also derive a type from their context, be it an enclosing pattern
|
|
or the way it is used; this set of situations is not yet fully determined.
|
|
|
|
.. _langref.pattern.typed:
|
|
|
|
Typed Patterns
|
|
--------------
|
|
|
|
.. code-block:: none
|
|
|
|
pattern-typed ::= pattern-atom ':' type
|
|
|
|
A type annotation constrains a pattern to have a specific type. An annotated
|
|
pattern is fully-typed if its annotation type is fully-typed. It is
|
|
irrefutable if and only if its subpattern is irrefutable.
|
|
|
|
Type annotations are currently not allowed in the ``case`` labels of ``switch``
|
|
statements; case patterns always get their type from the subject of the switch.
|
|
|
|
.. _langref.pattern.any:
|
|
|
|
Any Patterns
|
|
------------
|
|
|
|
.. code-block:: none
|
|
|
|
pattern-any ::= '_'
|
|
|
|
The symbol ``_`` in a pattern matches and ignores any value. It is irrefutable.
|
|
|
|
.. _langref.pattern.var:
|
|
|
|
'var' and 'let' Patterns
|
|
------------------------
|
|
|
|
.. code-block:: none
|
|
|
|
pattern-var ::= 'let' pattern
|
|
pattern-var ::= 'var' pattern
|
|
|
|
The ``var`` and ``let`` keywords within a pattern introduces variable bindings.
|
|
Any identifiers within the subpattern bind new named variables to their
|
|
matching values. 'var' bindings are mutable within the bound scope, and 'let'
|
|
bindings are immutable.
|
|
|
|
::
|
|
|
|
var point = (0, 0, 0)
|
|
switch point {
|
|
// Bind x, y, z to the elements of point.
|
|
case (var x, var y, var z):
|
|
print("x=\(x) y=\(y) z=\(z)")
|
|
}
|
|
|
|
switch point {
|
|
// Same. 'var' distributes to the identifiers in its subpattern.
|
|
case var (x, y, z):
|
|
print("x=\(x) y=\(y) z=\(z)")
|
|
}
|
|
|
|
Outside of a <tt>var</tt> pattern, an identifier behaves as an :ref:`expression
|
|
pattern <langref.pattern.expr>` referencing an existing definition.
|
|
|
|
::
|
|
|
|
var zero = 0
|
|
switch point {
|
|
// x and z are bound as new variables.
|
|
// zero is a reference to the existing 'zero' variable.
|
|
case (var x, zero, var z):
|
|
print("point off the y axis: x=\(x) z=\(z)")
|
|
default:
|
|
print("on the y axis")
|
|
}
|
|
|
|
The left-hand pattern of a :ref:`var declaration <langref.decl.var>` and the
|
|
argument pattern of a :ref:`func declaration <langref.decl.func>` are
|
|
implicitly inside a ``var`` pattern; identifiers in their patterns always bind
|
|
variables. Variable bindings are irrefutable.
|
|
|
|
The type of a bound variable must be :ref:`materializable
|
|
<langref.types.materializable>` unless it appears in a :ref:`func-signature
|
|
<langref.decl.func.signature>` and is directly of a ``inout``\ -annotated type.
|
|
|
|
.. _langref.pattern.tuple:
|
|
|
|
Tuple Patterns
|
|
--------------
|
|
|
|
.. code-block:: none
|
|
|
|
pattern-tuple ::= '(' pattern-tuple-body? ')'
|
|
pattern-tuple-body ::= pattern-tuple-element (',' pattern-tuple-body)* '...'?
|
|
pattern-tuple-element ::= pattern
|
|
|
|
A tuple pattern is a list of zero or more patterns. Within a :ref:`function
|
|
signature <langref.decl.func.signature>`, patterns may also be given a
|
|
default-value expression.
|
|
|
|
A tuple pattern is irrefutable if all its sub-patterns are irrefutable.
|
|
|
|
A tuple pattern is fully-typed if all its sub-patterns are fully-typed, in
|
|
which case its type is the corresponding tuple type, where each
|
|
``type-tuple-element`` has the type, label, and default value of the
|
|
corresponding ``pattern-tuple-element``. A ``pattern-tuple-element`` has a
|
|
label if it is a named pattern or a type annotation of a named pattern.
|
|
|
|
A tuple pattern whose body ends in ``'...'`` is a varargs tuple. The last
|
|
element of such a tuple must be a typed pattern, and the type of that pattern
|
|
is changed from ``T`` to ``[T]``. The corresponding tuple type for a varargs
|
|
tuple is a varargs tuple type.
|
|
|
|
As a special case, a tuple pattern with one element that has no label, has no
|
|
default value, and is not varargs is treated as a grouping parenthesis: it has
|
|
the type of its constituent pattern, not a tuple type.
|
|
|
|
.. _langref.pattern.is:
|
|
|
|
``is`` Patterns
|
|
---------------
|
|
|
|
.. code-block:: none
|
|
|
|
pattern-is ::= 'is' type
|
|
|
|
``is`` patterns perform a type check equivalent to the ``x is T`` <a
|
|
href="#expr-cast">cast operator</a>. The pattern matches if the runtime type of
|
|
a value is of the given type. ``is`` patterns are refutable and thus cannot
|
|
appear in declarations.
|
|
|
|
::
|
|
|
|
class B {}
|
|
class D1 : B {}
|
|
class D2 : B {}
|
|
|
|
var bs : [B] = [B(), D1(), D2()]
|
|
|
|
for b in bs {
|
|
switch b {
|
|
case is B:
|
|
print("B")
|
|
case is D1:
|
|
print("D1")
|
|
case is D2:
|
|
print("D2")
|
|
}
|
|
}
|
|
|
|
|
|
.. _langref.pattern.enum_element:
|
|
|
|
Enum Element Patterns
|
|
---------------------
|
|
|
|
.. code-block:: none
|
|
|
|
pattern-enum-element ::= type-identifier? '.' identifier pattern-tuple?
|
|
|
|
Enum element patterns match a value of <a href="#type-enum">enum type</a> if
|
|
the value matches the referenced ``case`` of the enum. If the ``case`` has a
|
|
type, the value of that type can be matched against an optional subpattern.
|
|
|
|
::
|
|
|
|
enum HTMLTag {
|
|
case A(href: String)
|
|
case IMG(src: String, alt: String)
|
|
case BR
|
|
}
|
|
|
|
switch tag {
|
|
case .BR:
|
|
print("<br>")
|
|
case .IMG(var src, var alt):
|
|
print("<img src=\"\(escape(src))\" alt=\"\(escape(alt))\">")
|
|
case .A(var href):
|
|
print("<a href=\"\(escape(href))\">")
|
|
}
|
|
|
|
Enum element patterns are refutable and thus cannot appear in declarations.
|
|
(They are currently considered refutable even if the enum contains only a
|
|
single ``case``.)
|
|
|
|
.. _langref.pattern.expr:
|
|
|
|
Expressions in Patterns
|
|
-----------------------
|
|
|
|
Patterns may include arbitrary expressions as subpatterns. Expression patterns
|
|
are refutable and thus cannot appear in declarations. An expression pattern is
|
|
compared to its corresponding value using the ``~=`` operator. The match
|
|
succeeds if ``expr ~= value`` evaluates to true. The standard library provides
|
|
a default implementation of ``~=`` using ``==`` equality; additionally, range
|
|
objects may be matched against integer and floating-point values. The ``~=``
|
|
operator may be overloaded like any function.
|
|
|
|
::
|
|
|
|
var point = (0, 0, 0)
|
|
switch point {
|
|
// Equality comparison.
|
|
case (0, 0, 0):
|
|
print("origin")
|
|
// Range comparison.
|
|
case (-10...10, -10...10, -10...10):
|
|
print("close to the origin")
|
|
default:
|
|
print("too far away")
|
|
}
|
|
|
|
// Define pattern matching of an integer value to a string expression.
|
|
func ~=(pattern:String, value:Int) -> Bool {
|
|
return pattern == "\(value)"
|
|
}
|
|
|
|
// Now we can pattern-match strings to integers:
|
|
switch point {
|
|
case ("0", "0", "0"):
|
|
print("origin")
|
|
default:
|
|
print("not the origin")
|
|
}
|
|
|
|
The order of evaluation of expressions in patterns, including whether an
|
|
expression is evaluated at all, is unspecified. The compiler is free to
|
|
reorder or elide expression evaluation in patterns to improve dispatch
|
|
efficiency. Expressions in patterns therefore cannot be relied on for side
|
|
effects.
|
|
|
|
.. _langref.expr:
|
|
|
|
Expressions
|
|
===========
|
|
|
|
...
|
|
|
|
.. _langref.expr.call:
|
|
|
|
Function Application
|
|
--------------------
|
|
|
|
...
|
|
|
|
.. _langref.stmt:
|
|
|
|
Statements
|
|
==========
|
|
|
|
...
|
|
|
|
.. _langref.stmt.break:
|
|
|
|
``break`` Statement
|
|
-------------------
|
|
|
|
.. code-block:: none
|
|
|
|
stmt-return ::= 'break'
|
|
|
|
The 'break' statement transfers control out of the enclosing 'for' loop or
|
|
'while' loop.
|
|
|
|
.. _langref.stmt.continue:
|
|
|
|
``continue`` Statement
|
|
----------------------
|
|
|
|
.. code-block:: none
|
|
|
|
stmt-return ::= 'continue'
|
|
|
|
The 'continue' statement transfers control back to the start of the enclosing
|
|
'for' loop or 'while' loop.
|
|
|
|
...
|
|
|
|
.. _langref.stmt.switch:
|
|
|
|
``switch`` Statement
|
|
--------------------
|
|
|
|
.. code-block:: none
|
|
|
|
stmt-switch ::= 'switch' expr-basic '{' stmt-switch-case* '}'
|
|
|
|
stmt-switch-case ::= (case-label | default-label) brace-item+
|
|
stmt-switch-case ::= (case-label | default-label) ';'
|
|
|
|
case-label ::= 'case' pattern ('where' expr)? (',' pattern ('where' expr)?)* ':'
|
|
default-label ::= 'default' ':'
|
|
|
|
'switch' statements branch on the value of an expression by :ref:`pattern
|
|
matching <langref.pattern>`. The subject expression of the switch is evaluated
|
|
and tested against the patterns in its ``case`` labels in source order. When a
|
|
pattern is found that matches the value, control is transferred into the
|
|
matching ``case`` block. ``case`` labels may declare multiple patterns
|
|
separated by commas. Only a single ``case`` labels may precede a block of
|
|
code. Case labels may optionally specify a *guard* expression, introduced by
|
|
the ``where`` keyword; if present, control is transferred to the case only if
|
|
the subject value both matches the corresponding pattern and the guard
|
|
expression evaluates to true. Patterns are tested "as if" in source order; if
|
|
multiple cases can match a value, control is transferred only to the first
|
|
matching case. The actual execution order of pattern matching operations, and
|
|
in particular the evaluation order of :ref:`expression patterns
|
|
<langref.pattern.expr>`, is unspecified.
|
|
|
|
A switch may also contain a ``default`` block. If present, it receives control
|
|
if no cases match the subject value. The ``default`` block must appear at the
|
|
end of the switch and must be the only label for its block. ``default`` is
|
|
equivalent to a final ``case _`` pattern. Switches are required to be
|
|
exhaustive; either the contained case patterns must cover every possible value
|
|
of the subject's type, or else an explicit ``default`` block must be specified
|
|
to handle uncovered cases.
|
|
|
|
Every case and default block has its own scope. Declarations within a case or
|
|
default block are only visible within that block. Case patterns may bind
|
|
variables using the :ref:`var keyword <langref.pattern.var>`; those variables
|
|
are also scoped into the corresponding case block, and may be referenced in the
|
|
``where`` guard for the case label. However, if a case block matches multiple
|
|
patterns, none of those patterns may contain variable bindings.
|
|
|
|
Control does not implicitly 'fall through' from one case block to the next.
|
|
:ref:`fallthrough statements <langref.stmt.fallthrough>` may explicitly
|
|
transfer control among case blocks. :ref:`break <langref.stmt.break>` and
|
|
:ref:`continue <langref.stmt.continue>` within a switch will break or continue
|
|
out of an enclosing 'while' or 'for' loop, not out of the 'switch' itself.
|
|
|
|
At least one ``brace-item`` is required in every case or default block. It is
|
|
allowed to be a no-op. Semicolon can be used as a single no-op statement in
|
|
otherwise empty cases in switch statements.
|
|
|
|
::
|
|
|
|
func classifyPoint(point: (Int, Int)) {
|
|
switch point {
|
|
case (0, 0):
|
|
print("origin")
|
|
|
|
case (_, 0):
|
|
print("on the x axis")
|
|
|
|
case (0, _):
|
|
print("on the y axis")
|
|
|
|
case (var x, var y) where x == y:
|
|
print("on the y = x diagonal")
|
|
|
|
case (var x, var y) where -x == y:
|
|
print("on the y = -x diagonal")
|
|
|
|
case (var x, var y):
|
|
print("length \(sqrt(x*x + y*y))")
|
|
}
|
|
}
|
|
|
|
switch x {
|
|
case 1, 2, 3:
|
|
print("x is 1, 2 or 3")
|
|
default:
|
|
;
|
|
}
|
|
|
|
.. _langref.stmt.fallthrough:
|
|
|
|
``fallthrough`` Statement
|
|
-------------------------
|
|
|
|
.. code-block:: none
|
|
|
|
stmt-fallthrough ::= 'fallthrough'
|
|
|
|
``fallthrough`` transfers control from a ``case`` block of a :ref:`switch
|
|
statement <langref.stmt.switch>` to the next ``case`` or ``default`` block
|
|
within the switch. It may only appear inside a ``switch``. ``fallthrough``
|
|
cannot be used in the final block of a ``switch``. It also cannot transfer
|
|
control into a ``case`` block whose pattern contains :ref:`var bindings
|
|
<langref.pattern.var>`.
|
|
|
|
.. _langref.stdlib:
|
|
|
|
Standard Library
|
|
================
|
|
|
|
.. admonition:: Commentary
|
|
|
|
It would be really great to have literate swift code someday, that way this
|
|
could be generated directly from the code. This would also be powerful for
|
|
Swift library developers to be able to depend on being available and
|
|
standardized.
|
|
|
|
This describes some of the standard swift code as it is being built up. Since
|
|
Swift is designed to give power to the library developers, much of what is
|
|
normally considered the "language" is actually just implemented in the
|
|
library.
|
|
|
|
All of this code is published by the '``swift``' module, which is implicitly
|
|
imported into each source file, unless some sort of pragma in the code
|
|
(attribute on an import?) is used to change or disable this behavior.
|
|
|
|
.. _langref.stdlib.builtin:
|
|
|
|
Builtin Module
|
|
==============
|
|
|
|
In the initial Swift implementation, a module named ``Builtin`` is imported
|
|
into every file. Its declarations can only be found by <a href="#expr-dot">dot
|
|
syntax</a>. It provides access to a small number of primitive representation
|
|
types and operations defined over them that map directly to LLVM IR.
|
|
|
|
The existence of and details of this module are a private implementation detail
|
|
used by our implementation of the standard library. Swift code outside the
|
|
standard library should not be aware of this library, and an independent
|
|
implementation of the swift standard library should be allowed to be
|
|
implemented without the builtin library if it desires.
|
|
|
|
For reference below, the description of the standard library uses the
|
|
"``Builtin.``" namespace to refer to this module, but independent
|
|
implementations could use another implementation if they so desire.
|
|
|
|
.. _langref.stdlib.simple-types:
|
|
|
|
Simple Types
|
|
------------
|
|
|
|
Void
|
|
^^^^
|
|
|
|
::
|
|
|
|
// Void is just a type alias for the empty tuple.
|
|
typealias Void = ()
|
|
|
|
.. _langref.stdlib.int:
|
|
|
|
Int, Int8, Int16, Int32, Int64
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. admonition:: Commentary
|
|
|
|
Having a single standardized integer type that can be used by default
|
|
everywhere is important. One advantage Swift has is that by the time it is
|
|
in widespread use, 64-bit architectures will be pervasive, and the LLVM
|
|
optimizer should grow to be good at shrinking 64-bit integers to 32-bit in
|
|
many cases for those 32-bit architectures that persist.
|
|
|
|
::
|
|
|
|
// Fixed size types are simple structs of the right size.
|
|
struct Int8 { value : Builtin.Int8 }
|
|
struct Int16 { value : Builtin.Int16 }
|
|
struct Int32 { value : Builtin.Int32 }
|
|
struct Int64 { value : Builtin.Int64 }
|
|
struct Int128 { value : Builtin.Int128 }
|
|
|
|
// Int is just an alias for the 64-bit integer type.
|
|
typealias Int = Int64
|
|
|
|
.. _langref.stdlib.float:
|
|
|
|
Int, Int8, Int16, Int32, Int64
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
::
|
|
|
|
struct Float { value : Builtin.FPIEEE32 }
|
|
struct Double { value : Builtin.FPIEEE64 }
|
|
|
|
.. _langref.stdlib.bool:
|
|
|
|
Bool, true, false
|
|
^^^^^^^^^^^^^^^^^
|
|
|
|
::
|
|
|
|
// Bool is a simple enum.
|
|
enum Bool {
|
|
true, false
|
|
}
|
|
|
|
// Allow true and false to be used unqualified.
|
|
var true = Bool.true
|
|
var false = Bool.false
|
|
|
|
.. _langref.stdlib.oper:
|
|
|
|
Arithmetic and Logical Operations
|
|
---------------------------------
|
|
|
|
.. _langref.stdlib.oper.arithmetic:
|
|
|
|
Arithmetic Operators
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
::
|
|
|
|
func * (lhs: Int, rhs: Int) -> Int
|
|
func / (lhs: Int, rhs: Int) -> Int
|
|
func % (lhs: Int, rhs: Int) -> Int
|
|
func + (lhs: Int, rhs: Int) -> Int
|
|
func - (lhs: Int, rhs: Int) -> Int
|
|
|
|
.. _langref.stdlib.oper.comparison:
|
|
|
|
Relational and Equality Operators
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
::
|
|
|
|
func < (lhs : Int, rhs : Int) -> Bool
|
|
func > (lhs : Int, rhs : Int) -> Bool
|
|
func <= (lhs : Int, rhs : Int) -> Bool
|
|
func >= (lhs : Int, rhs : Int) -> Bool
|
|
func == (lhs : Int, rhs : Int) -> Bool
|
|
func != (lhs : Int, rhs : Int) -> Bool
|
|
|
|
.. _langref.stdlib.oper.short-circuit-logical:
|
|
|
|
Short Circuiting Logical Operators
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
::
|
|
|
|
func && (lhs: Bool, rhs: () -> Bool) -> Bool
|
|
func || (lhs: Bool, rhs: () -> Bool) -> Bool
|
|
|
|
Swift has a simplified precedence levels when compared with C. From highest to
|
|
lowest:
|
|
|
|
::
|
|
|
|
"exponentiative:" <<, >>
|
|
"multiplicative:" *, /, %, &
|
|
"additive:" +, -, |, ^
|
|
"comparative:" ==, !=, <, <=, >=, >
|
|
"conjunctive:" &&
|
|
"disjunctive:" ||
|