home *** CD-ROM | disk | FTP | other *** search
- ;;; (C) Copyright 1984 by Gold Hill Computers
-
- (MACRO DEFMACRO (X) (DEFMACRO1 (CDR X)))
-
- (DEFVAR *OPTIONAL-SPECIFIED-FLAGS*)
-
- ;; whether &BODY was specified
- (DEFVAR *DEFMACRO-&BODY-FLAG*)
-
- ;; X is the cdr of the macro definition form.
- (DEFUN DEFMACRO1 (X)
- (UNLESS (TYPEP (CAR X) 'SYMBOL)
- (ERROR "~S: wrong type argument: ~S. A SYMBOL was expected."
- 'DEFMACRO (CAR X)))
- (LET* ((WHOLE-P (AND (LISTP (CADR X)) (EQ '&WHOLE (CAADR X))))
- (*VARLIST* (IF WHOLE-P (LIST (CAR (CDADR X)))))
- (*VALLIST* (IF WHOLE-P (LIST '*MACROARG*)))
- *OPTIONAL-SPECIFIED-FLAGS* *DEFMACRO-&BODY-FLAG*)
- (LET ((PAIR (DEFMACRO-PARSE-&
- (IF WHOLE-P (CDR (CDADR X))(CADR X))
- '(CDR *MACROARG*) 0 (CADR X)))
- (BODY (CDDR X)))
- `(MACRO ,(CAR X) (*MACROARG*)
- ,@(IF (NOT (AND (ZEROP (CAR PAIR))
- (NULL (CDR PAIR))))
- `((AND ,(COND ((ZEROP (CAR PAIR))
- `(> (LENGTH *MACROARG*)
- ,(1+ (CDR PAIR))))
- ((NULL (CDR PAIR))
- `(< (LENGTH *MACROARG*)
- ,(1+ (CAR PAIR))))
- (T `(OR (< (LENGTH *MACROARG*)
- ,(1+ (CAR PAIR)))
- (> (LENGTH *MACROARG*)
- ,(1+ (CDR PAIR))))))
- (ERROR "Wrong number of args to macro: ~S"
- *MACROARG*))))
- ,(DEFMACRO2 (NREVERSE *VARLIST*) (NREVERSE *VALLIST*)
- *OPTIONAL-SPECIFIED-FLAGS* BODY)))))
-
- ;; Put together the various bindings and the body.
- ;; The VARS are bound sequentially since their initializations may depend
- ;; on each other (in left-to-right fashion).
- (DEFUN DEFMACRO2 (VARS VALS FLAGS BODY)
- `(LET* (,@FLAGS
- ,@(MAPCAR #'(LAMBDA (X Y)(LIST X Y)) VARS VALS)
- (*MACROARG1* ,(IF (CDR BODY)
- `(PROGN . ,BODY)
- (CAR BODY))))
- (IF (CONSP *MACROARG1*)
- (RPLACB *MACROARG* *MACROARG1*)
- *MACROARG1*)))
-
- (DEFUN DEFMACRO-PARSE-& (PATTERN PATH STATE EPAT)
- (COND ((NULL PATTERN) (CONS 0 0))
- ((ATOM PATTERN)
- (COND ((> STATE 1) (ERROR "Bad pattern to DEFMACRO: ~S" EPAT))
- (T (DEFMACRO-COLLECT PATTERN PATH)
- (NCONS 0))))
- ((EQ (CAR PATTERN) '&OPTIONAL)
- (COND ((> STATE 0) (ERROR "Bad pattern to DEFMACRO: ~S" EPAT))
- (T (DEFMACRO-PARSE-& (CDR PATTERN) PATH 1 EPAT))))
- ((MEMBER (CAR PATTERN) '(&REST &BODY))
- (AND (EQ (CAR PATTERN) '&BODY)
- (SETQ *DEFMACRO-&BODY-FLAG* T))
- (AND (NULL (CDR PATTERN))
- (ERROR "Bad pattern to DEFMACRO: ~S" EPAT))
- (COND ((> STATE 1) (ERROR "Bad pattern to DEFMACRO: ~S" EPAT))
- (T (DEFMACRO-PARSE-& (CDR PATTERN) PATH 2 EPAT))))
- ((EQ (CAR PATTERN) '&AUX)
- (COND ((> STATE 2) (ERROR "Bad pattern to DEFMACRO: ~S" EPAT))
- (T (DEFMACRO-PARSE-& (CDR PATTERN) PATH 3 EPAT))))
- ((= STATE 0)
- (DEFMACRO-COLLECT (CAR PATTERN) (LIST 'CAR PATH))
- (LET ((PAIR (DEFMACRO-PARSE-&
- (CDR PATTERN) (LIST 'CDR PATH) 0 EPAT)))
- (WHEN (CDR PAIR) (INCF (CDR PAIR)))
- (INCF (CAR PAIR))
- PAIR))
- ((= STATE 1)
- (COND ((ATOM (CAR PATTERN))
- (DEFMACRO-COLLECT (CAR PATTERN)
- `(CAR ,PATH)))
- (T
- (AND (CAR (CDDAR PATTERN))
- (PUSH (CAR (CDDAR PATTERN))
- *OPTIONAL-SPECIFIED-FLAGS*))
- (DEFMACRO-COLLECT (CAAR PATTERN)
- `(COND (,PATH
- ,(AND (CAR (CDDAR PATTERN))
- `(SETQ ,(CAR (CDDAR PATTERN)) T))
- (CAR ,PATH))
- (T ,(CADAR PATTERN))))))
- (LET ((PAIR (DEFMACRO-PARSE-&
- (CDR PATTERN) (LIST 'CDR PATH) 1 EPAT)))
- (IF (NULL (CDR PAIR))
- PAIR
- (INCF (CDR PAIR)))
- PAIR))
- ((= STATE 2)
- (DEFMACRO-COLLECT (CAR PATTERN) PATH)
- (WHEN (CDR PATTERN)
- (WHEN (OR (ATOM (CDR PATTERN))
- (NOT (EQ (CADR PATTERN) '&AUX)))
- (ERROR "Bad pattern to DEFMACRO: ~S" EPAT))
- (DEFMACRO-PARSE-& (CDDR PATTERN) PATH 3 EPAT))
- (NCONS 0))
- ((= STATE 3)
- (IF (ATOM (CAR PATTERN))
- (DEFMACRO-COLLECT (CAR PATTERN) NIL)
- (DEFMACRO-COLLECT (CAAR PATTERN) (CADAR PATTERN)))
- (DEFMACRO-PARSE-& (CDR PATTERN) (LIST 'CDR PATH) 3 EPAT))
- ))
-
- (DEFUN DEFMACRO-COLLECT (PATTERN PATH)
- (COND ((NULL PATTERN))
- ((ATOM PATTERN)
- (WHEN (MEMBER PATTERN '(&REST &AUX &OPTIONAL &WHOLE &BODY))
- (ERROR "~S can only be used in top-level lambda lists."
- PATTERN))
- (SETQ *VARLIST* (CONS PATTERN *VARLIST*))
- (SETQ *VALLIST* (CONS PATH *VALLIST*)))
- (T
- (DEFMACRO-COLLECT (CAR PATTERN) (LIST 'CAR PATH))
- (DEFMACRO-COLLECT (CDR PATTERN) (LIST 'CDR PATH)))))