Incorporated Araq's initial feedback.

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

View file

@ -46,7 +46,7 @@ and ``a ^* b`` is short for ``(a (b a)*)?``. Example::
arrayConstructor = '[' expr ^* ',' ']' 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. 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, The nature of this executable depends on the compiler implementation; it may,
for example, be a native binary or JavaScript source code. 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 In a typical Nim program, most of the code is compiled into the executable.
execution at `runtime`:idx:. However, some of the code may be executed at However, some of the code may be executed at
`compile time`:idx:. This can include constant expressions, macro definitions, `compile time`:idx:. This can include constant expressions, macro definitions,
and Nim procedures used by macro definitions. Most of the Nim language is and Nim procedures used by macro definitions. Most of the Nim language is
supported at compile time, but there are some restrictions -- see `Restrictions supported at compile time, but there are some restrictions -- see `Restrictions
on Compile-Time Execution <#restrictions-on-compileminustime-execution>`_ for 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 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 `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 during semantic analysis is called a `static error`:idx:. Errors described in
this manual are static errors when not otherwise specified. this manual are static errors when not otherwise specified.
An error detected during code execution (whether at compile time or at runtime) A `checked runtime error`:idx: is an error that the implementation detects
is a `checked execution error`:idx:. The method for reporting such errors is via and reports at runtime. The method for reporting such errors is via
*raising exceptions* or *dying with a fatal error*. However, the implementation *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. 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 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 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 .. code-block:: nim
var a: array[0..1, char] 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: except IndexError:
echo "invalid index" 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 detected, and can cause the subsequent behavior of the computation to
be arbitrary. Unchecked execution errors cannot occur if only `safe`:idx: be arbitrary. Unchecked runtime errors cannot occur if only `safe`:idx:
language features are used and if no execution-time checks are disabled. language features are used and if no runtime checks are disabled.
A `constant expression`:idx: is an expression whose value can be computed during 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 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 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 expression. Constant expressions are restricted to depend only on the following
semantic analysis of the code in which it appears. However, constant categories of values and operations, because these are either built into the
expressions are not limited to the capabilities of semantic analysis; they language or declared and evaluated before semantic analysis of the constant
can use all Nim language features that are supported for expression:
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:
* literals * literals
* built-in operators * 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 the operation of functions as ``inc``, ``ord``, ``dec`` on ordinal types to
be defined. be defined.
- Ordinal values have a smallest possible value. Trying to count further - 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 - 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 Integers, bool, characters and enumeration types (and subranges of these
types) belong to ordinal types. For reasons of simplicity of implementation 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. to 5. ``PositiveFloat`` defines a subrange of all positive floating point values.
NaN does not belong to any subrange of floating point types. NaN does not belong to any subrange of floating point types.
Assigning any other value to a variable of type ``Subrange`` is a 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 semantic analysis). Assignments from the base type to one of its subrange types
(and vice versa) are allowed. (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. implicitly convertable to this type.
Sequences are similar to arrays but of dynamic length which may change 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 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. indexed by integers from 0 to ``len(S)-1`` and its bounds are checked.
Sequences can be constructed by the array constructor ``[]`` in conjunction 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``. 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 checks can be disabled via pragmas or invoking the compiler with the
``--boundChecks:off`` command line switch. ``--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 **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 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 age: natural # and an age
Objects provide many features that tuples do not. Object provide inheritance and 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`` the ``of`` operator can be used to determine the object's type. The ``of``
operator is similar to the ``instanceof`` operator in Java. 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 not yet know the size of the object. To complete an incomplete object
the ``package`` pragma has to be used. ``package`` implies ``byref``. 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. 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`` ``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: Example:
.. code-block:: nim .. code-block:: nim
proc someProcThatMayRunInCompileTime(): bool = proc someProcThatMayRunInCompileTime(): bool =
when nimvm: when nimvm:
# This code executes at compile time # This branch is taken at compile time.
result = true result = true
else: else:
# This code executes at runtime # This branch is taken in the executable.
result = false result = false
const ctValue = someProcThatMayRunInCompileTime() const ctValue = someProcThatMayRunInCompileTime()
let rtValue = 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 Every exception inherits from ``system.Exception``. Exceptions that indicate
programming bugs inherit from ``system.Defect`` (which is a subtype of ``Exception``) 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 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`` error that can be caught inherit from ``system.CatchableError``
(which is a subtype of ``Exception``). (which is a subtype of ``Exception``).
@ -5454,19 +5449,19 @@ Macros
A macro is a special function that is executed at compile time. A macro is a special function that is executed at compile time.
Normally the input for a macro is an abstract syntax 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 tree (AST) of the code that is passed to it. The macro can then do
transformations on it and return the transformed AST. The transformations on it and return the transformed AST. This can be used to
transformed AST is then passed to the compiler as if the macro add custom language features and implement `domain specific languages`:idx:.
invocation would have been replaced by its result in the source
code. This can be used to implement `domain specific
languages`:idx:.
Macro invocation is a case where semantic analyis does **not** entirely proceed 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, * Semantic analysis recognizes and resolves the macro invocation.
* execute the macro body, * The compiler executes the macro body (which may invoke other procs).
* replace the AST of the macro invocation with the AST returned by the macro, * It replaces the AST of the macro invocation with the AST returned by the macro.
* and finally repeat semantic analysis of that region of the code. * 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 While macros enable advanced compile-time code transformations, they
cannot change Nim's syntax. However, this is no real restriction because cannot change Nim's syntax. However, this is no real restriction because
@ -6968,7 +6963,7 @@ structure:
pure pragma pure pragma
----------- -----------
An object type can be marked with the ``pure`` pragma so that its type field 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. necessary for binary compatibility with other compiled languages.
An enum type can be marked as ``pure``. Then access of its fields always 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 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. checks on or off.
boundChecks on|off Turns the code generation for array bound boundChecks on|off Turns the code generation for array bound
checks on or off. checks on or off.
@ -7176,7 +7171,7 @@ Example:
.. code-block:: nim .. code-block:: nim
{.checks: off, optimization: speed.} {.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 push and pop pragmas
@ -7186,7 +7181,7 @@ but are used to override the settings temporarily. Example:
.. code-block:: nim .. code-block:: nim
{.push checks: off.} {.push checks: off.}
# compile this section without execution-time checks as it is # compile this section without runtime checks as it is
# speed critical # speed critical
# ... some code ... # ... some code ...
{.pop.} # restore old settings {.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 conveniently. It is *assumed* (but not enforced) that every top level statement
is executed before any concurrent action happens. 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 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 .. code-block:: nim
template lock(a: TLock; body: untyped) = 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 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: and ``b`` of the same lock level:
.. code-block:: nim .. code-block:: nim