home *** CD-ROM | disk | FTP | other *** search
- ;;; (C) Copyright 1984 by Gold Hill Computers
-
- ;; The DEFSTRUCT package
-
- ;; Notes: The DEFSTRUCT package is not completely COMMON Lisp compatible yet.
- ;; The contructor is a macro and not a function as per COMMON Lisp.
-
- ;; The currently supported options are shown below:
-
- ;; (DEFSTRUC NAME-OR-OPTIONS &REST SLOTS)
- ;; Options:
- ;; :CONC-NAME
- ;; :CONSTRUCTOR
- ;; :NAMED
- ;; :PREDICATE
- ;; :PRINT-FUNCTION
- ;; :TYPE {VECTOR | LIST}
-
- ;; Accessor macros
- ;; These macros take the object that is on the STRUCTURE-DESCRIPTOR
- ;; property of the structure name.
- (DEFMACRO DEFST-SLOTS X `(CAR ,(CAR X))) ; returns structures slots
- ; hard wired in DESCRIBE
- (DEFMACRO DEFST-TYPE X `(CADR ,(CAR X))) ; returns type
- (DEFMACRO DEFST-OPTIONS X `(CADDR ,(CAR X))) ; returns all defstruct options
- ; hard wired in DESCRIBE
- (DEFMACRO DEFST-SLOT-CNT X `(NTH 3 ,(CAR X))) ; number of slots (local?)
- (DEFMACRO DEFST-NAMEDP X `(NTH 4 ,(CAR X))) ; whether named structure
-
- ;; These macros take a slot descriptor, member of the DEFST-SLOTS list.
- (DEFMACRO SLOT-NAME X `(CAR ,(CAR X))) ; name of slot
- ; hard wired in DESCRIBE
- (DEFMACRO SLOT-POS X `(CADR ,(CAR X))) ; structure position (local?)
- (DEFMACRO SLOT-DEFAULT X `(CDDR ,(CAR X))) ; default form, returns a LIST
-
- ;;; This function returns the accessor definition function and the
- ;;; form used to tell setf how to perform the update operation.
- (DEFUN DEF-ACCESSOR (SLOT-D CONC-NAME TYPE)
- (LET ((NAME (IF CONC-NAME
- (INTERN (STRING-APPEND CONC-NAME (CAR SLOT-D)))
- (CAR SLOT-D))))
- `((DEFUN ,NAME
- (OBJ)
- ,(CASE TYPE
- (VECTOR `(AREF OBJ ,(CADR SLOT-D)))
- (LIST `(NTH ,(CADR SLOT-D) OBJ))))
- (SETF (GET ',NAME 'SETF-EXPANDER)
- '((,NAME OBJ) . ,(CASE TYPE
- (VECTOR `(AREF OBJ ,(CADR SLOT-D)))
- (LIST `(NTH ,(CADR SLOT-D) OBJ))))))))
-
- ;;; Second value indicates whether value is present or not.
- ;;; Either on LST or default.
- (DEFUN DEFST-GETV (LST SLOT)
- (DO ((I LST (CDDR I)))
- ((NULL I) (WHEN (SLOT-DEFAULT SLOT)
- (VALUES (CAR (SLOT-DEFAULT SLOT))
- (SLOT-NAME SLOT))))
- (WHEN (SAMEPNAMEP (CAR I) (SLOT-NAME SLOT))
- (RETURN (VALUES (SECOND I) (FIRST I))))))
-
- (DEFUN DEFST-KLIST (LST)
- (DO ((I LST (CDDR I))
- (RES NIL (CONS (CAR I) RES)))
- ((NULL I) RES)))
-
-
- ;; Returns the macro that will make the structure.
- (DEFUN MAKE-STRUCTURE (STRUCT NAME NAMEDP)
- `(DEFMACRO ,NAME X (MAKE-STRUCTURE1 ',STRUCT X ',NAMEDP)))
-
- (DEFUN MAKE-STRUCTURE1 (STRUCT ARGS NAMEDP)
- (LET* ((STRUCTURE-DESCRIPTOR (GET STRUCT 'STRUCTURE-DESCRIPTOR))
- (TYPE (DEFST-TYPE STRUCTURE-DESCRIPTOR))
- (SLOT-ALIST (DEFST-SLOTS STRUCTURE-DESCRIPTOR))
- (OPTIONS (DEFST-OPTIONS STRUCTURE-DESCRIPTOR))
- (ST)
- (KLIST (DEFST-KLIST ARGS)))
- (CASE TYPE
- (LIST
- `(LIST
- ,@(DO ((S (DEFST-SLOTS (GET STRUCT 'STRUCTURE-DESCRIPTOR))
- (CDR S))
- VAL KEYP
- (RES (WHEN (DEFST-NAMEDP STRUCTURE-DESCRIPTOR)
- `(NCONS ',STRUCT))))
- ((NULL S)
- (WHEN KLIST
- (ERROR "While making structure ~S, bad keywords: ~S"
- STRUCT KLIST))
- (NREVERSE RES))
- (SETF (VALUES VAL KEYP)
- (DEFST-GETV ARGS (CAR S)))
- (SETQ KLIST (DELETE KEYP KLIST))
- (PUSH VAL RES))))
- (VECTOR
- `(LET ((,(SETQ ST (MAKE-SYMBOL "VAR"))
- (MAKE-ARRAY ,(DEFST-SLOT-CNT STRUCTURE-DESCRIPTOR)
- ,@(WHEN NAMEDP
- `(:NAMED-STRUCTURE-SYMBOL ',STRUCT)))))
- ,@(DO ((S (DEFST-SLOTS (GET STRUCT 'STRUCTURE-DESCRIPTOR))
- (CDR S))
- VAL KEYP
- (RES NIL))
- ((NULL S)
- (WHEN KLIST
- (ERROR "While making structure ~S, bad keywords: ~S"
- STRUCT KLIST))
- (NREVERSE (CONS ST RES)))
- (SETF (VALUES VAL KEYP)
- (DEFST-GETV ARGS (CAR S)))
- (WHEN KEYP
- (PUSH `(ASET ,VAL ,ST ,(SLOT-POS (CAR S)))
- RES))
- (SETQ KLIST (DELETE KEYP KLIST))))))))
-
-
- (DEFUN UPDATE-OFFSET (TYPE NAMEDP)
- (IF NAMEDP 1 0))
-
- (DEFUN DEFSTRUCT-PROCESS-OPTIONS (STRUCT-NAME OPTIONS)
- (LET ((CONC-NAME (STRING-APPEND STRUCT-NAME #\-)) ; set up defaults
- (TYPE 'VECTOR)
- (OFFSET 1)
- (EXP-NAMEDP) ; whether NAMED/UNNAMED specified
- (NAMEDP T)
- (PRINT-FUNCTION)
- (CONSER (INTERN (STRING-APPEND "MAKE-" STRUCT-NAME)))
- (PREDICATE T)
- )
- (DOLIST (OPT OPTIONS)
- (CASE (IF (CONSP OPT) (CAR OPT) 'ATOMIC)
- (:CONC-NAME
- (SETQ CONC-NAME (CADR OPT)))
- (:TYPE
- (UNLESS (MEMBER (SETQ TYPE (CADR OPT))
- '(VECTOR LIST))
- (ERROR "Illegal DEFSTRUCT type: ~S" OPT))
- (UNLESS EXP-NAMEDP (SETQ NAMEDP NIL))
- (SETQ OFFSET (UPDATE-OFFSET TYPE NAMEDP))
- )
- (:NAMED
- (SETQ NAMEDP T EXP-NAMEDP T OFFSET (UPDATE-OFFSET TYPE NAMEDP)))
- (:CONSTRUCTOR
- (SETQ CONSER (CADR OPT)))
- (:PREDICATE
- (SETQ PREDICATE (CADR OPT)))
- (:PRINT-FUNCTION
- (SETQ PRINT-FUNCTION `(PUTPROP ',STRUCT-NAME
- ,(CADR OPT)
- ':PRINT-FUNCTION)))
- (ATOMIC
- (CASE OPT
- ((:CONSTRUCTOR :CONC-NAME)) ; just ignore
- (:NAMED
- (SETQ NAMEDP T EXP-NAMEDP T
- OFFSET (UPDATE-OFFSET TYPE NAMEDP)))
- (OTHERWISE
- (ERROR "Illegal DEFSTRUCT option: ~S" OPT))))
- (OTHERWISE
- (ERROR "Illegal DEFSTRUCT option: ~S" OPT))))
- (WHEN PREDICATE
- (IF (EQ PREDICATE T)
- (SETQ PREDICATE (IF NAMEDP
- (INTERN (STRING-APPEND STRUCT-NAME "-P"))
- NIL))
- (UNLESS NAMEDP
- (ERROR "Can't have PREDICATE with UNNAMED structure"))))
- (WHEN PREDICATE
- (SETQ PREDICATE
- `(DEFUN ,PREDICATE (X)
- ,(IF (EQ TYPE 'LIST)
- `(EQ (CAR X) ',STRUCT-NAME)
- `(TYPEP X ',STRUCT-NAME)))))
- (VALUES CONC-NAME ; prefix for accessor macros or NIL
- TYPE ; structure type
- OFFSET ; offset to structure elements
- NAMEDP ; wheter its named
- PRINT-FUNCTION ; the print function or NIL
- CONSER ; name of the conser or NIL
- PREDICATE ; name of predicate or NIL
- )))
-
-
-
- ; The structure definition info is kept on the STRUCTURE-DESCRIPTOR property
- ; of the structure name. It consists of a list:
- ; ( slot-alist type options)
-
- (DEFMACRO DEFSTRUCT FRM
- (LET* ((SLOTS (MAPCAR '(LAMBDA (X) (IF (CONSP X) X (NCONS X))) (CDR FRM)))
- (S-NAME (IFN (CONSP (CAR FRM)) (CAR FRM) (CAAR FRM)))
- (OPTIONS (IF (CONSP (CAR FRM)) (CDAR FRM) NIL))
- (RESULT `(',S-NAME))
- (SLOT-ALIST))
- (IF (STRINGP (CAAR SLOTS)) (POP SLOTS)) ; dump DOC string
- (MULTIPLE-VALUE-BIND (CONC-NAME STRUCT-TYPE OFFSET NAMEDP
- PRINT-FUNCTION CONSER PREDICATE)
- (DEFSTRUCT-PROCESS-OPTIONS S-NAME OPTIONS)
-
- (SETQ SLOT-ALIST ; entries: (SLOT-NAME INDEX DEFAULT)
- (DO ((I OFFSET (1+ I))
- (SLOT SLOTS (CDR SLOT))
- (ALIST NIL (CONS (IF (CONSP (CDAR SLOT))
- (LIST (CAAR SLOT) I (CADAR SLOT))
- (LIST (CAAR SLOT) I)) ALIST)))
- ((NULL SLOT) (NREVERSE ALIST))))
-
- (PUTPROP S-NAME
- (LIST SLOT-ALIST ; alist of slots
- STRUCT-TYPE ; type of structure
- OPTIONS ; options
- (+ OFFSET (LENGTH SLOT-ALIST)) ; size of structure
- NAMEDP)
- 'STRUCTURE-DESCRIPTOR)
- ;; hook into to the type mechanism
- (WHEN NAMEDP (SETF (GET S-NAME 'SUPER-TYPES)
- (LIST S-NAME (GET 'STRUCTURE 'SUPER-TYPES))))
-
- (DOLIST (SLT SLOT-ALIST) ; define accessors
- (SETQ RESULT
- (APPEND (DEF-ACCESSOR SLT CONC-NAME STRUCT-TYPE) RESULT)))
- (WHEN CONSER ; define make macro
- (PUSH (MAKE-STRUCTURE S-NAME CONSER NAMEDP) RESULT))
- (WHEN PREDICATE (PUSH PREDICATE RESULT))
- (WHEN PRINT-FUNCTION (PUSH PRINT-FUNCTION RESULT))
- (CONS 'PROGN RESULT)
- )))