<- ^ ->

Module system

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);
<- ^ ->

Module system