summary refs log tree commit diff stats
path: root/doc/manual/modules.txt
blob: 813505769313c888b5cd396d849cabbf648d9188 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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