SPIN(3) SPIN(3)
1 March 1988
NAME
spin - simple programmable interface library
SYNOPSIS
#include "spin.h"
% ld <your program etc.> spin.a
DESCRIPTION
Spin is a simple interpreter intended for use as a program development
tool and modest programmable interface. It contains a parser and
execution engine, with the ability to easily extend the basic engine
with additional features such as control constructs or new operations.
The spin interpreter has been set up to be usable in a bare-bones
configuration, in which there are almost no capabilities or functions
available other than application-specific ones. There are also a set
of various simple extensions available which raise the application-
independent capabilities of spin up to a level where it is almost
usable by itself. The intent is for the application to add whatever
application-specific functions it needs and to select the level of
application-independent support needed. The spin library was designed
to be modular enough that the application program could pick and
choose among almost all of the aspects of the interpreter. If there
is a capability which is not needed, it does not need to be loaded.
If there is a capability which the programmer feels he can implement
better, it is typically a fairly simple job for him to rewrite that
capability without worrying about other parts of the system. In
addition to the generic extensions, an application program can add
whatever application-specific functions are desired. Each function
requires a one-line call to one of the spin primitives, to be executed
during program startup time. Once this has been done, the function is
available to the user of the application. There are a small number of
data types known to spin (e.g. int, float, string), which can be
specified as the argument and return types for functions. The spin
interpreter will do type checking on all arguments passed to
functions. To use spin, a program need only link with the spin
library and call the appropriate initialization routines during
startup.
BASIC FUNCTIONS
The minimal program requires a call to one of two functions:
SPmainfile or SPmainstring. These routines will parse and execute a
stream (FILE *) or string (respectively) until EOF or EOS. However,
if the main program never invokes any other spin primitive, there will
not be any legal functions available for the parsed code to call!
There are two ways to initialize functions: by calling the
initialization routines for one of the application-independent
packages, or by adding application-specific functions by calling
SPdeffunc. The complete set of application-independent packages can
be loaded by calling SPinitsubs. Typically an application will call
SPdeffunc a number of times (once for each of its functions), and will
- 1 - Formatted: October 27, 2025
SPIN(3) SPIN(3)
1 March 1988
call either SPinitsubs or a subset of the functions SPinitsubs calls.
DATA TYPES
The spin interpreter understands the following data types: nil,
integer, float, string, and list. Because there are no built-in
operations, there are also no built-in conversions (nor for that
matter any built-in explicit casting mechanism!). Note in particular
that there is no automatic conversion between int and float: if a
program is expecting an int, passing a float to it will cause an
error. The one exception to this is that all types have an
interpretation as a boolean, so that any variable can be directly used
as a boolean to a function which is expecting a boolean.
ARGUMENT AND RETURN TYPES AND DEFAULTS
In the SPdeffunc call, the second argument is a string which encodes
the types of the return value and arguments of a function. The first
character specifies the return type of the function, the remainder
specify the types of each consecutive argument. The list is
terminated by a null (EOS) or by a semicolon. (In the future, spin
will probably accept some descriptive text after a semicolon which
gives names for each of the arguments.) Typically, the type of an
argument is represented by a single character. In some cases, a
default can also be included, in which case it appears immediately
after the type character. The valid argument type code characters
are:
b - boolean
Any type can be passed to a function expecting a boolean; the
value will be cast to a boolean, and the function will receive an
integer zero or one.
i - integer
I - optional integer
The default value immediately follows the I, such as "I0" or "I-
99".
f - float
n - name
A name is a subset of string; it can not contain any characters
other than alphanumerics (with leading alpha) or underscore, and
it may be specified within quotes or with no quotes.
s - string
S - optional string
The default value immediately follows the S, in double quotes
(remember to escape the quotes with backslashes). For example,
"S
- 2 - Formatted: October 27, 2025
SPIN(3) SPIN(3)
1 March 1988
V - untyped variable
A single evaluated variable of any type (passed to the
application function as a spin token).
L - a list variable
A single unevaluated token. This if useful for building such
things as the "if" construct, in which only one of the clauses
should be executed.
R - remainder
The remainder of the arguments as a list, unevaluated. The valid
return type code characters are:
i - integer
v - void
This is used when the function returns no value. Any value
returned by the function is ignored.
f - float
n - name
s - static string
Spin will make an allocated copy of a static string, so functions
may return pointers to internal buffers which are overwritten on
the next call.
S - allocated string
This code is used when the function allocates the string using
malloc and returns it. Spin will not make a copy of the string,
but will assume that it owns it from then on.
V - allocated variable
The function allocates a spin token and returns it as the value
of the function. Spin will assume that it owns the token from
then on. A function can use this type to return a value of
arbitrary type.
l - static list of variables
Spin will make a copy of the list, as with the "s" type.
L - allocated list of variables
Spin assumes the entire list belongs to it from then on, as with
the "S" type.
ERRORS AND GOTO
The spin routines handle exceptions by executing a "goto" to a label
which is different depending on what the exception is. If this label
is defined, execution continues at that point; if not, execution
terminates, and the label is printed along with an error message.
- 3 - Formatted: October 27, 2025
SPIN(3) SPIN(3)
1 March 1988
Note that this mechanism involves the function execution extension to
the core, so any programmer implementing his own function execution
should be sure to include this aspect.
BUGS
The documentation is too skimpy. The data types are not one of the
easily-changed aspects of spin; they are pretty firmly wired into the
core interpreter. The argument and return type codes are not
particularly consistent or complete. The implementations of variables
and functions should be considered only as an example of how this kind
of extension could be added to the basic interpreter. These
implementations are decidedly inferior in both performance and
functionality, but they do show how such a thing could be done. There
are lots of memory leaks; garbage collection is probably the way to
go. The parser is line-oriented, so has problems with things like
multi-line comments. This definitely needs to be improved. The
syntax should be that of some previously defined language. This whole
package could be replaced by a simple Lisp package that could be
linked with an application, but I don't have one handy.
- 4 - Formatted: October 27, 2025