Incorporated Araq's initial feedback.

This commit is contained in:
deansher
2019-01-30 16:22:08 -05:00
parent 7295468516
commit e16310525c

View File

@@ -46,7 +46,7 @@ and ``a ^* b`` is short for ``(a (b a)*)?``. Example::
arrayConstructor = '[' expr ^* ',' ']'
Other parts of Nim, like scoping rules or execution semantics, are
Other parts of Nim, like scoping rules or runtime semantics, are
described informally.
@@ -78,13 +78,14 @@ Nim code. It is processed by a Nim `compiler`:idx: into an `executable`:idx:.
The nature of this executable depends on the compiler implementation; it may,
for example, be a native binary or JavaScript source code.
In a typical Nim program, most of the code is compiled into the executable for
execution at `runtime`:idx:. However, some of the code may be executed at
In a typical Nim program, most of the code is compiled into the executable.
However, some of the code may be executed at
`compile time`:idx:. This can include constant expressions, macro definitions,
and Nim procedures used by macro definitions. Most of the Nim language is
supported at compile time, but there are some restrictions -- see `Restrictions
on Compile-Time Execution <#restrictions-on-compileminustime-execution>`_ for
details.
details. We use the term `runtime`:idx: to cover both compile-time execution
and code execution in the executable.
The compiler parses Nim source code into an internal data structure called the
`abstract syntax tree`:idx: (`AST`:idx:). Then, before executing the code or
@@ -94,16 +95,16 @@ identifier meanings, and in some cases expression values. An error detected
during semantic analysis is called a `static error`:idx:. Errors described in
this manual are static errors when not otherwise specified.
An error detected during code execution (whether at compile time or at runtime)
is a `checked execution error`:idx:. The method for reporting such errors is via
A `checked runtime error`:idx: is an error that the implementation detects
and reports at runtime. The method for reporting such errors is via
*raising exceptions* or *dying with a fatal error*. However, the implementation
provides a means to disable these `execution-time checks`:idx:. See the section
provides a means to disable these `runtime checks`:idx:. See the section
pragmas_ for details.
Whether a checked execution error results in an exception or in a fatal error is
Whether a checked runtime error results in an exception or in a fatal error is
implementation specific. Thus the following program is invalid; even though the
code purports to catch the `IndexError` from an out-of-bounds array access, the
compiler may instead choose to allow execution to die with a fatal error.
compiler may instead choose to allow the program to die with a fatal error.
.. code-block:: nim
var a: array[0..1, char]
@@ -113,10 +114,10 @@ compiler may instead choose to allow execution to die with a fatal error.
except IndexError:
echo "invalid index"
An `unchecked execution error`:idx: is an error that is not guaranteed to be
An `unchecked runtime error`:idx: is an error that is not guaranteed to be
detected, and can cause the subsequent behavior of the computation to
be arbitrary. Unchecked execution errors cannot occur if only `safe`:idx:
language features are used and if no execution-time checks are disabled.
be arbitrary. Unchecked runtime errors cannot occur if only `safe`:idx:
language features are used and if no runtime checks are disabled.
A `constant expression`:idx: is an expression whose value can be computed during
semantic analysis of the code in which it appears. It is never an l-value and
@@ -710,17 +711,10 @@ Constants and Constant Expressions
==================================
A `constant`:idx: is a symbol that is bound to the value of a constant
expression. This is an expression whose value can be computed during
semantic analysis of the code in which it appears. However, constant
expressions are not limited to the capabilities of semantic analysis; they
can use all Nim language features that are supported for
compile-time execution. Compile-time execution is interleaved with semantic
analysis as necessary. A constant's value cannot change after it is first
computed.
Constant expressions are restricted to depend only on the following categories
of values and operations, because these are either built into the language or
declared and evaluated before semantic analysis of the constant expression:
expression. Constant expressions are restricted to depend only on the following
categories of values and operations, because these are either built into the
language or declared and evaluated before semantic analysis of the constant
expression:
* literals
* built-in operators
@@ -817,9 +811,9 @@ Ordinal types have the following characteristics:
the operation of functions as ``inc``, ``ord``, ``dec`` on ordinal types to
be defined.
- Ordinal values have a smallest possible value. Trying to count further
down than the smallest value gives a checked execution or static error.
down than the smallest value gives a checked runtime or static error.
- Ordinal values have a largest possible value. Trying to count further
than the largest value gives a checked execution or static error.
than the largest value gives a checked runtime or static error.
Integers, bool, characters and enumeration types (and subranges of these
types) belong to ordinal types. For reasons of simplicity of implementation
@@ -927,7 +921,7 @@ lowest and highest value of the type. For example:
to 5. ``PositiveFloat`` defines a subrange of all positive floating point values.
NaN does not belong to any subrange of floating point types.
Assigning any other value to a variable of type ``Subrange`` is a
checked execution error (or static error if it can be determined during
checked runtime error (or static error if it can be determined during
semantic analysis). Assignments from the base type to one of its subrange types
(and vice versa) are allowed.
@@ -1237,7 +1231,7 @@ inferred from the type of the first element. All other elements need to be
implicitly convertable to this type.
Sequences are similar to arrays but of dynamic length which may change
during execution (like strings). Sequences are implemented as growable arrays,
during runtime (like strings). Sequences are implemented as growable arrays,
allocating pieces of memory as items are added. A sequence ``S`` is always
indexed by integers from 0 to ``len(S)-1`` and its bounds are checked.
Sequences can be constructed by the array constructor ``[]`` in conjunction
@@ -1271,7 +1265,7 @@ operator, and remove (and get) the last element of a sequence with the
The notation ``x[i]`` can be used to access the i-th element of ``x``.
Arrays are always bounds checked (statically or during execution). These
Arrays are always bounds checked (statically or at runtime). These
checks can be disabled via pragmas or invoking the compiler with the
``--boundChecks:off`` command line switch.
@@ -1378,7 +1372,7 @@ is currently not checked.
**Future directions**: GC'ed memory should be allowed in unchecked arrays and
there should be an explicit annotation of how the GC is to determine the
execution-time size of the array.
runtime size of the array.
@@ -1435,7 +1429,7 @@ can also be defined with indentation instead of ``[]``:
age: natural # and an age
Objects provide many features that tuples do not. Object provide inheritance and
information hiding. Objects have access to their type during execution, so that
information hiding. Objects have access to their type during at runtime, so that
the ``of`` operator can be used to determine the object's type. The ``of``
operator is similar to the ``instanceof`` operator in Java.
@@ -1547,7 +1541,7 @@ contexts (``var/ref/ptr IncompleteObject``) in general since the compiler does
not yet know the size of the object. To complete an incomplete object
the ``package`` pragma has to be used. ``package`` implies ``byref``.
As long as a type ``T`` is incomplete, neither ``sizeof(T)`` nor execution-time
As long as a type ``T`` is incomplete, neither ``sizeof(T)`` nor runtime
type information for ``T`` is available.
@@ -2909,17 +2903,18 @@ When nimvm statement
--------------------
``nimvm`` is a special symbol, that may be used as expression of ``when nimvm``
statement to differentiate execution path between runtime and compile time.
statement to differentiate execution path between compile time and the
executable.
Example:
.. code-block:: nim
proc someProcThatMayRunInCompileTime(): bool =
when nimvm:
# This code executes at compile time
# This branch is taken at compile time.
result = true
else:
# This code executes at runtime
# This branch is taken in the executable.
result = false
const ctValue = someProcThatMayRunInCompileTime()
let rtValue = someProcThatMayRunInCompileTime()
@@ -4215,7 +4210,7 @@ The exception tree is defined in the `system <system.html>`_ module.
Every exception inherits from ``system.Exception``. Exceptions that indicate
programming bugs inherit from ``system.Defect`` (which is a subtype of ``Exception``)
and are stricly speaking not catchable as they can also be mapped to an operation
that terminates the whole process. Exceptions that indicate any other execution
that terminates the whole process. Exceptions that indicate any other runtime
error that can be caught inherit from ``system.CatchableError``
(which is a subtype of ``Exception``).
@@ -5454,19 +5449,19 @@ Macros
A macro is a special function that is executed at compile time.
Normally the input for a macro is an abstract syntax
tree (AST) of the code that is passed to it. The macro can then do
transformations on it and return the transformed AST. The
transformed AST is then passed to the compiler as if the macro
invocation would have been replaced by its result in the source
code. This can be used to implement `domain specific
languages`:idx:.
transformations on it and return the transformed AST. This can be used to
add custom language features and implement `domain specific languages`:idx:.
Macro invocation is a case where semantic analyis does **not** entirely proceed
top to bottom and left to right. The compiler must
top to bottom and left to right. Instead, semantic analysis happens at least
twice:
* perform semantic analysis through the end of the macro invocation,
* execute the macro body,
* replace the AST of the macro invocation with the AST returned by the macro,
* and finally repeat semantic analysis of that region of the code.
* Semantic analysis recognizes and resolves the macro invocation.
* The compiler executes the macro body (which may invoke other procs).
* It replaces the AST of the macro invocation with the AST returned by the macro.
* It repeats semantic analysis of that region of the code.
* If the AST returned by the macro contains other macro invocations,
this process iterates.
While macros enable advanced compile-time code transformations, they
cannot change Nim's syntax. However, this is no real restriction because
@@ -6968,7 +6963,7 @@ structure:
pure pragma
-----------
An object type can be marked with the ``pure`` pragma so that its type field
which is used for execution-time type identification is omitted. This used to be
which is used for runtime type identification is omitted. This used to be
necessary for binary compatibility with other compiled languages.
An enum type can be marked as ``pure``. Then access of its fields always
@@ -7149,7 +7144,7 @@ others may be added later).
=============== =============== ============================================
pragma allowed values description
=============== =============== ============================================
checks on|off Turns the code generation for all execution
checks on|off Turns the code generation for all runtime
checks on or off.
boundChecks on|off Turns the code generation for array bound
checks on or off.
@@ -7176,7 +7171,7 @@ Example:
.. code-block:: nim
{.checks: off, optimization: speed.}
# compile without execution-time checks and optimize for speed
# compile without runtime checks and optimize for speed
push and pop pragmas
@@ -7186,7 +7181,7 @@ but are used to override the settings temporarily. Example:
.. code-block:: nim
{.push checks: off.}
# compile this section without execution-time checks as it is
# compile this section without runtime checks as it is
# speed critical
# ... some code ...
{.pop.} # restore old settings
@@ -8408,9 +8403,9 @@ Top level accesses to ``gdata`` are always allowed so that it can be initialized
conveniently. It is *assumed* (but not enforced) that every top level statement
is executed before any concurrent action happens.
The ``locks`` section deliberately looks ugly because it has no execution-time
The ``locks`` section deliberately looks ugly because it has no runtime
semantics and should not be used directly! It should only be used in templates
that also implement some form of locking during execution:
that also implement some form of locking at runtime:
.. code-block:: nim
template lock(a: TLock; body: untyped) =
@@ -8529,7 +8524,7 @@ single ``locks`` section:
Here is how a typical multilock statement can be implemented in Nim. Note how
the execution check is required to ensure a global ordering for two locks ``a``
the runtime check is required to ensure a global ordering for two locks ``a``
and ``b`` of the same lock level:
.. code-block:: nim