123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515 |
- ================
- Not a Nim Manual
- ================
- :Authors: Andreas Rumpf, Zahary Karadjov
- :Version: |nimversion|
- .. role:: nim(code)
- :language: nim
- .. default-role:: nim
- .. contents::
- "Complexity" seems to be a lot like "energy": you can transfer it from the
- end-user to one/some of the other players, but the total amount seems to remain
- pretty much constant for a given task. -- Ran
- About this document
- ===================
- **Note**: This document is a draft! Several of Nim's features may need more
- precise wording. This manual is constantly evolving into a proper specification.
- **Note**: The experimental features of Nim are
- covered `here <manual_experimental.html>`_.
- **Note**: Assignments, moves, and destruction are specified in
- the `destructors <destructors.html>`_ document.
- 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.
- Non-terminals start with a lowercase letter, abstract terminal symbols are in
- UPPERCASE. Verbatim terminal symbols (including keywords) are quoted
- with ``'``. An example::
- ifStmt = 'if' expr ':' stmts ('elif' expr ':' stmts)* ('else' stmts)?
- 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. We use the term `runtime`:idx: to cover both compile-time execution
- and code execution in the executable.
- .. code-block:: nim
- var a: array[0..1, char]
- let i = 5
- try:
- a[i] = 'N'
- except IndexDefect:
- echo "invalid index"
- Encoding
- --------
- All Nim source files are in the UTF-8 encoding (or its ASCII subset). Other
- encodings are not supported. Any of the standard platform line termination
- sequences can be used - the Unix form using ASCII LF (linefeed), the Windows
- form using the ASCII sequence CR LF (return followed by linefeed), or the old
- Macintosh form using the ASCII CR (return) character. All of these forms can be
- used equally, regardless of the platform.
- Indentation
- -----------
- Nim's standard grammar describes an `indentation sensitive`:idx: language.
- This means that all the control structures are recognized by indentation.
- Indentation consists only of spaces; tabulators are not allowed.
- With this notation we can now easily define the core of the grammar: A block of
- statements (simplified example)::
- ifStmt = 'if' expr ':' stmt
- (IND{=} 'elif' expr ':' stmt)*
- (IND{=} 'else' ':' stmt)?
- simpleStmt = ifStmt / ...
- stmt = IND{>} stmt ^+ IND{=} DED # list of statements
- / simpleStmt # or a simple statement
- String literals can be delimited by matching double quotes, and can
- contain the following `escape sequences`:idx:\ :
- ================== ===================================================
- Escape sequence Meaning
- ================== ===================================================
- ``\p`` platform specific newline: CRLF on Windows,
- LF on Unix
- ``\r``, ``\c`` `carriage return`:idx:
- ``\n``, ``\l`` `line feed`:idx: (often called `newline`:idx:)
- ``\f`` `form feed`:idx:
- ``\t`` `tabulator`:idx:
- ``\v`` `vertical tabulator`:idx:
- ``\\`` `backslash`:idx:
- ``\"`` `quotation mark`:idx:
- ``\'`` `apostrophe`:idx:
- ``\`` '0'..'9'+ `character with decimal value d`:idx:;
- all decimal digits directly
- following are used for the character
- ``\a`` `alert`:idx:
- ``\b`` `backspace`:idx:
- ``\e`` `escape`:idx: `[ESC]`:idx:
- ``\x`` HH `character with hex value HH`:idx:;
- exactly two hex digits are allowed
- ``\u`` HHHH `unicode codepoint with hex value HHHH`:idx:;
- exactly four hex digits are allowed
- ``\u`` {H+} `unicode codepoint`:idx:;
- all hex digits enclosed in ``{}`` are used for
- the codepoint
- ================== ===================================================
- .. code-block:: nim
- """"long string within quotes""""
- Produces::
- "long string within quotes"
- Operators
- ---------
- Nim allows user defined operators. An operator is any combination of the
- following characters::
- = + - * / < >
- @ $ ~ & % |
- ! ? ^ . : \
- (The grammar uses the terminal OPR to refer to operator symbols as
- defined here.)
- The following strings denote other tokens::
- ` ( ) { } [ ] , ; [. .] {. .} (. .) [:
- Otherwise, precedence is determined by the first character.
- ================ ======================================================= ================== ===============
- Precedence level Operators First character Terminal symbol
- ================ ======================================================= ================== ===============
- 10 (highest) ``$ ^`` OP10
- 9 ``* / div mod shl shr %`` ``* % \ /`` OP9
- 8 ``+ -`` ``+ - ~ |`` OP8
- 7 ``&`` ``&`` OP7
- 6 ``..`` ``.`` OP6
- 5 ``== <= < >= > != in notin is isnot not of as from`` ``= < > !`` OP5
- 4 ``and`` OP4
- 3 ``or xor`` OP3
- 2 ``@ : ?`` OP2
- 1 *assignment operator* (like ``+=``, ``*=``) OP1
- 0 (lowest) *arrow like operator* (like ``->``, ``=>``) OP0
- ================ ======================================================= ================== ===============
- Constants and Constant Expressions
- ==================================
- A `constant`:idx: is a symbol that is bound to the value of a constant
- 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
- * previously declared constants and compile-time variables
- * previously declared macros and templates
- * previously declared procedures that have no side effects beyond
- possibly modifying compile-time variables
- These integer types are pre-defined:
- ``int``
- the generic signed integer type; its size is platform-dependent and has the
- same size as a pointer. This type should be used in general. An integer
- literal that has no type suffix is of this type if it is in the range
- ``low(int32)..high(int32)`` otherwise the literal's type is ``int64``.
- intXX
- additional signed integer types of XX bits use this naming scheme
- (example: int16 is a 16-bit wide integer).
- The current implementation supports ``int8``, ``int16``, ``int32``, ``int64``.
- Literals of these types have the suffix 'iXX.
- ``uint``
- the generic `unsigned integer`:idx: type; its size is platform-dependent and has the same size as a pointer. An integer literal with the type suffix ``'u`` is of this type.
- Let ``T``'s be ``p``'s return type. NRVO applies for ``T``
- if ``sizeof(T) >= N`` (where ``N`` is implementation dependent),
- in other words, it applies for "big" structures.
- Apart from built-in operations like array indexing, memory allocation, etc.
- the ``raise`` statement is the only way to raise an exception.
- .. XXX document this better!
- `typedesc` used as a parameter type also introduces an implicit
- generic. `typedesc` has its own set of rules:
- The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
- templates:
- | ``a > b`` is transformed into ``b < a``.
- | ``a in b`` is transformed into ``contains(b, a)``.
- | ``notin`` and ``isnot`` have the obvious meanings.
- A template where every parameter is ``untyped`` is called an `immediate`:idx:
- template. For historical reasons templates can be explicitly annotated with
- an ``immediate`` pragma and then these templates do not take part in
- overloading resolution and the parameters' types are *ignored* by the
- compiler. Explicit immediate templates are now deprecated.
- Symbol lookup in generics
- -------------------------
- Open and Closed symbols
- ~~~~~~~~~~~~~~~~~~~~~~~
- The symbol binding rules in generics are slightly subtle: There are "open" and
- "closed" symbols. A "closed" symbol cannot be re-bound in the instantiation
- context, an "open" symbol can. Per default overloaded symbols are open
- and every other symbol is closed.
- In templates identifiers can be constructed with the backticks notation:
- .. code-block:: nim
- :test: "nim c $1"
- template typedef(name: untyped, typ: typedesc) =
- type
- `T name`* {.inject.} = typ
- `P name`* {.inject.} = ref `T name`
- typedef(myint, int)
- var x: PMyInt
- In the example ``name`` is instantiated with ``myint``, so \`T name\` becomes
- ``Tmyint``.
- Only top-level symbols that are marked with an asterisk (``*``) are
- exported.
- The algorithm for compiling modules is:
- - compile the whole module as usual, following import statements recursively
- - if there is a cycle only import the already parsed symbols (that are
- exported); if an unknown identifier occurs then abort
- Collective imports from a directory
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The syntax ``import dir / [moduleA, moduleB]`` can be used to import multiple modules
- from the same directory.
- Pragmas
- =======
- Pragmas are Nim's method to give the compiler additional information /
- commands without introducing a massive number of new keywords. Pragmas are
- processed on the fly during semantic checking. Pragmas are enclosed in the
- special ``{.`` and ``.}`` curly brackets. Pragmas are also often used as a
- first implementation to play with a language feature before a nicer syntax
- to access the feature becomes available.
- deprecated pragma
- -----------------
- The deprecated pragma is used to mark a symbol as deprecated:
- **Note**: `c2nim <https://github.com/nim-lang/c2nim/blob/master/doc/c2nim.rst>`_ can parse a large subset of C++ and knows
- about the ``importcpp`` pragma pattern language. It is not necessary
- to know all the details described here.
- Pure libraries do not depend on any external ``*.dll`` or ``lib*.so`` binary
- while impure libraries do. A wrapper is an impure library that is a very
- low-level interface to a C library.
- Pure libraries
- ==============
- Automatic imports
- -----------------
- * `system <system.html>`_
- Basic procs and operators that every program needs. It also provides IO
- facilities for reading and writing text and binary files. It is imported
- implicitly by the compiler. Do not import it directly. It relies on compiler
- magic to work.
- * `threads <threads.html>`_
- Basic Nim thread support. **Note**: This is part of the system module. Do not
- import it explicitly. Enabled with ``--threads:on``.
- Code reordering
- ===============
- The code reordering feature can implicitly rearrange procedure, template, and
- macro definitions along with variable declarations and initializations at the top
- level scope so that, to a large extent, a programmer should not have to worry
- about ordering definitions correctly or be forced to use forward declarations to
- preface definitions inside a module.
- ..
- NOTE: The following was documentation for the code reordering precursor,
- which was {.noForward.}.
- In this mode, procedure definitions may appear out of order and the compiler
- will postpone their semantic analysis and compilation until it actually needs
- to generate code using the definitions. In this regard, this mode is similar
- to the modus operandi of dynamic scripting languages, where the function
- calls are not resolved until the code is executed. Here is the detailed
- algorithm taken by the compiler:
- 1. When a callable symbol is first encountered, the compiler will only note
- the symbol callable name and it will add it to the appropriate overload set
- in the current scope. At this step, it won't try to resolve any of the type
- expressions used in the signature of the symbol (so they can refer to other
- not yet defined symbols).
- 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, 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 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 times, but if exhaustive compilation of all definitions is
- required, using ``nim check`` provides this option as well.
- Example:
- .. code-block:: nim
- {.experimental: "codeReordering".}
- proc foo(x: int) =
- bar(x)
- proc bar(x: int) =
- echo(x)
- foo(10)
- ..
- TODO: Let's table this for now. This is an *experimental feature* and so the
- specific manner in which ``declared`` operates with it can be decided in
- eventuality, because right now it works a bit weirdly.
- The values of expressions involving ``declared`` are decided *before* the
- code reordering process, and not after. As an example, the output of this
- code is the same as it would be with code reordering disabled.
- .. code-block:: nim
- {.experimental: "codeReordering".}
- proc x() =
- echo(declared(foo))
- var foo = 4
- x() # "false"
- It is important to note that reordering *only* works for symbols at top level
- scope. Therefore, the following will *fail to compile:*
- Parameter constraints
- ---------------------
- The `parameter constraint`:idx: expression can use the operators ``|`` (or),
- ``&`` (and) and ``~`` (not) and the following predicates:
- The ``~`` operator
- ~~~~~~~~~~~~~~~~~~
- The ``~`` operator is the **not** operator in patterns:
- The ``**`` operator
- ~~~~~~~~~~~~~~~~~~~
- The ``**`` is much like the ``*`` operator, except that it gathers not only
- all the arguments, but also the matched operators in reverse polish notation:
- Nim significantly improves on the safety of these features via additional
- pragmas:
- 1) A `guard`:idx: annotation is introduced to prevent data races.
- 2) Every access of a guarded memory location needs to happen in an
- appropriate `locks`:idx: statement.
- 3) Locks and routines can be annotated with `lock levels`:idx: to allow
- potential deadlocks to be detected during semantic analysis.
- 1. Two output parameters should never be aliased.
- 2. An input and an output parameter should not be aliased.
- 3. An output parameter should never be aliased with a global or thread local
- variable referenced by the called proc.
- 4. An input parameter should not be aliased with a global or thread local
- variable updated by the called proc.
- One problem with rules 3 and 4 is that they affect specific global or thread
- local variables, but Nim's effect tracking only tracks "uses no global variable"
- via ``.noSideEffect``. The rules 3 and 4 can also be approximated by a different rule:
- 5. A global or thread local variable (or a location derived from such a location)
- can only passed to a parameter of a ``.noSideEffect`` proc.
- These two procs are the two modus operandi of the real-time garbage collector:
- (1) GC_SetMaxPause Mode
- You can call ``GC_SetMaxPause`` at program startup and then each triggered
- garbage collector run tries to not take longer than ``maxPause`` time. However, it is
- possible (and common) that the work is nevertheless not evenly distributed
- as each call to ``new`` can trigger the garbage collector and thus take ``maxPause``
- time.
- (2) GC_step Mode
- This allows the garbage collector to perform some work for up to ``us`` time.
- This is useful to call in the main loop to ensure the garbage collector can do its work.
- To bind all garbage collector activity to a ``GC_step`` call,
- deactivate the garbage collector with ``GC_disable`` at program startup.
- If ``strongAdvice`` is set to ``true``,
- then the garbage collector will be forced to perform the collection cycle.
- Otherwise, the garbage collector may decide not to do anything,
- if there is not much garbage to collect.
- You may also specify the current stack size via ``stackSize`` parameter.
- It can improve performance when you know that there are no unique Nim references
- below a certain point on the stack. Make sure the size you specify is greater
- than the potential worst-case size.
- It can improve performance when you know that there are no unique Nim
- references below a certain point on the stack. Make sure the size you specify
- is greater than the potential worst-case size.
- These procs provide a "best effort" real-time guarantee; in particular the
- cycle collector is not aware of deadlines. Deactivate it to get more
- predictable real-time behaviour. Tests show that a 1ms max pause
- time will be met in almost all cases on modern CPUs (with the cycle collector
- disabled).
- Time measurement with garbage collectors
- ----------------------------------------
- The garbage collectors' way of measuring time uses
- (see ``lib/system/timers.nim`` for the implementation):
- 1) ``QueryPerformanceCounter`` and ``QueryPerformanceFrequency`` on Windows.
- 2) ``mach_absolute_time`` on Mac OS X.
- 3) ``gettimeofday`` on Posix systems.
- As such it supports a resolution of nanoseconds internally; however, the API
- uses microseconds for convenience.
- Introduction
- ============
- .. raw:: html
- <blockquote><p>
- "Der Mensch ist doch ein Augentier -- schöne Dinge wünsch ich mir."
- </p></blockquote>
- This document is a tutorial for the programming language *Nim*.
- This tutorial assumes that you are familiar with basic programming concepts
- like variables, types, or statements but is kept very basic. The `manual
- <manual.html>`_ contains many more examples of the advanced language features.
- All code examples in this tutorial, as well as the ones found in the rest of
- Nim's documentation, follow the `Nim style guide <nep1.html>`_.
- However, this does not work. The problem is that the procedure should not
- only ``return``, but return and **continue** after an iteration has
- finished. This *return and continue* is called a `yield` statement. Now
- the only thing left to do is to replace the ``proc`` keyword by ``iterator``
- and here it is - our first iterator:
- | A1 header | A2 \| not fooled
- | :--- | ----: |
- | C1 | C2 **bold** | ignored |
- | D1 `code \|` | D2 | also ignored
- | E1 \| text |
- | | F2 without pipe
- not in table
|