SH-ALPHABET(1)SH-ALPHABET(1)NAME
alphabet, typeset, declare, import, type, define, autodeclare, autocon‐
vert, -, rewrite, modules, types, usage, info, clear - typed shell
interface
SYNOPSIS
load alphabet
type qname...
declare name [ usage ]
undeclare name...
define name expr
import qname...
typeset qname
autoconvert srctype dsttype expr
autodeclare 0|1
- {expression}
${rewrite {expression} [ dsttype ] }
${modules}
${types typeset }
${usage qname }
info
clear
DESCRIPTION
Alphabet is a loadable sh(1) module providing an interface to a simple,
experimental, typed shell. It initially provides a small set of basic
types, which can be added to by loading new typesets. Types are
atomic; alphabet provides no support for higher-order types. The root
typeset, named /, consists of the following kinds of value:
string A simple string literal, represented by itself, or quoted
according to the usual shell quoting rules.
cmd A shell command or uninterpreted alphabet expression, repre‐
sented by the syntax "{block}.
fd A file open for reading.
wfd A file open for reading and writing.
status The status of a completed command.
Each typeset implements a set of types, and has an associated set of
modules. Initially, types may only be referred to by their qualified
names, consisting of the name of the type prefixed with the name of its
typeset; for instance /string for the string type, or /grid/data for a
type named data in the typeset /grid. An unqualified name is the qual‐
ified name without the typeset prefix; for instance string or data.
To make a type available as its unqualified name, use the type command,
which imports the type named by the qualified name qname from its par‐
ent typeset. This is a no-op if the type has previously been imported
from the same typeset; an error is raised if the type has previously
been imported from a different typeset.
Declare declares the module name with type usage. If name is a quali‐
fied name, the module must exist in the specified typeset and be com‐
patible with the specified usage. If usage is not given, the module
itself will be loaded and queried to find it out. If name is not qual‐
ified, the declaration is virtual: the module cannot actually be used,
but is available for typechecking and expression rewriting. Declare is
a no-op if the module has already been declared with a compatible
usage, otherwise an error is raised. The syntax of usage is similar to
the usage messages printed by normal shell commands, and defines the
argument types expected by a module. For example:
declare /foo/bar '[-a] [-x string] fd string [string...] -> fd'
The above declares the module bar from typeset /foo, which takes two
possible options (one of which requires a single associated argument of
type string), two mandatory arguments, of type fd and string respec‐
tively, and any number of additional arguments of type string. The
module returns a value of type fd.
When first loaded, alphabet is lax about declaration requirements: if a
module is referred to by its qualified name, and is not currently
declared, the module will automatically be declared and used as appro‐
priate (as long as the module actually exists). Use autodeclare to
change this behaviour. Autodeclare 0 turns off all automatic declara‐
tion: all modules used in an expression must have previously been
declared; autodeclare 1 reverts to the original behaviour.
Once a module is declared, it may be referred to by its qualified name.
Import makes the module available under its unqualified name. It is an
error if a module of the same name has already been imported from a
different typeset. For instance:
declare /read 'string -> fd'
import /read
This would declare a module named read from the root typeset (checking
that it accepts a single string argument and returns a file), and make
it available under the name read.
Undeclare removes the previously declared name. Note that an imported
module has two names: its qualified name and its unqualified name.
Typeset loads the new typeset qname. Typesets are hierarchical in the
same way that types and modules are: a typeset adds some types to its
parent typeset, and has an associated set of modules that provide
transformations between those types and between those of its parent.
Autoconvert specifies an automatic conversion between srctype and dst‐
type, i.e. whereever a module expects an argument of type dsttype, and
the argument is actually of type srctype, the module block (see below
for definition) expr (which must be compatible with type srctype->dst‐
type), will be invoked to convert between the two. Several conversions
will be applied atop one another if necessary. It is an error if
adding the auto-conversion creates an ambiguous conversion path between
two types. As a convenience, expr may simply be the name of a module,
in which case the expression will be rewritten as its identity module
block: {(srctype); expr}.
The - command evaluates the alphabet expression, of the form:
{command arg...}
Usually, command is the name of a previously declared module, which
must also have been imported if it is not a qualified name. The argu‐
ments must conform to those expected by the module. Each argument is
either a literal string or shell-command, as described earlier, or a
subexpression of the same form as above. All subexpressions are evalu‐
ated fully before command is invoked. The result of the outermost
expression must be convertible to the type /status; the shell status of
the - command will reflect this when the command has completed.
As a convenience, alphabet provides a pipe-like syntax. It will rewrite
any expression of the form m1 m1args|m2 m2args as m2 {m1 m1args}m2args.
This occurs before any auto-conversions have been applied.
Command may also be a module block, of the form:
{(argtype...); command arg...}
The argtype values given in the brackets specify the types of the argu‐
ments expected by the module block; these can be referred to in the
arguments to command (and subexpressions thereof) with values of the
form $1, $2, etc. For instance,
{(/string); echo $1} hello}
is exactly equivalent to:
{echo hello}
In a module block with no arguments, the argument declaration section
may be omitted.
Define defines a new module in terms of previously declared modules.
Name (which must be an unqualified name) gives the name of the module
to define, and expr is a module block giving the expression to evaluate
when name is used. The usage of the module is taken from the types
declared in the module block; its return type is inferred from the
return type of expr. All modules used in the evaluation of expr are
evaluated when the definition takes place, so evaluation of name is
unaffected if any modules it uses are later undeclared.
To show the complete form of an expression, after pipe transformations
and auto-conversions have been applied, and module definitions
expanded, use ${rewrite}, which returns the expression's canonical form
without actually executing it. If dsttype is given, auto-conversions
will be applied to try to convert the result of expression to dsttype.
Rewrite raises an error if it finds any declarations incompatible with
expression or if the final type cannot be converted successfully.
Alphabet also provides some shell operations that give information on
its current state: ${modules} yields a list of all the currently
declared module names (including entries for both qualified and unqual‐
ified names); ${types} yields a list of all currently available types
(giving only the types in typeset if specified); and ${usage} provides
usage information on module qname, which need not be declared. Addi‐
tionally, info searches the module directories on all currently loaded
typesets, and prints usage information for everything it can find
there, along with information on all currently installed auto-conver‐
sions.
Finally, clear clears all existing declarations and definitions, and
starts again with a clean slate.
EXAMPLE
load alphabet
type /string
type /fd
type /status
import /cat /filter
autoconvert string fd /read
autoconvert fd status {(fd); /print $1 1}
define wc {(fd); /filter $1 "{wc}}
- {cat /lib/polyhedra /dis/sh.dis | wc}
echo ${rewrite {cat /lib/polyhedra /dis/sh.dis | wc} status}
SOURCE
/appl/alphabet/*.b
/appl/alphabet/*/*.b
BUGS
Alphabet expressions involving external typesets and file descriptors
cannot have their I/O redirected at the shell level. Unfortunately it
is not possible to provide a diagnostic when this occurs.
SEE ALSOsh(1), alphabet(2), alphabet-main(1), alphabet-fs(1), alphabet-grid(1)SH-ALPHABET(1)