summary refs log tree commit diff stats
path: root/doc/manual/modules.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/manual/modules.txt')
-rw-r--r--doc/manual/modules.txt202
1 files changed, 202 insertions, 0 deletions
diff --git a/doc/manual/modules.txt b/doc/manual/modules.txt
new file mode 100644
index 000000000..fe3360773
--- /dev/null
+++ b/doc/manual/modules.txt
@@ -0,0 +1,202 @@
+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)
+
+
+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