Annotation of 43BSD/ucb/lisp/lisplib/record.l, revision 1.1.1.1

1.1       root        1: (setq rcs-common0-
                      2:    "$Header: record.l,v 1.3 84/02/29 19:33:50 jkf Exp $")
                      3: 
                      4: ;;                                     -[Mon Feb 20 15:00:52 1984 by jkf]-
                      5: ;; simple record package
                      6: ;;
                      7: 
                      8: (eval-when (compile)
                      9:    (or (get 'record 'version) (load 'record)))
                     10: 
                     11: (defvar record-pkg-indicator 'record-package-dr-record)
                     12: 
                     13: (declare (macros nil))
                     14: 
                     15: ;; internal macro
                     16: (defmacro dr-error (message &rest args)
                     17:    ;; print an error preceeded by 'defrecord'
                     18:    ;; internal use only
                     19:    `(error ',(concat "defrecord: " message) ,@args))
                     20: 
                     21: 
                     22: ;(defrecord dr-record
                     23: ;      name    ; name of record
                     24: ;      storage ; 'list' or 'vector'
                     25: ;      options ; subset of 'named', 'access-check'
                     26: ;      fields  ; list of dr-field records
                     27: ;)
                     28: 
                     29: (eval-when (compile eval)
                     30:    (putprop 'dr-record
                     31:            '(dr-record list nil ((fields 3 nil)
                     32:                                  (options 2 nil)
                     33:                                  (storage 1 nil)
                     34:                                  (name 0 nil)))
                     35:            record-pkg-indicator))
                     36: (defmacro make-dr-record (&rest args) (record-pkg-construct 'dr-record args))
                     37: (defmacro dr-record-storage (arg) `(nth 1 ,arg))
                     38: (defmacro dr-record-options (arg) `(nth 2 ,arg))
                     39: (defmacro dr-record-fields (arg) `(nth 3 ,arg))
                     40: 
                     41: ;(defrecord dr-field
                     42: ;   ;; internal structure used to store info on fields
                     43: ;   name
                     44: ;   offset
                     45: ;   defaultvalue)
                     46: 
                     47: (eval-when (compile eval)
                     48:    (putprop 'dr-field
                     49:            '(dr-field list nil ((defaultvalue 2 nil)
                     50:                                 (offset 1 nil)
                     51:                                 (name 0 nil)))
                     52:            record-pkg-indicator))
                     53: (defmacro make-dr-field (&rest args) (record-pkg-construct 'dr-field args))
                     54: 
                     55: (defmacro dr-field-name (arg) `(nth 0 ,arg))
                     56: (defmacro dr-field-offset (arg) `(nth 1 ,arg))
                     57: (defmacro dr-field-defaultvalue (arg) `(nth 2 ,arg))
                     58: 
                     59: ;; internal functions (called by macros)
                     60: 
                     61: (defun record-pkg-construct (recname args)
                     62:    ;; called to expand a make- form.
                     63:    ;; recname is the name of a record
                     64: 
                     65:    ; convert to an assq list, verifing field names
                     66:    (let* ((dr-record (get recname record-pkg-indicator))
                     67:          (fields (dr-record-fields dr-record))
                     68:          (given))
                     69:       (do ((xx args (cddr xx)))
                     70:          ((null xx))
                     71:          (if (assq (car xx) fields)
                     72:             then (push (cons (car xx) (cadr xx)) given)
                     73:             else (dr-error " for record " recname
                     74:                           ", this field doesn't exist " (car xx))))
                     75:       ;; now build a list of values.
                     76:       ;; use the fact that the fields list is in the reverse order
                     77:       (do ((xx fields (cdr xx))
                     78:           (got)
                     79:           (res))
                     80:          ((null xx)
                     81:           ;; now we have a list of values to compute to build this
                     82:           ;; form.  
                     83:           (caseq (dr-record-storage dr-record)
                     84:              (list `(list ,@res))
                     85:              (vector `(vector ,@res))
                     86:              (t (error "record package is confused about storage type "))))
                     87:          (if (setq got (assq (dr-field-name (car xx)) given))
                     88:             then (push (cdr got) res)  ; given value
                     89:             else (push (dr-field-defaultvalue (car xx))
                     90:                        res)))))
                     91: 
                     92: 
                     93: 
                     94: (defun record-pkg-access (recname fieldname arg)
                     95:    ;; return code access the given field in the given record
                     96:    (let ((dr-record (get recname record-pkg-indicator))
                     97:         (recnamefield)
                     98:         (fieldinfo)
                     99:         (options)
                    100:         (storage))
                    101:       (setq fieldinfo (assq fieldname (dr-record-fields dr-record)))
                    102:       (setq options (dr-record-options dr-record))
                    103:       (setq storage (dr-record-storage dr-record))
                    104:       (if (null fieldinfo)
                    105:         then (dr-error "internal error: can't find field " fieldname
                    106:                        " in record " recname))
                    107:       (if (memq 'access-check options)
                    108:         then (setq recnamefield (assq '-record-field-name-
                    109:                                       (dr-record-fields dr-record)))
                    110:              `((lambda (defrecord-acma)
                    111:                   (cond ((not (eq ',recname
                    112:                                   ,(dr-accessor storage
                    113:                                                 (dr-field-offset
                    114:                                                    recnamefield)
                    115:                                                 'defrecord-acma)))
                    116:                          (record-pkg-illegal-access ',recname ',fieldname
                    117:                                                     defrecord-acma))
                    118:                         (t ,(dr-accessor storage
                    119:                                          (dr-field-offset fieldinfo)
                    120:                                          'defrecord-acma))))
                    121:                ,arg)
                    122:         else (dr-accessor storage (dr-field-offset fieldinfo) arg))))
                    123: 
                    124: 
                    125: (defun dr-accessor (class index obj)
                    126:    ;; determine the correct field accessor to get the index'th element
                    127:    ;; from obj, give the storage type class (either list or vector).
                    128:    ;;
                    129:    (caseq class
                    130:       (list `(nth ,index ,obj))
                    131:       (vector `(vref ,obj ,index))
                    132:       (t (error "record package: illegal storage class " class))))
                    133: 
                    134: (defun record-pkg-illegal-access (recname fieldname value)
                    135:    (error "Unable to access field " fieldname " of record " recname
                    136:          " because this is not an instance of that record: "
                    137:          value))
                    138:                    
                    139:       
                    140:          
                    141:          
                    142: (defun defrecord-name (form)
                    143:    ;; user callable function to return the record name of
                    144:    ;; a record
                    145:    (if (defrecord-namedp form)
                    146:       then (if (dtpr form) then (cadr form)
                    147:            elseif (vectorp form)
                    148:              then (vref form 1))
                    149:       else (error "record-name: this record doesn't have a name " form)))
                    150: 
                    151: (defun defrecord-namedp (form)
                    152:    ;; return t iff form is a named record
                    153:    (let (name)
                    154:       (and (or (and (dtpr form)
                    155:                    (cdr form)
                    156:                    (progn (setq name (cadr form)) t)
                    157:                    (symbolp name))
                    158:               (and (vectorp form)
                    159:                    (>& (vsize form) 1)
                    160:                    (progn (setq name (vref form 1)) t)
                    161:                    (symbolp name)))
                    162:           (get name record-pkg-indicator)
                    163:           t)))
                    164: 
                    165: ;; external functions
                    166: ;; The following functions are user callable
                    167: 
                    168: 
                    169: (declare (macros t))
                    170: 
                    171: (defvar defrecord-default-flags nil)  ; what is assumed in the flag field
                    172: 
                    173: (defmacro defrecord (&rest form)
                    174:    ;; user callable function
                    175:    (if (null form)
                    176:       then (error "defrecord: missing record name in " form))
                    177: 
                    178:    (let ((name (car form))
                    179:         (args (cdr form))
                    180:         (fields)
                    181:         (nameargs)
                    182:         (givenoptions defrecord-default-flags)
                    183:         (savedoptions)
                    184:         ;;options
                    185:         (namedp)(access-checkp) (vectorp))
                    186:       (if (dtpr name)
                    187:         then (setq givenoptions (append givenoptions (cdr name))
                    188:                    name (car name)))
                    189: 
                    190:       (if (not (symbolp name))
                    191:         then (dr-error "non symbol record name " name))
                    192: 
                    193:       ;; process given options
                    194:       (do ((xx  givenoptions (cdr xx)))
                    195:          ((null xx))
                    196:          (caseq (car xx)
                    197:             (named (setq namedp t))
                    198:             (access-check (setq access-checkp t))
                    199:             (vector (setq vectorp t))
                    200:             (t ; ignore
                    201:             )))
                    202:       ;; look for conflicting options
                    203:       (if (and access-checkp (not namedp))
                    204:         then (error "defrecord: Can't specify access-check without also specifying named " form))
                    205: 
                    206:       (if namedp then (push 'named savedoptions))
                    207:       (if access-checkp then (push 'access-check savedoptions))
                    208: 
                    209:       (if namedp
                    210:         then (let ((namefield `(-record-field-name- ',name)))
                    211:                 (if args
                    212:                    then (setq args (cons (car args)
                    213:                                          (cons namefield
                    214:                                                (cdr args))))
                    215:                         else (setq args (list namefield)))))
                    216: 
                    217:       (do ((xx args (cdr xx))
                    218:           (off 0 (1+ off)))
                    219:          ((null xx))
                    220:          (if (dtpr (car xx))
                    221:             then (push (make-dr-field
                    222:                           name (caar xx)
                    223:                           offset off
                    224:                           defaultvalue (cadar xx))
                    225:                        fields)
                    226:             else (push (make-dr-field
                    227:                           name (car xx)
                    228:                           offset off)
                    229:                        fields)))
                    230: 
                    231:       
                    232:       ; return a progn compile of an accessor and a collection
                    233:       ; of accessors
                    234:       `(progn 'compile
                    235:              (eval-when (compile load eval)
                    236:                         (putprop ',name ',(make-dr-record
                    237:                                            name name
                    238:                                            storage (if vectorp
                    239:                                                        then 'vector
                    240:                                                        else 'list)
                    241:                                            options savedoptions
                    242:                                            fields fields)
                    243:                                  ',record-pkg-indicator))
                    244:              (defmacro ,(concat 'make- name) (&rest args)
                    245:                         (record-pkg-construct ',name args))
                    246:              ,@(mapcar '(lambda (dr-field)
                    247:                            `(defmacro ,(concat name
                    248:                                                '-
                    249:                                                (dr-field-name dr-field))
                    250:                                        (arg)
                    251:                                        (record-pkg-access
                    252:                                           ',name
                    253:                                           ',(dr-field-name dr-field)
                    254:                                           arg)))
                    255:                        fields))))
                    256: 
                    257: 
                    258: (putprop 'record t 'version)

unix.superglobalmegacorp.com

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