ALPHABET-INTRO(2)ALPHABET-INTRO(2)NAME
Alphabet - experimental typed shell
DESCRIPTION
Values, type characters and signatures
Each Alphabet typeset defines one Limbo data type, conventionally named
Value. It is usually a discriminated union (pick), with each arm of
the pick representing one of the types in the typeset. Each one of
these types is given a character. These characters are used to describe
all value- and module-types within alphabet. The set of typeset char‐
acters implemented by a typeset is known as its alphabet.
For example, in the alphabet root typeset (see alphabet-main(2)), a
string is represented by the letter ``s'', held at the Limbo level as a
ref Value.S.
Each alphabet module has a type signature which describes its return
type and the number and type of any flags or arguments that it allows.
Inside an alphabet typeset, this signature is represented as a simple
string where the first character (always present) indicates the return
type of the module. Subsequent characters up until the first minus
(``-'') sign (or the end of the string) indicate the module's required
argument types. If the last character is an asterisk (*), it allows an
unlimited repetition of the preceding argument type.
These may be followed by any number of options, each indicated with a
minus character, followed by the option character and then the type
characters of any arguments it requires.
For instance, the following Alphabet declaration:
/mount [-abc] [-x /string] /wfd /string -> /status
can be represented by the signature ``rws-a-b-xs-c''.
Typesets and proxies
The root typeset (see alphabet-main(2)) is implemented internally to
the alphabet module. All other types are defined by external typesets.
An external alphabet typeset is conventionally represented by two
header files defining the interface to the typeset, and two modules
giving its implementation. Suppose we are to create a new typeset, say
/foo . We would create the following files:
/module/alphabet/foo.m
Foo.m declares the interface used by all modules within the
typeset. The existing typeset interface files (for instance
alphabet/grid.m, documented in alphabet-grid(2)) provide
examples of this kind of interface.
/appl/alphabet/footypes.b
This module translates between internal values (each held as
a Value as declared in foo.m) and external values (each held
as a Value as declared in the parent typeset, in this case by
the alphabet module itself). Since Limbo does not provide a
way of holding an arbitrary type directly, internal values
are instead stored in a table by a local proxy (see below),
and referred to externally by their index there.
/appl/alphabet/foo.b
Foo.b provides the basic type-manipulation primitives needed
by the typeset, for instance the translation from type char‐
acter to type name. It is also a convenient place to imple‐
ment helper functions to make using the typeset easier. For
instance, it is conventional for a typeset's Value adt to
contain one eponymously named member function for each type
character, making sure that the Value is actually of that
type and returning the widened type, or raising an exception
otherwise. For instance, in the root typeset, v.s() returns
the type ref Value.S, or raises an error if v is not of that
type.
/module/alphabet/footypes.m
Footypes.m provides an interface to the typeset proxy module,
footypes.b, that allows direct access to values in the foo
typeset, while still allowing manipulation of those values by
an alphabet instance.
The proxy module, footypes.b, must define at least one function, proxy,
which returns a channel through which all operations on the typeset
take place. The Proxy module (see alphabet-proxy(2)) provides a
generic implementation of such a translator; if footypes.b uses this,
it needs only define the mapping between values in its parent typeset
and its own values.
alphabet-main(2)types() Types is always the first function in a module to be called.
It should do nothing but return the type signature string of
the module.
init() Init is called to allow the module to initialise its global
state. It is called once only. It is permissible for this
function to raise a ``fail:'' exception on failure. The text
following the ``fail:'' prefix should describe the reason
why.
run(errorc, r, opts, args)
Run runs an actual instance of the module. It must be re-
entrant. The signature of the run function varies from type‐
set to typeset, but usually includes the above arguments.
Args holds a list of the arguments passed to the module; opts
holds all the flags that have been specified. Each flag is
represented with a tuple, say: (c, optargs), where c gives
the option character, and optargs is a list holding any argu‐
ments the flag requires. The arguments and options passed to
the module are guaranteed to conform with the type signature
returned from types. Note that each flag may be passed mul‐
tiple times to the module.
If the run succeeds, it should return the resulting value. If
the module returns a value that was passed in, and it con‐
tains a reference-count, the count should be incremented
before returning, If the module succeeds, it is responsible
for the disposal of any arguments and option arguments that
it has been given. Appropriate disposal depends on the type
of the argument, but v.free(0) is always sufficient to dis‐
pose of value v.
If the run fails, it should return nil; its arguments will
automatically be freed in this case.
While processing the run request, the module should send
error and debugging diagnostics to the errorc channel (it
should take care never to send an empty string). If it
spawns any new processes, it can use the Report, r, (see
alphabet-reports(2)) to create new diagnostic channels for
these processes. When such an diagnostic channel is no
longer in use, the module should send an empty string on it.
It should take care that Report.start is called before run
returns.
ALPHABET-INTRO(2)