Initial: 2003-07-28
Update: 2003-07-29

BGBSCM4 API


I will attempt to document the workings of the LANG/BGB interpreter sufficiently that one could try to use it in a project.
This will not be viewed as "complete", so looking at the source may be needed to gain a clearer understanding of the code.

scmcc.h
    Some Constants
    Conses/Lists
    Objects
    Numbers
    Strings
    Symbols
    Vectors
    Locatives
    Predicates for Types
TypeX
Print Interface
Misc
Comments


scmcc.h

The file scmcc.h contains the main definitions for the interpreter (others exist but are used for special purposes...).

There will be the type 'elem', which is to be used for references to types under the control of the interpreter.

Some Constants

Name
Meaning
MISC_FALSE
false value, #f
MISC_TRUE
true value, #t
MISC_NULL
null value, #z
MISC_EOL
end of list/empty list, ()
MISC_UNDEFINED
undefined value, used within interpreter to flag errors
MISC_EOF
end of file object, result of some operations on ports

Conses/Lists

These are macros related to the manipulation of conses and lists.
Name
Description
ELEM_FROMCONS(c)
Takes a pointer of type 'elem *' and gives a cons reference.
ELEM_FROMWEAKCONS(c)
Takes a pointer of type 'elem *' and gives a weak cons reference.
ELEM_TOCONS(c)
Takes a reference to a cons and gives a pointer of type 'elem *'.
CONS(a, b)
Takes the 2 references and generates a cons (a . b)
CAR(c)
Extracts the car of the cons reference c.
CDR(c)
Extracts the cdr of the cons reference c.
CAAR(c)
A compound: CAR(CAR(c))
CAAAR(c)
...
CAAAAR(c)

CADR(c)

CDDR(c)

CADDR(c)

CDDDR(c)

CADDDR(c)

CDDDDR(c)

...
Other compounds may be added later, these are the most common in my experience.

A list is a set of cons cells, with car pointing to the value and cdr to the next in the list.
Name
Description
LENGTH(c)
Get the length of the list referred to by c, EOL/terminals are not counted, the result is a c integer.
LIST_REF(a, b)
Refer to element b in list a, b is a c integer.

Objects

Objects are types which:
Require storage in memory;
Are not cons cells.

Name
Description
ELEM_FROMOBJECT(c)
Takes a pointer of type 'elem *' and gives an object reference.
ELEM_FROMWEAKOBJECT(c)
Takes a pointer of type 'elem *' and gives a weak object reference.
ELEM_TOOBJECT(c)
Takes a reference to an object and gives a pointer of type 'elem *'.

Numbers

Name
Description
ELEM_FROMFIXNUM(c)
Converts a c integer c into an fixnum.
ELEM_TOFIXNUM(c)
Converts a fixnum c into a c integer (may not do type checking, is only safe for fixnums).
FIXNUM(a)
Converts a c integer c into an fixnum (this is a shorthand for ELEM_FROMFIXNUM).
TOINT(a)
Converts a number into a c integer, handles types besides fixnum as well.
ELEM_FROMFLONUM(c)
Converts a c double into a flonum.
ELEM_TOFLONUM(c)
Converts a flonum into a c double.
FLONUM(a)
Converts a c double into a flonum (shorthand for ELEM_FROMFLONUM).
TOFLOAT(a)
Converts a number into a c double (safe for fixnum or other numbers).

Though not treated like numbers, these are represented in c as integer values.
ELEM_FROMCHAR(c)
Takes a c integer and generates a character value.
ELEM_TOCHAR(c)
Takes a character value and generates a c integer.
ELEM_FROMSPECIAL(c)
Takes a c integer and generates a special value (the meaning of 'specials' is context dependent).
ELEM_TOSPECIAL(c)
Takes a special value and generates a c integer.
ELEM_FROMBOOL(c)
Takes a c integer, generating MISC_FALSE if 0, MISC_TRUE otherwise
ELEM_TOBOOL(c)
Converts MISC_FALSE to 0, all other values to non-zero values.


Strings

Name
Description
ELEM_FROMSTRING(a)
Takes a c string and converts it to a string-object.
ELEM_TOSTRING(c)
Takes a string object and converts to a c-string (the returned string is not in a stable location).
ELEM_TOSTRING16(c)
Takes a string object and converts to a short string (0 terminated string of shorts).
STRING(a)
Shorthand for ELEM_FROMSTRING.
STRING16(a)
Takes a short string and generates a string-object.

Symbols

Name
Description
ELEM_TOSYMBOL(c)
Takes a symbol object and returns a c-string (volatile).
SYM(a)
Takes a c-string and returns a symbol-object.
SYMG(a, b)
Cache the symbol-object of 'b' in the variable referenced by a 'a'. 'a' is to initially contain MISC_NULL.

