Annotation of 42BSD/ucb/lisp/pearl/create.l, revision 1.1.1.1

1.1       root        1: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; create.l ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                      2: ; Functions for creating, copying, and merging structures.
                      3: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                      4: ; Copyright (c) 1983 ,  The Regents of the University of California.
                      5: ; All rights reserved.  
                      6: ; Authors: Joseph Faletti and Michael Deering.
                      7: 
                      8: ; Create a new structure of one of the five types:
                      9: ;     BASE:        build a new structure with all new slots.
                     10: ;     EXPANDED:    build new slots in addition to slots inherited from
                     11: ;                     a BASE or EXPANDED structure.
                     12: ;     INDIVIDUAL:  create an instance of a BASE or EXPANDED structure,
                     13: ;                     filling in slots or inheriting defaults from above.
                     14: ;     PATTERN:     create an instance of a BASE or EXPANDED structure but
                     15: ;                     fill in unspecified slots with ?*ANY*.
                     16: ;     FUNCTION:    build a new structure with slots describing the
                     17: ;                     arguments to the function.
                     18:  
                     19: ; Generalized syntax for this function is:
                     20: ;
                     21: ; (CREATE <StructureType> <ExpandedorBaseName> <NewItemName>
                     22: ;         [{HashingInfo} <OldSlotName> {{{:=} <SlotValue>} | ^}
                     23: ;                        { : <Variable> }
                     24: ;                        {<ListOfRestrictionStructureOrSlotIfNames>} ]
                     25: ;    . . . . . . .
                     26: ;         [{HashingInfo} <NewSlotName> <Type> {{{:=} <SlotValue>} | ^}
                     27: ;                        { : <Variable> }
                     28: ;                        {<ListOfRestrictionStructureOrSlotIfNames>} ] )
                     29:  
                     30: ; BASE structures have no <ExpandedorBaseName> and only new slots.
                     31: ; EXPANDED structures should have at least one new slot and inherit
                     32: ;       default values from the <ExpandedorBaseName>.
                     33: ; INDIVIDUAL structures have only old slots and inherit default values from
                     34: ;       the <ExpandedorBaseName>;  if the <NewItemName> occurs, the atom
                     35: ;       <NewItemName> is set to point to the internal form which is also
                     36: ;       returned as the value of CREATE.
                     37: ; PATTERN structures have only old slots and all unspecified slots are
                     38: ;       set to ?*ANY* rather than inheriting a default.
                     39: ; FUNCTION structures have no <ExpandedOrBaseName> and only new slots.
                     40: ;       They are interpreted as functions to be run rather than structures
                     41: ;       to be accessed when they are MATCHed, FETCHed or PATHed.
                     42: ;
                     43: ; The structure created is always stored in the SPECIAL variable *LASTCREATED*
                     44: ;       in addition to the <NewItemName> if specified and the atom formed
                     45: ;       by prepending a 'd:' to the front of the <ExpandedOrBaseName>.
                     46: ;
                     47: ; If the SlotValue for a slot in a BASE or EXPANDED structure is preceded
                     48: ;       by a :=, then the slot is filled with this value but it is not
                     49: ;       used as the default for this slot in future INDIVIDUALS and
                     50: ;       EXPANDEDS.
                     51: ; If the SlotValue is not preceded by a :=, then the value represents a
                     52: ;       default to be inherited by INDIVIDUALs and new EXPANDEDS.
                     53:  
                     54: ; This just sets the two atoms *toplevelp* and *currentcreatetype*
                     55: ;   and calls the real workhorse "insidecreate".
                     56: (df create (l)
                     57:   (setq *toplevelp* t)
                     58:   (setq *currentcreatetype* (car l))
                     59:   (apply (function insidecreate) l))
                     60:  
                     61: ; Pick apart the atoms before the slots, handle them and pass the
                     62: ;    rest on to the appropriate version of create XXX.
                     63: (df insidecreate (l)
                     64:   (let ((type (car l))
                     65:        (abbrev (cond (*toplevelp* '*buildabbrev*)
                     66:                      ( t nil)))
                     67:        (name1 (cadr l))
                     68:        (name2 (caddr l))
                     69:        (name3 (cadddr l))
                     70:        slots)
                     71:        (cond ((reallitatom name2)
                     72:              (setq abbrev name2)
                     73:              (setq slots (cdddr l))
                     74:              (cond ((reallitatom name3)
                     75:                     (setq abbrev name3)
                     76:                     (setq slots (cddddr l)))
                     77:                    ( t  (setq name3 name2))))
                     78:             ( t (setq name3 (setq name2 name1))
                     79:                 (setq slots (cddr l))))
                     80:        (and (memq type '(ind individual pat pattern))
                     81:            (eq name1 name3)
                     82:            (setq name3 '*lastcreated*))
                     83:        (set name3
                     84:            (setq *lastcreated*
                     85:                  (selectq type
                     86:                           ((individual ind)
                     87:                            (createindividual name1 abbrev slots))
                     88:                           (base
                     89:                            (createbase name1 abbrev slots))
                     90:                           ((expanded exp)
                     91:                            (createexpanded name1 name2 abbrev slots))
                     92:                           ((pattern pat)
                     93:                            (createpattern name1 abbrev slots))
                     94:                           ((function fn)
                     95:                            (createfunction name1 abbrev slots))
                     96:                           (otherwise (msg t "CREATE: Illegal selector: " type
                     97:                                           " in created structure: " l t)
                     98:                                      (pearlbreak)))))))
                     99:  
                    100: ; Create a new structure and insert it in the database.
                    101: (defmacro dbcreate (&rest rest)
                    102:   `(insertdb (create .,rest)))
                    103: 
                    104: (defmacro cb (&rest rest)
                    105:   `(create base .,rest))
                    106: 
                    107: (defmacro ci (&rest rest)
                    108:   `(create individual .,rest))
                    109: 
                    110: (defmacro ce (&rest rest)
                    111:   `(create expanded .,rest))
                    112: 
                    113: (defmacro cp (&rest rest)
                    114:   `(create pattern .,rest))
                    115: 
                    116: (defmacro cf (&rest rest)
                    117:   `(create function .,rest))
                    118:  
                    119: (defmacro base (&rest rest)
                    120:   `(create base .,rest))
                    121: 
                    122: (defmacro ind (&rest rest)
                    123:   `(create individual .,rest))
                    124: 
                    125: (defmacro individual (&rest rest)
                    126:   `(create individual .,rest))
                    127: 
                    128: (defmacro pexp (&rest rest)
                    129:   `(create expanded .,rest))
                    130: 
                    131: (defmacro expanded (&rest rest)
                    132:   `(create expanded .,rest))
                    133: 
                    134: (defmacro pat (&rest rest)
                    135:   `(create pattern .,rest))
                    136: 
                    137: (defmacro pattern (&rest rest)
                    138:   `(create pattern .,rest))
                    139: 
                    140: (defmacro fn (&rest rest)
                    141:   `(create function .,rest))
                    142:  
                    143: (defmacro pfunction (&rest rest)
                    144:   `(create function .,rest))
                    145:  
                    146: ;  Put a *VAR* variable in the structure's assoc-list and return the cons-cell.
                    147: (defmacro installvar (varname)
                    148:   `(cond ((eq '*any* ,varname) *any*conscell*)
                    149:         ; else, if there, return it.
                    150:         ((assq ,varname (getalist *currenttopcreated*)))
                    151:         ; else, add it (which also returns the special conscell).
                    152:         (  t   (addalist ,varname *currenttopcreated*))))
                    153:  
                    154: ; Install an adjunct variable in the slot.
                    155: (defmacro installadjunct (adjunctvar)
                    156:   `(let (var)
                    157:        (cond ((dtpr ,adjunctvar)
                    158:               (setq var (cadr ,adjunctvar))
                    159:               (selectq (car ,adjunctvar)
                    160:                        (*var* (installvar var))
                    161:                        (*global* var)
                    162:                        (otherwise
                    163:                         (msg t "CREATE: no adjunct variable given after colon "
                    164:                              "-- rest of slot is: " ,adjunctvar slot t)
                    165:                         (pearlbreak))))
                    166:              (  t  (msg t "CREATE: no adjunct variable given after colon. "
                    167:                         "Rest of slot is: " ,adjunctvar slot t)
                    168:                    (pearlbreak)))))
                    169: 
                    170: (dm handlepossibleadjunctvar (none) ; but assumes SLOT, SLOTVALUE, & VALUETYPE.
                    171:   '(let ((adjunctvar (car slot)))
                    172:        (and (eq adjunctvar ':)
                    173:             (cond ((neq valuetype 'CONSTANT)
                    174:                    (msg t "CREATE: Adjunct variables not allowed in "
                    175:                         "slots whose values are also variables." t)
                    176:                    (pearlbreak))
                    177:                   ( t (setq slot (cdr slot)) ; throw away ":".
                    178:                       (setq adjunctvar (pop slot))
                    179:                       (setq valuetype 'ADJUNCT)
                    180:                       (setq slotvalue (cons slotvalue
                    181:                                             (installadjunct adjunctvar))))))))
                    182: 
                    183: ; Ensure that value is of type TYPENUM (used after ! or on value in atom
                    184: ;    where setof value expected).  Value returned (t / never) is used
                    185: ;    only in evaluating atom.  If error, doesn't return.
                    186: (de enforcetype (value typenum)
                    187:   (or (selectq typenum
                    188:               (0 (structurep value))
                    189:               (1 (psymbolp value))
                    190:               (2 (numberp value))
                    191:               (3 (not (reallitatom value)))
                    192:               (otherwise
                    193:                (apply (function and)
                    194:                       (mapcar (funl (singlevalue)
                    195:                                     (enforcetype singlevalue
                    196:                                                  (- typenum 4)))
                    197:                               value))))
                    198:       (progn (msg t "CREATE: Value after ! or bound to atom in SETOF "
                    199:                  "slot is of wrong type.  Value is: " value t)
                    200:             (pearlbreak))))
                    201: 
                    202: ; Get the value for a slot.
                    203: ; If preceded by an ! then it is already in internal form but verify this.
                    204: ; If is preceded by a $ then it should be evaluated before continuing
                    205: ;    processing (on its value).
                    206: (dm constructvalue (none)
                    207:   '(let ((typenum (getslottype slotnum defblock))
                    208:         (ppset   (getppset    slotnum defblock)))
                    209:        (selectq (car slot)
                    210:                 (\!  (setq slot (cdr slot))
                    211:                      (setq newvalue (eval (pop slot)))
                    212:                      (enforcetype newvalue typenum)
                    213:                      (setq valuetype 'CONSTANT)
                    214:                      (setq slotvalue newvalue))
                    215:                 (\$  (setq slot (cdr slot))
                    216:                      (setq newvalue (eval (pop slot)))
                    217:                      (setq valuetype 'CONSTANT)
                    218:                      (setq slotvalue (buildvalue newvalue typenum ppset)))
                    219:                 (otherwise
                    220:                  (cond ((and (dtpr (car slot))
                    221:                              (eq (caar slot) '*var*))
                    222:                         (setq valuetype 'LOCAL)
                    223:                         (setq newvalue (cadr (pop slot)))
                    224:                         (setq slotvalue (installvar newvalue)))
                    225:                        ((and (dtpr (car slot))
                    226:                              (eq (caar slot) '*global*))
                    227:                         (setq valuetype 'GLOBAL)
                    228:                         (setq slotvalue (cadr (pop slot))))
                    229:                        (  t  (setq valuetype 'CONSTANT)
                    230:                              (setq slotvalue
                    231:                                    (buildvalue (pop slot) typenum ppset))))))))
                    232:  
                    233: ; Generate the default value for slots of the given type.
                    234: (defmacro defaultfortype (typenum)
                    235:   `(selectq ,typenum
                    236:            (0 (eval (instatom 'nilstruct)))
                    237:            (1 (eval (symatom 'nilsym)))
                    238:            (2 0)
                    239:            (3 nil)))
                    240:  
                    241: ; Look at the ISA to find the default value, or the else use
                    242: ;    the default default for that type.
                    243: (defmacro inheritvalue (structdef)
                    244:   `(let ((isa ,structdef))
                    245:        (cond ((or (null isa)
                    246:                   (not (getenforce slotnum isa)))
                    247:               (setq slotvalue (defaultfortype (getslottype slotnum defblock)))
                    248:               (setq valuetype 'CONSTANT))
                    249:              ( t (let ((default (getdefaultinst isa)))
                    250:                       (setq slotvalue (getslotvalue slotnum default))
                    251:                       (setq valuetype (getslotvaluetype slotnum default)))))))
                    252:  
                    253: ; Look for predicates and hooks.  Use tconc to keep in order.
                    254: (dm handlepredicatesandhooks (none)
                    255:   '(progn
                    256:     (setq predlist (ncons nil))
                    257:     (setq slothooklist (ncons nil))
                    258:     (while (setq fcn (pop slot))
                    259:           (cond ((atom fcn)
                    260:                  (cond ((eq fcn 'instead)
                    261:                         ; Don't inherit hooks.
                    262:                         (putpred slotnum nil valblock))
                    263:                        ((memq fcn '(if hook))
                    264:                         ; A hook follows.
                    265:                         (tconc slothooklist (cons (pop slot) (pop slot))))
                    266:                        ; Structure predicate.
                    267:                        ((structurenamep fcn)
                    268:                         (tconc predlist (eval (defatom fcn))))
                    269:                        ; Otherwise, a predicate name.
                    270:                        ( t (tconc predlist fcn))))
                    271:                 ; Otherwise an s-expression predicate.
                    272:                 ( t (tconc predlist fcn))))
                    273:     (putpred      slotnum
                    274:                  (nconc (car predlist) (getpred slotnum valblock))
                    275:                  valblock)
                    276:     (putslothooks slotnum
                    277:                  (nconc (car slothooklist) (getslothooks slotnum valblock))
                    278:                  valblock)))
                    279: 
                    280: ; Build a new slot in the current structure.
                    281: (dm buildslot (none)
                    282:   '(progn
                    283:     (setq slotname (pop slot))
                    284:     (clearhashandformat slotnum defblock)
                    285:     ; To gather hashing and enforce information before installing in defblock.
                    286:     (setq hashcollect 0)
                    287:     (setq reqstruct nil)
                    288: 
                    289:     ; Check for hashing marks first.
                    290:     (while (selectq slotname
                    291:                    ; First starred slot used for > hashing if no & present.
                    292:                    (*   (and (\=& 0 first*edslot)
                    293:                              (setq first*edslot (minus slotnum)))
                    294:                         (addhash*   hashcollect))
                    295:                    (**  (addhash**  hashcollect))
                    296:                    (*** (addhash*** hashcollect))
                    297:                    (&   (cond ((not (\=& 0 hashalias))
                    298:                                (msg t "CREATE: Only 1 hash alias (&) or "
                    299:                                     "selected slot (^) allowed in: "
                    300:                                     newname t)
                    301:                                t)
                    302:                               ( t (setq hashalias slotnum))))
                    303:                    (^   (cond ((not (\=& 0 hashalias))
                    304:                                (msg t "CREATE: Only 1 hash alias (&) or "
                    305:                                     "selected slot (^) allowed in: "
                    306:                                     newname t)
                    307:                                t)
                    308:                               ( t (setq hashalias (minus slotnum)))))
                    309:                    (&&  (cond ((not (\=& 0 hashfocus))
                    310:                                (msg t "CREATE: Only 1 hash focus (&&) "
                    311:                                     "allowed in: " newname t)
                    312:                                t)
                    313:                               ( t (setq reqstruct t)
                    314:                                   (setq hashfocus slotnum))))
                    315:                    (:   (addhash:   hashcollect))
                    316:                    (::  (addhash::  hashcollect))
                    317:                    (>   (addhash>   hashcollect))
                    318:                    (<   (addhash<   hashcollect)))
                    319:           (setq slotname (pop slot)))
                    320:     (and (\=& 0 (length slot))
                    321:         (progn (msg t "CREATE: Missing slot name and/or type in slot number "
                    322:                     slotnum " of structure: " newname t)
                    323:                (pearlbreak)))
                    324: 
                    325:     ;  Slotname now holds the slotname.  Should be checked for duplicates!!
                    326:     (putslotname slotnum (ncons slotname) defblock)
                    327: 
                    328:     ; Now look for the type.
                    329:     (setq typenum 0)
                    330:     (setq slottype (pop slot))
                    331:     (while (selectq slottype
                    332:                    (struct (setq reqstruct nil)
                    333:                            nil)     ; i. e., add 0 to TYPENUM.
                    334:                    (symbol (setq typenum (1+ typenum))  nil)
                    335:                    (int    (setq typenum (+ 2 typenum))  nil)
                    336:                    (lisp   (cond ((not (\=& 0 typenum))
                    337:                                   (msg t "CREATE: <setof lisp> not allowed. "
                    338:                                        "Type changed to <lisp> in slot "
                    339:                                        slotname " of " newname t)
                    340:                                   (setq typenum 3) nil)
                    341:                                  ((not (\=& 0 hashcollect))
                    342:                                   (setq hashcollect 0)
                    343:                                   (msg t "CREATE: No hashing allowed on "
                    344:                                        "<lisp> slots in slot " slotname
                    345:                                        " of " newname t)))
                    346:                            (setq typenum 3) nil)
                    347:                    (setof (setq typenum (+ 4 typenum))    t)
                    348:                    (otherwise
                    349:                     ; Either an ordinal type ==> integer,
                    350:                     ;   or a structure name ==> struct, or an error.
                    351:                     (cond ((memq slottype *ordinalnames*)
                    352:                            (setq typenum (+ 2 typenum)) nil)
                    353:                           ((structurenamep slottype)
                    354:                            (setq reqstruct nil)
                    355:                            nil)     ; i. e., add 0 to TYPENUM.
                    356:                           (  t  (msg t "CREATE: Illegal type: " slottype
                    357:                                      " in slot: " slotname " of " newname t)
                    358:                                 nil))))
                    359:           (setq slottype (pop slot)))
                    360:     (and reqstruct
                    361:         (progn (msg t "CREATE: && hashing only allowed on STRUCT slots."
                    362:                     t " Bad slot is called " slotname
                    363:                     " and is of type " slottype t)
                    364:                (pearlbreak)))
                    365:     ; Save the last word of the type which is possibly a structure or
                    366:     ; ordinal type name for future use.
                    367:     (putppset slotnum slottype defblock)
                    368:     (putslottype slotnum typenum defblock)
                    369: 
                    370:     ; Next, look for a value, or ^ to inherit from above;
                    371:     ;     these may be preceded by := or == to determine future
                    372:     ;     "enforcing" (should be less strong term) of this default.
                    373:     (setq slotvalue nil)
                    374:     (setq valuetype nil)
                    375:     (setq enforce (pop slot))
                    376:     (selectq enforce
                    377:             (:\=  (cond ((eq (car slot) '^)
                    378:                          (setq slot (cdr slot))
                    379:                          (inheritvalue nil))
                    380:                         ( t (constructvalue))))
                    381:             (\=\= (addenforce hashcollect)
                    382:                   (cond ((eq (car slot) '^)
                    383:                          (setq slot (cdr slot))
                    384:                          (inheritvalue nil))
                    385:                         ( t (constructvalue))))
                    386:             ((^ nil)
                    387:              (addenforce hashcollect)
                    388:              (inheritvalue nil))
                    389:             (otherwise (push enforce slot)
                    390:                        (addenforce hashcollect)
                    391:                        (constructvalue)))
                    392: 
                    393:     (handlepossibleadjunctvar)
                    394: 
                    395:     ; Hash, enforce, slotvalue and valuetype can now be installed.
                    396:     (puthashandenforce slotnum hashcollect defblock)
                    397:     (putslotvaluetype  slotnum valuetype   valblock)
                    398:     (putslotvalue      slotnum slotvalue   valblock)
                    399: 
                    400:     (handlepredicatesandhooks)))
                    401:  
                    402: ; Create a new structure of type BASE:  a structure with ALL NEW slots.
                    403: (de createbase (newname abbrev slots)
                    404:   (and (eq newname 'nilstruct)
                    405:        (boundp (defatom 'nilstruct))
                    406:        (progn (msg t "CREATE BASE: Cannot redefine nilstruct." t)
                    407:              (pearlbreak)))
                    408:   (and (structurenamep newname)
                    409:        *warn*
                    410:        (msg t "CREATE BASE: Warning: Creating a new definition"
                    411:            " of an existing structure: " newname t))
                    412:   (prog (defblock slotname slottype enforce fcn ppset slot length isa
                    413:                  typenum valblock predlist slothooklist
                    414:                  first*edslot basehooks basehookbefore newvalue reqstruct
                    415:                  hashalias hashfocus hashcollect slotvalue valuetype)
                    416: 
                    417:        ; Process base hooks if the first "slot" is named "if" or "hook".
                    418:        (cond ((memq (caar slots) '(if hook))
                    419:               (setq basehookbefore (cdr (pop slots)))
                    420:               (setq basehooks (ncons nil))
                    421: 
                    422:               ; Use tconc to preserve order.
                    423:               (while basehookbefore ; is not NIL
                    424:                      (tconc basehooks (cons (pop basehookbefore)
                    425:                                             (pop basehookbefore))))
                    426:               (setq basehooks (car basehooks)))
                    427:              ( t (setq basehooks nil)))
                    428: 
                    429:        ; Allocate hunks for definition and default instance (valblock)
                    430:        ;     based on number of slots.
                    431:        (setq defblock (allocdef (setq length (length slots))))
                    432:        (setq valblock (allocval length))
                    433:        (puttypetag '*pearldef* defblock)
                    434:        (puttypetag '*pearlinst* valblock)
                    435:        (cond (*toplevelp* (setq *currenttopcreated* valblock)
                    436:                           (setq *currentpearlstructure* valblock)
                    437:                           (initbothalists valblock)
                    438:                           (setq *currenttopalists* (getbothalists valblock))
                    439:                           ; Include the current environment in 
                    440:                           ;    the variable assoc-list.
                    441:                           (and *blockstack*
                    442:                                (putalist (cdar *blockstack*) valblock))
                    443:                           (setq *toplevelp* nil))
                    444:              ( t (putbothalists *currenttopalists* valblock)))
                    445: 
                    446:        (putdef defblock valblock)
                    447:        (putdefaultinst valblock defblock)
                    448:        (set (instatom newname) valblock)
                    449:        (set (defatom newname) defblock)
                    450:        (and abbrev
                    451:             (cond ((eq abbrev '*buildabbrev*)
                    452:                    (putabbrev (instatom newname) valblock))
                    453:                   ( t (putabbrev abbrev valblock))))
                    454:        (putuniquenum (newnum) defblock)
                    455:        (putstructlength length defblock)
                    456:        (putisa nil defblock)
                    457:        (putexpansionlist nil defblock)
                    458:        (putbasehooks basehooks defblock)
                    459:        (putpname newname defblock)
                    460: 
                    461:        (setq hashalias 0)
                    462:        (setq hashfocus 0)
                    463:        (setq first*edslot 0)
                    464:        (for slotnum 1 length
                    465:             (setq slot (pop slots))
                    466:             (buildslot))
                    467: 
                    468:        (cond ((\=& 0 hashalias) (puthashalias first*edslot defblock))
                    469:              ( t  (puthashalias hashalias defblock)))
                    470:        (puthashfocus hashfocus defblock)
                    471: 
                    472:        (return valblock)))
                    473:  
                    474: ; Create a new individual just for this slot.
                    475: (defmacro buildstructvalue (struct)
                    476:   `(cond ((and (atom ,struct)                      ; if an atom
                    477:               (boundp ,struct)                    ; and bound
                    478:               (structurep (eval ,struct)))        ; to a structure,
                    479:          (eval ,struct))                          ; evaluate it.
                    480:         ; Otherwise, recursively call create.
                    481:         ( t (selectq (car ,struct)
                    482:                      ; New create type in slot.
                    483:                      ((ind individual pat pattern fn function
                    484:                            base exp expanded)
                    485:                       (let ((*currentcreatetype* (car ,struct)))
                    486:                            (apply (function insidecreate) ,struct)))
                    487:                      (otherwise
                    488:                       ; Otherwise, use current create type.
                    489:                       (apply (function insidecreate)
                    490:                              (cons *currentcreatetype* ,struct)))))))
                    491:  
                    492: ; Get a pointer to the symbol.
                    493: (defmacro buildsymbolvalue (sym)
                    494:   `(cond ((symbolnamep ,sym)   (eval (symatom ,sym)))
                    495:         ; If not a symbol name, then ...
                    496:          ((and (atom ,sym)                      ; if an atom
                    497:               (boundp ,sym)                    ; and bound
                    498:               (psymbolp (eval ,sym)))          ; to a symbol,
                    499:          (eval ,sym))                          ; evaluate it.
                    500:         ; Otherwise, error.
                    501:         ( t  (msg t "CREATE: " ,sym " is used in a slot of type SYMBOL but "
                    502:                   "neither is the name of a symbol nor evaluates to one." t)
                    503:              (pearlbreak))))
                    504:  
                    505: ; Get an integer using PPSET if not an integer.
                    506: (defmacro buildintvalue (intval bppset)
                    507:   `(let (assocval)
                    508:        (cond ((numberp ,intval) ,intval)
                    509:              ; Ordinal type given for ppset.
                    510:              ((and ,bppset    ; is not NIL.
                    511:                    (setq assocval (assq ,intval (eval (ordatom ,bppset)))))
                    512:               (cdr assocval))
                    513:              ; Some other atom which is bound to an integer.
                    514:              ((and (atom ,intval)
                    515:                    (boundp ,intval)
                    516:                    (numberp (eval ,intval)))
                    517:               (eval ,intval))
                    518:              ; Otherwise, error.
                    519:              ( t (msg t "CREATE: Unbound atom or non-integer value: "
                    520:                       ,intval " in integer slot." t) 
                    521:                  (pearlbreak)))))
                    522:  
                    523: ; Construct a new value of the specified type using the pplist if necessary
                    524: (de buildvalue (value typenum ppset)
                    525:   (selectq typenum
                    526:           (0 (buildstructvalue value))
                    527:           (1 (buildsymbolvalue value))
                    528:           (2 (buildintvalue    value ppset))
                    529:           (3 value) ; i.e., could be anything they want.
                    530:           (otherwise
                    531:            (cond ((and (atom value)
                    532:                        (boundp value)
                    533:                        (enforcetype (eval value) typenum))
                    534:                   (eval value))
                    535:                  ( t (mapcar (funl (singlevalue)
                    536:                                    (buildvalue singlevalue
                    537:                                                (- typenum 4) ppset))
                    538:                              value))))))
                    539:  
                    540: ; Return the position number of SLOTNAME in structure DEFBLOCK.
                    541: (defmacro slotnametonumber (slotname defblock)
                    542:   `(progn
                    543:     (setq slotlocation 0)
                    544:     (for slotnum 1 (getstructlength ,defblock)
                    545:         (and (memq ,slotname (getslotname slotnum ,defblock))
                    546:              (setq slotlocation slotnum)))
                    547:     slotlocation))
                    548:  
                    549: ; Find the slotname in SLOT, put it in SLOTNAME, and find its SLOTNUM.
                    550: (dm findslotnum (none)
                    551:   '(progn
                    552:     (setq slotname slot)
                    553:     (while (memq (car slotname) '(* ** *** & ^ && : :: < > +))
                    554:           (setq slotname (cdr slotname)))
                    555:     (cond ((and (dtpr (cadr slotname))
                    556:                (eq '*slot* (car (cadr slotname))))
                    557:           (setq slotname (cadr (cadr slotname)))
                    558:           (minus (slotnametonumber slotname olddefblock)))
                    559:          ( t (setq slotname (car slotname))
                    560:              (slotnametonumber slotname olddefblock)))))
                    561:  
                    562: ; Look up through ISA links and add name to Expansion Lists.
                    563: ;    Assumes PROG vars NEWNAME and OLDDEFBLOCK.
                    564: (dm addtoexpansionlists (none)
                    565:   '(progn
                    566:     (setq isa olddefblock)
                    567:     (while isa         ; is not null
                    568:           (putexpansionlist (cons defblock (getexpansionlist isa)) isa)
                    569:           (setq isa (getisa isa)))))
                    570:  
                    571: ; Copy definition for one slot.
                    572: (dm copyslice (none)
                    573:   '(progn
                    574:     (putslottype      slotnum (getslottype      slotnum olddefblock) defblock)
                    575:     (putslotname      slotnum (getslotname      slotnum olddefblock) defblock)
                    576:     (putppset         slotnum (getppset         slotnum olddefblock) defblock)
                    577:     (puthashandformat slotnum (gethashandformat slotnum olddefblock) defblock)))
                    578:  
                    579: ; Copy default values, predicates, and hooks for one slot.
                    580: (dm copyslot (none)
                    581:   '(progn
                    582:     (putslotvaluetype slotnum (getslotvaluetype slotnum oldvalblock) valblock)
                    583:     (putslotvalue     slotnum (getslotvalue     slotnum oldvalblock) valblock)
                    584:     (putpred          slotnum (getpred          slotnum oldvalblock) valblock)
                    585:     (putslothooks     slotnum (getslothooks     slotnum oldvalblock) valblock)))
                    586:  
                    587: ; Copy an old slot from an ISA into the current structure.
                    588: (dm fillbaseslot (none)
                    589:   '(progn
                    590:     (cond ((<& slotnum 0)
                    591:           (setq slotnum (minus slotnum))
                    592:           (setq newslotnamep t))
                    593:          ( t (setq newslotnamep nil)))
                    594: 
                    595:     ; First check for changed hashing.
                    596:     (setq slotname (pop slot))
                    597:     (clearhashandformat slotnum defblock)
                    598:     (setq hashcollect 0)
                    599:     (while (selectq slotname
                    600:                    (*   (and (\=& 0 first*edslot)
                    601:                              (setq first*edslot (minus slotnum)))
                    602:                         (addhash*   hashcollect) t)
                    603:                    (**  (addhash**  hashcollect) t)
                    604:                    (*** (addhash*** hashcollect) t)
                    605:                    (&   (cond ((not (\=& 0 hashalias))
                    606:                                (msg t "CREATE EXPANDED: Only 1 hash alias "
                    607:                                     "(&) or selected slot (^) allowed in: "
                    608:                                     newname t)
                    609:                                t)
                    610:                               ( t (setq hashalias slotnum))))
                    611:                    (^   (cond ((not (\=& 0 hashalias))
                    612:                                (msg t "CREATE EXPANDED: Only 1 hash alias "
                    613:                                     "(&) or selected slot (^) allowed in: "
                    614:                                     newname t)
                    615:                                t)
                    616:                               ( t (setq hashalias (minus slotnum)))))
                    617:                    (&&  (cond ((not (\=& 0 hashfocus))
                    618:                                (msg t "CREATE EXPANDED: Only 1 hash focus "
                    619:                                     "(&&) allowed in: " newname t)
                    620:                                t)
                    621:                               ( t (setq hashfocus slotnum))))
                    622:                    (:   (addhash:   hashcollect) t)
                    623:                    (::  (addhash::  hashcollect) t)
                    624:                    (>   (addhash>   hashcollect) t)
                    625:                    (<   (addhash<   hashcollect) t)
                    626:                    (+   (setq hashcollect (gethashinfo slotnum olddefblock))
                    627:                         t))
                    628:           (setq slotname (pop slot)))
                    629: 
                    630:     (and (\=& 0 (length slot))
                    631:         (progn (msg t "CREATE EXPANDED: Missing slot name and/or value in: "
                    632:                     newname t)
                    633:                (pearlbreak)))
                    634: 
                    635:     (and newslotnamep
                    636:         (pop slot)
                    637:         (addslotname slotnum slotname defblock))
                    638: 
                    639:     ; Next, check for value or ^, possibly preceded by := or ==.
                    640:     (setq enforce (pop slot))
                    641:     (selectq enforce
                    642:             (:\= (cond ((eq (car slot) '^)  ; a waste.
                    643:                         (setq slot (cdr slot))
                    644:                         (inheritvalue (getisa defblock)))
                    645:                        ( t (constructvalue))))
                    646:             (\=\= (addenforce hashcollect)
                    647:                   (cond ((eq (car slot) '^)
                    648:                          (setq slot (cdr slot))
                    649:                          (inheritvalue (getisa defblock)))
                    650:                         ( t (constructvalue))))
                    651:             ((^ nil)  (addenforce hashcollect)
                    652:                       (inheritvalue (getisa defblock)))
                    653:             (otherwise (push enforce slot)
                    654:                        (addenforce hashcollect)
                    655:                        (constructvalue)))
                    656:     
                    657:     (handlepossibleadjunctvar)
                    658: 
                    659:     ; Hash, enforce, slotvalue and valuetype can now be installed.
                    660:     (puthashandenforce slotnum hashcollect defblock)
                    661:     (putslotvaluetype  slotnum valuetype   valblock)
                    662:     (putslotvalue      slotnum slotvalue   valblock)
                    663: 
                    664:     (handlepredicatesandhooks)))
                    665:  
                    666: ; Create a new structure of type EXPANDED:  build new slots in
                    667: ;    addition to slots inherited from a BASE or EXPANDED structure.
                    668: (de createexpanded (basename newname abbrev slots)
                    669:   (and (eq newname 'nilstruct)
                    670:        (progn (msg t "CREATE EXPANDED: Cannot redefine nilstruct." t)
                    671:              (pearlbreak)))
                    672:   (and (structurenamep newname)
                    673:        *warn*
                    674:        (msg t "CREATE EXPANDED: Warning: Creating a new definition of "
                    675:            "an existing structure: " newname t))
                    676:   (or (structurenamep basename)
                    677:       (progn (msg t "CREATE EXPANDED: " basename
                    678:                  " is not the name of a previously declared structure." t
                    679:                  "     New name is " newname ". Slots are: " slots t)
                    680:             (pearlbreak)))
                    681:   (prog (defblock valblock oldvalblock olddefblock slotname
                    682:                  slottype enforce slot oldlength length slotnum
                    683:                  typenum slotnumlist beginslots predlist slothooklist
                    684:                  fcn ppset isa first*edslot slotlocation basehooks
                    685:                  basehookbefore newvalue result item reqstruct
                    686:                  newslotnamep hashalias hashfocus hashcollect
                    687:                  slotvalue valuetype)
                    688:        (setq olddefblock (eval (defatom basename)))
                    689:        (setq oldlength (getstructlength olddefblock))
                    690:        
                    691:        ; Handle base hooks, if first "slot" is called "if" or "hook".
                    692:        (cond ((memq (caar slots) '(if hook))
                    693:               (setq basehookbefore (cdr (pop slots)))
                    694:               (setq basehooks (ncons nil))
                    695:               (while basehookbefore ; is not NIL
                    696:                      (tconc basehooks (cons (pop basehookbefore)
                    697:                                             (pop basehookbefore))))
                    698:               (setq basehooks (nconc (car basehooks)
                    699:                                      (getbasehooks olddefblock))))
                    700:              ( t (setq basehooks (getbasehooks olddefblock))))
                    701:        
                    702:        ; Create a list of slotnumbers for the slotnames in SLOTS,
                    703:        ; meanwhile also determining the LENGTH.
                    704:        (setq beginslots slots)   ; save to process again.
                    705:        (setq slotnumlist (ncons nil))
                    706:        (setq length oldlength)
                    707:        (while (setq slot (pop slots))
                    708:               (cond ((not (\=& 0 (setq slotnum (findslotnum))))
                    709:                      ; Old slot name or new name for old slot (negative).
                    710:                      (tconc slotnumlist slotnum))
                    711:                     ; Otherwise, new slot name: increase length.
                    712:                     (  t   (setq length (1+ length))
                    713:                            (tconc slotnumlist length))))
                    714:        (setq slotnumlist (car slotnumlist))
                    715:        (setq slots beginslots)
                    716:        
                    717:        ; Allocate new hunks.
                    718:        (setq defblock (allocdef length))
                    719:        (setq valblock (allocval length))
                    720:        (puttypetag '*pearldef* defblock)
                    721:        (puttypetag '*pearlinst* valblock)
                    722:        (cond (*toplevelp* (setq *currenttopcreated* valblock)
                    723:                           (setq *currentpearlstructure* valblock)
                    724:                           (initbothalists valblock)
                    725:                           (setq *currenttopalists* (getbothalists valblock))
                    726:                           ; Include the current environment in 
                    727:                           ;    the variable assoc-list.
                    728:                           (and *blockstack*
                    729:                                (putalist (cdar *blockstack*) valblock))
                    730:                           (setq *toplevelp* nil))
                    731:              ( t (putbothalists *currenttopalists* valblock)))
                    732: 
                    733:        (putdef defblock valblock)
                    734:        (putdefaultinst valblock defblock)
                    735:        (set (instatom newname) valblock)
                    736:        (set (defatom newname) defblock)
                    737:        (and abbrev
                    738:             (cond ((eq abbrev '*buildabbrev*)
                    739:                    (putabbrev (instatom newname) valblock))
                    740:                   ( t (putabbrev abbrev valblock))))
                    741:        (putuniquenum (newnum) defblock)
                    742:        (putstructlength length defblock)
                    743: 
                    744:        ; Set up the hierarchy of ISAs.
                    745:        (putisa olddefblock defblock)
                    746:        (putexpansionlist nil defblock)
                    747:        (addtoexpansionlists)
                    748: 
                    749:        (putbasehooks basehooks defblock)
                    750:        (putpname newname defblock)
                    751:        (setq oldvalblock (getdefaultinst olddefblock))
                    752: 
                    753:        ; (puthashalias 0   defblock)
                    754:        (setq hashalias 0)
                    755:        (setq hashfocus 0)
                    756:        (or (<& (setq first*edslot (gethashalias olddefblock)) 0)
                    757:            (setq first*edslot 0))
                    758:        ; Copy old slots in first.
                    759:        (for slotnum 1 oldlength
                    760:             (copyslice)
                    761:             (copyslot olddefblock))
                    762:        ; Run base hooks attached to the base we are expanding.
                    763:        (and (getbasehooks olddefblock)
                    764:             (setq item valblock)
                    765:             (checkrunhandlebasehooks1 '<expanded *runexpandedhooks*)
                    766:             (setq valblock item))
                    767: 
                    768:        ; For each slot, if it's new, build a new slot;
                    769:        ;                if it's old, fill it in differently.
                    770:        (while (setq slot (pop slots))
                    771:               (setq slotnum (pop slotnumlist))
                    772:               (cond ((>& slotnum oldlength)
                    773:                      (buildslot))
                    774:                     (  t  (fillbaseslot))))
                    775:        (cond ((\=& 0 hashalias) (puthashalias first*edslot defblock))
                    776:              ( t (puthashalias hashalias defblock)))
                    777:        (cond ((\=& 0 hashfocus) (puthashfocus (gethashfocus olddefblock)
                    778:                                               defblock))
                    779:              ( t (puthashfocus hashfocus defblock)))
                    780: 
                    781:        ; Run base hooks attached to the base we are expanding.
                    782:        (and (getbasehooks olddefblock)
                    783:             (setq item valblock)
                    784:             (checkrunhandlebasehooks1 '>expanded *runexpandedhooks*)
                    785:             (setq valblock item))
                    786:        (return valblock)))
                    787:  
                    788: ; Fill in an individual slot with the value specified.  If the value is
                    789: ;   prefaced by the character "^" then the value should be inherited from
                    790: ;   above but there are still predicates and/or IFs to process.
                    791: (dm fillindivslot (none)
                    792:   '(progn
                    793:     (setq slotname (pop slot))
                    794:     ; Find slot number.
                    795:     (and (\=& 0 (setq slotnum (slotnametonumber slotname defblock)))
                    796:         (progn (msg t "CREATE: Undefined slot: " slotname
                    797:                     ", in individual or pattern: " basename)
                    798:                (pearlbreak)))
                    799:     (cond ((\=& 0 (length slot))
                    800:           (msg t "Missing value in: CREATE INDIVIDUAL (or PATTERN) "
                    801:                basename ".  Remaining slots are: " slots t)
                    802:           (pearlbreak))
                    803:          ; If ^, inherit.
                    804:          ((eq (car slot) '^)
                    805:           (setq slot (cdr slot))
                    806:           (inheritvalue defblock))
                    807:          ; Otherwise, construct a new value and insert.
                    808:          ( t (constructvalue)))
                    809:     
                    810:     (handlepossibleadjunctvar)
                    811: 
                    812:     ; Store type and value.
                    813:     (putslotvaluetype  slotnum valuetype   valblock)
                    814:     (putslotvalue      slotnum slotvalue   valblock)
                    815: 
                    816:     (handlepredicatesandhooks)))
                    817:  
                    818: ; Create a new structure of type INDIVIDUAL:  an instance of a
                    819: ;    BASE or EXPANDED structure.  Slots are either filled explicitly
                    820: ;    or they inherit defaults from above.
                    821: (de createindividual (basename abbrev slots)
                    822:   (or (structurenamep basename)
                    823:       (progn (msg t "CREATE INDIVIDUAL: " basename
                    824:                  " is not the name of a previously declared structure."
                    825:                  t "     Slots are: " slots t)
                    826:             (pearlbreak)))
                    827:   (prog (defblock valblock slotname length slotnum oldvalblock
                    828:                  isa typenum ppset slot predlist slothooklist fcn
                    829:                  slotlocation newvalue result item
                    830:                  slotvalue valuetype)
                    831: 
                    832:        ; Find definition and allocate hunk for individual.
                    833:        (setq defblock (eval (defatom basename)))
                    834:        (setq valblock (allocval (setq length (getstructlength defblock))))
                    835:        (puttypetag '*pearlinst* valblock)
                    836:        (cond (*toplevelp* (setq *currenttopcreated* valblock)
                    837:                           (setq *currentpearlstructure* valblock)
                    838:                           (initbothalists valblock)
                    839:                           (setq *currenttopalists* (getbothalists valblock))
                    840:                           ; Include the current environment in 
                    841:                           ;    the variable assoc-list.
                    842:                           (and *blockstack*
                    843:                                (putalist (cdar *blockstack*) valblock))
                    844:                           (setq *toplevelp* nil))
                    845:              ( t (putbothalists *currenttopalists* valblock)))
                    846: 
                    847:        (and abbrev
                    848:             (cond ((eq abbrev '*buildabbrev*)
                    849:                    (putabbrev (eval `(newsym ,(getpname defblock))) valblock))
                    850:                   ( t (putabbrev abbrev valblock))))
                    851:        (putdef defblock valblock)
                    852:        (setq oldvalblock (getdefaultinst defblock))
                    853: 
                    854:        ; Copy slots from old structure first, then run base hooks.
                    855:        (for slotnum 1 length
                    856:             (copyslot defblock))
                    857:        (and (getbasehooks defblock)
                    858:             (setq item valblock)
                    859:             (checkrunhandlebasehooks1 '<individual *runindividualhooks*)
                    860:             (setq valblock item))
                    861: 
                    862:        ; Replace copied values for slots that are actually listed
                    863:        ;    then run base hooks.
                    864:        (while (setq slot (pop slots))
                    865:               (fillindivslot))
                    866:        (and (getbasehooks defblock)
                    867:             (setq item valblock)
                    868:             (checkrunhandlebasehooks1 '>individual *runindividualhooks*)
                    869:             (setq valblock item))
                    870:        (return valblock)))
                    871:  
                    872: ; Copy default values, predicates, and hooks for one slot.
                    873: (dm copypatternslot (none)
                    874:   '(progn
                    875:     (putslotvaluetype slotnum 'LOCAL                             valblock)
                    876:     (putslotvalue     slotnum *any*conscell*                     valblock)
                    877:     (putpred          slotnum (getpred      slotnum oldvalblock) valblock)
                    878:     (putslothooks     slotnum (getslothooks slotnum oldvalblock) valblock)))
                    879:  
                    880: ; Create a new structure of type PATTERN:  an instance of a BASE or
                    881: ;    EXPANDED structure.  Unspecified slots are filled with ?*ANY*.
                    882: (de createpattern (basename abbrev slots)
                    883:   (prog (defblock valblock oldvalblock slotname length slotnum isa
                    884:                  slotlocation slot predlist slothooklist fcn typenum
                    885:                  ppset newvalue result item slotvalue valuetype)
                    886:        (or (structurenamep basename)
                    887:            (progn (msg t "CREATE PATTERN: " basename
                    888:                        " is not the name of a previously declared structure."
                    889:                        t)
                    890:                   (pearlbreak)))
                    891: 
                    892:        ; Get definition and allocate hunk for pattern.
                    893:        (setq defblock (eval (defatom basename)))
                    894:        (setq valblock (allocval (setq length (getstructlength defblock))))
                    895:        (setq oldvalblock (getdefaultinst defblock))
                    896:        (puttypetag '*pearlinst* valblock)
                    897:        (cond (*toplevelp* (setq *currenttopcreated* valblock)
                    898:                           (setq *currentpearlstructure* valblock)
                    899:                           (initbothalists valblock)
                    900:                           (setq *currenttopalists* (getbothalists valblock))
                    901:                           ; Include the current environment in 
                    902:                           ;    the variable assoc-list.
                    903:                           (and *blockstack*
                    904:                                (putalist (cdar *blockstack*) valblock))
                    905:                           (setq *toplevelp* nil))
                    906:              ( t (putbothalists *currenttopalists* valblock)))
                    907: 
                    908:        (putdef defblock valblock)
                    909:        (and abbrev
                    910:             (cond ((eq abbrev '*buildabbrev*)
                    911:                    (putabbrev (eval `(newsym ,(getpname defblock))) valblock))
                    912:                   ( t (putabbrev abbrev valblock))))
                    913: 
                    914:        ; Copy slot values from base and run base hooks on base structure.
                    915:        (for slotnum 1 length
                    916:             (copypatternslot))
                    917:        (and (getbasehooks defblock)
                    918:             (setq item valblock)
                    919:             (checkrunhandlebasehooks1 '<pattern *runpatternhooks*)
                    920:             (setq valblock item))
                    921: 
                    922:        ; Fill in new values for any slots listed and run base hooks.
                    923:        (while (setq slot (pop slots))
                    924:               (fillindivslot))
                    925:        (and (getbasehooks defblock)
                    926:             (setq item valblock)
                    927:             (checkrunhandlebasehooks1 '>pattern *runpatternhooks*)
                    928:             (setq valblock item))
                    929:        (return valblock)))
                    930:  
                    931: ; Create a new structure of type FUNCTION: a structure with slots
                    932: ;    describing the arguments to the function of the same name.
                    933: (de createfunction (fcnname abbrev slots)
                    934:   ; Function must already be defined and be a lambda (expr).
                    935:   (cond ((islambda fcnname)
                    936:         (putprop fcnname t 'functionstruct)
                    937:         (createbase fcnname abbrev slots))
                    938:        ( t  (msg t "CREATE FUNCTION: Only lambdas (exprs) allowed as "
                    939:                  "function structures: " fcnname slots t)
                    940:             (pearlbreak))))
                    941:  
                    942: ; vi: set lisp:

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.