mirror of
https://github.com/PDP-10/its.git
synced 2026-01-11 23:53:12 +00:00
249 lines
12 KiB
Plaintext
Executable File
249 lines
12 KiB
Plaintext
Executable File
|
||
DEFVST is an acronym for "DEFine a Vector-like STructure"
|
||
All entries in a Vector-like structure are "pointers" (FIXNUMs, LISTs, etc)
|
||
Future plans call for
|
||
DEFBST - "DEFine a Bitstring-like STructure", useful where
|
||
the structure is an interface to some memory
|
||
block required to be sequential by, say, operating
|
||
system conventions, or hardware needs.
|
||
DEFSTRUCT - "DEFine a general STRUCTure"
|
||
which will be done by composing DEFVST and DEFBST.
|
||
Vector-like structures are implemented as EXTENDs, which are emulated in
|
||
maclisp by HUNKs, and on the LISPMachine by 1-dimensional
|
||
ART-Q arrays; EXTENDs interface to a CLASS system, which in MacLISP
|
||
interface will be activated at any time when the CLASS system is loaded --
|
||
only a skeletal amount of information is necessary in each class
|
||
of vector-like structures in order to prepare for the link-up.
|
||
|
||
Free (global) variables controlling actions:
|
||
CONSTRUCTOR-NAMESTRING-PREFIX - constructor name is obtained by
|
||
concatenating this string with the
|
||
structure name.
|
||
SELECTOR-NAMESTRING-STYLE - () ==> selector macro name is same
|
||
as keyword (variable name).
|
||
- "xxx" ==> selector macro name gotten
|
||
by concatenating structure
|
||
name, "xxx", and keyword.
|
||
|
||
Basic macros: DEFVST for defining a structure
|
||
SETVST for updating a selected component
|
||
(and SETF)
|
||
Also, an interface from DEFSTRUCT has been defined (see its documentation).
|
||
|
||
Additional functions:
|
||
STRUCT-TYPEP for "structures", returns the given name,
|
||
and for non-structures, returns ().
|
||
|defvst-construction/||, |defvst-initialize/||, |defvst-typchk/||,
|
||
|defvst-construction-1/||, |defvst-selection/||, and |defvst-xref/||
|
||
are internal helper functions.
|
||
|
||
Usage is like:
|
||
(DEFVST SHIP
|
||
(X-POSITION /: FIXNUM)
|
||
Y-POSITION
|
||
(MASS = 1000.)
|
||
(COST (DAY-HIGH-PRICE))
|
||
COLOR )
|
||
(SETVST (SHIP-X-POSITION QE2) 109.)
|
||
or alternatively,
|
||
(SETF (SHIP-X-POSITION QE2) 109.)
|
||
since SETF will macroexpand out the component selector, and thus turn
|
||
into SETVST, on structures references. Also, a set of "options" may
|
||
be specified by including the structure name in a list:
|
||
(DEFVST (SHIP <option1> <option2> ...) ...)
|
||
currently, only :CONSTRUCTOR and :NO-SELECTOR-MACROS are valid options.
|
||
|
||
Note that "=" is used as a keyword in the component part to mean
|
||
an initialization form follows; and that a component specification
|
||
which is just a 2-list is expanded like
|
||
(<component-name> <form>) ==> (<component-name> = <form>)
|
||
This is done for compatibility of style with the LISPM defstructure.
|
||
See further notes below for the meaning of the ":" in the default form.
|
||
|
||
|
||
|
||
The SETVST macro (and SETF) is used in conjunction with DEFVST. The
|
||
example use of DEFVST "defines" a vector-like structure of 4 components;
|
||
the generic name of this structure is "SHIP", and the components are
|
||
identified by the ordering of what are called keywords - X-POSITION,
|
||
Y-POSITION, MASS, and COLOR. Each "definition" causes the creation of
|
||
1) A constructor macro, whose name (normally) is obtained by prefixing
|
||
the string "CONS-A-" onto the generic name of the structure.
|
||
(Actually, it gets this prefix string from the variable
|
||
CONSTRUCTOR-NAMESTRING-PREFIX, so that it can be modified)
|
||
In the example, this becomes CONS-A-SHIP. The constructor
|
||
permits installing values into the component slots at instantiation
|
||
time, which are evaluated from either the (default) forms supplied
|
||
by the invocation of DEFVST, or from the forms obtained by keyword
|
||
parameters in the instantiating form. E.g.
|
||
(CONS-A-BANK DOLLARS (PLUS 300. WALLET) MANAGER '|Jones, J.|)
|
||
would put the numerical value of 300.+WALLET in the DOLLARS
|
||
component of a newly-created bank, and install |Jones, J.| as
|
||
its MANAGER. When the CONSTRUCTOR option is given, the user
|
||
supplies a specific name for this macro.
|
||
2) N selector macros, one for each keyword (which denotes one
|
||
component slot), which are obtained (normally) by concatenating
|
||
the generic name, a "-", and the keyword name. (Actually,
|
||
the middle string is obtained from the value of the variable
|
||
SELECTOR-NAMESTRING-STYLE, so that it can be modified)
|
||
In the example, we have SHIP-X-POSITION, SHIP-Y-POSITION,
|
||
SHIP-MASS, and SHIP-COLOR.
|
||
2a: (SHIP-X-POSITION QE2)
|
||
to obtain the x-coordinate of QE2
|
||
2b: (SETVST (SHIP-X-POSITION QE2) 109.)
|
||
to change the x-coordinate to of QE2 to 109.
|
||
One interesting facet of the selector macroexpansions is that
|
||
when done for compilation, the turn into the MacLISP CXR,
|
||
which can generally be open-coded in one or two instructions.
|
||
But when expanded during interpretation, the go thru a
|
||
safety checking function, which assures that a selector
|
||
created for a SHIP structure is only applied to SHIP structures,
|
||
and not to other kinds of data, or other structures.
|
||
When the NO-SELECTOR-MACROS option is given, then these macros,
|
||
like SHIP-X-POSITION, are not created; this is intended to
|
||
delete the spurious creation of macros, when another macro
|
||
package is using DEFVST like a subroutine.
|
||
3) An information structure, stored as the STRUCT=INFO property
|
||
of the generic name symbol. This information has the shape
|
||
(DEFVST STRUCT=INFO
|
||
VERSION-NUMBER
|
||
GENERIC-NAME
|
||
CONSTRUCTOR-NAME
|
||
NUMBER-OF-NAMED-COMPONENTS
|
||
COMPONENT-DEFAULT-INITIALIZATION-LISTS
|
||
CLASS-SKELETON)
|
||
The generic name corresponds to the "name" of the structure
|
||
being defined; in the example, it is BANK. The version number
|
||
corresponds to a version of "implementation status" for DEFVST --
|
||
thus it should be possible to make rather radical changes in
|
||
the future implementation, while maintain compatibility with
|
||
previously compiled structures (that means that existing FASL
|
||
files won't have to be recompiled whenever some change to
|
||
DEFVST is made).
|
||
The zero'th element of the initializations is either (), or a
|
||
3-list of the key-name, selector-name, and default size for the
|
||
&REST component - the "block" of unnamed components in the
|
||
structure. The remaining elements of the initializations are
|
||
the "initialization lists" for each named component:
|
||
(<key-name> <corresponding-selector>)
|
||
;() initial value, no restrictions
|
||
(<key-name> <corresponding-selector> <ini-val-form>)
|
||
;no restrictions
|
||
(<key-name> <corresponding-selector>
|
||
<ini-val-form> . <list-of-types-for-restrictions>)
|
||
|
||
|
||
CONSTRAINTS, and INITIAL VALUES
|
||
Each of the components may be constrained to be a particular
|
||
type datum, and may be initialized according to the form supplied
|
||
as default by the call to DEFVST.
|
||
The syntax for a non-simple component specification is a list with
|
||
the first element being the key name, the item following the first
|
||
"=" in the list being a form which is the default form to be evaluated
|
||
for that component in any creations of instances of that structure,
|
||
and the element following the first ":" is either a type name or list
|
||
of type names that restricts any creating instance from supplying an
|
||
initial value of the wrong type. If a key has a restriction
|
||
associated with it, but no default initial-value form, then DEFVST
|
||
picks some default value consistent with the restriction.
|
||
|
||
Consider the example
|
||
|
||
(DEFVST BANK
|
||
(DOLLARS : (FIXNUM FLONUM MUMBLE))
|
||
MANAGER
|
||
(LIMIT : (FIXNUM FLONUM) = 1000000.0)
|
||
&REST
|
||
VAULTS
|
||
30.)
|
||
|
||
First, the macro invocation of DEFVST would expand into
|
||
|
||
(EVAL-WHEN (EVAL COMPILE LOAD)
|
||
(AND (STATUS FEATURE COMPLR) (SPECIAL BANK-CLASS))
|
||
(DEFPROP BANK BANK-CLASS CLASS-VAR)
|
||
(|defvst-initialize/||
|
||
'BANK ;structure name
|
||
'CONS-A-BANK ;constructor name
|
||
3 ;number of components in each structure
|
||
'#((VAULTS BANK-VAULTS 36) ;vector of slot information
|
||
(DOLLARS BANK-DOLLARS 0 FIXNUM FLONUM MUMBLE)
|
||
(MANAGER BANK-MANAGER)
|
||
(LIMIT BANK-LIMIT 1000000.0 FIXNUM FLONUM))
|
||
2 ;"generation" number of DEFVST
|
||
'((DSK JONL) TEST EXAMPL)) ;file being processed when DEFVST expanded
|
||
(DEFPROP BANK-VAULTS (BANK 4 &REST) SELECTOR)
|
||
'BANK)
|
||
|
||
The internal function |defvst-initialize/|| creates the STRUCT=INFO
|
||
property for BANK, and sets up macro definitions for all the selector
|
||
names, and for the constructor name; also, a "skeleton" is framed
|
||
so that all instances may be grouped into a CLASS of such structures.
|
||
(This information is kept in in the STRUCT=INFO property.) When the
|
||
CLASS system is actually loaded, the skeletons will be fleshed out
|
||
to the full degree [ see the documentation on the MacLISP SEND
|
||
facility, and on the EXTENDed CLASS system].
|
||
After that, then, a "simple" creation instance will take default values
|
||
for all components with either initial value or restriction
|
||
specifications, and null in the unspecified components; for example
|
||
(CONS-A-BANK)
|
||
then yields an instance, which when printed as a VECTOR, is like
|
||
#( 0 () 1.0E6 () . . . () )
|
||
namely, a bank with three named components, and with 30. unnamed
|
||
components which are accessed as if VAULTS were a vector name.
|
||
Note that the the function CLASS-OF (and also SI:EXTEND-CLASS-OF)
|
||
gets the class descriptor for this class of structures, which
|
||
may be only a "skeleton" when the CLASS system isn't loaded.
|
||
|
||
A more complex example of construction, such as,
|
||
|
||
(CONS-A-BANK DOLLARS (CASEQ VIP
|
||
(FEDERAL 15.0E9)
|
||
(SAVINGS-&-LOAN 10.0E6)
|
||
(MICKEY-MOUSE 1))
|
||
MANAGER '|Jones, J.|
|
||
LIMIT (BANK-DOLLARS CURRENT-CONSTRUCTION)
|
||
VAULTS 12.)
|
||
|
||
illustrates four points of a creating instance - -
|
||
(1) keywords paired with initial values are just alternating
|
||
pairs in the list, and
|
||
(2) the forms for initial values are substituted into a piece of
|
||
code output by the macro, so that they are evaluated at
|
||
instantiation time, and
|
||
(3) the variable CURRENT-CONSTRUCTION is temporarily bound to the
|
||
structure being created so that it may be referenced; the
|
||
installing of initial values happens last.
|
||
(4) components which are under a restriction, and are not constant
|
||
(at compile time) must be submitted to dynamic type checking.
|
||
Notice how this macro-expands --
|
||
|
||
(LET ((CURRENT-CONSTRUCTION (SI:MAKE-EXTEND 33. BANK-CLASS)))
|
||
(SETVST (BANK-DOLLARS CURRENT-CONSTRUCTION)
|
||
(|defvst-typchk/|| (CASEQ VIP
|
||
(FEDERAL 1.5E+10)
|
||
(SAVINGS-&-LOAN 10000000.0)
|
||
(MICKEY-MOUSE 1))
|
||
'(FIXNUM FLONUM MUMBLE)
|
||
'BANK-DOLLARS))
|
||
(SETVST (BANK-LIMIT CURRENT-CONSTRUCTION)
|
||
(|defvst-typchk/|| (BANK-DOLLARS CURRENT-CONSTRUCTION)
|
||
'(FIXNUM FLONUM)
|
||
'BANK-LIMIT))
|
||
CURRENT-CONSTRUCTION)
|
||
|
||
This code might actually not run, since it could stop on a Restriction
|
||
Violation if the variable VIP does not have a value among
|
||
FEDERAL, SAVINGS-&-LOAN, MICKEY-MOUSE
|
||
for then it would turn up a () for the DOLLARS component, which
|
||
was specified to be restricted to fixnums.
|
||
|
||
Further macro-expansion causes the "SETVST"s to become "SI:XSET"s.
|
||
In maclisp, SI:XREF becomes CXR, SI:XSET becomes RPLACX, and
|
||
SI:MAKE-EXTEND becomes MAKHUNK (that is how EXTEND's are emulated
|
||
there). Neither the EXTEND package nor any runtime CLASS facilities
|
||
need be loaded in the runtime environment of code which uses structures,
|
||
since dynamic tests are made before any of these facilites are are used
|
||
(that is, any facility beyond the MacLISP native HUNK capability).
|
||
|