|
|
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)))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.