Vectors

Name
Description
VECTOR_REF(a, b)
Refer to the slot 'b '(c-int) within vector 'a'.
VECTOR_SET(a, b, c)
Assign the slot 'b' in vector 'a' to value 'c' (reference).
VECTOR_REFF(a, b)
Refer to the slot 'b '(c-int) within vector 'a', in this case the return value is a double containing the numeric value within the slot.
VECTOR_NEW(a)
Creates a new vector with 'a' (c-int) slots.
VECTOR_LEN(a)
Returns the lenght of the vector 'a' in the form of a c-int.
VECTOR_NEWT(a, b)
Creates a new vector with 'a' (c-int) slots and being of type 'b'.

Basic vector types:
Name
Description
VECTOR_VARIABLE
Undefined contents.
VECTOR_ELEMENT
Array of references.
VECTOR_F32
Array of 32 bit floats.
VECTOR_F64
Array of 64 bit doubles.
VECTOR_U8
Array of unsigned bytes.
VECTOR_U16
Array of unsigned shorts.
VECTOR_U32
Array of unsigned longs.
VECTOR_U64
Array of unsigned long longs.
VECTOR_S8
Array of signed bytes.
VECTOR_S16
Array of signed shorts.
VECTOR_S32
Array of signed longs.
VECTOR_S64
Array of signed long longs.

Locatives (any more not really used)

Name
Description
ELEM_LOCATIVEP(c)
Nonzero if value is a locative.
ELEM_FROMLOCATIVE(c)
Get a locative for the pointer c.
ELEM_TOLOCATIVE(c)
Get the pointer associated with the locative c.
ELEM_SETLOCATIVE(a, b)
Set the pointer associated with the locative a to b.

Predicates for Types

Name
Description
ELEM_FIXNUMP(c)
Non-zero if value is a fixnum.
ELEM_STRONGCONSP(c)
Non-zero if value is a strong cons reference.
ELEM_WEAKCONSP(c)
Non-zero if value is a weak cons reference.
ELEM_CONSP(c)
Non-zero if value is a cons reference.
ELEM_STRONGOBJECTP(c)
Non-zero if value is a strong object reference.
ELEM_WEAKOBJECTP(c)
Non-zero if value is a weak object reference.
ELEM_OBJECTP(c)
Non-zero if value is an object reference (all types which do not fit within an elem and are not conses).
ELEM_LONGREFP(c)
Non-zero if value is a "long reference" (used within store to flag special references).
ELEM_VECTORP(c)
Non-zero if value is a vector (basic vector type, non-disjoint, ie: for closures, objects, ...).
ELEM_BYTEVECTORP(c)
Non-zero if value is a bytevector.
ELEM_NVECTORP(c)
Non-zero if value is a normal vector (contains references or numeric values).
ELEM_FUNCTIONP(c)
Non-zero if value is a builtin function.
ELEM_BOXP(c)
Non-zero if value is a box.
ELEM_STRINGP(c)
Non-zero if value is a string.
ELEM_SYMBOLP(c)
Non-zero if value is a symbol.
ELEM_SYMKEYWORDP(c)
Non-zero if value is a keyword.
ELEM_SYMHYGENICP(c)
Non-zero if value is a "hygenic" symbol.
ELEM_SYMNORMALP(c)
Non-zero if value is a normal symbol (not keyword or hygenic).
ELEM_WIDENUMP(c)
Non-zero if value is a widenum (includes flonums, bignums, ...).
ELEM_TYPEXP(c)
Non-zero if value is a type-extended object.
ELEM_CLOSUREP(c)
Non-zero if value is a closure.
ELEM_ENVP(c)
Non-zero if value is an environment.
ELEM_ENVOBJP(c)
Non-zero if value is an object (ie: within the object system).
ELEM_CONTEXTP(c)
Non-zero if value is a context/thread.
ELEM_MINIFRAGP(c)
Non-zero if value is a minicode fragment.
ELEM_FLONUMP(c)
Non-zero if value is a flonum.
ELEM_BIGNUMP(c)
Non-zero if value is a bignum.
ELEM_CHARP(c)
Non-zero if value is a character.
ELEM_OPCODEP(c)
Non-zero if value is an interpreter opcode.
ELEM_SPECIALP(c)
Non-zero if value is a special.
ELEM_EOLP(c)
Non-zero if value is MISC_EOL (same as c==MISC_EOL).
ELEM_NULLP(c)
Non-zero if value is MISC_NULL (same as c==MISC_NULL).
ELEM_UNDEFP(c)
Non-zero if value is MISC_UNDEFINED (same as c==MISC_UNDEFINED).

Type Extensions (TypeX)

