mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-23 03:16:53 +00:00
Merge pull request #2789 from ozra/devel
Change wording in some parts. Fix some typos.
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
About this document
|
||||
===================
|
||||
|
||||
**Note**: This document is a draft! Several of Nim's features need more
|
||||
precise wording. This manual will evolve into a proper specification some
|
||||
day.
|
||||
**Note**: This document is a draft! Several of Nim's features may need more
|
||||
precise wording. This manual is constantly evolving until the 1.0 release and is
|
||||
not to be considered as the final proper specification.
|
||||
|
||||
This document describes the lexis, the syntax, and the semantics of Nim.
|
||||
|
||||
The language constructs are explained using an extended BNF, in
|
||||
which ``(a)*`` means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and
|
||||
``(a)?`` means an optional *a*. Parentheses may be used to group elements.
|
||||
The language constructs are explained using an extended BNF, in which ``(a)*``
|
||||
means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and ``(a)?`` means an
|
||||
optional *a*. Parentheses may be used to group elements.
|
||||
|
||||
``&`` is the lookahead operator; ``&a`` means that an ``a`` is expected but
|
||||
not consumed. It will be consumed in the following rule.
|
||||
@@ -33,5 +33,5 @@ and ``a ^* b`` is short for ``(a (b a)*)?``. Example::
|
||||
arrayConstructor = '[' expr ^* ',' ']'
|
||||
|
||||
Other parts of Nim - like scoping rules or runtime semantics are only
|
||||
described in an informal manner for now.
|
||||
described in the, more easily comprehensible, informal manner for now.
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ exceptions* or *dying with a fatal error*. However, the implementation
|
||||
provides a means to disable these runtime checks. See the section pragmas_
|
||||
for details.
|
||||
|
||||
Wether a checked runtime error results in an exception or in a fatal error at
|
||||
Whether a checked runtime error results in an exception or in a fatal error at
|
||||
runtime is implementation specific. Thus the following program is always
|
||||
invalid:
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ possibly raised exceptions; the algorithm operates on ``p``'s call graph:
|
||||
However if the call is of the form ``f(...)`` where ``f`` is a parameter
|
||||
of the currently analysed routine it is ignored. The call is optimistically
|
||||
assumed to have no effect. Rule 2 compensates for this case.
|
||||
2. Every expression of some proc type wihtin a call that is not a call
|
||||
2. Every expression of some proc type within a call that is not a call
|
||||
itself (and not nil) is assumed to be called indirectly somehow and thus
|
||||
its raises list is added to ``p``'s raises list.
|
||||
3. Every call to a proc ``q`` which has an unknown body (due to a forward
|
||||
|
||||
@@ -25,7 +25,7 @@ a separate token. This trick allows parsing of Nim with only 1 token of
|
||||
lookahead.
|
||||
|
||||
The parser uses a stack of indentation levels: the stack consists of integers
|
||||
counting the spaces. The indentation information is queried at strategic
|
||||
counting the spaces. The indentation information is queried at strategic
|
||||
places in the parser but ignored otherwise: The pseudo terminal ``IND{>}``
|
||||
denotes an indentation that consists of more spaces than the entry at the top
|
||||
of the stack; IND{=} an indentation that has the same number of spaces. ``DED``
|
||||
@@ -80,7 +80,7 @@ underscores ``__`` are not allowed::
|
||||
digit ::= '0'..'9'
|
||||
IDENTIFIER ::= letter ( ['_'] (letter | digit) )*
|
||||
|
||||
Currently any unicode character with an ordinal value > 127 (non ASCII) is
|
||||
Currently any Unicode character with an ordinal value > 127 (non ASCII) is
|
||||
classified as a ``letter`` and may thus be part of an identifier but later
|
||||
versions of the language may assign some Unicode characters to belong to the
|
||||
operator characters instead.
|
||||
|
||||
@@ -178,8 +178,7 @@ Module scope
|
||||
~~~~~~~~~~~~
|
||||
All identifiers of a module are valid from the point of declaration until
|
||||
the end of the module. Identifiers from indirectly dependent modules are *not*
|
||||
available. The `system`:idx: module is automatically imported in every other
|
||||
module.
|
||||
available. The `system`:idx: module is automatically imported in every module.
|
||||
|
||||
If a module imports an identifier by two different modules, each occurrence of
|
||||
the identifier has to be qualified, unless it is an overloaded procedure or
|
||||
|
||||
@@ -18,9 +18,7 @@ The deprecated pragma is used to mark a symbol as deprecated:
|
||||
proc p() {.deprecated.}
|
||||
var x {.deprecated.}: char
|
||||
|
||||
It can also be used as a statement. Then it takes a list of *renamings*. The
|
||||
upcoming ``nimfix`` tool can automatically update the code and perform these
|
||||
renamings:
|
||||
It can also be used as a statement, in that case it takes a list of *renamings*.
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
@@ -28,6 +26,9 @@ renamings:
|
||||
Stream = ref object
|
||||
{.deprecated: [TFile: File, PStream: Stream].}
|
||||
|
||||
The ``nimfix`` tool can be used to, without effort, automatically update your
|
||||
code and refactor it by performing these renamings.
|
||||
|
||||
|
||||
noSideEffect pragma
|
||||
-------------------
|
||||
@@ -54,9 +55,7 @@ destructor pragma
|
||||
-----------------
|
||||
|
||||
The ``destructor`` pragma is used to mark a proc to act as a type destructor.
|
||||
Its usage is deprecated, use the ``override`` pragma instead.
|
||||
See `type bound operations`_.
|
||||
|
||||
Its usage is deprecated, See `type bound operations`_ instead.
|
||||
|
||||
override pragma
|
||||
---------------
|
||||
@@ -371,7 +370,7 @@ The ``register`` pragma is for variables only. It declares the variable as
|
||||
in a hardware register for faster access. C compilers usually ignore this
|
||||
though and for good reasons: Often they do a better job without it anyway.
|
||||
|
||||
In highly specific cases (a dispatch loop of an bytecode interpreter for
|
||||
In highly specific cases (a dispatch loop of a bytecode interpreter for
|
||||
example) it may provide benefits, though.
|
||||
|
||||
|
||||
@@ -429,13 +428,13 @@ Example:
|
||||
2. When a top level call is encountered (usually at the very end of the module),
|
||||
the compiler will try to determine the actual types of all of the symbols in the
|
||||
matching overload set. This is a potentially recursive process as the signatures
|
||||
of the symbols may include other call expressions, whoose types will be resolved
|
||||
of the symbols may include other call expressions, whose types will be resolved
|
||||
at this point too.
|
||||
|
||||
3. Finally, after the best overload is picked, the compiler will start compiling
|
||||
the body of the respective symbol. This in turn will lead the compiler to discover
|
||||
more call expresions that need to be resolved and steps 2 and 3 will be repeated
|
||||
as necessary.
|
||||
3. Finally, after the best overload is picked, the compiler will start
|
||||
compiling the body of the respective symbol. This in turn will lead the
|
||||
compiler to discover more call expressions that need to be resolved and steps
|
||||
2 and 3 will be repeated as necessary.
|
||||
|
||||
Please note that if a callable symbol is never used in this scenario, its body
|
||||
will never be compiled. This is the default behavior leading to best compilation
|
||||
|
||||
@@ -2,17 +2,46 @@ Procedures
|
||||
==========
|
||||
|
||||
What most programming languages call `methods`:idx: or `functions`:idx: are
|
||||
called `procedures`:idx: in Nim (which is the correct terminology). A
|
||||
procedure declaration defines an identifier and associates it with a block
|
||||
of code.
|
||||
A procedure may call itself recursively. A parameter may be given a default
|
||||
value that is used if the caller does not provide a value for this parameter.
|
||||
called `procedures`:idx: in Nim (which is the correct terminology). A procedure
|
||||
declaration consists of an identifier, zero or more formal parameters, a return
|
||||
value type and a block of code. Formal parameters are declared as a list of
|
||||
identifiers separated by either comma or semicolon. A parameter is given a type
|
||||
by ``: typename``. The type applies to all parameters immediately before it,
|
||||
until either the beginning of the parameter list, a semicolon separator or an
|
||||
already typed parameter, is reached. The semicolon can be used to make
|
||||
separation of types and subsequent identifiers more distinct.
|
||||
|
||||
If the proc declaration has no body, it is a `forward`:idx: declaration. If
|
||||
the proc returns a value, the procedure body can access an implicitly declared
|
||||
.. code-block:: nim
|
||||
# Using only commas
|
||||
proc foo(a, b: int, c, d: bool): int
|
||||
|
||||
# Using semicolon for visual distinction
|
||||
proc foo(a, b: int; c, d: bool): int
|
||||
|
||||
# Will fail: a is untyped since ';' stops type propagation.
|
||||
proc foo(a; b: int; c, d: bool): int
|
||||
|
||||
A parameter may be declared with a default value which is used if the caller
|
||||
does not provide a value for the argument.
|
||||
|
||||
.. code-block:: nim
|
||||
# b is optional with 47 as its default value
|
||||
proc foo(a: int, b: int = 47): int
|
||||
|
||||
Parameters can be declared mutable and so allow the proc to modify those
|
||||
arguments, by using the type modifier `var`.
|
||||
|
||||
.. code-block:: nim
|
||||
# "returning" a value to the caller through the 2nd argument
|
||||
# Notice that the function uses no actual return value at all (ie void)
|
||||
proc foo(inp: int, outp: var int) =
|
||||
outp = inp + 47
|
||||
|
||||
If the proc declaration has no body, it is a `forward`:idx: declaration. If the
|
||||
proc returns a value, the procedure body can access an implicitly declared
|
||||
variable named `result`:idx: that represents the return value. Procs can be
|
||||
overloaded. The overloading resolution algorithm tries to find the proc that is
|
||||
the best match for the arguments. Example:
|
||||
overloaded. The overloading resolution algorithm determines which proc is the
|
||||
best match for the arguments. Example:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
@@ -41,9 +70,8 @@ Calling a procedure can be done in many different ways:
|
||||
# call as a command statement: no () needed:
|
||||
callme 0, 1, "abc", '\t'
|
||||
|
||||
A procedure may call itself recursively.
|
||||
|
||||
A procedure cannot modify its parameters (unless the parameters have the type
|
||||
`var`).
|
||||
|
||||
`Operators`:idx: are procedures with a special operator symbol as identifier:
|
||||
|
||||
@@ -475,7 +503,7 @@ If the for loop has exactly 2 variables, a ``pairs`` iterator is implicitly
|
||||
invoked.
|
||||
|
||||
Symbol lookup of the identifiers ``items``/``pairs`` is performed after
|
||||
the rewriting step, so that all overloadings of ``items``/``pairs`` are taken
|
||||
the rewriting step, so that all overloads of ``items``/``pairs`` are taken
|
||||
into account.
|
||||
|
||||
|
||||
@@ -511,11 +539,12 @@ Closure iterators have other restrictions than inline iterators:
|
||||
|
||||
1. ``yield`` in a closure iterator can not occur in a ``try`` statement.
|
||||
2. For now, a closure iterator cannot be evaluated at compile time.
|
||||
3. ``return`` is allowed in a closure iterator (but rarely useful).
|
||||
4. Both inline and closure iterators cannot be recursive.
|
||||
3. ``return`` is allowed in a closure iterator (but rarely useful) and ends
|
||||
iteration.
|
||||
4. Neither inline nor closure iterators can be recursive.
|
||||
|
||||
Iterators that are neither marked ``{.closure.}`` nor ``{.inline.}`` explicitly
|
||||
default to being inline, but that this may change in future versions of the
|
||||
default to being inline, but this may change in future versions of the
|
||||
implementation.
|
||||
|
||||
The ``iterator`` type is always of the calling convention ``closure``
|
||||
@@ -612,8 +641,8 @@ parameters of an outer factory proc:
|
||||
Implicit return type
|
||||
--------------------
|
||||
|
||||
Since inline interators must always produce values that will be consumed in
|
||||
a for loop, the compiler will implicity use the ``auto`` return type if no
|
||||
Since inline iterators must always produce values that will be consumed in
|
||||
a for loop, the compiler will implicitly use the ``auto`` return type if no
|
||||
type is given by the user. In contrast, since closure iterators can be used
|
||||
as a collaborative tasking system, ``void`` is a valid return type for them.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Statements are separated into `simple statements`:idx: and
|
||||
Simple statements are statements that cannot contain other statements like
|
||||
assignments, calls or the ``return`` statement; complex statements can
|
||||
contain other statements. To avoid the `dangling else problem`:idx:, complex
|
||||
statements always have to be intended. The details can be found in the grammar.
|
||||
statements always have to be indented. The details can be found in the grammar.
|
||||
|
||||
|
||||
Statement list expression
|
||||
@@ -229,22 +229,18 @@ the expression after the ``elif`` is evaluated (if there is an
|
||||
``elif`` branch), if it is true the corresponding statements after
|
||||
the ``:`` are executed. This goes on until the last ``elif``. If all
|
||||
conditions fail, the ``else`` part is executed. If there is no ``else``
|
||||
part, execution continues with the statement after the ``if`` statement.
|
||||
part, execution continues with the next statement.
|
||||
|
||||
The scoping for an ``if`` statement is slightly subtle to support an important
|
||||
use case. A new scope starts for the ``if``/``elif`` condition and ends after
|
||||
the corresponding *then* block:
|
||||
In ``if`` statements new scopes begin immediately after the ``if``/``elif``/``else`` keywords and ends after the corresponding *then* block.
|
||||
For visualization purposes the scopes have been enclosed in ``{| |}`` in the following example:
|
||||
|
||||
.. code-block:: nim
|
||||
if {| (let m = input =~ re"(\w+)=\w+"; m.isMatch):
|
||||
echo "key ", m[0], " value ", m[1] |}
|
||||
elif {| (let m = input =~ re""; m.isMatch):
|
||||
echo "new m in this scope" |}
|
||||
else:
|
||||
# 'm' not declared here
|
||||
|
||||
In the example the scopes have been enclosed in ``{| |}``.
|
||||
|
||||
echo "new m in this scope" |}
|
||||
else: {|
|
||||
echo "m not declared here" |}
|
||||
|
||||
Case statement
|
||||
--------------
|
||||
@@ -601,7 +597,7 @@ A table constructor is syntactic sugar for an array constructor:
|
||||
|
||||
The empty table can be written ``{:}`` (in contrast to the empty set
|
||||
which is ``{}``) which is thus another way to write as the empty array
|
||||
constructor ``[]``. This slightly unusal way of supporting tables
|
||||
constructor ``[]``. This slightly unusual way of supporting tables
|
||||
has lots of advantages:
|
||||
|
||||
* The order of the (key,value)-pairs is preserved, thus it is easy to
|
||||
|
||||
@@ -43,6 +43,10 @@ Fortunately Nim supports side effect analysis:
|
||||
|
||||
echo f() * 2 # not optimized ;-)
|
||||
|
||||
You can make one overload matching with a constraint and one without, and the
|
||||
one with a constraint will have precedence, and so you can handle both cases
|
||||
differently.
|
||||
|
||||
So what about ``2 * a``? We should tell the compiler ``*`` is commutative. We
|
||||
cannot really do that however as the following code only swaps arguments
|
||||
blindly:
|
||||
@@ -105,8 +109,10 @@ Predicate Meaning
|
||||
with the marked parameter.
|
||||
=================== =====================================================
|
||||
|
||||
Predicates that share their name with a keyword have to be escaped with
|
||||
backticks: `` `const` ``.
|
||||
The ``alias`` and ``noalias`` predicates refer not only to the matching AST,
|
||||
but also to every other bound parameter; syntactially they need to occur after
|
||||
but also to every other bound parameter; syntactically they need to occur after
|
||||
the ordinary AST predicates:
|
||||
|
||||
.. code-block:: nim
|
||||
@@ -144,7 +150,7 @@ constant folding, so the following does not work:
|
||||
|
||||
The reason is that the compiler already transformed the 1 into "1" for
|
||||
the ``echo`` statement. However, a term rewriting macro should not change the
|
||||
semantics anyway. In fact they can be deactived with the ``--patterns:off``
|
||||
semantics anyway. In fact they can be deactivated with the ``--patterns:off``
|
||||
command line option or temporarily with the ``patterns`` pragma.
|
||||
|
||||
|
||||
@@ -345,15 +351,15 @@ optimization for types that have copying semantics:
|
||||
## puts a (key, value)-pair into `t`. The semantics of string require
|
||||
## a copy here:
|
||||
let idx = findInsertionPosition(key)
|
||||
t[idx] = key
|
||||
t[idx] = val
|
||||
t[idx].key = key
|
||||
t[idx].val = val
|
||||
|
||||
proc `[]=`*(t: var Table, key: string{call}, val: string{call}) =
|
||||
## puts a (key, value)-pair into `t`. Optimized version that knows that
|
||||
## the strings are unique and thus don't need to be copied:
|
||||
let idx = findInsertionPosition(key)
|
||||
shallowCopy t[idx], key
|
||||
shallowCopy t[idx], val
|
||||
shallowCopy t[idx].key, key
|
||||
shallowCopy t[idx].val, val
|
||||
|
||||
var t: Table
|
||||
# overloading resolution ensures that the optimized []= is called here:
|
||||
|
||||
@@ -9,11 +9,11 @@ Type equality
|
||||
-------------
|
||||
Nim uses structural type equivalence for most types. Only for objects,
|
||||
enumerations and distinct types name equivalence is used. The following
|
||||
algorithm (in pseudo-code) determines type equality:
|
||||
algorithm, *in pseudo-code*, determines type equality:
|
||||
|
||||
.. code-block:: nim
|
||||
proc typeEqualsAux(a, b: PType,
|
||||
s: var set[PType * PType]): bool =
|
||||
s: var HashSet[(PType, PType)]): bool =
|
||||
if (a,b) in s: return true
|
||||
incl(s, (a,b))
|
||||
if a.kind == b.kind:
|
||||
@@ -43,7 +43,7 @@ algorithm (in pseudo-code) determines type equality:
|
||||
a.callingConvention == b.callingConvention
|
||||
|
||||
proc typeEquals(a, b: PType): bool =
|
||||
var s: set[PType * PType] = {}
|
||||
var s: HashSet[(PType, PType)] = {}
|
||||
result = typeEqualsAux(a, b, s)
|
||||
|
||||
Since types are graphs which can have cycles, the above algorithm needs an
|
||||
|
||||
@@ -803,7 +803,7 @@ exclude ``nil`` as a valid value with the ``not nil`` annotation:
|
||||
p(x)
|
||||
|
||||
The compiler ensures that every code path initializes variables which contain
|
||||
not nilable pointers. The details of this analysis are still to be specified
|
||||
non nilable pointers. The details of this analysis are still to be specified
|
||||
here.
|
||||
|
||||
|
||||
@@ -1132,7 +1132,7 @@ that don't. Distinct types provide a means to introduce a new string type
|
||||
|
||||
|
||||
It is an essential property of abstract types that they **do not** imply a
|
||||
subtype relation between the abtract type and its base type. Explict type
|
||||
subtype relation between the abstract type and its base type. Explicit type
|
||||
conversions from ``string`` to ``SQL`` are allowed:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
Reference in New Issue
Block a user