Modules in zeptoforth - tabemann/zeptoforth GitHub Wiki
Modules in zeptoforth provide a user-friendly means of managing namespace which is far less error-prone than managing namespace with set-order
and set-current
directly. Internally modules are wordlists referenced by constants, but here we will refer to them as modules rather than as wordlists.
Modules are defined using three words, begin-module
, continue-module
, and private-module
. begin-module
( "name" -- ) creates a new module bound to a specified constant with the following name defined within the current module's definition and begins its definition. If a word exists within the current namespace with the same name an exception is raised. continue-module
continues the definition of a preexisting named module. If no named module exists within the current namespace an exception is raised. private-module
( -- ) starts the definition of an anonymous module and does not bind it to a constant.
Module definitions are ended with one of two words, end-module
( -- ) and end-module>
( -- module ). The difference between these two words is that end-module>
pushes the module that was being defined onto the stack while end-module
does not. The common use case for this is to pass the module into import
to import it into the containing module.
Modules are imported into the current namespace with import
( module -- ) to enable the use of words defined within in the current namespace. They are automatically unimported at the end of the current module definition. They may also be manually unimported from the current namespace with unimport
( module -- ). Note that modules imported into a given module namespace may not shadow any words defined within the current module definition, even if those words were defined before the import.
Individual words from modules can be imported into the current namespace with import-from
( module "name" -- ), which takes the specified module and imports name (which can incorporate the token separator ::
like normal word references) into the namespace of the module currently being defined. These words persist until end-module
or end-module>
is reached. Note that these words are permanent in the case of the outer-most (i.e. default or forth
) module, as it will not be closed by any call to end-module
or end-module>
, so it is a good idea to use this between begin-module
and end-module
or end-module>
. Within the current module definition stack there is a limit of a total of 128 individually-imported words that may exist.
Namespaces inherit the definitions within their containing namespaces but do not modify them. Importing and unimporting modules within a module definition does not affect the namespace of any containing module definitions.
Names within modules may be looked up using the token separator ::
, which takes a token containing the name of a constant referring to a module before it and a name to look up within that module after it. This may be applied recursively, so one can refer to, say, foo::bar::baz
, which refers to a name baz
within module bar
within module foo
. Note that such names may be used with constructs such as '
, [']
, and postpone
.
For an example of modules in action, take the following:
begin-module test
uart import
private-module
: config-pins ( -- ) 1 4 uart-pin 1 5 uart-pin ;
: config-uart ( -- ) 921600 1 uart-baud! ;
: send-bytes ( -- )
[:
[char] Z 1+ [char] A [: 1 >uart 500 ms ;] qcount
;] qagain
;
end-module> import
: init-test ( -- )
config-uart
config-pins
0 ['] send-bytes 320 128 512 [ task ] :: spawn [ task ] :: run
;
end-module
Here we begin the definition of the test
module, with the word test
being defined within the default forth
module. Then we import the uart
module into the current namespace. Afterwards we create an anonymous module, define config-pins
, config-uart
, and send-bytes
within it, and then end its definition, importing it into the containing namespace. Once we have defined init-test
, which refers to words in the anonymous module and which refers to spawn
and run
within the task
module, we end the definition of the test
module.