SH-ALPHABET(1) SH-ALPHABET(1)
NAME
alphabet, typeset, declare, import, type, define,
autodeclare, autoconvert, -, 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
- {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 pro-
vides 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 expres-
sion, represented 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 associ-
ated 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
Page 1 Plan 9 (printed 10/25/25)
SH-ALPHABET(1) SH-ALPHABET(1)
qualified 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 parent 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 qualified name, the module must exist in the specified
typeset and be compatible 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 qualified, the dec-
laration 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 argu-
ments, of type fd and string respectively, 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 auto-
matically be declared and used as appropriate (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
Page 2 Plan 9 (printed 10/25/25)
SH-ALPHABET(1) SH-ALPHABET(1)
(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 hierarchi-
cal 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 dsttype, 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->dsttype),
will be invoked to convert between the two. Several conver-
sions 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 mod-
ule, which must also have been imported if it is not a qual-
ified name. The arguments 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 evaluated
fully before command is invoked. The result of the outer-
most 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
Page 3 Plan 9 (printed 10/25/25)
SH-ALPHABET(1) SH-ALPHABET(1)
of the arguments 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 declara-
tion 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 unde-
clared.
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 incom-
patible with expression or if the final type cannot be con-
verted 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 unqualified 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. Additionally, info searches the module directo-
ries on all currently loaded typesets, and prints usage
information for everything it can find there, along with
information on all currently installed auto-conversions.
Finally, clear clears all existing declarations and defini-
tions, and starts again with a clean slate.
EXAMPLE
load alphabet
type /string
Page 4 Plan 9 (printed 10/25/25)
SH-ALPHABET(1) SH-ALPHABET(1)
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 diag-
nostic when this occurs.
SEE ALSO
sh(1), alphabet(2), alphabet-main(1), alphabet-fs(1),
alphabet-grid(1)
Page 5 Plan 9 (printed 10/25/25)