7 Module system
Modules provide way of separate compilation along with
possibility of avoiding namespace conflicts. Current module system is
based on ideas from OCaml. However it is very limited, we only support
one level of modules, there are no functors and so on. Module Foo
consist of two files: foo.g (implementation) and foo.gi (interface).
Whatever names
are placed in foo.* files, they are all prefixed with `Foo::'. gontc
compiles foo.gi file to foo.gio, and foo.g to foo.o. foo.gio is needed
whenever you access Foo:: symbols from other modules.
Example:
list.gi:
// this is to output information,
// that we implement type `t', but not to
// disclosure what it is.
type <'a>t;
// return first element (head) of the list
'a hd(<'a>t x);
// return all but first element (tail) of the list
<'a>t tl(<'a>t x);
// some bogus, random variable -- you can export variables
// the same way as you would with functions
int cnt;
// create new empty list
<'a>t create();
// apply f to all elements of l, return list of results
<'b>t map(*('a) -> 'b f, <'a>t l);
// call f on all elements of the list
void iter(*('a) -> void f, <'a>t l);
list.g:
// this is local datatype.
opt_struct <'a>t {
'a data;
<'a>opt_struct next;
}
// this will be exported out (`public')
'a hd(<'a>t x) { return x.data; }
<'a>t tl(<'a>t x) { return x.next; }
// this is local, can't be called from outside the module
void helper(<'a>t x) { ... }
// and more publics
int cnt;
<'a>t create() { cnt++; return null; }
<'b>t map(*('a) -> 'b f, <'a>t l) { ... }
void iter(*('a) -> void f, <'a>t l) { ... }
// ...
Then if you want to use the module, it can be done with :: notation, like
this:
<int>List::t l = List::create();
...
int k = List::hd(l);
In case of some modules it might be useful to open them, i.e. import
all symbols from module intro current namespace, so you no longer have to
use :: notation (but you still can, it is often suggested for readability):
open List;
...
<int>List::t l = List::create();
...
int k = hd(l);
<int>List rest = tl(l);