mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +00:00
211 lines
6.0 KiB
Plaintext
211 lines
6.0 KiB
Plaintext
Modules
|
|
=======
|
|
Nim supports splitting a program into pieces by a module concept.
|
|
Each module needs to be in its own file and has its own `namespace`:idx:.
|
|
Modules enable `information hiding`:idx: and `separate compilation`:idx:.
|
|
A module may gain access to symbols of another module by the `import`:idx:
|
|
statement. `Recursive module dependencies`:idx: are allowed, but slightly
|
|
subtle. Only top-level symbols that are marked with an asterisk (``*``) are
|
|
exported. A valid module name can only be a valid Nim identifier (and thus its
|
|
filename is ``identifier.nim``).
|
|
|
|
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
|
|
|
|
|
|
Import statement
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
After the ``import`` statement a list of module names can follow or a single
|
|
module name followed by an ``except`` list to prevent some symbols to be
|
|
imported:
|
|
|
|
.. code-block:: nim
|
|
import strutils except `%`, toUpper
|
|
|
|
# doesn't work then:
|
|
echo "$1" % "abc".toUpper
|
|
|
|
|
|
It is not checked that the ``except`` list is really exported from the module.
|
|
This feature allows to compile against an older version of the module that
|
|
does not export these identifiers.
|
|
|
|
|
|
Include statement
|
|
~~~~~~~~~~~~~~~~~
|
|
The ``include`` statement does something fundamentally different than
|
|
importing a module: it merely includes the contents of a file. The ``include``
|
|
statement is useful to split up a large module into several files:
|
|
|
|
.. code-block:: nim
|
|
include fileA, fileB, fileC
|
|
|
|
|
|
|
|
Module names in imports
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
A module alias can be introduced via the ``as`` keyword:
|
|
|
|
.. code-block:: nim
|
|
import strutils as su, sequtils as qu
|
|
|
|
echo su.format("$1", "lalelu")
|
|
|
|
The original module name is then not accessible. The
|
|
notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"``
|
|
can be used to refer to a module in subdirectories:
|
|
|
|
.. code-block:: nim
|
|
import lib.pure.strutils, lib/pure/os, "lib/pure/times"
|
|
|
|
Note that the module name is still ``strutils`` and not ``lib.pure.strutils``
|
|
and so one **cannot** do:
|
|
|
|
.. code-block:: nim
|
|
import lib.pure.strutils
|
|
echo lib.pure.strutils
|
|
|
|
Likewise the following does not make sense as the name is ``strutils`` already:
|
|
|
|
.. code-block:: nim
|
|
import lib.pure.strutils as strutils
|
|
|
|
|
|
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
|
|
full qualification:
|
|
|
|
.. code-block:: nim
|
|
from strutils import `%`
|
|
|
|
echo "$1" % "abc"
|
|
# always possible: full qualification:
|
|
echo strutils.replace("abc", "a", "z")
|
|
|
|
It's also possible to use ``from module import nil`` if one wants to import
|
|
the module but wants to enforce fully qualified access to every symbol
|
|
in ``module``.
|
|
|
|
|
|
Export statement
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
An ``export`` statement can be used for symbol fowarding so that client
|
|
modules don't need to import a module's dependencies:
|
|
|
|
.. code-block:: nim
|
|
# module B
|
|
type MyObject* = object
|
|
|
|
.. code-block:: nim
|
|
# module A
|
|
import B
|
|
export B.MyObject
|
|
|
|
proc `$`*(x: MyObject): string = "my object"
|
|
|
|
|
|
.. code-block:: nim
|
|
# module C
|
|
import A
|
|
|
|
# B.MyObject has been imported implicitly here:
|
|
var x: MyObject
|
|
echo($x)
|
|
|
|
Note on paths
|
|
-----------
|
|
In module related statements, if any part of the module name /
|
|
path begins with a number, you may have to quote it in double quotes.
|
|
In the following example, it would be seen as a literal number '3.0' of type
|
|
'float64' if not quoted, if uncertain - quote it:
|
|
.. code-block:: nim
|
|
import "gfx/3d/somemodule"
|
|
|
|
Scope rules
|
|
-----------
|
|
Identifiers are valid from the point of their declaration until the end of
|
|
the block in which the declaration occurred. The range where the identifier
|
|
is known is the scope of the identifier. The exact scope of an
|
|
identifier depends on the way it was declared.
|
|
|
|
Block scope
|
|
~~~~~~~~~~~
|
|
The *scope* of a variable declared in the declaration part of a block
|
|
is valid from the point of declaration until the end of the block. If a
|
|
block contains a second block, in which the identifier is redeclared,
|
|
then inside this block, the second declaration will be valid. Upon
|
|
leaving the inner block, the first declaration is valid again. An
|
|
identifier cannot be redefined in the same block, except if valid for
|
|
procedure or iterator overloading purposes.
|
|
|
|
|
|
Tuple or object scope
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
The field identifiers inside a tuple or object definition are valid in the
|
|
following places:
|
|
|
|
* To the end of the tuple/object definition.
|
|
* Field designators of a variable of the given tuple/object type.
|
|
* In all descendant types of the object type.
|
|
|
|
Module scope
|
|
~~~~~~~~~~~~
|
|
All identifiers of a module are valid from the point of declaration until
|
|
the end of the module. Identifiers from indirectly dependent modules are *not*
|
|
available. The `system`:idx: module is automatically imported in every module.
|
|
|
|
If a module imports an identifier by two different modules, each occurrence of
|
|
the identifier has to be qualified, unless it is an overloaded procedure or
|
|
iterator in which case the overloading resolution takes place:
|
|
|
|
.. code-block:: nim
|
|
# Module A
|
|
var x*: string
|
|
|
|
.. code-block:: nim
|
|
# Module B
|
|
var x*: int
|
|
|
|
.. code-block:: nim
|
|
# Module C
|
|
import A, B
|
|
write(stdout, x) # error: x is ambiguous
|
|
write(stdout, A.x) # no error: qualifier used
|
|
|
|
var x = 4
|
|
write(stdout, x) # not ambiguous: uses the module C's x
|