Annotation of 43BSD/ucb/lisp/lisplib/macros.l, revision 1.1

1.1     ! root        1: (setq rcs-macros-
        !             2:    "$Header: macros.l,v 1.6 83/11/09 07:09:42 jkf Exp $")
        !             3: 
        !             4: ;; macros.l                            -[Wed Nov  9 07:09:26 1983 by jkf]-
        !             5: ;;
        !             6: ;;  The file contains the common macros for Franz lisp.
        !             7: ;; contents:
        !             8: ;;     defmacro
        !             9: ;;     setf
        !            10: ;;     defsetf
        !            11: ;;     push
        !            12: ;;     pop
        !            13: ;;     let
        !            14: ;;     let*
        !            15: ;;     caseq
        !            16: ;;     listify
        !            17: ;;     include-if
        !            18: ;;     includef-if
        !            19: ;;     defvar
        !            20: 
        !            21: 
        !            22: (declare (macros t))
        !            23: 
        !            24: ;; defmacro
        !            25: (declare (special defmacrooptlist protect-list protect-evform))
        !            26: 
        !            27: ;--- defmacro - name - name of macro being defined
        !            28: ;            - pattrn - formal arguments plus other fun stuff
        !            29: ;            - body   - body of the macro
        !            30: ; This is an intellegent macro creator.  The pattern may contain
        !            31: ; symbols which are formal paramters, lists which show how the
        !            32: ; actual paramters will appear in the args, and these key words
        !            33: ;  &rest name  - the rest of the args (or nil if there are no other args)
        !            34: ;               is bound to name
        !            35: ;  &optional name - bind the next arg to name if it exists, otherwise
        !            36: ;                  bind it to nil
        !            37: ;  &optional (name init) - bind the next arg to name if it exists, otherwise
        !            38: ;                  bind it to init evaluted. (the evaluation is done left
        !            39: ;                  to right for optional forms)
        !            40: ;  &optional (name init given) - bind the next arg to name and given to t
        !            41: ;                  if the arg exists, else bind name to the value of
        !            42: ;                  init and given to nil.
        !            43: ;  &aux name
        !            44: ;  &aux (name init)
        !            45: ;
        !            46: ; Method of operation:
        !            47: ;  the list returned from defmcrosrc has the form ((cxxr name) ...)
        !            48: ;      where cxxr is the loc of the macro arg and name is it formal name
        !            49: ;  defmcrooptlist has the form ((initv cxxr name) ...)
        !            50: ; which is use for &optional args with an initial value.
        !            51: ;  here cxxr looks like cdd..dr which will test of the arg exists.
        !            52: ;
        !            53: ; the variable defmacro-for-compiling determines if the defmacro forms
        !            54: ; will be compiled. If it is t, then we return (progn 'compile (def xx..))
        !            55: ; to insure that it is compiled
        !            56: ;
        !            57: (declare (special defmacro-for-compiling))
        !            58: (cond ((null (boundp 'defmacro-for-compiling))   ; insure it has a value
        !            59:        (setq defmacro-for-compiling nil)))
        !            60: 
        !            61: (def defmacro
        !            62:   (macro (args)
        !            63:     ((lambda 
        !            64:        (tmp tmp2 defmacrooptlist body protect-evform protect-list gutz)
        !            65:        (setq tmp (defmcrosrch (caddr args) '(d r) nil)
        !            66:             body
        !            67:             `(def ,(cadr args)
        !            68:                   (macro (defmacroarg)
        !            69:                     ((lambda ,(mapcar 'cdr tmp)
        !            70:                              ,@(mapcar 
        !            71:                                   '(lambda (arg)
        !            72:                                      `(cond ((setq ,(caddr arg)
        !            73:                                                    (,(cadr arg) 
        !            74:                                                      defmacroarg))
        !            75:                                              ,@(cond ((setq tmp2 (cadddr arg))
        !            76:                                                       `((setq ,tmp2 t))))
        !            77:                                              (setq ,(caddr arg)
        !            78:                                                    (car ,(caddr arg))))
        !            79:                                             (t (setq ,(caddr arg)
        !            80:                                                      ,(car arg)))))
        !            81:                                        defmacrooptlist)
        !            82:                              ,@(cond (protect-evform 
        !            83:                                       (setq gutz 
        !            84:                                             (eval `((lambda ,(mapcar 'cdr tmp)
        !            85:                                                             ,@(cdddr args))
        !            86:                                                     ,@(mapcar
        !            87:                                                        '(lambda (x) `',(cdr x))
        !            88:                                                        tmp))))
        !            89:                                       (ncons 
        !            90:                                        `(cond (,protect-evform
        !            91:                                                      (copy
        !            92:                                                         `((lambda ,',(mapcar 'cdr tmp)
        !            93:                                                              ,',gutz)
        !            94:                                                           ,,@(mapcar 'cdr tmp))))
        !            95:                                               (t ,@(cdddr args)))))
        !            96:                                      (t (cdddr args))))
        !            97:                      ,@(mapcar '(lambda (arg) 
        !            98:                                         (cond ((dtpr (car arg))
        !            99:                                                (caar arg))
        !           100:                                               ((car arg)
        !           101:                                                `(,(car arg) defmacroarg))))
        !           102:                               tmp)))))
        !           103:       (cond (defmacro-for-compiling `(progn 'compile ,body))
        !           104:            (t body)))
        !           105: 
        !           106:      nil nil nil nil nil nil nil)))
        !           107: 
        !           108: (def defmcrosrch
        !           109:   (lambda (pat form sofar)
        !           110:          (cond ((null pat) sofar)
        !           111:                ((atom pat) (cons (cons (concatl `(c ,@form)) pat)
        !           112:                                  sofar))
        !           113:                ((memq (car pat) '(&rest &body))
        !           114:                 (append (defmcrosrch (cadr pat) form nil)
        !           115:                         (defmcrosrch (cddr pat) form sofar)))
        !           116:                ((eq (car pat) '&optional)
        !           117:                 (defmcrooption (cdr pat) form sofar))
        !           118:                ((eq (car pat) '&protect)
        !           119:                 (setq protect-list (cond ((atom (cadr pat))
        !           120:                                           (ncons (cadr pat)))
        !           121:                                          (t (cadr pat)))
        !           122:                       protect-evform (cons 'or (mapcar '(lambda (x)
        !           123:                                                                 `(dtpr ,x))
        !           124:                                                        protect-list)))
        !           125:                 (defmcrosrch (cddr pat) form sofar))
        !           126:                ((eq (car pat) '&aux)
        !           127:                 (mapcar '(lambda (frm)
        !           128:                                  (cond ((atom frm) `((nil) . ,frm))
        !           129:                                        (t `((,(cadr frm)) . ,(car frm)))))
        !           130:                         (cdr pat)))
        !           131:                (t (append (defmcrosrch (car pat) (cons 'a form) nil)
        !           132:                           (defmcrosrch (cdr pat) (cons 'd form) sofar))))))
        !           133: 
        !           134: (def defmcrooption
        !           135:   (lambda (pat form sofar)
        !           136:     ((lambda (tmp tmp2)
        !           137:          (cond ((null pat) sofar)
        !           138:                ((memq (car pat) '(&rest &body))
        !           139:                 (defmcrosrch (cadr pat) form sofar))
        !           140:                (t (cond ((atom (car pat))
        !           141:                          (setq tmp (car pat)))
        !           142:                         (t (setq tmp (caar pat))
        !           143:                            (setq defmacrooptlist 
        !           144:                                  `((,(cadar pat) 
        !           145:                                        ,(concatl `(c ,@form))
        !           146:                                        ,tmp
        !           147:                                        ,(setq tmp2 (caddar pat)))
        !           148:                                    . ,defmacrooptlist))))
        !           149:                   (defmcrooption 
        !           150:                        (cdr pat) 
        !           151:                        (cons 'd form) 
        !           152:                        `( (,(concatl `(ca ,@form)) . ,tmp)
        !           153:                           ,@(cond (tmp2 `((nil . ,tmp2))))
        !           154:                          . ,sofar)))))
        !           155:      nil nil)))
        !           156: 
        !           157: 
        !           158: ;--- lambdacvt :: new lambda converter.
        !           159: ;
        !           160: ; - input is  a lambda body beginning with the argument list.
        !           161: ;
        !           162: ; vrbls   :: list of (name n) where n is the arg number for name
        !           163: ; optlist :: list of (name n defval pred) where optional variable name is
        !           164: ;           (arg n) [if it exists], initval is the value if it doesn't
        !           165: ;           exist,  pred is set to non nil if the arg exists
        !           166: ; auxlist :: list of (name initial-value) for auxillary variables. (&aux)
        !           167: ; restform :: (name n) where args n to #args should be consed and assigned
        !           168: ;              to name.
        !           169: ;
        !           170: ;; strategy:
        !           171: ;  Until the compiler can compiler lexprs better, we try to avoid creating
        !           172: ; a lexpr.  A lexpr is only required if &optional or &rest forms
        !           173: ; appear.
        !           174: ;   Formal parameters which come after &aux are bound and evaluated in a let*
        !           175: ; surrounding the body.  The parameter after a &rest is put in the let*
        !           176: ; too, with an init form which is a complex do loop.  The parameters
        !           177: ; after &optional are put in the lambda expression just below the lexpr.
        !           178: ;
        !           179: (defun lambdacvt (exp)
        !           180:    (prog (vrbls optlist auxlist restform vbl fl-type optcode mainvar
        !           181:          minargs maxargs)
        !           182:       (do ((reallist (car exp) (cdr reallist))
        !           183:           (count 1 (1+ count)))
        !           184:          ((null reallist))
        !           185:          (setq vbl (car reallist))
        !           186:          (cond ((memq vbl '(&rest &body))
        !           187:                 (setq fl-type '&rest count (1- count)))
        !           188:                ((eq '&aux vbl)
        !           189:                 (setq fl-type '&aux count (1- count)))
        !           190:                ((eq '&optional vbl)
        !           191:                 (setq fl-type '&optional count (1- count)))
        !           192:                ((null fl-type)          ; just a variable
        !           193:                 (setq vrbls (cons (list vbl count) vrbls)))
        !           194:                ((eq fl-type '&rest)
        !           195:                 (cond (restform (error "Too many &rest parameters " vbl)))
        !           196:                 (setq restform (list vbl count)))
        !           197:                ((eq fl-type '&aux)
        !           198:                 (cond ((atom vbl)
        !           199:                        (setq auxlist (cons (list vbl nil) auxlist)))
        !           200:                       (t (setq auxlist (cons (list (car vbl) (cadr vbl))
        !           201:                                              auxlist)))))
        !           202:                ((eq fl-type '&optional)
        !           203:                 (cond ((atom vbl)
        !           204:                        (setq optlist
        !           205:                              (cons (list vbl count) optlist)))
        !           206:                       (t (setq optlist
        !           207:                                (cons (cons (car vbl)
        !           208:                                            (cons count
        !           209:                                                  (cdr vbl)))
        !           210:                                      optlist)))))))
        !           211: 
        !           212:       ;; arguments are collected in reverse order, but set them straight
        !           213:       (setq vrbls (nreverse vrbls)
        !           214:            optlist (nreverse optlist)
        !           215:            auxlist (nreverse auxlist)
        !           216:            minargs (length vrbls)
        !           217:            maxargs (cond (restform nil)
        !           218:                          (t (+ (length optlist) minargs))))
        !           219: 
        !           220:       ;; we must covert to a lexpr if there are &optional or &rest forms
        !           221:       (cond ((or optlist restform) (setq mainvar (gensym))))
        !           222:       
        !           223:       ; generate optionals code
        !           224:       (cond (optlist
        !           225:               (setq optcode
        !           226:                     (mapcar '(lambda (x)
        !           227:                                 `(cond ((> ,(cadr x) ,mainvar)
        !           228:                                         (setq ,(car x) ,(caddr x)))
        !           229:                                        (t (setq ,(car x)
        !           230:                                                  (arg ,(cadr x)))
        !           231:                                           ,(cond ((cdddr x)
        !           232:                                                   `(setq ,(cadddr x) t))))))
        !           233:                             optlist))))
        !           234: 
        !           235:       ;; do the rest forms
        !           236:       (cond (restform
        !           237:               (let ((dumind (gensym))
        !           238:                     (dumcol (gensym)))
        !           239:                  (setq restform
        !           240:                        `((,(car restform)
        !           241:                            (do ((,dumind ,mainvar (1- ,dumind))
        !           242:                                 (,dumcol nil (cons (arg ,dumind) ,dumcol)))
        !           243:                                ((< ,dumind ,(cadr restform)) ,dumcol))))))))
        !           244:       
        !           245:       ;; calculate body
        !           246:       (let (body)
        !           247:         (setq body (cond ((or auxlist restform)
        !           248:                             `((let* ,(append restform auxlist)
        !           249:                                  ,@(cdr exp))))
        !           250:                          (t (cdr exp))))
        !           251:         (cond ((null mainvar)          ; no &optional or &rest
        !           252:                (return `(lambda ,(mapcar 'car vrbls)
        !           253:                            (declare (*args ,minargs ,maxargs))
        !           254:                            ,@body)))
        !           255:               (t (return
        !           256:                     `(lexpr (,mainvar)
        !           257:                         (declare (*args ,minargs ,maxargs))
        !           258:                         ((lambda
        !           259:                             ,(nconc
        !           260:                                 (mapcar 'car vrbls)
        !           261:                                 (mapcan '(lambda (x)   ; may be two vrbls
        !           262:                                             (cons (car x)
        !           263:                                                   (cond ((cdddr x) ;pred?
        !           264:                                                          (ncons
        !           265:                                                             (cadddr x))))))
        !           266:                                         optlist))
        !           267:                             ,@optcode ,@body)
        !           268:                          ,@(nconc (mapcar '(lambda (x) `(arg ,(cadr x)))
        !           269:                                           vrbls)
        !           270:                                   (mapcan '(lambda (x)
        !           271:                                               (cond ((cdddr x)
        !           272:                                                      (list nil nil))
        !           273:                                                     (t (list nil))))
        !           274:                                           optlist))))))))))
        !           275: 
        !           276: ;--- defcmacro :: like defmacro but result ends up under cmacro ind
        !           277: ;
        !           278: (def defcmacro
        !           279:    (macro (args)
        !           280:        (let ((name (concat (cadr args) "::cmacro:" (gensym))))
        !           281:           `(eval-when (compile load eval)
        !           282:                    (defmacro ,name ,@(cddr args))
        !           283:                    (putprop ',(cadr args) (getd ',name) 'cmacro)
        !           284:                    (remob ',name)))))
        !           285: 
        !           286: ;;; --- setf macro
        !           287: ;
        !           288: ;(setf (cadr x) 3) --> (rplaca (cdr x) 3)
        !           289: 
        !           290: (defmacro setf (expr val &rest rest)
        !           291:          (cond ((atom expr)
        !           292:                 (or (symbolp expr)
        !           293:                     (error '|-- setf can't handle this.| expr))
        !           294:                 `(setq ,expr ,val))
        !           295:                (t
        !           296:                 (do ((y)
        !           297:                      (tmp))
        !           298:                     (nil)
        !           299:                     (and (dtpr (car expr))
        !           300:                          (setq tmp
        !           301:                                (setf-record-package-access-check expr val))
        !           302:                          (return tmp))
        !           303:                     (or (symbolp (car expr))
        !           304:                         (error '|-- setf can't handle this.| expr))
        !           305:                     (and (setq y (get (car expr) 'setf-expand))
        !           306:                          (return (apply y `(,expr ,val ,@rest))))
        !           307:                     (or (setf-check-cad+r (car expr))
        !           308:                         (and
        !           309:                            (or (setq y (get (car expr) 'cmacro))
        !           310:                                (setq y (getd (car expr))))
        !           311:                            (or (and (dtpr y)
        !           312:                                     (eq (car y) 'macro))
        !           313:                                (and (bcdp y)
        !           314:                                     (eq (getdisc y) 'macro)))
        !           315:                            (setq expr (apply y expr)))
        !           316:                         (error '|-- setf can't handle this.| expr))))))
        !           317: 
        !           318: (defun setf-check-cad+r (name)
        !           319:    ;; invert all c{ad}+r combinations
        !           320:    (if (eq (getcharn name 1) #/c)
        !           321:       then (let ((letters (nreverse (cdr (exploden name)))))
        !           322:              (if (eq (car letters) #/r)
        !           323:                 then (do ((xx (cdr letters) (cdr xx)))
        !           324:                          ((null xx)
        !           325:                           ;; form is c{ad}+r, setf form is
        !           326:                           ;; (rplac<first a or d> (c<rest of a's + d's>r x))
        !           327:                           (setq letters (nreverse letters))
        !           328:                           (eval
        !           329:                              `(defsetf ,name (e v)
        !           330:                                  (list
        !           331:                                     ',(concat "rplac" (ascii (car letters)))
        !           332:                                      (list
        !           333:                                         ',(implode `(#/c ,@(cdr letters)))
        !           334:                                         (cadr e))
        !           335:                                      v)))
        !           336:                           t)
        !           337:                          (if (not (memq (car xx) '(#/a #/d)))
        !           338:                              then (return nil)))))))
        !           339: 
        !           340: (defun setf-record-package-access-check (form val)
        !           341:    ;; When the record package is given the 'access-check' flag,
        !           342:    ;; the access macros it generates have this form:
        !           343:    ;; ((lambda (defrecord-acma)
        !           344:    ;;    (cond (...)
        !           345:    ;;          (t (access-form))))
        !           346:    ;;   res)
        !           347:    ;; To invert this, we make a copy of the form and replace the
        !           348:    ;; access-form with (setf (access-form) val)
        !           349:    ;;
        !           350:    ;; we return nil if the form passed isn't a recognized form
        !           351:    ;;
        !           352:    (cond ((and (dtpr form)
        !           353:               (dtpr (car form))
        !           354:               (eq 'lambda (car (car form)))
        !           355:               (dtpr (cadr (car form)))
        !           356:               (eq (car (cadr (car form)))
        !           357:                   'defrecord-acma))
        !           358:          ((lambda (newform acc)
        !           359:              ; newform is a copy of the given form, so we can
        !           360:              ; clobber it
        !           361:              ; locate the second clause of the cond
        !           362:              (setq acc (cadr   ;; right the 't'
        !           363:                          (caddr  ;; second cond clause
        !           364:                            (caddr  ;; cond is third thing in lambda
        !           365:                               (car newform)))))
        !           366:              (rplaca (cdaddaddar newform) (list 'setf acc val))
        !           367:              newform)
        !           368:           (copy form) nil))
        !           369:         (t nil)))
        !           370:                      
        !           371: (defmacro defsetf (name vars &rest body)
        !           372:          `(eval-when 
        !           373:            (compile load eval)
        !           374:            (defun (,name setf-expand) ,vars . ,body)))
        !           375: 
        !           376: ;--- other setf's for car's and cdr's are generated automatically
        !           377: ;
        !           378: (defsetf car (e v) `(rplaca ,(cadr e) ,v))
        !           379: (defsetf caar (e v) `(rplaca (car ,(cadr e)) ,v))
        !           380: (defsetf cadr (e v) `(rplaca (cdr ,(cadr e)) ,v))
        !           381: (defsetf cdr (e v) `(rplacd ,(cadr e) ,v))
        !           382: (defsetf cdar (e v) `(rplacd (car ,(cadr e)) ,v))
        !           383: (defsetf cddr (e v) `(rplacd (cdr ,(cadr e)) ,v))
        !           384: (defsetf cxr (e v) `(rplacx ,(cadr e) ,(caddr e) ,v))
        !           385: 
        !           386: (defsetf vref (e v) `(vset ,(cadr e) ,(caddr e) ,v))
        !           387: (defsetf vrefi-byte (e v) `(vseti-byte ,(cadr e) ,(caddr e) ,v))
        !           388: (defsetf vrefi-word (e v) `(vseti-word ,(cadr e) ,(caddr e) ,v))
        !           389: (defsetf vrefi-long (e v) `(vseti-long ,(cadr e) ,(caddr e) ,v))
        !           390: 
        !           391: (defsetf nth (e v) `(rplaca (nthcdr ,(cadr e) ,(caddr e)) ,v))
        !           392: (defsetf nthelem (e v) `(rplaca (nthcdr (1- ,(cadr e)) ,(caddr e)) ,v))
        !           393: (defsetf nthcdr (e v) `(rplacd (nthcdr (1- ,(cadr e)) ,(caddr e)) ,v))
        !           394: 
        !           395: (defsetf arraycall (e v) `(store ,e ,v))
        !           396: (defsetf get (e v) `(putprop ,(cadr e) ,v ,(caddr e)))
        !           397: 
        !           398: (defsetf plist (e v) `(setplist ,(cadr e) ,v))
        !           399: 
        !           400: (defsetf symeval (e v) `(set ,(cadr e) ,v))
        !           401: 
        !           402: (defsetf arg (e v) `(setarg ,(cadr e) ,v))
        !           403: 
        !           404: (defsetf args (e v) `(args ,(cadr e) ,v))
        !           405: 
        !           406: 
        !           407: (defmacro push (object list) `(setf ,list (cons ,object ,list)))
        !           408: 
        !           409: ; this relies on the fact that setf returns the value stored.
        !           410: (defmacro pop (list &optional (into nil into-p))
        !           411:   (cond (into-p `(prog1 (setf ,into (car ,list))
        !           412:                         (setf ,list (cdr ,list))))
        !           413:         (t `(prog1 (car ,list)
        !           414:                    (setf ,list (cdr ,list))))))
        !           415: 
        !           416: ; let for franz (with destructuring)
        !           417: ;--- let
        !           418: ;      - binds - binding forms
        !           419: ;      - . body - forms to execute
        !           420: ; the binding forms may have these forms
        !           421: ;   a  local variable a, initially nil
        !           422: ;  (a x)  local variable a, x is evaled and a gets its value initially
        !           423: ;  ((a . (b . c)) x)   three local variables, a,b and c which are given
        !           424: ;                      values corresponding to the location in the value
        !           425: ;                      of x.  Any structure is allowed here. 
        !           426: ;
        !           427: (defmacro let (binds &rest body &aux vrbls vals destrs newgen)
        !           428:   (mapc '(lambda (form)
        !           429:                (cond ((atom form)
        !           430:                       (setq vrbls (cons form vrbls)
        !           431:                             vals  (cons nil vals)))
        !           432:                      ((atom (car form))
        !           433:                       (setq vrbls (cons (car form) vrbls)
        !           434:                             vals  (cons (cadr form) vals)))
        !           435:                      (t (setq newgen (gensym)
        !           436:                               destrs `((,newgen ,@(de-compose (car form) '(r)))
        !           437:                                        ,@destrs)
        !           438:                               vrbls  (cons newgen vrbls)
        !           439:                               vals   (cons (cadr form) vals)))))
        !           440:        binds)
        !           441: 
        !           442:   (mapc '(lambda (frm)
        !           443:                (do ((ll (cdr frm) (cdr ll)))
        !           444:                    ((null ll))
        !           445:                    (setq vrbls (cons (cdar ll) vrbls)
        !           446:                          vals  (cons nil vals))))
        !           447:        destrs)
        !           448: 
        !           449:   (setq vals (nreverse vals)
        !           450:        vrbls (nreverse vrbls)
        !           451:        destrs (nreverse destrs))
        !           452:   `((lambda ,vrbls
        !           453:            ,@(mapcan '(lambda (frm)
        !           454:                               (mapcar '(lambda (vrb)
        !           455:                                                `(setq ,(cdr vrb) (,(car vrb)
        !           456:                                                                  ,(car frm))))
        !           457:                                       (cdr frm)))
        !           458:                      destrs)
        !           459:            ,@body)
        !           460:     ,@vals))
        !           461: 
        !           462: ;--- de-compose
        !           463: ;              form - pattern to de-compose
        !           464: ;              sofar - the sequence of cxxr's needed to get to this part
        !           465: ;                      of the pattern
        !           466: ;  de-compose returns a list of this form
        !           467: ;
        !           468: ;      ((cxxr . a) (cyyr . b) ... )
        !           469: ; which tells how to get to the value for a and b ..etc..
        !           470: ;
        !           471: (def de-compose 
        !           472:   (lambda (form sofar)
        !           473:          (cond ((null form ) nil)
        !           474:                ((atom form) (ncons (cons (apply 'concat (cons 'c sofar))
        !           475:                                          form)))
        !           476:                (t (nconc (de-compose (car form) (cons 'a sofar))
        !           477:                          (de-compose (cdr form) (cons 'd sofar)))))))
        !           478: 
        !           479: ;--- caseq
        !           480: ; use is 
        !           481: ;    (caseq expr
        !           482: ;          (match1 do1)
        !           483: ;          (match2 do2)
        !           484: ;          (t  doifallelsefails))
        !           485: ; the matchi can be atoms in which case an 'eq' test is done, or they
        !           486: ; can be lists in which case a 'memq' test is done.
        !           487: ;
        !           488: 
        !           489: (defmacro caseq (switch &body clauses &aux var code)
        !           490:    (setq var (cond ((symbolp switch) switch) ((gensym 'Z))))
        !           491:    (setq code
        !           492:         `(cond . ,(mapcar '(lambda (clause)
        !           493:                               (cons
        !           494:                                  (let ((test (car clause)))
        !           495:                                     (cond ((eq test t) t)
        !           496:                                           ((dtpr test)
        !           497:                                            `(memq ,var ',test))
        !           498:                                           (t `(eq ,var ',test))))
        !           499:                                  (cdr clause)))
        !           500:                           clauses)))
        !           501:    (cond ((symbolp switch) code)
        !           502:         (`((lambda (,var) ,code) ,switch))))
        !           503: 
        !           504: ;--- selectq :: just like caseq
        !           505: ; except 'otherwise' is recogized as equivalent to 't' as a key
        !           506: ;
        !           507: (defmacro selectq (key . forms)
        !           508:          (setq forms
        !           509:                (mapcar '(lambda (form) (if (eq (car form) 'otherwise)
        !           510:                                             (cons t (cdr form)) form))
        !           511:                        forms))
        !           512:          `(caseq ,key . ,forms))
        !           513: 
        !           514: ;--- let*
        !           515: ;      - binds  - binding forms (like let)
        !           516: ;      - body   - forms to eval (like let)
        !           517: ; this is the same as let, except forms are done in a left to right manner
        !           518: ; in fact, all we do is generate nested lets
        !           519: ;
        !           520: (defmacro let* (binds &rest body)
        !           521:   (do ((ll (reverse binds) (cdr ll)))
        !           522:       ((null ll) (car body))
        !           523:       (setq body `((let (,(car ll)) ,@body)))))
        !           524: 
        !           525: 
        !           526:                   
        !           527: ;--- listify : n  - integer
        !           528: ;      returns a list of the first n args to the enclosing lexpr if
        !           529: ; n is positive, else returns the last -n args to the lexpr if n is
        !           530: ; negative.
        !           531: ; returns nil if n is 0
        !           532: ;
        !           533: (def listify 
        !           534:   (macro (lis)
        !           535:         `(let ((n ,(cadr lis)))
        !           536:               (cond ((eq n 0) nil)
        !           537:                     ((minusp n)
        !           538:                      (do ((i (arg nil)  (1- i))
        !           539:                           (result nil (cons (arg i) result)))
        !           540:                          ((<& i (+ (arg nil) n  1)) result) ))
        !           541:                     (t (do ((i n  (1- i))
        !           542:                             (result nil (cons (arg i) result)))
        !           543:                            ((<& i 1) result) ))))))
        !           544: 
        !           545: ;--- include-if
        !           546: ; form: (include-if <predicate> <filename>)
        !           547: ;  will return (include <filename>) if <predicate> is non-nil
        !           548: ;  This is useful at the beginning of a file to conditionally
        !           549: ;  include a file based on whether it has already been included.
        !           550: ;
        !           551: (defmacro include-if (pred filename)
        !           552:    (cond ((eval pred) `(include ,filename))))
        !           553: 
        !           554: ;--- includef-if
        !           555: ; form: (includef-if <predicate> '<filename>)
        !           556: ;  like the above except it includef's the file.
        !           557: ;
        !           558: (defmacro includef-if (pred filenameexpr)
        !           559:    (cond ((eval pred) `(includef ,filenameexpr))))
        !           560: 
        !           561: ;--- if :: macro for doing conditionalization
        !           562: ;
        !           563: ;  This macro is compatible with both the crufty mit-version and
        !           564: ; the keyword version at ucb.
        !           565: ;
        !           566: ;  simple summary:
        !           567: ;   non-keyword use:
        !           568: ;      (if a b) ==> (cond (a b))
        !           569: ;      (if a b c d e ...) ==> (cond (a b) (t c d e ...))
        !           570: ;   with keywords:
        !           571: ;      (if a then b) ==> (cond (a b))
        !           572: ;      (if a thenret) ==> (cond (a))
        !           573: ;      (if a then b c d e) ==> (cond (a b c d e))
        !           574: ;      (if a then b c  else d) ==> (cond (a b c) (t d))
        !           575: ;      (if a then b c  elseif d  thenret  else g)
        !           576: ;              ==> (cond (a b c) (d) (t g))
        !           577: ;
        !           578: ;   
        !           579: ;
        !           580: ;
        !           581: ; In the syntax description below,
        !           582: ;    optional parts are surrounded by [ and ],
        !           583: ;    + means one or more instances.
        !           584: ;    | means 'or'
        !           585: ;    <expr> is an lisp expression which isn't a keyword
        !           586: ;       The keywords are:  then, thenret, else, elseif.
        !           587: ;    <pred> is also a lisp expression which isn't a keyword.
        !           588: ; 
        !           589: ; <if-stmt> ::=  <simple-if-stmt>
        !           590: ;             | <keyword-if-stmt>
        !           591: ; 
        !           592: ; <simple-if-stmt> ::=  (if <pred> <expr>)
        !           593: ;                    | (if <pred> <expr> <expr>)
        !           594: ; 
        !           595: ; <keyword-if-stmt> ::= (if <pred> <then-clause> [ <else-clause> ] )
        !           596: ; 
        !           597: ; <then-clause> ::=  then <expr>+
        !           598: ;                 | thenret
        !           599: ; 
        !           600: ; <else-clause> ::=  else <expr>+
        !           601: ;                 | elseif <pred> <then-clause> [ <else-clause> ]
        !           602: ;
        !           603: 
        !           604: (declare (special if-keyword-list))
        !           605: 
        !           606: (eval-when (compile load eval)
        !           607:    (setq if-keyword-list '(then thenret elseif else)))
        !           608: 
        !           609: ;--- if
        !           610: ;
        !           611: ;  the keyword if expression is parsed using a simple four state
        !           612: ; automaton.  The expression is parsed in reverse.
        !           613: ; States:
        !           614: ;      init - have parsed a complete predicate,  then clause
        !           615: ;      col  - have collected at least one non keyword in col
        !           616: ;      then - have just seen a then, looking for a predicate
        !           617: ;      compl - have just seen a predicate after an then, looking
        !           618: ;              for elseif or if (i.e. end of forms).
        !           619: ;
        !           620: (defmacro if (&rest args)
        !           621:    (let ((len (length args)))
        !           622:       ;; first eliminate the non-keyword if macro cases
        !           623:       (cond ((<& len 2)
        !           624:             (error "if: not enough arguments " args))
        !           625:            ((and (=& len 2)
        !           626:                  (not (memq (cadr args) if-keyword-list)))
        !           627:             `(cond (,(car args) ,(cadr args))))
        !           628:            ; clause if there are not keywords (and len > 2)
        !           629:            ((do ((xx args (cdr xx)))
        !           630:                 ((null xx) t)
        !           631:                 (cond ((memq (car xx) if-keyword-list)
        !           632:                        (return nil))))
        !           633:             `(cond (,(car args) ,(cadr args))
        !           634:                    (t ,@(cddr args))))
        !           635:            
        !           636:            ;; must be an instance of a keyword if macro
        !           637:            
        !           638:            (t (do ((xx (reverse args) (cdr xx))
        !           639:                    (state 'init)
        !           640:                    (elseseen nil)
        !           641:                    (totalcol nil)
        !           642:                    (col nil))
        !           643:                   ((null xx)
        !           644:                    (cond ((eq state 'compl)
        !           645:                           `(cond ,@totalcol))
        !           646:                          (t (error "if: illegal form " args))))
        !           647:                   (cond ((eq state 'init)
        !           648:                          (cond ((memq (car xx) if-keyword-list)
        !           649:                                 (cond ((eq (car xx) 'thenret)
        !           650:                                        (setq col nil
        !           651:                                              state 'then))
        !           652:                                       (t (error "if: bad keyword "
        !           653:                                                 (car xx) args))))
        !           654:                                (t (setq state 'col
        !           655:                                         col nil)
        !           656:                                   (push (car xx) col))))
        !           657:                         ((eq state 'col)
        !           658:                          (cond ((memq (car xx) if-keyword-list)
        !           659:                                 (cond ((eq (car xx) 'else)
        !           660:                                        (cond (elseseen
        !           661:                                                 (error
        !           662:                                                    "if: multiples elses "
        !           663:                                                    args)))
        !           664:                                        (setq elseseen t)
        !           665:                                        (setq state 'init)
        !           666:                                        (push `(t ,@col) totalcol))
        !           667:                                       ((eq (car xx) 'then)
        !           668:                                        (setq state 'then))
        !           669:                                       (t (error "if: bad keyword "
        !           670:                                                 (car xx) args))))
        !           671:                                (t (push (car xx) col))))
        !           672:                         ((eq state 'then)
        !           673:                          (cond ((memq (car xx) if-keyword-list)
        !           674:                                 (error "if: keyword at the wrong place "
        !           675:                                        (car xx) args))
        !           676:                                (t (setq state 'compl)
        !           677:                                   (push `(,(car xx) ,@col) totalcol))))
        !           678:                         ((eq state 'compl)
        !           679:                          (cond ((not (eq (car xx) 'elseif))
        !           680:                                 (error "if: missing elseif clause " args)))
        !           681:                          (setq state 'init))))))))
        !           682: 
        !           683: ;--- If :: the same as 'if' but defined for those programs that still
        !           684: ;      use it.
        !           685: ;
        !           686: (putd 'If (getd 'if))
        !           687: 
        !           688: ;--- defvar :: a macro for declaring a variable special
        !           689: ;  a variable declared special with defvar will be special when the
        !           690: ; file containing the variable is compiled and also when the file
        !           691: ; containing the defvar is loaded in.  Furthermore, you can specify
        !           692: ; an default value for the variable. It will be set to that value
        !           693: ; iff it is unbound
        !           694: ;
        !           695: (defmacro defvar (variable &optional (initial-value nil iv-p) documentation)
        !           696:   (if iv-p
        !           697:      then `(progn 'compile
        !           698:                   (eval-when (eval compile load)
        !           699:                          (eval '(liszt-declare (special ,variable))))
        !           700:                   (or (boundp ',variable) (setq ,variable ,initial-value)))
        !           701:      else `(eval-when (eval compile load)
        !           702:                  (eval '(liszt-declare (special ,variable))))))
        !           703: 
        !           704: 
        !           705: 
        !           706: 
        !           707: (defmacro list* (&rest forms)
        !           708:          (cond ((null forms) nil)
        !           709:                ((null (cdr forms)) (car forms))
        !           710:                (t (construct-list* forms))))
        !           711: 
        !           712: (eval-when (load compile eval)
        !           713:    (defun construct-list* (forms)
        !           714:          (setq forms (reverse forms))
        !           715:          (do ((forms (cddr forms) (cdr forms))
        !           716:               (return-form `(cons ,(cadr forms) ,(car forms))
        !           717:                             `(cons ,(car forms) ,return-form)))
        !           718:              ((null forms) return-form))))
        !           719: 
        !           720: ;; (<= a b) --> (not (> a b))
        !           721: ;; (<= a b c) --> (not (or (> a b) (> b c)))
        !           722: ;; funny arglist to check for correct number of arguments.
        !           723: 
        !           724: 
        !           725: (defmacro <= (arg1 arg2 &rest rest &aux result)
        !           726:   (setq rest (list* arg1 arg2 rest))
        !           727:   (do l rest (cdr l) (null (cdr l))
        !           728:       (push `(> ,(car l) ,(cadr l)) result))
        !           729:   (cond ((null (cdr result)) `(not ,(car result)))
        !           730:        (t `(not (or . ,(nreverse result))))))
        !           731: 
        !           732: (defmacro <=& (x y)
        !           733:    `(not (>& ,x ,y)))
        !           734: 
        !           735: ;; (>= a b) --> (not (< a b))
        !           736: ;; (>= a b c) --> (not (or (< a b) (< b c)))
        !           737: ;; funny arglist to check for correct number of arguments.
        !           738: 
        !           739: (defmacro >= (arg1 arg2 &rest rest &aux result)
        !           740:   (setq rest (list* arg1 arg2 rest))
        !           741:   (do l rest (cdr l) (null (cdr l))
        !           742:       (push `(< ,(car l) ,(cadr l)) result))
        !           743:   (cond ((null (cdr result)) `(not ,(car result)))
        !           744:        (t `(not (or . ,(nreverse result))))))
        !           745: 
        !           746: 
        !           747: (defmacro >=& (x y)
        !           748:    `(not (<& ,x ,y)))

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.