(FILECREATED " 5-Oct-84 12:16:00" {ERIS}<LISPCORE>LIBRARY>MESATYPES.;3 12697 changes to: (VARS MESATYPESCOMS) previous date: "18-Apr-84 21:15:31" {ERIS}<LISPCORE>LIBRARY>MESATYPES.;2) (* Copyright (c) 1984 by Xerox Corporation. All rights reserved.) (PRETTYCOMPRINT MESATYPESCOMS) (RPAQQ MESATYPESCOMS ((* Defines three new record types: MESATYPE, MESARECORD, and MESAARAY. Also provides a number of macros to manipulate objects of these record types. None of this package need be present in the compiled version of a client package.) (* Public stuff) (MACROS MESASIZE MESASETQ MESAEQUAL FMESAELT MESAELT MESASETA) (PROP ARGNAMES MESASIZE MESASETQ MESAEQUAL FMESAELT MESAELT MESASETA) (* Private stuff) (INITVARS (\MESATYPES (HASHARRAY 20))) (P (pushnew CLISPRECORDTYPES (QUOTE MESATYPE)) (pushnew CLISPRECORDTYPES (QUOTE MESARECORD)) (pushnew CLISPRECORDTYPES (QUOTE MESAARRAY)) (MOVD (QUOTE RECORD) (QUOTE MESATYPE)) (MOVD (QUOTE RECORD) (QUOTE MESARECORD)) (MOVD (QUOTE RECORD) (QUOTE MESAARRAY))) (PROP USERRECORDTYPE MESATYPE MESARECORD MESAARRAY) (FNS MESATYPEFN MESARECORDFN MesaRecordFields MesaRecordSubblock MesaRecordCreateMethod MESAARRAYFN MesaArrayOffsets MesaArrayFindOffset RemoveLast))) (* Defines three new record types: MESATYPE, MESARECORD, and MESAARAY. Also provides a number of macros to manipulate objects of these record types. None of this package need be present in the compiled version of a client package.) (* Public stuff) (DECLARE: EVAL@COMPILE (PUTPROPS MESASIZE MACRO [args (PROG ((recordName (CAR args))) (* Returns the size of record recordName) (RETURN (EVAL (BQUOTE (INDEXF (fetch (, recordName THISISTHELASTFIELD) of T]) (PUTPROPS MESASETQ MACRO [args (PROG ((a (CAR args)) (b (CADR args)) (type (CADDR args))) (* Copies the contents of "b" into "a" Returns a. Should be used to translate statement of the form "a ← b;" when a and b are neither numbers nor pointers. A safer (ie, more correct) way to do this would be to say "(foreach field f in type st f has both a fetch and a replace method do (replace (type f) of a with (fetch (type f) of b)))") (RETURN (BQUOTE (\BLT , a , b (MESASIZE , type]) (PUTPROPS MESAEQUAL MACRO [args (PROG ((a (CAR args)) (b (CADR args)) (type (CADDR args))) (* Compares a and b for equality, where a and b are instances of record type. a and b can be multiple words long.) (RETURN (BQUOTE (for word from 0 to (SUB1 (MESASIZE , type)) always (EQ (\GETBASE , a word) (\GETBASE , b word]) (PUTPROPS FMESAELT MACRO [args (PROG ((array (CAR args)) (arrayType (CADR args)) (indexes (CDDR args)) indexRangeList indexOffsetList) (* Returns a pointer to the indicated element of array. Unsafe, because it returns a pointer to the middle of the structure, which would confuse the garbage collector if you held onto the element pointer longer than the array pointer.) [SETQ indexRangeList (EVAL (BQUOTE (fetch (, arrayType INDEXLIST) of T] [SETQ indexOffsetList (EVAL (BQUOTE (fetch (, arrayType OFFSETLIST) of T] (RETURN (LIST (QUOTE \ADDBASE) array (CONS (QUOTE IPLUS) (for index in indexes as indexRange in indexRangeList as offset in indexOffsetList collect (BQUOTE ([OPENLAMBDA (index) (OR (AND (ILEQ , (CAR indexRange) index) (ILEQ index , (CDR indexRange))) (ERROR (QUOTE indexOutOfRange))) (ITIMES , offset (IDIFFERENCE index , (CAR indexRange] , index]) (PUTPROPS MESAELT MACRO [args (PROG ((arrayType (CADR args)) elementType) (* Returns the selected element of the array. Copies it into a freshly allocated box to avoid returning a pointer to the middle of the structure, which might confuse the garbage collector.) [SETQ elementType (EVAL (BQUOTE (fetch (, arrayType ELEMENTTYPE) of T] (RETURN (BQUOTE (MESASETQ (create , elementType) , (CONS (QUOTE FMESAELT) args) , elementType]) (PUTPROPS MESASETA MACRO [args (PROG ((eltArgs (RemoveLast args)) (arrayType (CADR args)) (newValue (CAR (LAST args))) elementType) (* Replaces the index'th element of array, provided that array is a contiguous run of objects of type elementType) [SETQ elementType (EVAL (BQUOTE (fetch (, arrayType ELEMENTTYPE) of T] (RETURN (BQUOTE (MESASETQ , (CONS (QUOTE FMESAELT) eltArgs) , newValue , elementType]) ) (PUTPROPS MESASIZE ARGNAMES (recordName)) (PUTPROPS MESASETQ ARGNAMES (a b type)) (PUTPROPS MESAEQUAL ARGNAMES (a b type)) (PUTPROPS FMESAELT ARGNAMES (array arrayType index1 ... indexn)) (PUTPROPS MESAELT ARGNAMES (array arrayType index1 ... indexn)) (PUTPROPS MESASETA ARGNAMES (array arrayType index1 ... indexn newValue)) (* Private stuff) (RPAQ? \MESATYPES (HASHARRAY 20)) (pushnew CLISPRECORDTYPES (QUOTE MESATYPE)) (pushnew CLISPRECORDTYPES (QUOTE MESARECORD)) (pushnew CLISPRECORDTYPES (QUOTE MESAARRAY)) (MOVD (QUOTE RECORD) (QUOTE MESATYPE)) (MOVD (QUOTE RECORD) (QUOTE MESARECORD)) (MOVD (QUOTE RECORD) (QUOTE MESAARRAY)) (PUTPROPS MESATYPE USERRECORDTYPE MESATYPEFN) (PUTPROPS MESARECORD USERRECORDTYPE MESARECORDFN) (PUTPROPS MESAARRAY USERRECORDTYPE MESAARRAYFN) (DEFINEQ (MESATYPEFN [LAMBDA (typeDecl) (* hts: "24-Mar-84 19:46") (PROG ((typeName (CADR typeDecl)) (isType (CADDR typeDecl)) (rest (CDDDR typeDecl))) (RETURN (NCONC (LIST (QUOTE MESARECORD) typeName (LIST (CONS (QUOTE DATA) isType))) rest]) (MESARECORDFN [LAMBDA (recordDecl) (* edited: "31-Mar-84 16:34") (* Translates a MESARECORD declaration into a BLOCKRECORD.) (* For each multi-word (gt 2) field, creates a special fetch method that returns a pointer to the beginning of the field, and a replace method that uses \BLT to copy over the entire field. This is done by replacing the fieldname with fieldnameSTARTOFTHISFIELD and making the fetch method for fieldname be a LOCF on fieldnameSTARTOFTHISFIELD) (* Note that a field can be declared to be a multi-word field by saying either (fieldname N WORD) or (fieldname mumble), where mumble is a previously defined MESARECORD.) (* Also includes a CREATE method for the type. if the user has not already done so. (Uses \ALLOCBLOCK. The messy-looking arithmetic is because MESASIZE returns the size of a record in words, and \ALLOCBLOCK's arg specifies the # of pointer cells (2 words each) to allocate)) (PROG ((recordName (CADR recordDecl)) (fieldDeclarations (CADDR recordDecl)) (subblocks (CONS)) (rest (CDDDR recordDecl))) (RETURN (PROG1 (NCONC [LIST (QUOTE BLOCKRECORD) recordName (NCONC (MesaRecordFields fieldDeclarations) (LIST (QUOTE (THISISTHELASTFIELD WORD] (CAR subblocks) (MesaRecordCreateMethod recordName rest) rest) (PUTHASH recordName T \MESATYPES) (* Record that recordName is a new MESARECORD) ]) (MesaRecordFields [LAMBDA (fieldDeclarations) (* hts: "29-Mar-84 18:04") (for field in fieldDeclarations collect (if [AND (CAR field) (OR (GETHASH (CADR field) \MESATYPES) (AND (EQ (CADDR field) (QUOTE WORD)) (FIXP (CADR field)) (IGREATERP (CADR field) 2] then (TCONC subblocks (MesaRecordSubblock recordName field)) (LIST (PACK* (CAR field) (QUOTE STARTOFTHISFIELD)) [OR (FIXP (CADR field)) (EVAL (BQUOTE (MESASIZE , (CADR field] (QUOTE WORD)) else field]) (MesaRecordSubblock [LAMBDA (recordName fieldDeclaration) (* hts: "29-Mar-84 18:05") (* Returns the appropriate accessfn declaration to make fieldDeclaration a multi-word subblock.) (PROG ((fieldName (CAR fieldDeclaration)) (fieldSize (CADR fieldDeclaration))) [OR (FIXP fieldSize) (SETQ fieldSize (EVAL (BQUOTE (MESASIZE , fieldSize] (RETURN (LIST (QUOTE ACCESSFNS) (LIST fieldName (LIST (QUOTE LOCF) (LIST (QUOTE fetch) (LIST recordName (PACK* fieldName (QUOTE STARTOFTHISFIELD))) (QUOTE of) (QUOTE DATUM))) (LIST (QUOTE PROGN) (LIST (QUOTE \BLT) (LIST (QUOTE fetch) (LIST recordName fieldName) (QUOTE of) (QUOTE DATUM)) (QUOTE NEWVALUE) fieldSize) (QUOTE NEWVALUE]) (MesaRecordCreateMethod [LAMBDA (recordName rest) (* edited: "31-Mar-84 16:31") (* Returns a create method for the type, if the user has not already done so.) (if (for thing in rest thereis (EQ (QUOTE CREATE) (CAR thing))) then NIL else (LIST (BQUOTE (CREATE (\ALLOCBLOCK (LRSH (ADD1 (MESASIZE , recordName)) 1]) (MESAARRAYFN [LAMBDA (arrayDecl) (* hts: "18-Apr-84 14:21") (PROG ((arrayName (CADR arrayDecl)) (indexDeclarations (CADDR arrayDecl)) (elementType (CADDDR arrayDecl)) (rest (CDDDDR arrayDecl)) arrayOffsets) [SETQ indexDeclarations (for indexDecl in indexDeclarations collect (CONS (EVAL (CAR indexDecl)) (EVAL (CADR indexDecl] (* Evaluate arraybounds so that they can be expressions rather than integers.) (SETQ arrayOffsets (MesaArrayOffsets indexDeclarations elementType)) (RETURN (APPEND [BQUOTE (MESARECORD , arrayName ((DATA , (MesaArrayFindOffset indexDeclarations arrayOffsets elementType) WORD)) (ACCESSFNS ((INDEXLIST (QUOTE , indexDeclarations)) (OFFSETLIST (QUOTE , arrayOffsets)) (ELEMENTTYPE (QUOTE , elementType] rest]) (MesaArrayOffsets [LAMBDA (indexDeclarations elementType) (* hts: "24-Mar-84 20:15") (if (NULL indexDeclarations) then NIL else (PROG ((restOfOffsets (MesaArrayOffsets (CDR indexDeclarations) elementType))) (RETURN (CONS (MesaArrayFindOffset (CDR indexDeclarations) restOfOffsets elementType) restOfOffsets]) (MesaArrayFindOffset [LAMBDA (indexDeclarations arrayOffsets elementType) (* hts: "18-Apr-84 14:29") (if indexDeclarations then (ITIMES (ADD1 (IDIFFERENCE (CDAR indexDeclarations) (CAAR indexDeclarations))) (CAR arrayOffsets)) else (EVAL (BQUOTE (MESASIZE , elementType]) (RemoveLast [LAMBDA (list) (* hts: "26-Mar-84 00:04") (PROG ((newList (COPY list)) length) (SETQ length (LENGTH newList)) (if (ILEQ length 1) then (RETURN NIL) else (RPLACD (FNTH newList (SUB1 length))) (RETURN newList]) ) (PUTPROPS MESATYPES COPYRIGHT ("Xerox Corporation" 1984)) (DECLARE: DONTCOPY (FILEMAP (NIL (6382 12617 (MESATYPEFN 6392 . 6729) (MESARECORDFN 6731 . 8364) (MesaRecordFields 8366 . 9074) (MesaRecordSubblock 9076 . 10012) (MesaRecordCreateMethod 10014 . 10510) (MESAARRAYFN 10512 . 11551) (MesaArrayOffsets 11553 . 11960) (MesaArrayFindOffset 11962 . 12284) (RemoveLast 12286 . 12615))))) STOP