;;; -*- Mode:Lisp; Package:SI; Lowercase:True; Base:8 -*- ;;; ** (c) Copyright 1980 Massachusetts Institute of Technology ** ;The master copy of this file is in MC:ALAN;NSTRUCT > ;The current Lisp machine copy is in AI:LISPM2;STRUCT > ;The current Multics copy is in >udd>Mathlab>Bawden>defstruct.lisp ;***** READ THIS PLEASE! ***** ;If you are thinking of munging anything in this file you might want ;to consider finding me (ALAN) and asking me to mung it for you. ;There is more than one copy of this file in the world (it runs in PDP10 ;and Multics MacLisp and on LispMachines) and whatever amazing ;features you are considering adding might be usefull to those people ;as well. If you still cannot contain yourself long enough to find ;me, AT LEAST send me a piece of mail describing what you did and why. ;Thanks for reading this flame. ; Alan Bawden (ALAN@MC) ;Things to fix: ;For LispMachine: ; :%P-LDB type (this is hard to do, punt for now.) ;For Multics: ; displacement is a problem (no displace) ; nth, nthcdr don't exist there ; ldb, dpb don't exist, so byte fields don't work without Mathlab macros ; callable accessors don't work ; dpb is needed at the user's compile time if he is using byte fields. (eval-when (compile) (cond ((status feature ITS) (load '|alan;lspenv init|)) ((status feature Multics) (load '|>udd>Mathlab>Bawden>lspenv.lisp|)))) #+PDP10 (cond ((status nofeature noldmsg) (terpri msgfiles) (princ '#.(and (status feature PDP10) (maknam (nconc (exploden ";Loading DEFSTRUCT ") (exploden (caddr (truename infile)))))) msgfiles))) #+Multics (declare (genprefix defstruct-internal-) (macros t)) #M (eval-when (eval compile) (setsyntax #/: (ascii #\space) nil)) (eval-when (eval) ;;So we may run the thing interpreted we need the simple ;;defstruct that lives here: (cond ((status feature ITS) (load '|alan;struct initial|)) ((status feature Multics) (load '|>udd>Mathlab>Bawden>initial_defstruct|)))) (eval-when (compile) ;;To compile the thing this probably is an old fasl: (!) (cond ((status feature ITS) (load '|alan;struct boot|)) ((status feature Multics) (load '|>udd>Mathlab>Bawden>boot_defstruct|)))) #+Multics (defun nth (n l) (do ((n n (1- n)) (l l (cdr l))) ((zerop n) (car l)))) #+Multics (defun nthcdr (n l) (do ((n n (1- n)) (l l (cdr l))) ((zerop n) l))) #+Multics (defun displace (x y) (cond ((atom y) (rplaca x 'progn) (rplacd x (list y))) (t (rplaca x (car y)) (rplacd x (cdr y)))) x) ;;; You might think you could use progn for this, but you can't! (defun defstruct-dont-displace (x y) x ;ignored y) ;;; Eval this before attempting incremental compilation (eval-when (eval compile) #+PDP10 (defmacro append-symbols args (do ((l (reverse args) (cdr l)) (x) (a nil (if (or (atom x) (not (eq (car x) 'quote))) (if (null a) `(exploden ,x) `(nconc (exploden ,x) ,a)) (let ((l (exploden (cadr x)))) (cond ((null a) `',l) ((= 1 (length l)) `(cons ,(car l) ,a)) (t `(append ',l ,a))))))) ((null l) `(implode ,a)) (setq x (car l)))) #+Multics (defmacro append-symbols args `(make_atom (catenate . ,args))) #+LispM (defmacro append-symbols args `(intern (string-append . ,args))) (defmacro defstruct-putprop (sym val ind) `(push `(defprop ,,sym ,,val ,,ind) returns)) (defmacro defstruct-put-macro (sym fcn) #M `(defstruct-putprop ,sym ,fcn 'macro) #Q (setq fcn (if (and (not (atom fcn)) (eq (car fcn) 'quote)) `'(macro . ,(cadr fcn)) `(cons 'macro ,fcn))) #Q `(push `(fdefine ',,sym ',,fcn t) returns)) (defmacro make-empty () `'%%defstruct-empty%%) (defmacro emptyp (x) `(eq ,x '%%defstruct-empty%%)) ;;;Here we must deal with the fact that error reporting works ;;;differently everywhere! #+PDP10 ;;;first arg is ALWAYS a symbol or a quoted symbol: (defmacro defstruct-error (message &rest args) (let* ((chars (nconc (exploden (if (atom message) message (cadr message))) '(#/.))) ;"Bad frob" => "Bad frob." (new-message (maknam (if (null args) chars (let ((c (car chars))) ;"Bad frob." => "-- bad frob." (or (< c #/A) (> c #/Z) (rplaca chars (+ c #o40))) (append '(#/- #/- #\space) chars)))))) `(error ',new-message ,@(cond ((null args) `()) ((null (cdr args)) `(,(car args))) (t `((list ,@args))))))) #+Multics ;;;first arg is ALWAYS a string: (defmacro defstruct-error (message &rest args) `(error ,(catenate "defstruct: " message (if (null args) "." ": ")) ,@(cond ((null args) `()) ((null (cdr args)) `(,(car args))) (t `((list ,@args)))))) #+LispM ;;;first arg is ALWAYS a string: (defmacro defstruct-error (message &rest args) `(ferror nil ,(string-append message (if (null args) "." ":~@{ ~S~}")) ,@args)) );End of eval-when (eval compile) ;;;If you mung the the ordering af any of the slots in this structure, ;;;be sure to change the version slot and the definition of the function ;;;get-defstruct-description. Munging the defstruct-slot-description ;;;structure should also cause you to change the version "number" in this manner. (defstruct (defstruct-description (:type :list) (:default-pointer description) (:conc-name defstruct-description-) (:alterant nil)) (version 'one) type (displace 'defstruct-dont-displace) slot-alist named-p constructors (default-pointer nil) (but-first nil) size (property-alist nil) ;;end of "expand-time" slots name include (initial-offset 0) (eval-when '(eval compile load)) alterant (conc-name nil) (callable-accessors #M nil #Q t) (size-macro nil) (size-symbol nil) ) (defun get-defstruct-description (name) (let ((description (get name 'defstruct-description))) (cond ((null description) (defstruct-error "A structure with this name has not been defined" name)) ((not (eq (defstruct-description-version) 'one)) (defstruct-error "The description of this structure is out of date, it should be recompiled using the current version of defstruct" name)) (t description)))) ;;;See note above defstruct-description structure before munging this one. (defstruct (defstruct-slot-description (:type :list) (:default-pointer slot-description) (:conc-name defstruct-slot-description-) (:alterant nil)) number (ppss nil) init-code (type 'notype) (property-alist nil) ref-macro-name ) ;;;Perhaps this structure wants a version slot too? (defstruct (defstruct-type-description (:type :list) (:default-pointer type-description) (:conc-name defstruct-type-description-) (:alterant nil)) ref-expander ref-no-args cons-expander cons-flavor (cons-keywords nil) (named-type nil) (overhead 0) (defstruct-expander nil) ) ;; (DEFSTRUCT ( . ) . ) or (DEFSTRUCT . ) ;; ;; is of the form (