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: December 26, 2024 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: December 26, 2024 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: December 26, 2024 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: December 26, 2024