diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/advopt.txt | 5 | ||||
-rw-r--r-- | doc/backends.txt | 17 | ||||
-rw-r--r-- | doc/basicopt.txt | 1 | ||||
-rw-r--r-- | doc/grammar.txt | 4 | ||||
-rw-r--r-- | doc/keywords.txt | 3 | ||||
-rw-r--r-- | doc/lib.rst | 27 | ||||
-rw-r--r-- | doc/manual/ffi.txt | 2 | ||||
-rw-r--r-- | doc/manual/generics.txt | 54 | ||||
-rw-r--r-- | doc/manual/locking.txt | 4 | ||||
-rw-r--r-- | doc/manual/modules.txt | 4 | ||||
-rw-r--r-- | doc/manual/pragmas.txt | 24 | ||||
-rw-r--r-- | doc/manual/procs.txt | 7 | ||||
-rw-r--r-- | doc/manual/special_ops.txt | 6 | ||||
-rw-r--r-- | doc/manual/stmts.txt | 6 | ||||
-rw-r--r-- | doc/manual/templates.txt | 2 | ||||
-rw-r--r-- | doc/manual/threads.txt | 2 | ||||
-rw-r--r-- | doc/manual/type_bound_ops.txt | 6 | ||||
-rw-r--r-- | doc/manual/type_rel.txt | 2 | ||||
-rw-r--r-- | doc/manual/type_sections.txt | 3 | ||||
-rw-r--r-- | doc/manual/types.txt | 70 | ||||
-rw-r--r-- | doc/tut1.rst | 123 | ||||
-rw-r--r-- | doc/tut2.rst | 69 |
22 files changed, 277 insertions, 164 deletions
diff --git a/doc/advopt.txt b/doc/advopt.txt index fb6fd719b..a1210118e 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -7,7 +7,8 @@ Advanced commands: //rst2html convert a reStructuredText file to HTML //rst2tex convert a reStructuredText file to TeX //jsondoc extract the documentation to a json file - //jsondoc2 extract documentation to a json file (uses doc2) + //jsondoc2 extract the documentation to a json file (uses doc2) + //ctags create a tags file //buildIndex build an index for the whole documentation //run run the project (with Tiny C backend; buggy!) //genDepend generate a DOT file containing the @@ -36,6 +37,7 @@ Advanced options: --noMain do not generate a main procedure --genScript generate a compile script (in the 'nimcache' subdirectory named 'compile_$project$scriptext') + --genDeps generate a '.deps' file containing the dependencies --os:SYMBOL set the target operating system (cross-compilation) --cpu:SYMBOL set the target processor (cross-compilation) --debuginfo enables debug information @@ -78,6 +80,7 @@ Advanced options: symbol matching is fuzzy so that --dynlibOverride:lua matches dynlib: "liblua.so.3" + --dynlibOverrideAll makes the dynlib pragma have no effect --listCmd list the commands used to execute external programs --parallelBuild:0|1|... perform a parallel build value = number of processors (0 for auto-detect) diff --git a/doc/backends.txt b/doc/backends.txt index 6446103ed..b7f5308ab 100644 --- a/doc/backends.txt +++ b/doc/backends.txt @@ -20,10 +20,12 @@ to compile to C++, Objective-C or JavaScript. This document tries to concentrate in a single place all the backend and interfacing options. The Nim compiler supports mainly two backend families: the C, C++ and -Objective-C targets and the JavaScript target. `The C like targets`_ creates -source files which can be compiled into a library or a final executable. `The -JavaScript target`_ can generate a ``.js`` file which you reference from an -HTML file or create a `standalone nodejs program <http://nodejs.org>`_. +Objective-C targets and the JavaScript target. `The C like targets +<#backends-the-c-like-targets>`_ creates source files which can be compiled +into a library or a final executable. `The JavaScript target +<#backends-the-javascript-target>`_ can generate a ``.js`` file which you +reference from an HTML file or create a `standalone nodejs program +<http://nodejs.org>`_. On top of generating libraries or standalone applications, Nim offers bidirectional interfacing with the backend targets through generic and @@ -205,9 +207,10 @@ from the previous section): Compile the Nim code to JavaScript with ``nim js -o:calculator.js calculator.nim`` and open ``host.html`` in a browser. If the browser supports -javascript, you should see the value ``10``. In JavaScript the `echo proc -<system.html#echo>`_ will modify the HTML DOM and append the string. Use the -`dom module <dom.html>`_ for specific DOM querying and modification procs. +javascript, you should see the value ``10`` in the browser's console. Use the +`dom module <dom.html>`_ for specific DOM querying and modification procs +or take a look at `karax <https://github.com/pragmagic/karax>`_ for how to +develop browser based applications. Backend code calling Nim diff --git a/doc/basicopt.txt b/doc/basicopt.txt index 3b0271077..4db2d5af7 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -5,7 +5,6 @@ Command: //compile, c compile project with default code generator (C) //doc generate the documentation for inputfile - //doc2 generate the documentation for inputfile Arguments: arguments are passed to the program being run (if --run option is selected) diff --git a/doc/grammar.txt b/doc/grammar.txt index 58b119331..eae3694a0 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -83,7 +83,8 @@ paramListColon = paramList? (':' optInd typeDesc)? doBlock = 'do' paramListArrow pragmas? colcom stmt procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)? distinct = 'distinct' optInd typeDesc -expr = (ifExpr +expr = (blockExpr + | ifExpr | whenExpr | caseExpr | tryExpr) @@ -141,6 +142,7 @@ tryExpr = 'try' colcom stmt &(optInd 'except'|'finally') exceptBlock = 'except' colcom stmt forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt blockStmt = 'block' symbol? colcom stmt +blockExpr = 'block' symbol? colcom stmt staticStmt = 'static' colcom stmt deferStmt = 'defer' colcom stmt asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLE_STR_LIT) diff --git a/doc/keywords.txt b/doc/keywords.txt index f8b444924..4eea3403a 100644 --- a/doc/keywords.txt +++ b/doc/keywords.txt @@ -1,10 +1,9 @@ -addr and as asm atomic +addr and as asm bind block break case cast concept const continue converter defer discard distinct div do elif else end enum except export finally for from func -generic if import in include interface is isnot iterator let macro method mixin mod diff --git a/doc/lib.rst b/doc/lib.rst index 64c3c11eb..755c11899 100644 --- a/doc/lib.rst +++ b/doc/lib.rst @@ -64,6 +64,10 @@ Core * `cpuinfo <cpuinfo.html>`_ This module implements procs to determine the number of CPUs / cores. +* `lenientops <lenientops.html>`_ + Provides binary operators for mixed integer/float expressions for convenience. + + Collections and algorithms -------------------------- @@ -88,6 +92,10 @@ Collections and algorithms * `sequtils <sequtils.html>`_ This module implements operations for the built-in seq type which were inspired by functional programming languages. +* `sharedtables <sharedtables.html>`_ + Nim shared hash table support. Contains shared tables. +* `sharedlist <sharedlist.html>`_ + Nim shared linked list support. Contains shared singly linked list. String handling @@ -98,6 +106,10 @@ String handling case of a string, splitting a string into substrings, searching for substrings, replacing substrings. +* `strformat <strformat.html>`_ + Macro based standard string interpolation / formatting. Inpired by + Python's ```f``-strings. + * `strmisc <strmisc.html>`_ This module contains uncommon string handling operations that do not fit with the commonly used operations in strutils. @@ -182,6 +194,12 @@ Generic Operating System Services This module implements asynchronous file reading and writing using ``asyncdispatch``. +* `distros <distros.html>`_ + This module implements the basics for OS distribution ("distro") detection and the OS's native package manager. + Its primary purpose is to produce output for Nimble packages, but it also contains the widely used **Distribution** enum + that is useful for writing platform specific code. + + Math libraries -------------- @@ -369,6 +387,7 @@ Cryptography and Hashing * `securehash <securehash.html>`_ This module implements a sha1 encoder and decoder. + Multimedia support ------------------ @@ -409,6 +428,9 @@ Miscellaneous * `unittest <unittest.html>`_ Implements a Unit testing DSL. +* `segfaults <segfaults.html>`_ + Turns access violations or segfaults into a ``NilAccessError`` exception. + Modules for JS backend --------------------------- @@ -418,6 +440,8 @@ Modules for JS backend * `jsffi <jsffi.html>`_ Types and macros for easier interaction with JavaScript. +* `asyncjs <asyncjs.html>`_ + Types and macros for writing asynchronous procedures in JavaScript. Deprecated modules ------------------ @@ -533,9 +557,6 @@ Database support Network Programming and Internet Protocols ------------------------------------------ -* `libuv <libuv.html>`_ - Wrapper for the libuv library used for async I/O programming. - * `joyent_http_parser <joyent_http_parser.html>`_ Wrapper for the joyent's high-performance HTTP parser. diff --git a/doc/manual/ffi.txt b/doc/manual/ffi.txt index 06fed1430..67a4c7caa 100644 --- a/doc/manual/ffi.txt +++ b/doc/manual/ffi.txt @@ -206,7 +206,7 @@ strings, because they are precompiled. **Note**: Passing variables to the ``dynlib`` pragma will fail at runtime because of order of initialization problems. -**Note**: A ``dynlib`` import can be overriden with +**Note**: A ``dynlib`` import can be overridden with the ``--dynlibOverride:name`` command line option. The Compiler User Guide contains further information. diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt index cceea33c0..1ba62bb5c 100644 --- a/doc/manual/generics.txt +++ b/doc/manual/generics.txt @@ -9,26 +9,26 @@ The following example shows a generic binary tree can be modelled: .. code-block:: nim type - BinaryTreeObj[T] = object # BinaryTreeObj is a generic type with - # with generic param ``T`` - le, ri: BinaryTree[T] # left and right subtrees; may be nil - data: T # the data stored in a node - BinaryTree[T] = ref BinaryTreeObj[T] # a shorthand for notational convenience + BinaryTree*[T] = ref object # BinaryTree is a generic type with + # generic param ``T`` + le, ri: BinaryTree[T] # left and right subtrees; may be nil + data: T # the data stored in a node - proc newNode[T](data: T): BinaryTree[T] = # constructor for a node + proc newNode*[T](data: T): BinaryTree[T] = + # constructor for a node new(result) result.data = data - proc add[T](root: var BinaryTree[T], n: BinaryTree[T]) = + proc add*[T](root: var BinaryTree[T], n: BinaryTree[T]) = + # insert a node into the tree if root == nil: root = n else: var it = root while it != nil: - var c = cmp(it.data, n.data) # compare the data items; uses - # the generic ``cmp`` proc that works for - # any type that has a ``==`` and ``<`` - # operator + # compare the data items; uses the generic ``cmp`` proc + # that works for any type that has a ``==`` and ``<`` operator + var c = cmp(it.data, n.data) if c < 0: if it.le == nil: it.le = n @@ -40,20 +40,28 @@ The following example shows a generic binary tree can be modelled: return it = it.ri - iterator inorder[T](root: BinaryTree[T]): T = - # inorder traversal of a binary tree - # recursive iterators are not yet implemented, so this does not work in - # the current compiler! - if root.le != nil: yield inorder(root.le) - yield root.data - if root.ri != nil: yield inorder(root.ri) + proc add*[T](root: var BinaryTree[T], data: T) = + # convenience proc: + add(root, newNode(data)) + + iterator preorder*[T](root: BinaryTree[T]): T = + # Preorder traversal of a binary tree. + # Since recursive iterators are not yet implemented, + # this uses an explicit stack (which is more efficient anyway): + var stack: seq[BinaryTree[T]] = @[root] + while stack.len > 0: + var n = stack.pop() + while n != nil: + yield n.data + add(stack, n.ri) # push right subtree onto the stack + n = n.le # and follow the left pointer var - root: BinaryTree[string] # instantiate a BinaryTree with the type string - add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and - add(root, newNode("world")) # ``add`` - for str in inorder(root): - writeLine(stdout, str) + root: BinaryTree[string] # instantiate a BinaryTree with ``string`` + add(root, newNode("hello")) # instantiates ``newNode`` and ``add`` + add(root, "world") # instantiates the second ``add`` proc + for str in preorder(root): + stdout.writeLine(str) Is operator diff --git a/doc/manual/locking.txt b/doc/manual/locking.txt index c1bd5ca46..99ffe8970 100644 --- a/doc/manual/locking.txt +++ b/doc/manual/locking.txt @@ -2,7 +2,7 @@ Guards and locks ================ Apart from ``spawn`` and ``parallel`` Nim also provides all the common low level -concurrency mechanisms like locks, atomic intristics or condition variables. +concurrency mechanisms like locks, atomic intrinsics or condition variables. Nim significantly improves on the safety of these features via additional pragmas: @@ -74,7 +74,7 @@ model low level lockfree mechanisms: The ``locks`` pragma takes a list of lock expressions ``locks: [a, b, ...]`` in order to support *multi lock* statements. Why these are essential is -explained in the `lock levels`_ section. +explained in the `lock levels <#guards-and-locks-lock-levels>`_ section. Protecting general locations diff --git a/doc/manual/modules.txt b/doc/manual/modules.txt index 9cb6a11af..4ef1bfd99 100644 --- a/doc/manual/modules.txt +++ b/doc/manual/modules.txt @@ -105,7 +105,7 @@ From import statement ~~~~~~~~~~~~~~~~~~~~~ After the ``from`` statement a module name follows followed by -an ``import`` to list the symbols one likes to use without explict +an ``import`` to list the symbols one likes to use without explicit full qualification: .. code-block:: nim @@ -123,7 +123,7 @@ in ``module``. Export statement ~~~~~~~~~~~~~~~~ -An ``export`` statement can be used for symbol fowarding so that client +An ``export`` statement can be used for symbol forwarding so that client modules don't need to import a module's dependencies: .. code-block:: nim diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt index bd90cd73d..835b6909d 100644 --- a/doc/manual/pragmas.txt +++ b/doc/manual/pragmas.txt @@ -70,7 +70,7 @@ compileTime pragma The ``compileTime`` pragma is used to mark a proc or variable to be used at compile time only. No code will be generated for it. Compile time procs are useful as helpers for macros. Since version 0.12.0 of the language, a proc -that uses ``system.NimNode`` within its parameter types is implictly declared +that uses ``system.NimNode`` within its parameter types is implicitly declared ``compileTime``: .. code-block:: nim @@ -102,6 +102,14 @@ collector to not consider objects of this type as part of a cycle: left, right: Node data: string +Or if we directly use a ref object: + +.. code-block:: nim + type + Node = ref object {.acyclic, final.} + left, right: Node + data: string + In the example a tree structure is declared with the ``Node`` type. Note that the type definition is recursive and the GC has to assume that objects of this type may form a cyclic graph. The ``acyclic`` pragma passes the @@ -316,7 +324,7 @@ factor. immediate pragma ---------------- -See `Ordinary vs immediate templates`_. +See `Typed vs untyped parameters`_. compilation option pragmas @@ -733,7 +741,8 @@ about the ``importcpp`` pragma pattern language. It is not necessary to know all the details described here. -Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the +Similar to the `importc pragma for C +<#foreign-function-interface-importc-pragma>`_, the ``importcpp`` pragma can be used to import `C++`:idx: methods or C++ symbols in general. The generated code then uses the C++ method calling syntax: ``obj->method(arg)``. In combination with the ``header`` and ``emit`` @@ -955,10 +964,11 @@ Produces: ImportObjC pragma ----------------- -Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the -``importobjc`` pragma can be used to import `Objective C`:idx: methods. The -generated code then uses the Objective C method calling syntax: ``[obj method -param1: arg]``. In addition with the ``header`` and ``emit`` pragmas this +Similar to the `importc pragma for C +<#foreign-function-interface-importc-pragma>`_, the ``importobjc`` pragma can +be used to import `Objective C`:idx: methods. The generated code then uses the +Objective C method calling syntax: ``[obj method param1: arg]``. +In addition with the ``header`` and ``emit`` pragmas this allows *sloppy* interfacing with libraries written in Objective C: .. code-block:: Nim diff --git a/doc/manual/procs.txt b/doc/manual/procs.txt index 6d09ac3f5..44aeb089a 100644 --- a/doc/manual/procs.txt +++ b/doc/manual/procs.txt @@ -142,10 +142,11 @@ The method call syntax conflicts with explicit generic instantiations: parsed as ``(x.p)[T]``. **Future directions**: ``p[.T.]`` might be introduced as an alternative syntax -to pass explict types to a generic and then ``x.p[.T.]`` can be parsed as +to pass explicit types to a generic and then ``x.p[.T.]`` can be parsed as ``x.(p[.T.])``. -See also: `Limitations of the method call syntax`_. +See also: `Limitations of the method call syntax +<#templates-limitations-of-the-method-call-syntax>`_. Properties @@ -178,7 +179,7 @@ different; for this a special setter syntax is needed: Command invocation syntax ------------------------- -Routines can be invoked without the ``()`` if the call is syntatically +Routines can be invoked without the ``()`` if the call is syntactically a statement. This command invocation syntax also works for expressions, but then only a single argument may follow. This restriction means ``echo f 1, f 2`` is parsed as ``echo(f(1), f(2))`` and not as diff --git a/doc/manual/special_ops.txt b/doc/manual/special_ops.txt index 1c7136bec..93977f81b 100644 --- a/doc/manual/special_ops.txt +++ b/doc/manual/special_ops.txt @@ -17,8 +17,8 @@ or dynamic file formats such as JSON or XML. When Nim encounters an expression that cannot be resolved by the standard overload resolution rules, the current scope will be searched for a dot operator that can be matched against a re-written form of -the expression, where the unknown field or proc name is converted to -an additional static string parameter: +the expression, where the unknown field or proc name is passed to +an ``untyped`` parameter: .. code-block:: nim a.b # becomes `.`(a, "b") @@ -28,7 +28,7 @@ The matched dot operators can be symbols of any callable kind (procs, templates and macros), depending on the desired effect: .. code-block:: nim - proc `.` (js: PJsonNode, field: string): JSON = js[field] + template `.` (js: PJsonNode, field: untyped): JSON = js[astToStr(field)] var js = parseJson("{ x: 1, y: 2}") echo js.x # outputs 1 diff --git a/doc/manual/stmts.txt b/doc/manual/stmts.txt index 3a86a9730..721b5cff8 100644 --- a/doc/manual/stmts.txt +++ b/doc/manual/stmts.txt @@ -199,7 +199,7 @@ The rules for compile-time computability are: (possibly empty) list of compile-time computable arguments. -Constants cannot be of type ``ptr``, ``ref``, ``var`` or ``object``, nor can +Constants cannot be of type ``ptr``, ``ref`` or ``var``, nor can they contain such a type. @@ -296,6 +296,10 @@ empty ``discard`` statement should be used. For non ordinal types it is not possible to list every possible value and so these always require an ``else`` part. +As case statements perform compile-time exhaustiveness checks, the value in +every ``of`` branch must be known at compile time. This fact is also exploited +to generate more performant code. + As a special semantic extension, an expression in an ``of`` branch of a case statement may evaluate to a set or array constructor; the set or array is then expanded into a list of its elements: diff --git a/doc/manual/templates.txt b/doc/manual/templates.txt index f01a703cd..af184589c 100644 --- a/doc/manual/templates.txt +++ b/doc/manual/templates.txt @@ -293,7 +293,7 @@ Limitations of the method call syntax The expression ``x`` in ``x.f`` needs to be semantically checked (that means symbol lookup and type checking) before it can be decided that it needs to be -rewritten to ``f(x)``. Therefore the dot syntax has some limiations when it +rewritten to ``f(x)``. Therefore the dot syntax has some limitations when it is used to invoke templates/macros: .. code-block:: nim diff --git a/doc/manual/threads.txt b/doc/manual/threads.txt index 15121ab6d..53071b5a5 100644 --- a/doc/manual/threads.txt +++ b/doc/manual/threads.txt @@ -5,7 +5,7 @@ To enable thread support the ``--threads:on`` command line switch needs to be used. The ``system`` module then contains several threading primitives. See the `threads <threads.html>`_ and `channels <channels.html>`_ modules for the low level thread API. There are also high level parallelism constructs -available. See `spawn`_ for further details. +available. See `spawn <#parallel-spawn>`_ for further details. Nim's memory model for threads is quite different than that of other common programming languages (C, Pascal, Java): Each thread has its own (garbage diff --git a/doc/manual/type_bound_ops.txt b/doc/manual/type_bound_ops.txt index c707979fe..b531abf31 100644 --- a/doc/manual/type_bound_ops.txt +++ b/doc/manual/type_bound_ops.txt @@ -7,12 +7,12 @@ There are 3 operations that are bound to a type: 2. Destruction 3. Deep copying for communication between threads -These operations can be *overriden* instead of *overloaded*. This means the +These operations can be *overridden* instead of *overloaded*. This means the implementation is automatically lifted to structured types. For instance if type -``T`` has an overriden assignment operator ``=`` this operator is also used +``T`` has an overridden assignment operator ``=`` this operator is also used for assignments of the type ``seq[T]``. Since these operations are bound to a type they have to be bound to a nominal type for reasons of simplicity of -implementation: This means an overriden ``deepCopy`` for ``ref T`` is really +implementation: This means an overridden ``deepCopy`` for ``ref T`` is really bound to ``T`` and not to ``ref T``. This also means that one cannot override ``deepCopy`` for both ``ptr T`` and ``ref T`` at the same time; instead a helper distinct or object type has to be used for one pointer type. diff --git a/doc/manual/type_rel.txt b/doc/manual/type_rel.txt index 1d1425934..3372691fb 100644 --- a/doc/manual/type_rel.txt +++ b/doc/manual/type_rel.txt @@ -491,4 +491,4 @@ metatypes ``typed`` and ``typedesc`` are not lazy. Varargs matching ---------------- -See `Varargs`_. +See `Varargs <#types-varargs>`_. diff --git a/doc/manual/type_sections.txt b/doc/manual/type_sections.txt index af761c77e..12b2a11ac 100644 --- a/doc/manual/type_sections.txt +++ b/doc/manual/type_sections.txt @@ -5,8 +5,7 @@ Example: .. code-block:: nim type # example demonstrating mutually recursive types - Node = ref NodeObj # a traced pointer to a NodeObj - NodeObj = object + Node = ref object # an object managed by the garbage collector (ref) le, ri: Node # left and right subtrees sym: ref Sym # leaves contain a reference to a Sym diff --git a/doc/manual/types.txt b/doc/manual/types.txt index 2c4b019ad..1477995dd 100644 --- a/doc/manual/types.txt +++ b/doc/manual/types.txt @@ -41,7 +41,8 @@ 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. + 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 @@ -114,7 +115,8 @@ if the literal's value fits this smaller type and such a conversion is less expensive than other implicit conversions, so ``myInt16 + 34`` produces an ``int16`` result. -For further details, see `Convertible relation`_. +For further details, see `Convertible relation +<#type-relations-convertible-relation>`_. Subrange types @@ -136,26 +138,6 @@ determined). Assignments from the base type to one of its subrange types A subrange type has the same size as its base type (``int`` in the example). -Nim requires `interval arithmetic`:idx: for subrange types over a set -of built-in operators that involve constants: ``x %% 3`` is of -type ``range[0..2]``. The following built-in operators for integers are -affected by this rule: ``-``, ``+``, ``*``, ``min``, ``max``, ``succ``, -``pred``, ``mod``, ``div``, ``%%``, ``and`` (bitwise ``and``). - -Bitwise ``and`` only produces a ``range`` if one of its operands is a -constant *x* so that (x+1) is a power of two. -(Bitwise ``and`` is then a ``%%`` operation.) - -This means that the following code is accepted: - -.. code-block:: nim - case (x and 3) + 7 - of 7: echo "A" - of 8: echo "B" - of 9: echo "C" - of 10: echo "D" - # note: no ``else`` required as (x and 3) + 7 has the type: range[7..10] - Pre-defined floating point types -------------------------------- @@ -570,7 +552,7 @@ order. The *names* of the fields also have to be identical. The assignment operator for tuples copies each component. The default assignment operator for objects copies each component. Overloading -of the assignment operator is described in `type-bound-operations-operator`_. +of the assignment operator is described in `type-bound-operations-operator`_. .. code-block:: nim @@ -697,6 +679,44 @@ branch switch ``system.reset`` has to be used. Also, when the fields of a particular branch are specified during object construction, the correct value for the discriminator must be supplied at compile-time. +Package level objects +--------------------- + +Every Nim module resides in a (nimble) package. An object type can be attached +to the package it resides in. If that is done, the type can be referenced from +other modules as an `incomplete`:idx: object type. This features allows to +break up recursive type dependencies accross module boundaries. Incomplete +object types are always passed ``byref`` and can only be used in pointer like +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 ``sizeof(T)`` or "runtime type +information" for ``T`` is not available. + + +Example: + +.. code-block:: nim + + # module A (in an arbitrary package) + type + Pack.SomeObject = object ## declare as incomplete object of package 'Pack' + Triple = object + a, b, c: ref SomeObject ## pointers to incomplete objects are allowed + + ## Incomplete objects can be used as parameters: + proc myproc(x: SomeObject) = discard + + +.. code-block:: nim + + # module B (in package "Pack") + type + SomeObject* {.package.} = object ## Use 'package' to complete the object + s, t: string + x, y: int + Set type -------- @@ -905,8 +925,8 @@ not compatible to ``pointer`` to prevent the following from compiling: Future directions: * Memory regions might become available for ``string`` and ``seq`` too. -* Builtin regions like ``private``, ``global`` and ``local`` will - prove very useful for the upcoming OpenCL target. +* Builtin regions like ``private``, ``global`` and ``local`` might be + useful for an OpenCL target. * Builtin "regions" can model ``lent`` and ``unique`` pointers. * An assignment operator can be attached to a region so that proper write barriers can be generated. This would imply that the GC can be implemented diff --git a/doc/tut1.rst b/doc/tut1.rst index be5cd8c11..9e6f1ab3c 100644 --- a/doc/tut1.rst +++ b/doc/tut1.rst @@ -30,6 +30,7 @@ The first program We start the tour with a modified "hello world" program: .. code-block:: Nim + :test: "nim c $1" # This is a comment echo "What's your name? " var name: string = readLine(stdin) @@ -72,6 +73,7 @@ you can leave out the type in the declaration (this is called `local type inference`:idx:). So this will work too: .. code-block:: Nim + :test: "nim c $1" var name = readLine(stdin) Note that this is basically the only form of type inference that exists in @@ -116,6 +118,7 @@ Comments start anywhere outside a string or character literal with the hash character ``#``. Documentation comments start with ``##``: .. code-block:: nim + :test: "nim c $1" # A comment. var myVariable: int ## a documentation comment @@ -129,6 +132,7 @@ Multiline comments are started with ``#[`` and terminated with ``]#``. Multilin comments can also be nested. .. code-block:: nim + :test: "nim c $1" #[ You can have any Nim code text commented out inside this with no indentation restrictions. @@ -142,6 +146,7 @@ You can also use the `discard statement <#procedures-discard-statement>`_ togeth literals* to create block comments: .. code-block:: nim + :test: "nim c $1" discard """ You can have any Nim code text commented out inside this with no indentation restrictions. yes("May I ask a pointless question?") """ @@ -169,6 +174,7 @@ Indentation can be used after the ``var`` keyword to list a whole section of variables: .. code-block:: + :test: "nim c $1" var x, y: int # a comment can occur here too @@ -186,10 +192,11 @@ to a storage location: x = "xyz" # assigns a new value to `x` ``=`` is the *assignment operator*. The assignment operator can be -overloaded. You can declare multiple variables with a single assignment +overloaded. You can declare multiple variables with a single assignment statement and all the variables will have the same value: .. code-block:: + :test: "nim c $1" var x, y = 3 # assigns 3 to the variables `x` and `y` echo "x ", x # outputs "x 3" echo "y ", y # outputs "y 3" @@ -212,12 +219,14 @@ cannot change. The compiler must be able to evaluate the expression in a constant declaration at compile time: .. code-block:: nim + :test: "nim c $1" const x = "abc" # the constant x contains the string "abc" Indentation can be used after the ``const`` keyword to list a whole section of constants: .. code-block:: + :test: "nim c $1" const x = 1 # a comment can occur here too @@ -243,6 +252,7 @@ and put it into a data section": const input = readLine(stdin) # Error: constant expression expected .. code-block:: + :test: "nim c $1" let input = readLine(stdin) # works @@ -260,6 +270,7 @@ If statement The if statement is one way to branch the control flow: .. code-block:: nim + :test: "nim c $1" let name = readLine(stdin) if name == "": echo "Poor soul, you lost your name?" @@ -281,6 +292,7 @@ Another way to branch is provided by the case statement. A case statement is a multi-branch: .. code-block:: nim + :test: "nim c $1" let name = readLine(stdin) case name of "": @@ -338,6 +350,7 @@ While statement The while statement is a simple looping construct: .. code-block:: nim + :test: "nim c $1" echo "What's your name? " var name = readLine(stdin) @@ -358,6 +371,7 @@ provides. The example uses the built-in `countup <system.html#countup>`_ iterator: .. code-block:: nim + :test: "nim c $1" echo "Counting to ten: " for i in countup(1, 10): echo i @@ -409,6 +423,7 @@ Other useful iterators for collections (like arrays and sequences) are * ``pairs`` and ``mpairs`` which provides the element and an index number (immutable and mutable respectively) .. code-block:: nim + :test: "nim c $1" for index, item in ["a","b"].pairs: echo item, " at index ", index # => a at index 0 @@ -421,6 +436,8 @@ new scope. This means that in the following example, ``x`` is not accessible outside the loop: .. code-block:: nim + :test: "nim c $1" + :status: 1 while false: var x = "hi" echo x # does not work @@ -430,6 +447,8 @@ are only visible within the block they have been declared. The ``block`` statement can be used to open a new block explicitly: .. code-block:: nim + :test: "nim c $1" + :status: 1 block myblock: var x = "hi" echo x # does not work either @@ -444,6 +463,7 @@ can leave a ``while``, ``for``, or a ``block`` statement. It leaves the innermost construct, unless a label of a block is given: .. code-block:: nim + :test: "nim c $1" block myblock: echo "entering block" while true: @@ -465,6 +485,7 @@ Like in many other programming languages, a ``continue`` statement starts the next iteration immediately: .. code-block:: nim + :test: "nim c $1" while true: let x = readLine(stdin) if x == "": continue @@ -477,6 +498,7 @@ When statement Example: .. code-block:: nim + :test: "nim c $1" when system.hostOS == "windows": echo "running on Windows!" @@ -549,6 +571,7 @@ an expression is allowed: .. code-block:: nim # computes fac(4) at compile time: + :test: "nim c $1" const fac4 = (var x = 1; for i in 1..4: x *= i; x) @@ -561,6 +584,7 @@ is needed. (Some languages call them *methods* or *functions*.) In Nim new procedures are defined with the ``proc`` keyword: .. code-block:: nim + :test: "nim c $1" proc yes(question: string): bool = echo question, " (y/n)" while true: @@ -597,6 +621,7 @@ automatically at the end of a procedure if there is no ``return`` statement at the exit. .. code-block:: nim + :test: "nim c $1" proc sumTillNegative(x: varargs[int]): int = for i in x: if i < 0: @@ -624,6 +649,7 @@ to be declared with ``var`` in the procedure body. Shadowing the parameter name is possible, and actually an idiom: .. code-block:: nim + :test: "nim c $1" proc printSeq(s: seq, nprinted: int = -1) = var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len) for i in 0 .. <nprinted: @@ -633,6 +659,7 @@ If the procedure needs to modify the argument for the caller, a ``var`` parameter can be used: .. code-block:: nim + :test: "nim c $1" proc divmod(a, b: int; res, remainder: var int) = res = a div b # integer division remainder = a mod b # integer modulo operation @@ -663,6 +690,7 @@ The return value can be ignored implicitly if the called proc/iterator has been declared with the ``discardable`` pragma: .. code-block:: nim + :test: "nim c $1" proc p(x, y: int): int {.discardable.} = return x + y @@ -772,6 +800,7 @@ The "``" notation can also be used to call an operator just like any other procedure: .. code-block:: nim + :test: "nim c $1" if `==`( `+`(3, 4), 7): echo "True" @@ -819,6 +848,7 @@ Iterators Let's return to the simple counting example: .. code-block:: nim + :test: "nim c $1" echo "Counting to ten: " for i in countup(1, 10): echo i @@ -840,6 +870,7 @@ the only thing left to do is to replace the ``proc`` keyword by ``iterator`` and here it is - our first iterator: .. code-block:: nim + :test: "nim c $1" iterator countup(a, b: int): int = var res = a while res <= b: @@ -894,7 +925,8 @@ evaluation. For example: Characters ---------- The `character type` is called ``char``. Its size is always one byte, so -it cannot represent most UTF-8 characters; but it *can* represent one of the bytes that makes up a multi-byte UTF-8 character. +it cannot represent most UTF-8 characters; but it *can* represent one of the bytes +that makes up a multi-byte UTF-8 character. The reason for this is efficiency: for the overwhelming majority of use-cases, the resulting programs will still handle UTF-8 properly as UTF-8 was specially designed for this. @@ -945,6 +977,7 @@ to specify a non-default integer type: .. code-block:: nim + :test: "nim c $1" let x = 0 # x is of type ``int`` y = 0'i8 # y is of type ``int8`` @@ -981,6 +1014,7 @@ Float literals can have a *type suffix* to specify a non-default float type: .. code-block:: nim + :test: "nim c $1" var x = 0.0 # x is of type ``float`` y = 0.0'f32 # y is of type ``float32`` @@ -1002,6 +1036,7 @@ Conversion between basic types is performed by using the type as a function: .. code-block:: nim + :test: "nim c $1" var x: int32 = 1.int32 # same as calling int32(1) y: int8 = int8('a') # 'a' == 97'i8 @@ -1023,6 +1058,7 @@ graphs with cycles. The following example shows that even for basic types there is a difference between the ``$`` and ``repr`` outputs: .. code-block:: nim + :test: "nim c $1" var myBool = true myCharacter = 'n' @@ -1047,6 +1083,7 @@ Advanced types In Nim new types can be defined within a ``type`` statement: .. code-block:: nim + :test: "nim c $1" type biggestInt = int64 # biggest integer type that is available biggestFloat = float64 # biggest float type that is available @@ -1063,6 +1100,7 @@ to an integer value internally. The first symbol is represented at runtime by 0, the second by 1 and so on. For example: .. code-block:: nim + :test: "nim c $1" type Direction = enum @@ -1087,6 +1125,7 @@ explicitly given is assigned the value of the previous symbol + 1. An explicit ordered enum can have *holes*: .. code-block:: nim + :test: "nim c $1" type MyEnum = enum a = 2, b = 4, c = 89 @@ -1125,6 +1164,7 @@ A subrange type is a range of values from an integer or enumeration type (the base type). Example: .. code-block:: nim + :test: "nim c $1" type MySubrange = range[0..5] @@ -1155,6 +1195,7 @@ an array has the same type. The array's index type can be any ordinal type. Arrays can be constructed using ``[]``: .. code-block:: nim + :test: "nim c $1" type IntArray = array[0..5, int] # an array that is indexed with 0..5 @@ -1177,6 +1218,7 @@ length. `low(a) <system.html#low>`_ returns the lowest valid index for the array `a` and `high(a) <system.html#high>`_ the highest valid index. .. code-block:: nim + :test: "nim c $1" type Direction = enum north, east, south, west @@ -1228,6 +1270,7 @@ It is quite common to have arrays start at zero, so there's a shortcut syntax to specify a range from zero to the specified index minus one: .. code-block:: nim + :test: "nim c $1" type IntArray = array[0..5, int] # an array that is indexed with 0..5 QuickArray = array[6, int] # an array that is indexed with 0..5 @@ -1260,6 +1303,7 @@ A sequence may be passed to an openarray parameter. Example: .. code-block:: nim + :test: "nim c $1" var x: seq[int] # a reference to a sequence of integers @@ -1282,6 +1326,7 @@ value. Here the ``for`` statement is looping over the results from the <system.html>`_ module. Examples: .. code-block:: nim + :test: "nim c $1" for value in @[3, 4, 5]: echo value # --> 3 @@ -1308,6 +1353,7 @@ with a compatible base type can be passed to an openarray parameter, the index type does not matter. .. code-block:: nim + :test: "nim c $1" var fruits: seq[string] # reference to a sequence of strings that is initialized with 'nil' capitals: array[3, string] # array of strings with a fixed size @@ -1337,6 +1383,7 @@ arguments to a procedure. The compiler converts the list of arguments to an array automatically: .. code-block:: nim + :test: "nim c $1" proc myWriteln(f: File, a: varargs[string]) = for s in items(a): write(f, s) @@ -1351,6 +1398,7 @@ last parameter in the procedure header. It is also possible to perform type conversions in this context: .. code-block:: nim + :test: "nim c $1" proc myWriteln(f: File, a: varargs[string, `$`]) = for s in items(a): write(f, s) @@ -1374,6 +1422,7 @@ context. A slice is just an object of type Slice which contains two bounds, define operators which accept Slice objects to define ranges. .. code-block:: nim + :test: "nim c $1" var a = "Nim is a progamming language" @@ -1388,27 +1437,31 @@ slice's bounds can hold any value supported by their type, but it is the proc using the slice object which defines what values are accepted. - To understand some of the different ways of specifying the indices of strings, arrays, sequences, etc., - it must be remembered that Nim uses zero-based indices. +To understand some of the different ways of specifying the indices of +strings, arrays, sequences, etc., it must be remembered that Nim uses +zero-based indices. - So the string ``b`` is of length 19, and two different ways of specifying the indices are +So the string ``b`` is of length 19, and two different ways of specifying the +indices are - .. code-block:: nim +.. code-block:: nim "Slices are useless." | | | 0 11 17 using indices ^19 ^8 ^2 using ^ syntax - where ``b[0..^1]`` is equivalent to ``b[0..b.len-1]`` and ``b[0..<b.len]``, and it can be seen that the ``^1`` provides a short-hand way of specifying the ``b.len-1`` +where ``b[0..^1]`` is equivalent to ``b[0..b.len-1]`` and ``b[0..<b.len]``, and it +can be seen that the ``^1`` provides a short-hand way of specifying the ``b.len-1``. - In the above example, because the string ends in a period, to get the portion of the string that is "useless" and replace it with "useful" +In the above example, because the string ends in a period, to get the portion of the +string that is "useless" and replace it with "useful". - ``b[11..^2]`` is the portion "useless", and - ``b[11..^2] = "useful"`` replaces the "useless" portion with "useful", - giving the result "Slices are useful." +``b[11..^2]`` is the portion "useless", and ``b[11..^2] = "useful"`` replaces the +"useless" portion with "useful", giving the result "Slices are useful." - Note: alternate ways of writing this are ``b[^8..^2] = "useful"`` or as ``b[11..b.len-2] = "useful"`` or as ``b[11..<b.len-1] = "useful"`` or as .... +Note: alternate ways of writing this are ``b[^8..^2] = "useful"`` or +as ``b[11..b.len-2] = "useful"`` or as ``b[11..<b.len-1] = "useful"``. Tuples ------ @@ -1425,6 +1478,7 @@ The assignment operator for tuples copies each component. The notation integer. .. code-block:: nim + :test: "nim c $1" type Person = tuple[name: string, age: int] # type representing a person: @@ -1470,6 +1524,7 @@ otherwise you will be assigning the same value to all the individual variables! For example: .. code-block:: nim + :test: "nim c $1" import os @@ -1509,10 +1564,10 @@ tuple/object field operator) and ``[]`` (array/string/sequence index operator) operators perform implicit dereferencing operations for reference types: .. code-block:: nim + :test: "nim c $1" type - Node = ref NodeObj - NodeObj = object + Node = ref object le, ri: Node data: int var @@ -1539,6 +1594,7 @@ techniques. Example: .. code-block:: nim + :test: "nim c $1" proc echoItem(x: int) = echo x proc forEach(action: proc (x: int)) = @@ -1556,9 +1612,11 @@ listed in the `manual <manual.html#types-procedural-type>`_. Distinct type ------------- -A Distinct type allows for the creation of new type that "does not imply a subtype relationship between it and its base type". +A Distinct type allows for the creation of new type that "does not imply a +subtype relationship between it and its base type". You must **explicitly** define all behaviour for the distinct type. -To help with this, both the distinct type and its base type can cast from one type to the other. +To help with this, both the distinct type and its base type can cast from one +type to the other. Examples are provided in the `manual <manual.html#types-distinct-type>`_. Modules @@ -1593,39 +1651,6 @@ Each module has a special magic constant ``isMainModule`` that is true if the module is compiled as the main file. This is very useful to embed tests within the module as shown by the above example. -Modules that depend on each other are possible, but strongly discouraged, -because then one module cannot be reused without the other. - -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. - -This is best illustrated by an example: - -.. code-block:: nim - # Module A - type - T1* = int # Module A exports the type ``T1`` - import B # the compiler starts parsing B - - proc main() = - var i = p(3) # works because B has been parsed completely here - - main() - -.. code-block:: nim - # Module B - import A # A is not parsed here! Only the already known symbols - # of A are imported. - - proc p*(x: A.T1): A.T1 = - # this works because the compiler has already - # added T1 to A's interface symbol table - result = x + 1 - - A symbol of a module *can* be *qualified* with the ``module.symbol`` syntax. And if a symbol is ambiguous, it *must* be qualified. A symbol is ambiguous if it is defined in two (or more) different modules and both modules are diff --git a/doc/tut2.rst b/doc/tut2.rst index 0bb4c94e1..91cb52834 100644 --- a/doc/tut2.rst +++ b/doc/tut2.rst @@ -55,6 +55,7 @@ Objects have access to their type at runtime. There is an ``of`` operator that can be used to check the object's type: .. code-block:: nim + :test: "nim c $1" type Person = ref object of RootObj name*: string # the * means that `name` is accessible from other modules @@ -103,16 +104,16 @@ would require arbitrary symbol lookahead which slows down compilation.) Example: .. code-block:: nim + :test: "nim c $1" type - Node = ref NodeObj # a traced reference to a NodeObj - NodeObj = object + Node = ref object # a reference to an object with the following field: le, ri: Node # left and right subtrees sym: ref Sym # leaves contain a reference to a Sym Sym = object # a symbol name: string # the symbol's name line: int # the line the symbol was declared in - code: Node # the symbol's abstract syntax tree + code: Node # the symbol's abstract syntax tree Type conversions @@ -145,6 +146,7 @@ variant types are needed. An example: .. code-block:: nim + :test: "nim c $1" # This is an example how an abstract syntax tree could be modelled in Nim type @@ -155,8 +157,7 @@ An example: nkAdd, # an addition nkSub, # a subtraction nkIf # an if statement - Node = ref NodeObj - NodeObj = object + Node = ref object case kind: NodeKind # the ``kind`` field is the discriminator of nkInt: intVal: int of nkFloat: floatVal: float @@ -203,9 +204,11 @@ This method call syntax is not restricted to objects, it can be used for any type: .. code-block:: nim + :test: "nim c $1" + import strutils echo "abc".len # is the same as echo len("abc") - echo "abc".toUpper() + echo "abc".toUpperAscii() echo({'a', 'b', 'c'}.card) stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo") @@ -215,6 +218,7 @@ postfix notation.) So "pure object oriented" code is easy to write: .. code-block:: nim + :test: "nim c $1" import strutils, sequtils stdout.writeLine("Give a list of numbers (separated by spaces): ") @@ -230,6 +234,7 @@ the same. But setting a value is different; for this a special setter syntax is needed: .. code-block:: nim + :test: "nim c $1" type Socket* = ref object of RootObj @@ -254,6 +259,7 @@ The ``[]`` array access operator can be overloaded to provide `array properties`:idx:\ : .. code-block:: nim + :test: "nim c $1" type Vector* = object x, y, z: float @@ -285,23 +291,24 @@ Procedures always use static dispatch. For dynamic dispatch replace the ``proc`` keyword by ``method``: .. code-block:: nim + :test: "nim c $1" type - PExpr = ref object of RootObj ## abstract base class for an expression - PLiteral = ref object of PExpr + Expression = ref object of RootObj ## abstract base class for an expression + Literal = ref object of Expression x: int - PPlusExpr = ref object of PExpr - a, b: PExpr + PlusExpr = ref object of Expression + a, b: Expression # watch out: 'eval' relies on dynamic binding - method eval(e: PExpr): int = + method eval(e: Expression): int = # override this base method quit "to override!" - method eval(e: PLiteral): int = e.x - method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b) + method eval(e: Literal): int = e.x + method eval(e: PlusExpr): int = eval(e.a) + eval(e.b) - proc newLit(x: int): PLiteral = PLiteral(x: x) - proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b) + proc newLit(x: int): Literal = Literal(x: x) + proc newPlus(a, b: Expression): PlusExpr = PlusExpr(a: a, b: b) echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4))) @@ -313,6 +320,7 @@ In a multi-method all parameters that have an object type are used for the dispatching: .. code-block:: nim + :test: "nim c $1" type Thing = ref object of RootObj @@ -367,6 +375,7 @@ Raise statement Raising an exception is done with the ``raise`` statement: .. code-block:: nim + :test: "nim c $1" var e: ref OSError new(e) @@ -387,6 +396,9 @@ Try statement The ``try`` statement handles exceptions: .. code-block:: nim + :test: "nim c $1" + from strutils import parseInt + # read the first two lines of a text file that should contain numbers # and tries to add them var @@ -481,12 +493,12 @@ with `type parameters`:idx:. They are most useful for efficient type safe containers: .. code-block:: nim + :test: "nim c $1" type - BinaryTreeObj[T] = object # BinaryTree is a generic type with - # with generic param ``T`` - le, ri: BinaryTree[T] # left and right subtrees; may be nil - data: T # the data stored in a node - BinaryTree*[T] = ref BinaryTreeObj[T] # type that is exported + BinaryTree*[T] = ref object # BinaryTree is a generic type with + # generic param ``T`` + le, ri: BinaryTree[T] # left and right subtrees; may be nil + data: T # the data stored in a node proc newNode*[T](data: T): BinaryTree[T] = # constructor for a node @@ -576,6 +588,7 @@ Templates are especially useful for lazy evaluation purposes. Consider a simple proc for logging: .. code-block:: nim + :test: "nim c $1" const debug = true @@ -593,6 +606,7 @@ evaluation for procedures is *eager*). Turning the ``log`` proc into a template solves this problem: .. code-block:: nim + :test: "nim c $1" const debug = true @@ -614,6 +628,7 @@ If the template has no explicit return type, To pass a block of statements to a template, use 'untyped' for the last parameter: .. code-block:: nim + :test: "nim c $1" template withFile(f: untyped, filename: string, mode: FileMode, body: untyped): typed = @@ -668,6 +683,7 @@ The following example implements a powerful ``debug`` command that accepts a variable number of arguments: .. code-block:: nim + :test: "nim c $1" # to work with Nim syntax trees, we need an API that is defined in the # ``macros`` module: import macros @@ -747,6 +763,7 @@ dynamic code into something that compiles statically. For the exercise we will use the following snippet of code as the starting point: .. code-block:: nim + :test: "nim c $1" import strutils, tables @@ -866,9 +883,9 @@ variables with ``cfg``. In essence, what the compiler is doing is replacing the line calling the macro with the following snippet of code: .. code-block:: nim - const cfgversion= "1.1" - const cfglicenseOwner= "Hyori Lee" - const cfglicenseKey= "M1Tl3PjBWO2CC48m" + const cfgversion = "1.1" + const cfglicenseOwner = "Hyori Lee" + const cfglicenseKey = "M1Tl3PjBWO2CC48m" You can verify this yourself adding the line ``echo source`` somewhere at the end of the macro and compiling the program. Another difference is that instead @@ -894,12 +911,13 @@ an expression macro. Since we know that we want to generate a bunch of see what the compiler *expects* from us: .. code-block:: nim + :test: "nim c $1" import macros dumpTree: const cfgversion: string = "1.1" - const cfglicenseOwner= "Hyori Lee" - const cfglicenseKey= "M1Tl3PjBWO2CC48m" + const cfglicenseOwner = "Hyori Lee" + const cfglicenseKey = "M1Tl3PjBWO2CC48m" During compilation of the source code we should see the following lines in the output (again, since this is a macro, compilation is enough, you don't have to @@ -999,6 +1017,7 @@ Lifting Procs +++++++++++++ .. code-block:: nim + :test: "nim c $1" import math template liftScalarProc(fname) = |