|
|
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)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.