|
|
1.1 ! root 1: ;;; -*- Mode:Lisp; Package:SI; Lowercase:True; Base:8 -*- ! 2: ;;; ** (c) Copyright 1980 Massachusetts Institute of Technology ** ! 3: (setq rcs-struct- ! 4: "$Header: /usr/lib/lisp/RCS/struct.l,v 1.2 83/08/06 08:41:10 jkf Exp $") ! 5: ! 6: ;The master copy of this file is in MC:ALAN;NSTRUCT > ! 7: ;The current Lisp machine copy is in AI:LISPM2;STRUCT > ! 8: ;The current Multics copy is in >udd>Mathlab>Bawden>defstruct.lisp ! 9: ! 10: ;***** READ THIS PLEASE! ***** ! 11: ;If you are thinking of munging anything in this file you might want ! 12: ;to consider finding me (ALAN) and asking me to mung it for you. ! 13: ;There is more than one copy of this file in the world (it runs in PDP10 ! 14: ;and Multics MacLisp and on LispMachines) and whatever amazing ! 15: ;features you are considering adding might be usefull to those people ! 16: ;as well. If you still cannot contain yourself long enough to find ! 17: ;me, AT LEAST send me a piece of mail describing what you did and why. ! 18: ;Thanks for reading this flame. ! 19: ; Alan Bawden (ALAN@MC) ! 20: ! 21: ;Things to fix: ! 22: ! 23: ;For LispMachine: ! 24: ; :%P-LDB type (this is hard to do, punt for now.) ! 25: ! 26: ;For Multics: ! 27: ; displacement is a problem (no displace) ! 28: ; nth, nthcdr don't exist there ! 29: ; ldb, dpb don't exist, so byte fields don't work without Mathlab macros ! 30: ; callable accessors don't work ! 31: ; dpb is needed at the user's compile time if he is using byte fields. ! 32: ! 33: #+Franz (environment-maclisp) ! 34: ! 35: (eval-when (compile) ! 36: (cond ((status feature ITS) ! 37: (load '|alan;lspenv init|)) ! 38: ((status feature Multics) ! 39: (load '|>udd>Mathlab>Bawden>lspenv.lisp|)))) ! 40: ! 41: #+PDP10 ! 42: (cond ((status nofeature noldmsg) ! 43: (terpri msgfiles) ! 44: (princ '#.(and (status feature PDP10) ! 45: (maknam (nconc (exploden ";Loading DEFSTRUCT ") ! 46: (exploden (caddr (truename infile)))))) ! 47: msgfiles))) ! 48: ! 49: #+Multics ! 50: (declare (genprefix defstruct-internal-) ! 51: (macros t)) ! 52: ! 53: #+Franz ! 54: (declare (macros t)) ! 55: ! 56: #M ! 57: (eval-when (eval compile) ! 58: (setsyntax #/: (ascii #\space) nil)) ! 59: ! 60: ;; #+Franz ! 61: ;; (eval-when (eval compile) ! 62: ;; (setsyntax #/: 'vseparator)) ; make :'s go away ! 63: ! 64: (eval-when (eval) ! 65: ;;So we may run the thing interpreted we need the simple ! 66: ;;defstruct that lives here: ! 67: (cond ((status feature ITS) ! 68: (load '|alan;struct initial|)) ! 69: ((status feature Multics) ! 70: (load '|>udd>Mathlab>Bawden>initial_defstruct|)) ! 71: ((status feature Franz) ! 72: (load 'structini.l)))) ! 73: ! 74: (eval-when (compile) ! 75: ;;To compile the thing this probably is an old fasl: (!) ! 76: (cond ((status feature ITS) ! 77: (load '|alan;struct boot|)) ! 78: ((status feature Multics) ! 79: (load '|>udd>Mathlab>Bawden>boot_defstruct|)) ! 80: ((status feature Franz) ; This is only needed for bootstrapping ! 81: (cond ((and (null (getd 'defstruct)) ! 82: (not (probef ! 83: (concat lisp-library-directory "//struct.o")))) ! 84: (load 'structini)))) ! 85: )) ! 86: ! 87: #+Multics ! 88: (defun nth (n l) ! 89: (do ((n n (1- n)) ! 90: (l l (cdr l))) ! 91: ((zerop n) (car l)))) ! 92: ! 93: #+Multics ! 94: (defun nthcdr (n l) ! 95: (do ((n n (1- n)) ! 96: (l l (cdr l))) ! 97: ((zerop n) l))) ! 98: ! 99: #+(or Franz Multics) ! 100: (defun displace (x y) ! 101: (cond ((atom y) ! 102: (rplaca x 'progn) ! 103: (rplacd x (list y))) ! 104: (t ! 105: (rplaca x (car y)) ! 106: (rplacd x (cdr y)))) ! 107: x) ! 108: ! 109: ;;; You might think you could use progn for this, but you can't! ! 110: (defun defstruct-dont-displace (x y) ! 111: x ;ignored ! 112: y) ! 113: ! 114: ;;; Eval this before attempting incremental compilation ! 115: (eval-when (eval compile) ! 116: ! 117: #+PDP10 ! 118: (defmacro append-symbols args ! 119: (do ((l (reverse args) (cdr l)) ! 120: (x) ! 121: (a nil (if (or (atom x) ! 122: (not (eq (car x) 'quote))) ! 123: (if (null a) ! 124: `(exploden ,x) ! 125: `(nconc (exploden ,x) ,a)) ! 126: (let ((l (exploden (cadr x)))) ! 127: (cond ((null a) `',l) ! 128: ((= 1 (length l)) `(cons ,(car l) ,a)) ! 129: (t `(append ',l ,a))))))) ! 130: ! 131: ((null l) `(implode ,a)) ! 132: (setq x (car l)))) ! 133: ! 134: #+Multics ! 135: (defmacro append-symbols args ! 136: `(make_atom (catenate . ,args))) ! 137: ! 138: #+LispM ! 139: (defmacro append-symbols args ! 140: `(intern (string-append . ,args))) ! 141: ! 142: #+Franz ! 143: (defmacro append-symbols (&rest args) ! 144: `(concat . ,args)) ! 145: ! 146: (defmacro defstruct-putprop (sym val ind) ! 147: `(push `(defprop ,,sym ,,val ,,ind) returns)) ! 148: ! 149: (defmacro defstruct-put-macro (sym fcn) ! 150: #M `(defstruct-putprop ,sym ,fcn 'macro) ! 151: #+lispm ! 152: (setq fcn (if (and (not (atom fcn)) ! 153: (eq (car fcn) 'quote)) ! 154: `'(macro . ,(cadr fcn)) ! 155: `(cons 'macro ,fcn))) ! 156: #+Franz ! 157: (setq fcn (if (and (not (atom fcn)) ! 158: (eq (car fcn) 'quote)) ! 159: `'(macro (macroarg) (,(cadr fcn) macroarg)) ! 160: `(cons 'macro ,fcn))) ;; probably incorrect ! 161: ! 162: #Q `(push `(fdefine ',,sym ',,fcn t) returns) ! 163: #+Franz `(push `(def ,,sym ,,fcn) returns) ! 164: ) ! 165: ! 166: (defmacro make-empty () `'%%defstruct-empty%%) ! 167: ! 168: (defmacro emptyp (x) `(eq ,x '%%defstruct-empty%%)) ! 169: ! 170: ;;;Here we must deal with the fact that error reporting works ! 171: ;;;differently everywhere! ! 172: ! 173: #+(or Franz PDP10) ! 174: ;;;first arg is ALWAYS a symbol or a quoted symbol: ! 175: (defmacro defstruct-error (message &rest args) ! 176: (let* ((chars (nconc (exploden (if (atom message) ! 177: message ! 178: (cadr message))) ! 179: '(#/.))) ;"Bad frob" => "Bad frob." ! 180: (new-message ! 181: (maknam (if (null args) ! 182: chars ! 183: (let ((c (car chars))) ;"Bad frob." => "-- bad frob." ! 184: (or (< c #/A) ! 185: (> c #/Z) ! 186: (rplaca chars (+ c #o40))) ! 187: (append '(#/- #/- #\space) chars)))))) ! 188: `(error ',new-message ! 189: ,@(cond ((null args) `()) ! 190: ((null (cdr args)) `(,(car args))) ! 191: (t `((list ,@args))))))) ! 192: ! 193: #+Multics ! 194: ;;;first arg is ALWAYS a string: ! 195: (defmacro defstruct-error (message &rest args) ! 196: `(error ,(catenate "defstruct: " ! 197: message ! 198: (if (null args) ! 199: "." ! 200: ": ")) ! 201: ,@(cond ((null args) `()) ! 202: ((null (cdr args)) `(,(car args))) ! 203: (t `((list ,@args)))))) ! 204: ! 205: #+LispM ! 206: ;;;first arg is ALWAYS a string: ! 207: (defmacro defstruct-error (message &rest args) ! 208: `(ferror nil ! 209: ,(string-append message ! 210: (if (null args) ! 211: "." ! 212: ":~@{ ~S~}")) ! 213: ,@args)) ! 214: ! 215: );End of eval-when (eval compile) ! 216: ! 217: ;;;If you mung the the ordering af any of the slots in this structure, ! 218: ;;;be sure to change the version slot and the definition of the function ! 219: ;;;get-defstruct-description. Munging the defstruct-slot-description ! 220: ;;;structure should also cause you to change the version "number" in this manner. ! 221: (defstruct (defstruct-description ! 222: (:type :list) ! 223: (:default-pointer description) ! 224: (:conc-name defstruct-description-) ! 225: (:alterant nil)) ! 226: (version 'one) ! 227: type ! 228: (displace 'defstruct-dont-displace) ! 229: slot-alist ! 230: named-p ! 231: constructors ! 232: (default-pointer nil) ! 233: (but-first nil) ! 234: size ! 235: (property-alist nil) ! 236: ;;end of "expand-time" slots ! 237: name ! 238: include ! 239: (initial-offset 0) ! 240: (eval-when '(eval compile load)) ! 241: alterant ! 242: (conc-name nil) ! 243: (callable-accessors #M nil #Q t) ! 244: (size-macro nil) ! 245: (size-symbol nil) ! 246: ) ! 247: ! 248: (defun get-defstruct-description (name) ! 249: (let ((description (get name 'defstruct-description))) ! 250: (cond ((null description) ! 251: (defstruct-error ! 252: "A structure with this name has not been defined" name)) ! 253: ((not (eq (defstruct-description-version) 'one)) ! 254: (defstruct-error "The description of this structure is out of date, ! 255: it should be recompiled using the current version of defstruct" ! 256: name)) ! 257: (t description)))) ! 258: ! 259: ;;;See note above defstruct-description structure before munging this one. ! 260: (defstruct (defstruct-slot-description ! 261: (:type :list) ! 262: (:default-pointer slot-description) ! 263: (:conc-name defstruct-slot-description-) ! 264: (:alterant nil)) ! 265: number ! 266: (ppss nil) ! 267: init-code ! 268: (type 'notype) ! 269: (property-alist nil) ! 270: ref-macro-name ! 271: ) ! 272: ! 273: ;;;Perhaps this structure wants a version slot too? ! 274: (defstruct (defstruct-type-description ! 275: (:type :list) ! 276: (:default-pointer type-description) ! 277: (:conc-name defstruct-type-description-) ! 278: (:alterant nil)) ! 279: ref-expander ! 280: ref-no-args ! 281: cons-expander ! 282: cons-flavor ! 283: (cons-keywords nil) ! 284: (named-type nil) ! 285: (overhead 0) ! 286: (defstruct-expander nil) ! 287: ) ! 288: ! 289: ;; (DEFSTRUCT (<name> . <options>) . <slots>) or (DEFSTRUCT <name> . <slots>) ! 290: ;; ! 291: ;; <options> is of the form (<option> <option> (<option> <val>) ...) ! 292: ;; ! 293: ;; <slots> is of the form (<slot> (<slot> <initial-value>) ...) ! 294: ;; ! 295: ;; Options: ! 296: ;; :TYPE defaults to HUNK ! 297: ;; :CONSTRUCTOR defaults to "MAKE-<name>" ! 298: ;; :DEFAULT-POINTER defaults to empty (if no <val> given defaults to "<name>") ! 299: ;; :CONC-NAME defaults to empty (if no <val> given defaults to "<name>-") ! 300: ;; :SIZE-SYMBOL defaults to empty (if no <val> given defaults to "<name>-SIZE") ! 301: ;; :SIZE-MACRO defaults to empty (if no <val> given defaults to "<name>-SIZE") ! 302: ;; :ALTERANT defaults to "ALTER-<name>" ! 303: ;; :BUT-FIRST must have a <val> given ! 304: ;; :INCLUDE must have a <val> given ! 305: ;; :PROPERTY (:property foo bar) gives the structure a foo property of bar. ! 306: ;; :INITIAL-OFFSET can cause defstruct to skip over that many slots. ! 307: ;; :NAMED takes no value. Tries to make the structure a named type. ! 308: ;; :CALLABLE-ACCESSORS defaults to T on the LispMachine, NIL elsewhere. ! 309: ;; <type> any type name can be used without a <val> instead of saying (TYPE <type>) ! 310: ;; <other> any symbol with a non-nil :defstruct-option property. You say ! 311: ;; (<other> <val>) and the effect is that of (:property <other> <val>) ! 312: ;; ! 313: ;; Properties used: ! 314: ;; DEFSTRUCT-TYPE-DESCRIPTION each type has one, it is a type-description. ! 315: ;; DEFSTRUCT-NAME each constructor, alterant and size macro has one, it is a name. ! 316: ;; DEFSTRUCT-DESCRIPTION each name has one, it is a description (see below). ! 317: ;; DEFSTRUCT-SLOT each accesor has one, it is of the form: (<name> . <slot>) ! 318: ;; :DEFSTRUCT-OPTION if a symbol FOO has this property then it can be used as an ! 319: ;; option giving the structure a FOO property of the value (which must be given). ! 320: ! 321: (defmacro defstruct (options &body items) ! 322: (let* ((description (defstruct-parse-options options)) ! 323: (type-description (get (defstruct-description-type) ! 324: 'defstruct-type-description)) ! 325: (name (defstruct-description-name)) ! 326: (new-slots (defstruct-parse-items items description)) ! 327: (returns nil)) ! 328: (push `',name returns) ! 329: (or (null (defstruct-type-description-defstruct-expander)) ! 330: (setq returns (append (funcall (defstruct-type-description-defstruct-expander) ! 331: description) ! 332: returns))) ! 333: #Q (push `(record-source-file-name ',name) returns) ! 334: (defstruct-putprop name description 'defstruct-description) ! 335: (let ((alterant (defstruct-description-alterant)) ! 336: (size-macro (defstruct-description-size-macro)) ! 337: (size-symbol (defstruct-description-size-symbol))) ! 338: (cond (alterant ! 339: (defstruct-put-macro alterant 'defstruct-expand-alter-macro) ! 340: (defstruct-putprop alterant name 'defstruct-name))) ! 341: (cond (size-macro ! 342: (defstruct-put-macro size-macro 'defstruct-expand-size-macro) ! 343: (defstruct-putprop size-macro name 'defstruct-name))) ! 344: (cond (size-symbol ! 345: (push `(#M defvar #Q defconst #F setq ,size-symbol ! 346: ,(+ (defstruct-description-size) ! 347: (defstruct-type-description-overhead))) ! 348: returns)))) ! 349: (do cs (defstruct-description-constructors) (cdr cs) (null cs) ! 350: (defstruct-put-macro (caar cs) 'defstruct-expand-cons-macro) ! 351: (defstruct-putprop (caar cs) name 'defstruct-name)) ! 352: `(eval-when ,(defstruct-description-eval-when) ! 353: ,.(defstruct-define-ref-macros new-slots description) ! 354: . ,returns))) ! 355: ! 356: (defun defstruct-parse-options (options) ! 357: (let ((name (if (atom options) options (car options))) ! 358: (type nil) ! 359: (constructors (make-empty)) ! 360: (alterant (make-empty)) ! 361: (included nil) ! 362: (named-p nil) ! 363: (description (make-defstruct-description))) ! 364: (setf (defstruct-description-name) name) ! 365: (do ((op) (val) (vals) ! 366: (options (if (atom options) nil (cdr options)) ! 367: (cdr options))) ! 368: ((null options)) ! 369: (if (atom (setq op (car options))) ! 370: (setq vals nil) ! 371: (setq op (prog1 (car op) (setq vals (cdr op))))) ! 372: (setq val (if (null vals) (make-empty) (car vals))) ! 373: #Q AGAIN ! 374: (selectq op ! 375: (:type ! 376: (if (emptyp val) ! 377: (defstruct-error ! 378: "The type option to defstruct must have a value given" ! 379: name)) ! 380: (setq type val)) ! 381: (:default-pointer ! 382: (setf (defstruct-description-default-pointer) ! 383: (if (emptyp val) name val))) ! 384: (:but-first ! 385: (if (emptyp val) ! 386: (defstruct-error ! 387: "The but-first option to defstruct must have a value given" ! 388: name)) ! 389: (setf (defstruct-description-but-first) val)) ! 390: (:conc-name ! 391: (setf (defstruct-description-conc-name) ! 392: (if (emptyp val) ! 393: (append-symbols name '-) ! 394: val))) ! 395: (:callable-accessors ! 396: (setf (defstruct-description-callable-accessors) ! 397: (if (emptyp val) t val))) ! 398: (:displace ! 399: (setf (defstruct-description-displace) ! 400: (cond ((or (emptyp val) ! 401: (eq val 't)) ! 402: 'displace) ! 403: ((null val) 'defstruct-dont-displace) ! 404: (t val)))) ! 405: (:constructor ! 406: (cond ((null val) ! 407: (setq constructors nil)) ! 408: (t ! 409: (and (emptyp val) ! 410: (setq val (append-symbols 'make- name))) ! 411: (setq val (cons val (cdr vals))) ! 412: (if (emptyp constructors) ! 413: (setq constructors (list val)) ! 414: (push val constructors))))) ! 415: (:alterant ! 416: (setq alterant val)) ! 417: (:size-macro ! 418: (setf (defstruct-description-size-macro) ! 419: (if (emptyp val) ! 420: (append-symbols name '-size) ! 421: val))) ! 422: (:size-symbol ! 423: (setf (defstruct-description-size-symbol) ! 424: (if (emptyp val) ! 425: (append-symbols name '-size) ! 426: val))) ! 427: (:include ! 428: (and (emptyp val) ! 429: (defstruct-error ! 430: "The include option to defstruct requires a value" ! 431: name)) ! 432: (setq included val) ! 433: (setf (defstruct-description-include) vals)) ! 434: (:property ! 435: (push (cons (car vals) (if (null (cdr vals)) t (cadr vals))) ! 436: (defstruct-description-property-alist))) ! 437: (:named ! 438: (or (emptyp val) ! 439: (defstruct-error ! 440: "The named option to defstruct doesn't take a value" name)) ! 441: (setq named-p t)) ! 442: (:eval-when ! 443: (and (emptyp val) ! 444: (defstruct-error ! 445: "The eval-when option to defstruct requires a value" ! 446: name)) ! 447: (setf (defstruct-description-eval-when) val)) ! 448: (:initial-offset ! 449: (and (or (emptyp val) ! 450: (not (fixp val))) ! 451: (defstruct-error ! 452: "The initial-offset option to defstruct requires a fixnum" ! 453: name)) ! 454: (setf (defstruct-description-initial-offset) val)) ! 455: (otherwise ! 456: (cond ((get op 'defstruct-type-description) ! 457: (or (emptyp val) ! 458: (defstruct-error ! 459: "defstruct type used as an option with a value" ! 460: op 'in name)) ! 461: (setq type op)) ! 462: ((get op ':defstruct-option) ! 463: (push (cons op (if (emptyp val) t val)) ! 464: (defstruct-description-property-alist))) ! 465: (t ! 466: #Q (multiple-value-bind (new foundp) ! 467: (intern-soft op si:pkg-user-package) ! 468: (or (not foundp) ! 469: (eq op new) ! 470: (progn (setq op new) (go AGAIN)))) ! 471: (defstruct-error ! 472: "defstruct doesn't understand this option" ! 473: op 'in name)))))) ! 474: (cond ((emptyp constructors) ! 475: (setq constructors ! 476: (list (cons (append-symbols 'make- name) ! 477: nil))))) ! 478: (setf (defstruct-description-constructors) constructors) ! 479: (cond ((emptyp alterant) ! 480: (setq alterant ! 481: (append-symbols 'alter- name)))) ! 482: (setf (defstruct-description-alterant) alterant) ! 483: (cond ((not (null type)) ! 484: (let ((type-description ! 485: (or (get type 'defstruct-type-description) ! 486: #Q (multiple-value-bind ! 487: (new foundp) ! 488: (intern-soft type si:pkg-user-package) ! 489: (and foundp ! 490: (not (eq type new)) ! 491: (progn (setq type new) ! 492: (get type 'defstruct-type-description)))) ! 493: (defstruct-error ! 494: "Unknown type in defstruct" ! 495: type 'in name)))) ! 496: (if named-p ! 497: (setq type ! 498: (or (defstruct-type-description-named-type) ! 499: (defstruct-error ! 500: "There is no way to make this defstruct type named" ! 501: type 'in name))))))) ! 502: (cond (included ! 503: (let ((d (get-defstruct-description included))) ! 504: (if (null type) ! 505: (setq type (defstruct-description-type d)) ! 506: (or (eq type (defstruct-description-type d)) ! 507: (defstruct-error ! 508: "defstruct types must agree for include option" ! 509: included 'included-by name))) ! 510: (and named-p ! 511: (not (eq type (defstruct-type-description-named-type ! 512: (or (get type 'defstruct-type-description) ! 513: (defstruct-error ! 514: "Unknown type in defstruct" ! 515: type 'in name 'including included))))) ! 516: (defstruct-error ! 517: "Included defstruct's type isn't a named type" ! 518: included 'included-by name)))) ! 519: ((null type) ! 520: (setq type ! 521: (cond (named-p ! 522: #+PDP10 ':named-hunk ! 523: #+Franz ':named-vector ! 524: #+Multics ':named-list ! 525: #+LispM ':named-array) ! 526: (t ! 527: #+PDP10 ':hunk ! 528: #+Franz ':named-vector ! 529: #+Multics ':list ! 530: #+LispM ':array))))) ! 531: (let ((type-description (or (get type 'defstruct-type-description) ! 532: (defstruct-error ! 533: "Undefined defstruct type" ! 534: type 'in name)))) ! 535: (setf (defstruct-description-type) type) ! 536: (setf (defstruct-description-named-p) ! 537: (eq (defstruct-type-description-named-type) type))) ! 538: description)) ! 539: ! 540: (defun defstruct-parse-items (items description) ! 541: (let ((name (defstruct-description-name)) ! 542: (offset (defstruct-description-initial-offset)) ! 543: (include (defstruct-description-include)) ! 544: (o-slot-alist nil) ! 545: (conc-name (defstruct-description-conc-name))) ! 546: (or (null include) ! 547: (let ((d (get (car include) 'defstruct-description))) ! 548: (setq offset (+ offset (defstruct-description-size d))) ! 549: (setq o-slot-alist ! 550: (subst nil nil (defstruct-description-slot-alist d))) ! 551: (do ((l (cdr include) (cdr l)) ! 552: (it) (val)) ! 553: ((null l)) ! 554: (cond ((atom (setq it (car l))) ! 555: (setq val (make-empty))) ! 556: (t ! 557: (setq val (cadr it)) ! 558: (setq it (car it)))) ! 559: (let ((slot-description (cdr (assq it o-slot-alist)))) ! 560: (and (null slot-description) ! 561: (defstruct-error ! 562: "Unknown slot in included defstruct" ! 563: it 'in include 'included-by name)) ! 564: (setf (defstruct-slot-description-init-code) val))))) ! 565: (do ((i offset (1+ i)) ! 566: (l items (cdr l)) ! 567: (slot-alist nil) ! 568: #+PDP10 (chars (exploden conc-name))) ! 569: ((null l) ! 570: (setq slot-alist (nreverse slot-alist)) ! 571: (setf (defstruct-description-size) i) ! 572: (setf (defstruct-description-slot-alist) ! 573: (nconc o-slot-alist slot-alist)) ! 574: slot-alist) ! 575: (cond ((atom (car l)) ! 576: (push (defstruct-parse-one-field ! 577: (car l) i nil nil conc-name #+PDP10 chars) ! 578: slot-alist)) ! 579: ((atom (caar l)) ! 580: (push (defstruct-parse-one-field ! 581: (caar l) i nil (cdar l) conc-name #+PDP10 chars) ! 582: slot-alist)) ! 583: (t ! 584: (do ll (car l) (cdr ll) (null ll) ! 585: (push (defstruct-parse-one-field ! 586: (caar ll) i (cadar ll) ! 587: (cddar ll) conc-name #+PDP10 chars) ! 588: slot-alist))))))) ! 589: ! 590: (defun defstruct-parse-one-field (it number ppss rest conc-name #+PDP10 chars) ! 591: (let ((mname (if conc-name #+PDP10 (implode (append chars (exploden it))) ! 592: #+Multics (make_atom (catenate conc-name it)) ! 593: #+Franz (concat conc-name it) ! 594: #+LispM (intern (string-append conc-name it)) ! 595: it))) ! 596: (cons it (make-defstruct-slot-description ! 597: number number ! 598: ppss ppss ! 599: init-code (if (null rest) (make-empty) (car rest)) ! 600: ref-macro-name mname)))) ! 601: ! 602: (defun defstruct-define-ref-macros (new-slots description) ! 603: (let ((name (defstruct-description-name)) ! 604: (returns nil)) ! 605: (if (not (defstruct-description-callable-accessors)) ! 606: (do ((l new-slots (cdr l)) ! 607: (mname)) ! 608: ((null l)) ! 609: (setq mname (defstruct-slot-description-ref-macro-name (cdar l))) ! 610: (defstruct-put-macro mname 'defstruct-expand-ref-macro) ! 611: (defstruct-putprop mname (cons name (caar l)) 'defstruct-slot)) ! 612: (let ((type-description ! 613: (get (defstruct-description-type) ! 614: 'defstruct-type-description))) ! 615: (let ((code (defstruct-type-description-ref-expander)) ! 616: (n (defstruct-type-description-ref-no-args)) ! 617: (but-first (defstruct-description-but-first)) ! 618: (default-pointer (defstruct-description-default-pointer))) ! 619: (do ((args nil (cons (gensym) args)) ! 620: (i n (1- i))) ! 621: ((< i 2) ! 622: ;;Last arg (if it exists) is name of structure, ! 623: ;; for documentation purposes. ! 624: (and (= i 1) ! 625: (setq args (cons name args))) ! 626: (let ((body (cons (if but-first ! 627: `(,but-first ,(car args)) ! 628: (car args)) ! 629: (cdr args)))) ! 630: (and default-pointer ! 631: (setq args `((,(car args) ,default-pointer) ! 632: &optional . ,(cdr args)))) ! 633: (setq args (reverse args)) ! 634: (setq body (reverse body)) ! 635: (do ((l new-slots (cdr l)) ! 636: (mname)) ! 637: ((null l)) ! 638: (setq mname (defstruct-slot-description-ref-macro-name ! 639: (cdar l))) ! 640: #M ;;This must come BEFORE the defun. THINK! ! 641: (defstruct-put-macro mname 'defstruct-expand-ref-macro) ! 642: (let ((ref (lexpr-funcall ! 643: code ! 644: (defstruct-slot-description-number (cdar l)) ! 645: description ! 646: body)) ! 647: (ppss (defstruct-slot-description-ppss (cdar l)))) ! 648: (push `(#+(or Franz Maclisp) ! 649: defun #Q defsubst ,mname ,args ! 650: ,(if (null ppss) ref `(ldb ,ppss ,ref))) ! 651: returns)) ! 652: (defstruct-putprop mname ! 653: (cons name (caar l)) ! 654: 'defstruct-slot)))))))) ! 655: returns)) ! 656: ! 657: (defun defstruct-expand-size-macro (x) ! 658: (let ((description (get-defstruct-description (get (car x) 'defstruct-name)))) ! 659: (let ((type-description (get (defstruct-description-type) ! 660: 'defstruct-type-description))) ! 661: (funcall (defstruct-description-displace) ! 662: x ! 663: (+ (defstruct-description-size) ! 664: (defstruct-type-description-overhead)))))) ! 665: ! 666: (defun defstruct-expand-ref-macro (x) ! 667: (let* ((pair (get (car x) 'defstruct-slot)) ! 668: (description (get-defstruct-description (car pair))) ! 669: (type-description ! 670: (get (defstruct-description-type) 'defstruct-type-description)) ! 671: (code (defstruct-type-description-ref-expander)) ! 672: (n (defstruct-type-description-ref-no-args)) ! 673: (args (reverse (cdr x))) ! 674: (nargs (length args)) ! 675: (default (defstruct-description-default-pointer)) ! 676: (but-first (defstruct-description-but-first))) ! 677: (cond ((= n nargs) ! 678: (and but-first ! 679: (rplaca args `(,but-first ,(car args))))) ! 680: ((and (= n (1+ nargs)) default) ! 681: (setq args (cons (if but-first ! 682: `(,but-first ,default) ! 683: default) ! 684: args))) ! 685: (t ! 686: (defstruct-error ! 687: "Wrong number of args to an accessor macro" x))) ! 688: (let* ((slot-description ! 689: (cdr (or (assq (cdr pair) ! 690: (defstruct-description-slot-alist)) ! 691: (defstruct-error ! 692: "This slot no longer exists in this structure" ! 693: (cdr pair) 'in (car pair))))) ! 694: (ref (lexpr-funcall ! 695: code ! 696: (defstruct-slot-description-number) ! 697: description ! 698: (nreverse args))) ! 699: (ppss (defstruct-slot-description-ppss))) ! 700: (funcall (defstruct-description-displace) ! 701: x ! 702: (if (null ppss) ! 703: ref ! 704: `(ldb ,ppss ,ref)))))) ! 705: ! 706: (defun defstruct-parse-setq-style-slots (l slots others x) ! 707: (do ((l l (cddr l)) ! 708: (kludge (cons nil nil))) ! 709: ((null l) kludge) ! 710: (or (and (cdr l) ! 711: (symbolp (car l))) ! 712: (defstruct-error ! 713: "Bad argument list to constructor or alterant macro" x)) ! 714: (defstruct-make-init-dsc kludge (car l) (cadr l) slots others x))) ! 715: ! 716: (defun defstruct-make-init-dsc (kludge name code slots others x) ! 717: (let ((p (assq name slots))) ! 718: (if (null p) ! 719: (if (memq name others) ! 720: (push (cons name code) (cdr kludge)) ! 721: (defstruct-error ! 722: "Unknown slot to constructor or alterant macro" x)) ! 723: (let* ((slot-description (cdr p)) ! 724: (number (defstruct-slot-description-number)) ! 725: (ppss (defstruct-slot-description-ppss)) ! 726: (dsc (assoc number (car kludge)))) ! 727: (cond ((null dsc) ! 728: (setq dsc (list* number nil (make-empty) 0 0 nil)) ! 729: (push dsc (car kludge)))) ! 730: (cond ((null ppss) ! 731: (setf (car (cddr dsc)) code) ! 732: (setf (cadr dsc) t)) ! 733: (t (cond #-Franz ! 734: ((and (numberp ppss) (numberp code)) ! 735: (setf (ldb ppss (cadr (cddr dsc))) -1) ! 736: (setf (ldb ppss (caddr (cddr dsc))) code)) ! 737: (t ! 738: (push (cons ppss code) (cdddr (cddr dsc))))) ! 739: (or (eq t (cadr dsc)) ! 740: (push name (cadr dsc))))))))) ! 741: ! 742: (defun defstruct-code-from-dsc (dsc) ! 743: (let ((code (car (cddr dsc))) ! 744: (mask (cadr (cddr dsc))) ! 745: (bits (caddr (cddr dsc)))) ! 746: (if (emptyp code) ! 747: (setq code bits) ! 748: (or (zerop mask) ! 749: (setq code (if (numberp code) ! 750: (boole 7 bits (boole 2 mask code)) ! 751: (if (zerop (logand mask ! 752: (1+ (logior mask (1- mask))))) ! 753: (let ((ss (haulong (boole 2 mask (1- mask))))) ! 754: `(dpb ,(lsh bits (- ss)) ! 755: ,(logior (lsh ss 6) ! 756: (logand #o77 ! 757: (- (haulong mask) ss))) ! 758: ,code)) ! 759: `(boole 7 ,bits (boole 2 ,mask ,code))))))) ! 760: (do l (cdddr (cddr dsc)) (cdr l) (null l) ! 761: (setq code `(dpb ,(cdar l) ,(caar l) ,code))) ! 762: code)) ! 763: ! 764: (defun defstruct-expand-cons-macro (x) ! 765: (let* ((description (get-defstruct-description (get (car x) 'defstruct-name))) ! 766: (type-description (get (defstruct-description-type) ! 767: 'defstruct-type-description)) ! 768: (slot-alist (defstruct-description-slot-alist)) ! 769: (cons-keywords (defstruct-type-description-cons-keywords)) ! 770: inits kludge ! 771: (constructor-description ! 772: (cdr (or (assq (car x) (defstruct-description-constructors)) ! 773: (defstruct-error ! 774: "This constructor is no longer defined for this structure" ! 775: (car x) 'in (defstruct-description-name))))) ! 776: (aux nil) ! 777: (aux-init nil)) ! 778: (if (null constructor-description) ! 779: (setq kludge (defstruct-parse-setq-style-slots (cdr x) ! 780: slot-alist ! 781: cons-keywords ! 782: x)) ! 783: (prog (args l) ! 784: (setq kludge (cons nil nil)) ! 785: (setq args (cdr x)) ! 786: (setq l (car constructor-description)) ! 787: R (cond ((null l) ! 788: (if (null args) ! 789: (return nil) ! 790: (go barf-tma))) ! 791: ((atom l) (go barf)) ! 792: ((eq (car l) '&optional) (go O)) ! 793: ((eq (car l) '&rest) (go S)) ! 794: ((eq (car l) '&aux) (go A)) ! 795: ((null args) (go barf-tfa))) ! 796: (defstruct-make-init-dsc kludge ! 797: (pop l) ! 798: (pop args) ! 799: slot-alist ! 800: cons-keywords ! 801: x) ! 802: (go R) ! 803: O (and (null args) (go OD)) ! 804: (pop l) ! 805: (cond ((null l) (go barf-tma)) ! 806: ((atom l) (go barf)) ! 807: ((eq (car l) '&optional) (go barf)) ! 808: ((eq (car l) '&rest) (go S)) ! 809: ((eq (car l) '&aux) (go barf-tma))) ! 810: (defstruct-make-init-dsc kludge ! 811: (if (atom (car l)) (car l) (caar l)) ! 812: (pop args) ! 813: slot-alist ! 814: cons-keywords ! 815: x) ! 816: (go O) ! 817: OD (pop l) ! 818: (cond ((null l) (return nil)) ! 819: ((atom l) (go barf)) ! 820: ((eq (car l) '&optional) (go barf)) ! 821: ((eq (car l) '&rest) (go S)) ! 822: ((eq (car l) '&aux) (go A))) ! 823: (or (atom (car l)) ! 824: (defstruct-make-init-dsc kludge ! 825: (caar l) ! 826: (cadar l) ! 827: slot-alist ! 828: cons-keywords ! 829: x)) ! 830: (go OD) ! 831: S (and (atom (cdr l)) (go barf)) ! 832: (defstruct-make-init-dsc kludge ! 833: (cadr l) ! 834: `(list . ,args) ! 835: slot-alist ! 836: cons-keywords ! 837: x) ! 838: (setq l (cddr l)) ! 839: (and (null l) (return nil)) ! 840: (and (atom l) (go barf)) ! 841: (or (eq (car l) '&aux) (go barf)) ! 842: A (pop l) ! 843: (cond ((null l) (return nil)) ! 844: ((atom l) (go barf)) ! 845: ((atom (car l)) ! 846: (push (car l) aux) ! 847: (push (make-empty) aux-init)) ! 848: (t ! 849: (push (caar l) aux) ! 850: (push (cadar l) aux-init))) ! 851: (go A) ! 852: barf (defstruct-error ! 853: "Bad format for defstruct constructor arglist" ! 854: `(,(car x) . ,(car constructor-description))) ! 855: barf-tfa (defstruct-error "Too few arguments to constructor macro" x) ! 856: barf-tma (defstruct-error "Too many arguments to constructor macro" x))) ! 857: (do l slot-alist (cdr l) (null l) ! 858: (let* ((name (caar l)) ! 859: (slot-description (cdar l)) ! 860: (code (do ((aux aux (cdr aux)) ! 861: (aux-init aux-init (cdr aux-init))) ! 862: ((null aux) (defstruct-slot-description-init-code)) ! 863: (and (eq name (car aux)) (return (car aux-init))))) ! 864: (ppss (defstruct-slot-description-ppss))) ! 865: (or (and (emptyp code) (null ppss)) ! 866: (let* ((number (defstruct-slot-description-number)) ! 867: (dsc (assoc number (car kludge)))) ! 868: (cond ((null dsc) ! 869: (setq dsc (list* number nil (make-empty) 0 0 nil)) ! 870: (push dsc (car kludge)))) ! 871: (cond ((emptyp code)) ! 872: ((eq t (cadr dsc))) ! 873: ((null ppss) ! 874: (and (emptyp (car (cddr dsc))) ! 875: (setf (car (cddr dsc)) code))) ! 876: ((memq name (cadr dsc))) ! 877: #-Franz ! 878: ((and (numberp ppss) (numberp code)) ! 879: (setf (ldb ppss (cadr (cddr dsc))) -1) ! 880: (setf (ldb ppss (caddr (cddr dsc))) code)) ! 881: (t ! 882: (push (cons ppss code) (cdddr (cddr dsc))))))))) ! 883: (selectq (defstruct-type-description-cons-flavor) ! 884: (:list ! 885: (do ((l nil (cons nil l)) ! 886: (i (defstruct-description-size) (1- i))) ! 887: ((= i 0) (setq inits l))) ! 888: (do l (car kludge) (cdr l) (null l) ! 889: (setf (nth (caar l) inits) ! 890: (defstruct-code-from-dsc (car l))))) ! 891: (:alist ! 892: (setq inits (car kludge)) ! 893: (do l inits (cdr l) (null l) ! 894: (rplacd (car l) (defstruct-code-from-dsc (car l))))) ! 895: (otherwise ! 896: (defstruct-error ! 897: "Unknown flavor to constructor macro expander" ! 898: (defstruct-description-type)))) ! 899: (funcall (defstruct-description-displace) ! 900: x (funcall (defstruct-type-description-cons-expander) ! 901: inits description (cdr kludge))))) ! 902: ! 903: (defun defstruct-expand-alter-macro (x) ! 904: (let* ((description (get-defstruct-description (get (car x) 'defstruct-name))) ! 905: (type-description (get (defstruct-description-type) ! 906: 'defstruct-type-description)) ! 907: (ref-code (defstruct-type-description-ref-expander))) ! 908: (or (= 1 (defstruct-type-description-ref-no-args)) ! 909: (defstruct-error ! 910: "Alterant macros cannot handle this defstruct type" ! 911: (defstruct-description-type))) ! 912: (do ((l (car (defstruct-parse-setq-style-slots ! 913: (cddr x) ! 914: (defstruct-description-slot-alist) ! 915: nil ! 916: x)) ! 917: (cdr l)) ! 918: (but-first (defstruct-description-but-first)) ! 919: (body nil) ! 920: (var (gensym)) ! 921: (vars nil) ! 922: (vals nil)) ! 923: ((null l) ! 924: (funcall (defstruct-description-displace) ! 925: x ! 926: `((lambda (,var) ! 927: . ,(if (null vars) ! 928: body ! 929: `(((lambda ,vars . ,body) . ,vals)))) ! 930: ,(if but-first ! 931: `(,but-first ,(cadr x)) ! 932: (cadr x))))) ! 933: (let ((ref (funcall ref-code (caar l) description var))) ! 934: (and (emptyp (car (cddr (car l)))) ! 935: (setf (car (cddr (car l))) ref)) ! 936: (let ((code (defstruct-code-from-dsc (car l)))) ! 937: (if (null (cdr l)) ! 938: (push `(setf ,ref ,code) body) ! 939: (let ((sym (gensym))) ! 940: (push `(setf ,ref ,sym) body) ! 941: (push sym vars) ! 942: (push code vals)))))))) ! 943: ! 944: (defmacro defstruct-define-type (type . options) ! 945: (do ((options options (cdr options)) ! 946: (op) (args) ! 947: (type-description (make-defstruct-type-description)) ! 948: (cons-expander nil) ! 949: (ref-expander nil) ! 950: (defstruct-expander nil)) ! 951: ((null options) ! 952: (or cons-expander ! 953: (defstruct-error "No cons option in defstruct-define-type" type)) ! 954: (or ref-expander ! 955: (defstruct-error "No ref option in defstruct-define-type" type)) ! 956: `(progn 'compile ! 957: ,cons-expander ! 958: ,ref-expander ! 959: ,@(and defstruct-expander (list defstruct-expander)) ! 960: (defprop ,type ,type-description defstruct-type-description))) ! 961: (cond ((atom (setq op (car options))) ! 962: (setq args nil)) ! 963: (t ! 964: (setq args (cdr op)) ! 965: (setq op (car op)))) ! 966: #Q AGAIN ! 967: (selectq op ! 968: (:cons ! 969: (or (> (length args) 2) ! 970: (defstruct-error ! 971: "Bad cons option in defstruct-define-type" ! 972: (car options) 'in type)) ! 973: (let ((n (length (car args))) ! 974: (name (append-symbols type '-defstruct-cons))) ! 975: (or (= n 3) ! 976: (defstruct-error ! 977: "Bad cons option in defstruct-define-type" ! 978: (car options) 'in type)) ! 979: (setf (defstruct-type-description-cons-flavor) ! 980: #-LispM (cadr args) ! 981: #+LispM (intern (string (cadr args)) si:pkg-user-package)) ! 982: (setf (defstruct-type-description-cons-expander) name) ! 983: (setq cons-expander `(defun ,name ,(car args) ! 984: . ,(cddr args))))) ! 985: (:ref ! 986: (or (> (length args) 1) ! 987: (defstruct-error ! 988: "Bad ref option in defstruct-define-type" ! 989: (car options) 'in type)) ! 990: (let ((n (length (car args))) ! 991: (name (append-symbols type '-defstruct-ref))) ! 992: (or (> n 2) ! 993: (defstruct-error ! 994: "Bad ref option in defstruct-define-type" ! 995: (car options) 'in type)) ! 996: (setf (defstruct-type-description-ref-no-args) (- n 2)) ! 997: (setf (defstruct-type-description-ref-expander) name) ! 998: (setq ref-expander `(defun ,name ,(car args) ! 999: . ,(cdr args))))) ! 1000: (:overhead ! 1001: (setf (defstruct-type-description-overhead) ! 1002: (if (null args) ! 1003: (defstruct-error ! 1004: "Bad option to defstruct-define-type" ! 1005: (car options) 'in type) ! 1006: (car args)))) ! 1007: (:named ! 1008: (setf (defstruct-type-description-named-type) ! 1009: (if (null args) ! 1010: type ! 1011: (car args)))) ! 1012: (:keywords ! 1013: (setf (defstruct-type-description-cons-keywords) args)) ! 1014: (:defstruct ! 1015: (or (> (length args) 1) ! 1016: (defstruct-error ! 1017: "Bad defstruct option in defstruct-define-type" ! 1018: (car options) 'in type)) ! 1019: (let ((name (append-symbols type '-defstruct-expand))) ! 1020: (setf (defstruct-type-description-defstruct-expander) name) ! 1021: (setq defstruct-expander `(defun ,name . ,args)))) ! 1022: (otherwise ! 1023: #Q (multiple-value-bind (new foundp) ! 1024: (intern-soft op si:pkg-user-package) ! 1025: (or (not foundp) ! 1026: (eq op new) ! 1027: (progn (setq op new) (go AGAIN)))) ! 1028: (defstruct-error ! 1029: "Unknown option to defstruct-define-type" ! 1030: (car options) 'in type))))) ! 1031: ! 1032: #Q ! 1033: (defprop :make-array t :defstruct-option) ! 1034: ! 1035: (defstruct-define-type :array ! 1036: #Q (:named :named-array) ! 1037: #Q (:keywords :make-array) ! 1038: (:cons ! 1039: (arg description etc) :alist ! 1040: #M etc ;ignored in MacLisp ! 1041: #F etc ;ignored in MacLisp ! 1042: #Q (lispm-array-for-defstruct arg #'(lambda (v a i) `(aset ,v ,a ,i)) ! 1043: description etc nil nil nil 1) ! 1044: #M (maclisp-array-for-defstruct arg description 't) ! 1045: #F (maclisp-array-for-defstruct arg description 't)) ! 1046: (:ref ! 1047: (n description arg) ! 1048: description ;ignored ! 1049: #M `(arraycall t ,arg ,n) ! 1050: #F `(arraycall t ,arg ,n) ! 1051: #Q `(aref ,arg ,n))) ! 1052: ! 1053: #Q ! 1054: (defstruct-define-type :named-array ! 1055: (:keywords :make-array) ! 1056: :named (:overhead 1) ! 1057: (:cons ! 1058: (arg description etc) :alist ! 1059: (lispm-array-for-defstruct arg #'(lambda (v a i) `(aset ,v ,a ,(1+ i))) ! 1060: description etc nil t nil 1)) ! 1061: (:ref (n description arg) ! 1062: description ;ignored ! 1063: `(aref ,arg ,(1+ n)))) ! 1064: ! 1065: (defstruct-define-type :fixnum-array ! 1066: #Q (:keywords :make-array) ! 1067: (:cons ! 1068: (arg description etc) :alist ! 1069: #M etc ;ignored in MacLisp ! 1070: #F etc ;ignored in MacLisp ! 1071: #Q (lispm-array-for-defstruct arg #'(lambda (v a i) `(aset ,v ,a ,i)) ! 1072: description etc 'art-32b nil nil 1) ! 1073: #M (maclisp-array-for-defstruct arg description 'fixnum) ! 1074: #F (maclisp-array-for-defstruct arg description 'fixnum)) ! 1075: (:ref ! 1076: (n description arg) ! 1077: description ;ignored ! 1078: #M `(arraycall fixnum ,arg ,n) ! 1079: #F `(arraycall fixnum ,arg ,n) ! 1080: #Q `(aref ,arg ,n))) ! 1081: ! 1082: (defstruct-define-type :flonum-array ! 1083: #Q (:keywords :make-array) ! 1084: (:cons ! 1085: (arg description etc) :alist ! 1086: #M etc ;ignored in MacLisp ! 1087: #F etc ;ignored in MacLisp ! 1088: #Q (lispm-array-for-defstruct arg #'(lambda (v a i) `(aset ,v ,a ,i)) ! 1089: description etc 'art-float nil nil 1) ! 1090: #M (maclisp-array-for-defstruct arg description 'flonum) ! 1091: #F (maclisp-array-for-defstruct arg description 'flonum)) ! 1092: (:ref ! 1093: (n description arg) ! 1094: description ;ignored ! 1095: #M `(arraycall flonum ,arg ,n) ! 1096: #F `(arraycall flonum ,arg ,n) ! 1097: #Q `(aref ,arg ,n))) ! 1098: ! 1099: #M ! 1100: (defstruct-define-type :un-gc-array ! 1101: (:cons ! 1102: (arg description etc) :alist ! 1103: etc ;ignored ! 1104: (maclisp-array-for-defstruct arg description 'nil)) ! 1105: (:ref ! 1106: (n description arg) ! 1107: description ;ignored ! 1108: `(arraycall nil ,arg ,n))) ! 1109: ! 1110: #Q ! 1111: (defstruct-define-type :array-leader ! 1112: (:named :named-array-leader) ! 1113: (:keywords :make-array) ! 1114: (:cons ! 1115: (arg description etc) :alist ! 1116: (lispm-array-for-defstruct arg #'(lambda (v a i) ! 1117: `(store-array-leader ,v ,a ,i)) ! 1118: description etc nil nil t 1)) ! 1119: (:ref ! 1120: (n description arg) ! 1121: description ;ignored ! 1122: `(array-leader ,arg ,n))) ! 1123: ! 1124: #Q ! 1125: (defstruct-define-type :named-array-leader ! 1126: (:keywords :make-array) ! 1127: :named (:overhead 1) ! 1128: (:cons ! 1129: (arg description etc) :alist ! 1130: (lispm-array-for-defstruct ! 1131: arg ! 1132: #'(lambda (v a i) ! 1133: `(store-array-leader ,v ,a ,(if (zerop i) ! 1134: 0 ! 1135: (1+ i)))) ! 1136: description etc nil t t 1)) ! 1137: (:ref ! 1138: (n description arg) ! 1139: description ;ignored ! 1140: (if (zerop n) ! 1141: `(array-leader ,arg 0) ! 1142: `(array-leader ,arg ,(1+ n))))) ! 1143: ! 1144: #Q ! 1145: (defprop :times t :defstruct-option) ! 1146: ! 1147: #Q ! 1148: (defstruct-define-type :grouped-array ! 1149: (:keywords :make-array :times) ! 1150: (:cons ! 1151: (arg description etc) :alist ! 1152: (lispm-array-for-defstruct ! 1153: arg ! 1154: #'(lambda (v a i) `(aset ,v ,a ,i)) ! 1155: description etc nil nil nil ! 1156: (or (cdr (or (assq ':times etc) ! 1157: (assq ':times (defstruct-description-property-alist)))) ! 1158: 1))) ! 1159: (:ref ! 1160: (n description index arg) ! 1161: description ;ignored ! 1162: (cond ((numberp index) ! 1163: `(aref ,arg ,(+ n index))) ! 1164: ((zerop n) ! 1165: `(aref ,arg ,index)) ! 1166: (t `(aref ,arg (+ ,n ,index)))))) ! 1167: ! 1168: #Q ! 1169: (defun lispm-array-for-defstruct (arg cons-init description etc type named-p leader-p times) ! 1170: (let ((p (cons nil nil)) ! 1171: (no-op 'nil)) ! 1172: (defstruct-grok-make-array-args ! 1173: (cdr (assq ':make-array (defstruct-description-property-alist))) ! 1174: p) ! 1175: (defstruct-grok-make-array-args ! 1176: (cdr (assq ':make-array etc)) ! 1177: p) ! 1178: (and type (putprop p type ':type)) ! 1179: (and named-p (putprop p `',(defstruct-description-name) ':named-structure-symbol)) ! 1180: (putprop p ! 1181: (let ((size (if named-p ! 1182: (1+ (defstruct-description-size)) ! 1183: (defstruct-description-size)))) ! 1184: (if (numberp times) ! 1185: (* size times) ! 1186: `(* ,size ,times))) ! 1187: (if leader-p ':leader-length ':dimensions)) ! 1188: (or leader-p ! 1189: (let ((type (get p ':type))) ! 1190: (or (atom type) ! 1191: (not (eq (car type) 'quote)) ! 1192: (setq type (cadr type))) ! 1193: (caseq type ! 1194: ((nil art-q art-q-list)) ! 1195: ((art-32b art-16b art-8b art-4b art-2b art-1b art-string) (setq no-op '0)) ! 1196: ((art-float) (setq no-op '0.0)) ! 1197: (t (setq no-op (make-empty)))))) ! 1198: (do ((creator ! 1199: (let ((dims (remprop p ':dimensions))) ! 1200: (do l (cdr p) (cddr l) (null l) ! 1201: (rplaca l `',(car l))) ! 1202: `(make-array ,(if (null dims) 0 (car dims)) ,@(cdr p)))) ! 1203: (var (gensym)) ! 1204: (set-ups nil (if (equal (cdar l) no-op) ! 1205: set-ups ! 1206: (cons (funcall cons-init (cdar l) var (caar l)) ! 1207: set-ups))) ! 1208: (l arg (cdr l))) ! 1209: ((null l) ! 1210: (if set-ups ! 1211: `((lambda (,var) ! 1212: ,@(nreverse set-ups) ! 1213: ,var) ! 1214: ,creator) ! 1215: creator))))) ! 1216: ! 1217: #Q ! 1218: (defun defstruct-grok-make-array-args (args p) ! 1219: (let ((nargs (length args))) ! 1220: (if (and (not (> nargs 7)) ! 1221: (or (oddp nargs) ! 1222: (do ((l args (cddr l))) ! 1223: ((null l) nil) ! 1224: (or (memq (car l) '(:area :type :displaced-to :leader-list ! 1225: :leader-length :displaced-index-offset ! 1226: :named-structure-symbol :dimensions ! 1227: :length)) ! 1228: (return t))))) ! 1229: (do ((l args (cdr l)) ! 1230: (keylist '(:area :type :dimensions :displaced-to :old-leader-length-or-list ! 1231: :displaced-index-offset :named-structure-symbol) ! 1232: (cdr keylist))) ! 1233: ((null l) ! 1234: (and (boundp 'compiler:compiler-warnings-context) ! 1235: (boundp 'compiler:last-error-function) ! 1236: (not (null compiler:compiler-warnings-context)) ! 1237: (compiler:barf args '|-- old style :MAKE-ARRAY constructor keyword argument| ! 1238: 'compiler:warn)) ! 1239: p) ! 1240: (putprop p (car l) (car keylist))) ! 1241: (do ((l args (cddr l))) ! 1242: ((null l) p) ! 1243: (if (or (null (cdr l)) ! 1244: (not (memq (car l) '(:area :type :displaced-to :leader-list ! 1245: :leader-length :displaced-index-offset ! 1246: :named-structure-symbol :dimensions ! 1247: :length)))) ! 1248: (defstruct-error ! 1249: "defstruct can't grok these make-array arguments" ! 1250: args)) ! 1251: (putprop p ! 1252: (cadr l) ! 1253: (if (eq (car l) ':length) ! 1254: ':dimensions ! 1255: (car l))))))) ! 1256: ! 1257: #+(or Franz Maclisp) ! 1258: (defun maclisp-array-for-defstruct (arg description type) ! 1259: (do ((creator `(array nil ,type ,(defstruct-description-size))) ! 1260: (var (gensym)) ! 1261: (no-op (caseq type ! 1262: (fixnum 0) ! 1263: (flonum 0.0) ! 1264: ((t nil) nil))) ! 1265: (set-ups nil (if (equal (cdar l) no-op) ! 1266: set-ups ! 1267: (cons `(store (arraycall ,type ,var ,(caar l)) ! 1268: ,(cdar l)) ! 1269: set-ups))) ! 1270: (l arg (cdr l))) ! 1271: ((null l) ! 1272: (if set-ups ! 1273: `((lambda (,var) ! 1274: ,@(nreverse set-ups) ! 1275: ,var) ! 1276: ,creator) ! 1277: creator)))) ! 1278: ! 1279: #+PDP10 ! 1280: (defprop :sfa-function t :defstruct-option) ! 1281: ! 1282: #+PDP10 ! 1283: (defprop :sfa-name t :defstruct-option) ! 1284: ! 1285: #+PDP10 ! 1286: (defstruct-define-type :sfa ! 1287: (:keywords :sfa-function :sfa-name) ! 1288: (:cons ! 1289: (arg description etc) :alist ! 1290: (do ((creator `(sfa-create ,(or (cdr (or (assq ':sfa-function etc) ! 1291: (assq ':sfa-function (defstruct-description-property-alist)))) ! 1292: `',(defstruct-description-name)) ! 1293: ,(defstruct-description-size) ! 1294: ,(or (cdr (or (assq ':sfa-name etc) ! 1295: (assq ':sfa-name (defstruct-description-property-alist)))) ! 1296: `',(defstruct-description-name)))) ! 1297: (l arg (cdr l)) ! 1298: (var (gensym)) ! 1299: (set-ups nil (if (null (cdar l)) ! 1300: set-ups ! 1301: (cons `(sfa-store ,var ,(caar l) ! 1302: ,(cdar l)) ! 1303: set-ups)))) ! 1304: ((null l) ! 1305: (if set-ups ! 1306: `((lambda (,var) ! 1307: ,@(nreverse set-ups) ! 1308: ,var) ! 1309: ,creator) ! 1310: creator)))) ! 1311: (:ref ! 1312: (n description arg) ! 1313: description ;ignored ! 1314: `(sfa-get ,arg ,n))) ! 1315: ! 1316: #+(or Franz PDP10) ! 1317: (defstruct-define-type :hunk ! 1318: (:named :named-hunk) ! 1319: (:cons ! 1320: (arg description etc) :list ! 1321: description ;ignored ! 1322: etc ;ignored ! 1323: (if arg ! 1324: #+PDP-10 `(hunk . ,(nconc (cdr arg) (ncons (car arg)))) ! 1325: #+Franz `(hunk . ,arg) ! 1326: (defstruct-error "No slots in hunk type defstruct"))) ! 1327: (:ref ! 1328: (n description arg) ! 1329: description ;ignored ! 1330: `(cxr ,n ,arg))) ! 1331: ! 1332: #+(or Franz PDP10) ! 1333: (defstruct-define-type :named-hunk ! 1334: :named (:overhead 1) ! 1335: (:cons ! 1336: (arg description etc) :list ! 1337: etc ;ignored ! 1338: (if arg ! 1339: #+PDP-10 `(hunk ',(defstruct-description-name) ! 1340: . ,(nconc (cdr arg) (ncons (car arg)))) ! 1341: #+Franz `(hunk ',(defstruct-description-name) ! 1342: . ,arg) ! 1343: `(hunk ',(defstruct-description-name) nil))) ! 1344: (:ref ! 1345: (n description arg) ! 1346: description ;ignored ! 1347: (cond #+PDP-10 ((= n 0) `(cxr 0 ,arg)) ! 1348: (t `(cxr ,(1+ n) ,arg))))) ! 1349: ! 1350: #+(or Franz PDP10 NIL ) ! 1351: (defstruct-define-type :vector ! 1352: #+Franz ! 1353: (:named :named-vector) ! 1354: (:cons ! 1355: (arg description etc) :list ! 1356: description ;ignored ! 1357: etc ;ignored ! 1358: `(vector ,@arg)) ! 1359: (:ref ! 1360: (n description arg) ! 1361: description ;ignored ! 1362: `(vref ,arg ,n))) ! 1363: ! 1364: #+Franz ! 1365: (defstruct-define-type :named-vector ! 1366: :named ! 1367: (:cons ! 1368: (arg description etc) :list ! 1369: description ;ignored ! 1370: etc ;ignored ! 1371: `(let ((nv (vector ,@arg))) ! 1372: (vsetprop nv ',(defstruct-description-name)) ! 1373: nv)) ! 1374: (:ref ! 1375: (n description arg) ! 1376: description ;ignored ! 1377: `(vref ,arg ,n))) ! 1378: ! 1379: (defstruct-define-type :list ! 1380: (:named :named-list) ! 1381: (:cons ! 1382: (arg description etc) :list ! 1383: description ;ignored ! 1384: etc ;ignored ! 1385: `(list . ,arg)) ! 1386: (:ref ! 1387: (n description arg) ! 1388: description ;ignored ! 1389: #+Multics `(,(let ((i (\ n 4))) ! 1390: (cond ((= i 0) 'car) ! 1391: ((= i 1) 'cadr) ! 1392: ((= i 2) 'caddr) ! 1393: (t 'cadddr))) ! 1394: ,(do ((a arg `(cddddr ,a)) ! 1395: (i (// n 4) (1- i))) ! 1396: ((= i 0) a))) ! 1397: #-Multics `(nth ,n ,arg))) ! 1398: ! 1399: (defstruct-define-type :named-list ! 1400: :named (:overhead 1) ! 1401: (:cons ! 1402: (arg description etc) :list ! 1403: etc ;ignored ! 1404: `(list ',(defstruct-description-name) . ,arg)) ! 1405: (:ref ! 1406: (n description arg) ! 1407: description ;ignored ! 1408: #+Multics `(,(let ((i (\ (1+ n) 4))) ! 1409: (cond ((= i 0) 'car) ! 1410: ((= i 1) 'cadr) ! 1411: ((= i 2) 'caddr) ! 1412: (t 'cadddr))) ! 1413: ,(do ((a arg `(cddddr ,a)) ! 1414: (i (// (1+ n) 4) (1- i))) ! 1415: ((= i 0) a))) ! 1416: #-Multics `(nth ,(1+ n) ,arg))) ! 1417: ! 1418: (defstruct-define-type :list* ! 1419: (:cons ! 1420: (arg description etc) :list ! 1421: description ;ignored ! 1422: etc ;ignored ! 1423: `(list* . ,arg)) ! 1424: (:ref ! 1425: (n description arg) ! 1426: (let ((size (1- (defstruct-description-size)))) ! 1427: #+Multics (do ((a arg `(cddddr ,a)) ! 1428: (i (// n 4) (1- i))) ! 1429: ((= i 0) ! 1430: (let* ((i (\ n 4)) ! 1431: (a (cond ((= i 0) a) ! 1432: ((= i 1) `(cdr ,a)) ! 1433: ((= i 2) `(cddr ,a)) ! 1434: (t `(cdddr ,a))))) ! 1435: (if (< n size) `(car ,a) a)))) ! 1436: #-Multics (if (< n size) ! 1437: `(nth ,n ,arg) ! 1438: `(nthcdr ,n ,arg)))) ! 1439: (:defstruct (description) ! 1440: (and (defstruct-description-include) ! 1441: (defstruct-error ! 1442: "Structure of type list* cannot include another" ! 1443: (defstruct-description-name))) ! 1444: nil)) ! 1445: ! 1446: (defstruct-define-type :tree ! 1447: (:cons ! 1448: (arg description etc) :list ! 1449: etc ;ignored ! 1450: (if (null arg) (defstruct-error ! 1451: "defstruct cannot make an empty tree" ! 1452: (defstruct-description-name))) ! 1453: (make-tree-for-defstruct arg (defstruct-description-size))) ! 1454: (:ref ! 1455: (n description arg) ! 1456: (do ((size (defstruct-description-size)) ! 1457: (a arg) ! 1458: (tem)) ! 1459: (()) ! 1460: (cond ((= size 1) (return a)) ! 1461: ((< n (setq tem (// size 2))) ! 1462: (setq a `(car ,a)) ! 1463: (setq size tem)) ! 1464: (t (setq a `(cdr ,a)) ! 1465: (setq size (- size tem)) ! 1466: (setq n (- n tem)))))) ! 1467: (:defstruct (description) ! 1468: (and (defstruct-description-include) ! 1469: (defstruct-error ! 1470: "Structure of type tree cannot include another" ! 1471: (defstruct-description-name))) ! 1472: nil)) ! 1473: ! 1474: (defun make-tree-for-defstruct (arg size) ! 1475: (cond ((= size 1) (car arg)) ! 1476: ((= size 2) `(cons ,(car arg) ,(cadr arg))) ! 1477: (t (do ((a (cdr arg) (cdr a)) ! 1478: (m (// size 2)) ! 1479: (n (1- (// size 2)) (1- n))) ! 1480: ((zerop n) ! 1481: `(cons ,(make-tree-for-defstruct arg m) ! 1482: ,(make-tree-for-defstruct a (- size m)))))))) ! 1483: ! 1484: (defstruct-define-type :fixnum ! 1485: (:cons ! 1486: (arg description etc) :list ! 1487: etc ;ignored ! 1488: (and (or (null arg) ! 1489: (not (null (cdr arg)))) ! 1490: (defstruct-error ! 1491: "Structure of type fixnum must have exactly 1 slot to be constructable" ! 1492: (defstruct-description-name))) ! 1493: (car arg)) ! 1494: (:ref ! 1495: (n description arg) ! 1496: n ;ignored ! 1497: description ;ignored ! 1498: arg)) ! 1499: ! 1500: #+Multics ! 1501: (defprop :external-ptr t :defstruct-option) ! 1502: ! 1503: #+Multics ! 1504: (defstruct-define-type :external ! 1505: (:keywords :external-ptr) ! 1506: (:cons (arg description etc) :alist ! 1507: (let ((ptr (cdr (or (assq ':external-ptr etc) ! 1508: (assq ':external-ptr ! 1509: (defstruct-description-property-alist)) ! 1510: (defstruct-error ! 1511: "No pointer given for external array" ! 1512: (defstruct-description-name)))))) ! 1513: (do ((creator `(array nil external ,ptr ,(defstruct-description-size))) ! 1514: (var (gensym)) ! 1515: (alist arg (cdr alist)) ! 1516: (inits nil (cons `(store (arraycall fixnum ,var ,(caar alist)) ! 1517: ,(cdar alist)) ! 1518: inits))) ! 1519: ((null alist) ! 1520: (if (null inits) ! 1521: creator ! 1522: `((lambda (,var) ,.inits ,var) ! 1523: ,creator)))))) ! 1524: (:ref (n description arg) ! 1525: description ;ignored ! 1526: `(arraycall fixnum ,arg ,n))) ! 1527: ! 1528: (defvar *defstruct-examine&deposit-arg*) ! 1529: ! 1530: (defun defstruct-examine (*defstruct-examine&deposit-arg* ! 1531: name slot-name) ! 1532: (eval (list (defstruct-slot-description-ref-macro-name ! 1533: (defstruct-examine&deposit-find-slot-description ! 1534: name slot-name)) ! 1535: '*defstruct-examine&deposit-arg*))) ! 1536: ! 1537: (defvar *defstruct-examine&deposit-val*) ! 1538: ! 1539: (defun defstruct-deposit (*defstruct-examine&deposit-val* ! 1540: *defstruct-examine&deposit-arg* ! 1541: name slot-name) ! 1542: (eval (list 'setf ! 1543: (list (defstruct-slot-description-ref-macro-name ! 1544: (defstruct-examine&deposit-find-slot-description ! 1545: name slot-name)) ! 1546: '*defstruct-examine&deposit-arg*) ! 1547: '*defstruct-examine&deposit-val*))) ! 1548: ! 1549: #Q ! 1550: (defun defstruct-get-locative (*defstruct-examine&deposit-arg* ! 1551: name slot-name) ! 1552: (let ((slot-description (defstruct-examine&deposit-find-slot-description ! 1553: name slot-name))) ! 1554: (or (null (defstruct-slot-description-ppss)) ! 1555: (defstruct-error ! 1556: "You cannot get a locative to a byte field" ! 1557: slot-name 'in name)) ! 1558: (eval (list 'locf ! 1559: (list (defstruct-slot-description-ref-macro-name) ! 1560: '*defstruct-examine&deposit-arg*))))) ! 1561: ! 1562: (defun defstruct-examine&deposit-find-slot-description (name slot-name) ! 1563: (let ((description (get-defstruct-description name))) ! 1564: (let ((slot-description ! 1565: (cdr (or (assq slot-name (defstruct-description-slot-alist)) ! 1566: (defstruct-error ! 1567: "No such slot in this structure" ! 1568: slot-name 'in name)))) ! 1569: (type-description ! 1570: (or (get (defstruct-description-type) 'defstruct-type-description) ! 1571: (defstruct-error ! 1572: "Undefined defstruct type" ! 1573: (defstruct-description-type))))) ! 1574: (or (= (defstruct-type-description-ref-no-args) 1) ! 1575: (defstruct-error ! 1576: "defstruct-examine and defstruct-deposit cannot handle structures of this type" ! 1577: (defstruct-description-type))) ! 1578: slot-description))) ! 1579: ! 1580: #+PDP10 ! 1581: (defprop defstruct ! 1582: #.(and (status feature PDP10) ! 1583: (caddr (truename infile))) ! 1584: version) ! 1585: ! 1586: (sstatus feature defstruct)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.