Change wording in some parts. Fix some typos.

This commit is contained in:
Oscar Campbell
2015-05-25 05:24:47 +02:00
parent 6c8f7cc481
commit feff2bae68
11 changed files with 71 additions and 60 deletions

View File

@@ -1,9 +1,8 @@
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.
@@ -33,5 +32,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.

View File

@@ -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:

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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,8 @@ 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 +54,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 +369,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 +427,10 @@ 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

View File

@@ -3,16 +3,36 @@ 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.
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.
.. 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, 47 is its default value
proc foo(a, 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
proc foo(inp: int, outp: var int): void =
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 +61,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 +494,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 +530,11 @@ 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 +631,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.

View File

@@ -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

View File

@@ -43,6 +43,8 @@ Fortunately Nim supports side effect analysis:
echo f() * 2 # not optimized ;-)
You can make one overload for constrained match and without, and the constrained will be prioritized, 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:
@@ -50,7 +52,7 @@ blindly:
.. code-block:: nim
template mulIsCommutative{`*`(a, b)}(a, b: int): int = b*a
What optimizers really need to do is a *canonicalization*:
What optimizers really need to do is a *canonization*:
.. code-block:: nim
template canonMul{`*`(a, b)}(a: int{lit}, b: int): int = b*a
@@ -106,8 +108,9 @@ Predicate Meaning
=================== =====================================================
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:
Predicates that share their name with a keyword have to be escaped with backticks: `` `const` ``.
.. code-block:: nim
template ex{a = b + c}(a: int{noalias}, b, c: int) =
@@ -144,7 +147,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 +348,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:

View File

@@ -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

View File

@@ -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