Type extensions have a type info structure:
typedef struct typexinfo_s {
struct typexinfo_s *next, *prev;
char *name;
elem (*apply)(elem obj, elem rest);            //vm
elem (*mark)(elem obj);                    //gc
elem (*swizin)(elem obj);                //store
elem (*swizout)(elem obj);                //store
elem (*print)(elem obj, typrint_info *inf);        //print
elem (*free)(elem obj);                    //gc
elem (*flatten)(elem obj);                //net, copy
elem (*unflatten)(elem def);                //net, copy
elem (*mirrors)(elem obj);                //net, mirroring
elem (*stub)(elem mirrors);                //net, mirroring
int (*notify)(elem obj, elem other, elem state);    //net, sync
int (*delta)(elem obj, elem var, elem val);        //net, sync
}typexinfo;

This may be extended later as needed.

Type Extensions allow types to be defined which are not normally part of the core interpreter and do not need special handling within the interpreter (likely most things added onto a system, eg: c-provided objects, user objects, ...).
These are not used where special handling is needed within the interpreter when the type is encountered (ie: such as something that would force evaluation when retrieved from a slot and substitute a value in place, unless such a feature were added to typex...).

Functions exist for the purpose of manipulating TypeX:
elem TyFcn_TypeX(elem sym, int sz, void *buf);
Creates a reference to a typex object of type sym, with sz bytes, and using the contents of buf if non-null.

void *TypeX_Alloc(char *type, int sz);
Creates a typex object with the given type and a defined size.
Returns a pointer to the body of the object.

elem TypeX_Sym(elem obj);
Extracts a symbol containing the type name of an object.

elem TypeX_Func(elem obj);
Extracts a builtin function representing the apply handler for the object.

void *TypeX_Data(elem obj);
Gets the body of a typex object.

int TypeX_TypeP(elem obj, char *type);
Returns a non-zero value if obj is of type 'type'.

These just forward to the handlers within the type info structure.
int TypeX_Mark(elem obj);
int TypeX_SwizIn(elem obj);
int TypeX_SwizOut(elem obj);
int TypeX_Print(elem obj, typrint_info *inf);
int TypeX_Free(elem obj);
elem TypeX_Flatten(elem obj);
elem TypeX_UnFlatten(elem type, elem def);
elem TypeX_Mirrors(elem obj);
elem TypeX_Stub(elem type, elem mirrors);
int TypeX_Notify(elem obj, elem other, elem state);

These functions will have default behaviors for the cases where the handlers are not defined.

typexinfo *TypeX_Lookup(char *name);
This looks up the type info structure for a given type name, returnning NULL if not found.

typexinfo *TypeX_GetInfo(char *name);
This looks up the type info structure for a given type name, creating a new one if needed.

Print Interface


TyPrint is an interface for printing values, it has flags and an info struct.

TYPRINT_DISPLAY        1 //more intended to look good than be parsed
TYPRINT_CODE        2 //parsable, but formatted as code
TYPRINT_FORMATTED    4 //strings list w possible format commands
TYPRINT_NOOBJ        8 //do not display object bodies

typedef struct typrint_info_s {
char *buf, *end;
int flags;
int ind;
}typrint_info;

elem TyPrint_PrintDefaults(elem obj);
Prints using the default flags (currently none), and sends the results to the sa_print interface.

elem TyPrint_PrintFlags(elem obj, elem flags);
Prints using the indicated flags (given as a fixnum), and sends the results to the sa_print interface.

elem TyPrint_PrintString(elem obj, elem flags);
Prints using the indicated flags (given as a fixnum), and returns the results in the form of a string object.

Misc

int Interp_Define(elem def, elem data);
Define the var 'def' to 'data' within the top level env.

int Interp_DefinePrimative(char *name, elem (*func)(), int pc);
Define the builtin 'name', using 'func', and accepting pc args (positive for a fixed number, negative (base+1) for variable).

pc:
3 would mean a 3 argument function;
-1 would mean a variable argument function (it is called with 1 arg representing the remainder of the application);
-3 would mean 2 base arguments, with a third arg containing the rest of the args.
the rest field for a variable argument function is sent in the form of a list.

int Interp_DefineSpecial(char *name, elem (*func)(), int pc);
Define the special 'name', using 'func', and accepting pc args.
A special is not a builtin, a special, when called, is expected to return compiled code fragments for use in the interpreter, and is expected to accept the same args as other compile functions (see the compiler code for examples).

elem Interp_Load(elem name);
Load a script indicated by 'name' and evaluate contents. The syntax is determined by the name extension.

Comments

See the 'main_*' files to see about integration with a project. A custom one may be written for compiling the interpreter into a project.
Anymore usage of the 'main_dll.c'+'main_dll_*.c' files is recommended.