-
Notifications
You must be signed in to change notification settings - Fork 4
Modules
Modules serve two purposes:
- Namespacing - allowing two functions with the same name to exist, each in a different module.
- Access control - definitions must be exported from a module, so that other modules can use them.
Modules are currently static and cannot be created at runtime nor at compile time. The current implementation also doesn't permit circular dependencies between modules (although this should be implemented in the future). Modules do not have absolute names (think Node.js instead of Java), their name is always resolved relative to a module which is importing them.
From the point of access control, modules form a tree hierarchy. For example, we could have the following 4 modules:
A
A/B
A/B/D
A/C
Using the Shem module
macro, we could define these modules like this:
A (module
...
B (module
...
D (module
...)
C (module
...))
In reality, the top module would be standalone and we would not define it using the module
macro. We can decide whether we want to define the "child" modules as standalone as well. When using Golem on the desktop or Shem's CLI, the representation of these standalone modules in file system would be:
A
index.shem
B
index.shem
D
index.shem
C.shem
Where index.shem
files store the definitions of the module named the same as the enclosing directory.
Note that the way module sources are stored is not of concern to the language itself, they can be stored in memory for example, as long as they can be provided given a relative path (relative to the initial module being compiled) or an absolute path. In the above example, if we are compiling the
A/B/D
module and the module requires theA
module, the compiler will ask for the../../A
module.
Definitions are imported from other modules using the req
(require) macro:
; in module C
[f] (req ../B/D)
; in module A
[g] (req ./C)
Absolute paths are used for requiring modules from other packages, providing namespacing of modules themselves. The first part of the module path is the alias given to the package. If package aliased X would have the same module structure as above, we could import from it using:
[f] (req X/B/D)
in any module of a package which has X as its dependency.