packages icon

 SPIN(3)                                                             SPIN(3)
                                1 March 1988

      spin - simple programmable interface library

      #include "spin.h"

      % ld <your program etc.> spin.a

      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

      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:  July 7, 2022

 SPIN(3)                                                             SPIN(3)
                                1 March 1988

      call either SPinitsubs or a subset of the functions SPinitsubs calls.

      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.

      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

      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-

      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,

                                    - 2 -           Formatted:  July 7, 2022

 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.

      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:  July 7, 2022

 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.

      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:  July 7, 2022