|
|
1.1 root 1: (setq rcs-macros-
2: "$Header: macros.l,v 1.4 83/09/12 15:24:08 layer Exp $")
3:
4: ;; macros.l -[Mon Aug 15 10:41:25 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: (or (symbolp (car expr))
298: (error '|-- setf can't handle this.| expr))
299: (and (setq y (get (car expr) 'setf-expand))
300: (return (apply y `(,expr ,val ,@rest))))
301: (or (setf-check-cad+r (car expr))
302: (and
303: (or (setq y (get (car expr) 'cmacro))
304: (setq y (getd (car expr))))
305: (or (and (dtpr y)
306: (eq (car y) 'macro))
307: (and (bcdp y)
308: (eq (getdisc y) 'macro)))
309: (setq expr (apply y expr)))
310: (error '|-- setf can't handle this.| expr))))))
311:
312: (defun setf-check-cad+r (name)
313: (if (eq (getcharn name 1) #/c)
314: then (let ((letters (nreverse (cdr (exploden name)))))
315: (if (eq (car letters) #/r)
316: then (do ((xx (cdr letters) (cdr xx)))
317: ((null xx)
318: ;; form is c{ad}+r, setf form is
319: ;; (rplac<first a or d> (c<rest of a's + d's>r x))
320: (setq letters (nreverse letters))
321: (eval
322: `(defsetf ,name (e v)
323: (list
324: ',(concat "rplac" (ascii (car letters)))
325: (list
326: ',(implode `(#/c ,@(cdr letters)))
327: (cadr e))
328: v)))
329: t)
330: (if (not (memq (car xx) '(#/a #/d)))
331: then (return nil)))))))
332:
333: (defmacro defsetf (name vars &rest body)
334: `(eval-when
335: (compile load eval)
336: (defun (,name setf-expand) ,vars . ,body)))
337:
338: ;--- other setf's for car's and cdr's are generated automatically
339: ;
340: (defsetf car (e v) `(rplaca ,(cadr e) ,v))
341: (defsetf caar (e v) `(rplaca (car ,(cadr e)) ,v))
342: (defsetf cadr (e v) `(rplaca (cdr ,(cadr e)) ,v))
343: (defsetf cdr (e v) `(rplacd ,(cadr e) ,v))
344: (defsetf cdar (e v) `(rplacd (car ,(cadr e)) ,v))
345: (defsetf cddr (e v) `(rplacd (cdr ,(cadr e)) ,v))
346: (defsetf cxr (e v) `(rplacx ,(cadr e) ,(caddr e) ,v))
347:
348: (defsetf vref (e v) `(vset ,(cadr e) ,(caddr e) ,v))
349: (defsetf vrefi-byte (e v) `(vseti-byte ,(cadr e) ,(caddr e) ,v))
350: (defsetf vrefi-word (e v) `(vseti-word ,(cadr e) ,(caddr e) ,v))
351: (defsetf vrefi-long (e v) `(vseti-long ,(cadr e) ,(caddr e) ,v))
352:
353: (defsetf nth (e v) `(rplaca (nthcdr ,(cadr e) ,(caddr e)) ,v))
354: (defsetf nthelem (e v) `(rplaca (nthcdr (1- ,(cadr e)) ,(caddr e)) ,v))
355: (defsetf nthcdr (e v) `(rplacd (nthcdr (1- ,(cadr e)) ,(caddr e)) ,v))
356:
357: (defsetf arraycall (e v) `(store ,e ,v))
358: (defsetf get (e v) `(putprop ,(cadr e) ,v ,(caddr e)))
359:
360: (defsetf plist (e v) `(setplist ,(cadr e) ,v))
361:
362: (defsetf symeval (e v) `(set ,(cadr e) ,v))
363:
364: (defsetf arg (e v) `(setarg ,(cadr e) ,v))
365:
366: (defsetf args (e v) `(args ,(cadr e) ,v))
367:
368:
369: (defmacro push (object list) `(setf ,list (cons ,object ,list)))
370:
371: ; this relies on the fact that setf returns the value stored.
372: (defmacro pop (list &optional (into nil into-p))
373: (cond (into-p `(prog1 (setf ,into (car ,list))
374: (setf ,list (cdr ,list))))
375: (t `(prog1 (car ,list)
376: (setf ,list (cdr ,list))))))
377:
378: ; let for franz (with destructuring)
379: ;--- let
380: ; - binds - binding forms
381: ; - . body - forms to execute
382: ; the binding forms may have these forms
383: ; a local variable a, initially nil
384: ; (a x) local variable a, x is evaled and a gets its value initially
385: ; ((a . (b . c)) x) three local variables, a,b and c which are given
386: ; values corresponding to the location in the value
387: ; of x. Any structure is allowed here.
388: ;
389: (defmacro let (binds &rest body &aux vrbls vals destrs newgen)
390: (mapc '(lambda (form)
391: (cond ((atom form)
392: (setq vrbls (cons form vrbls)
393: vals (cons nil vals)))
394: ((atom (car form))
395: (setq vrbls (cons (car form) vrbls)
396: vals (cons (cadr form) vals)))
397: (t (setq newgen (gensym)
398: destrs `((,newgen ,@(de-compose (car form) '(r)))
399: ,@destrs)
400: vrbls (cons newgen vrbls)
401: vals (cons (cadr form) vals)))))
402: binds)
403:
404: (mapc '(lambda (frm)
405: (do ((ll (cdr frm) (cdr ll)))
406: ((null ll))
407: (setq vrbls (cons (cdar ll) vrbls)
408: vals (cons nil vals))))
409: destrs)
410:
411: (setq vals (nreverse vals)
412: vrbls (nreverse vrbls)
413: destrs (nreverse destrs))
414: `((lambda ,vrbls
415: ,@(mapcan '(lambda (frm)
416: (mapcar '(lambda (vrb)
417: `(setq ,(cdr vrb) (,(car vrb)
418: ,(car frm))))
419: (cdr frm)))
420: destrs)
421: ,@body)
422: ,@vals))
423:
424: ;--- de-compose
425: ; form - pattern to de-compose
426: ; sofar - the sequence of cxxr's needed to get to this part
427: ; of the pattern
428: ; de-compose returns a list of this form
429: ;
430: ; ((cxxr . a) (cyyr . b) ... )
431: ; which tells how to get to the value for a and b ..etc..
432: ;
433: (def de-compose
434: (lambda (form sofar)
435: (cond ((null form ) nil)
436: ((atom form) (ncons (cons (apply 'concat (cons 'c sofar))
437: form)))
438: (t (nconc (de-compose (car form) (cons 'a sofar))
439: (de-compose (cdr form) (cons 'd sofar)))))))
440:
441: ;--- caseq
442: ; use is
443: ; (caseq expr
444: ; (match1 do1)
445: ; (match2 do2)
446: ; (t doifallelsefails))
447: ; the matchi can be atoms in which case an 'eq' test is done, or they
448: ; can be lists in which case a 'memq' test is done.
449: ;
450:
451: (defmacro caseq (switch &body clauses &aux var code)
452: (setq var (cond ((symbolp switch) switch) ((gensym 'Z))))
453: (setq code
454: `(cond . ,(mapcar '(lambda (clause)
455: (cons
456: (let ((test (car clause)))
457: (cond ((eq test t) t)
458: ((dtpr test)
459: `(memq ,var ',test))
460: (t `(eq ,var ',test))))
461: (cdr clause)))
462: clauses)))
463: (cond ((symbolp switch) code)
464: (`((lambda (,var) ,code) ,switch))))
465:
466: ;--- selectq :: just like caseq
467: ; except 'otherwise' is recogized as equivalent to 't' as a key
468: ;
469: (defmacro selectq (key . forms)
470: (setq forms
471: (mapcar '(lambda (form) (if (eq (car form) 'otherwise)
472: (cons t (cdr form)) form))
473: forms))
474: `(caseq ,key . ,forms))
475:
476: ;--- let*
477: ; - binds - binding forms (like let)
478: ; - body - forms to eval (like let)
479: ; this is the same as let, except forms are done in a left to right manner
480: ; in fact, all we do is generate nested lets
481: ;
482: (defmacro let* (binds &rest body)
483: (do ((ll (reverse binds) (cdr ll)))
484: ((null ll) (car body))
485: (setq body `((let (,(car ll)) ,@body)))))
486:
487:
488:
489: ;--- listify : n - integer
490: ; returns a list of the first n args to the enclosing lexpr if
491: ; n is positive, else returns the last -n args to the lexpr if n is
492: ; negative.
493: ; returns nil if n is 0
494: ;
495: (def listify
496: (macro (lis)
497: `(let ((n ,(cadr lis)))
498: (cond ((eq n 0) nil)
499: ((minusp n)
500: (do ((i (arg nil) (1- i))
501: (result nil (cons (arg i) result)))
502: ((<& i (+ (arg nil) n 1)) result) ))
503: (t (do ((i n (1- i))
504: (result nil (cons (arg i) result)))
505: ((<& i 1) result) ))))))
506:
507: ;--- include-if
508: ; form: (include-if <predicate> <filename>)
509: ; will return (include <filename>) if <predicate> is non-nil
510: ; This is useful at the beginning of a file to conditionally
511: ; include a file based on whether it has already been included.
512: ;
513: (defmacro include-if (pred filename)
514: (cond ((eval pred) `(include ,filename))))
515:
516: ;--- includef-if
517: ; form: (includef-if <predicate> '<filename>)
518: ; like the above except it includef's the file.
519: ;
520: (defmacro includef-if (pred filenameexpr)
521: (cond ((eval pred) `(includef ,filenameexpr))))
522:
523: ;--- if :: macro for doing conditionalization
524: ;
525: ; This macro is compatible with both the crufty mit-version and
526: ; the keyword version at ucb.
527: ;
528: ; simple summary:
529: ; non-keyword use:
530: ; (if a b) ==> (cond (a b))
531: ; (if a b c d e ...) ==> (cond (a b) (t c d e ...))
532: ; with keywords:
533: ; (if a then b) ==> (cond (a b))
534: ; (if a thenret) ==> (cond (a))
535: ; (if a then b c d e) ==> (cond (a b c d e))
536: ; (if a then b c else d) ==> (cond (a b c) (t d))
537: ; (if a then b c elseif d thenret else g)
538: ; ==> (cond (a b c) (d) (t g))
539: ;
540: ;
541: ;
542: ;
543: ; In the syntax description below,
544: ; optional parts are surrounded by [ and ],
545: ; + means one or more instances.
546: ; | means 'or'
547: ; <expr> is an lisp expression which isn't a keyword
548: ; The keywords are: then, thenret, else, elseif.
549: ; <pred> is also a lisp expression which isn't a keyword.
550: ;
551: ; <if-stmt> ::= <simple-if-stmt>
552: ; | <keyword-if-stmt>
553: ;
554: ; <simple-if-stmt> ::= (if <pred> <expr>)
555: ; | (if <pred> <expr> <expr>)
556: ;
557: ; <keyword-if-stmt> ::= (if <pred> <then-clause> [ <else-clause> ] )
558: ;
559: ; <then-clause> ::= then <expr>+
560: ; | thenret
561: ;
562: ; <else-clause> ::= else <expr>+
563: ; | elseif <pred> <then-clause> [ <else-clause> ]
564: ;
565:
566: (declare (special if-keyword-list))
567:
568: (eval-when (compile load eval)
569: (setq if-keyword-list '(then thenret elseif else)))
570:
571: ;--- if
572: ;
573: ; the keyword if expression is parsed using a simple four state
574: ; automaton. The expression is parsed in reverse.
575: ; States:
576: ; init - have parsed a complete predicate, then clause
577: ; col - have collected at least one non keyword in col
578: ; then - have just seen a then, looking for a predicate
579: ; compl - have just seen a predicate after an then, looking
580: ; for elseif or if (i.e. end of forms).
581: ;
582: (defmacro if (&rest args)
583: (let ((len (length args)))
584: ;; first eliminate the non-keyword if macro cases
585: (cond ((<& len 2)
586: (error "if: not enough arguments " args))
587: ((and (=& len 2)
588: (not (memq (cadr args) if-keyword-list)))
589: `(cond (,(car args) ,(cadr args))))
590: ; clause if there are not keywords (and len > 2)
591: ((do ((xx args (cdr xx)))
592: ((null xx) t)
593: (cond ((memq (car xx) if-keyword-list)
594: (return nil))))
595: `(cond (,(car args) ,(cadr args))
596: (t ,@(cddr args))))
597:
598: ;; must be an instance of a keyword if macro
599:
600: (t (do ((xx (reverse args) (cdr xx))
601: (state 'init)
602: (elseseen nil)
603: (totalcol nil)
604: (col nil))
605: ((null xx)
606: (cond ((eq state 'compl)
607: `(cond ,@totalcol))
608: (t (error "if: illegal form " args))))
609: (cond ((eq state 'init)
610: (cond ((memq (car xx) if-keyword-list)
611: (cond ((eq (car xx) 'thenret)
612: (setq col nil
613: state 'then))
614: (t (error "if: bad keyword "
615: (car xx) args))))
616: (t (setq state 'col
617: col nil)
618: (push (car xx) col))))
619: ((eq state 'col)
620: (cond ((memq (car xx) if-keyword-list)
621: (cond ((eq (car xx) 'else)
622: (cond (elseseen
623: (error
624: "if: multiples elses "
625: args)))
626: (setq elseseen t)
627: (setq state 'init)
628: (push `(t ,@col) totalcol))
629: ((eq (car xx) 'then)
630: (setq state 'then))
631: (t (error "if: bad keyword "
632: (car xx) args))))
633: (t (push (car xx) col))))
634: ((eq state 'then)
635: (cond ((memq (car xx) if-keyword-list)
636: (error "if: keyword at the wrong place "
637: (car xx) args))
638: (t (setq state 'compl)
639: (push `(,(car xx) ,@col) totalcol))))
640: ((eq state 'compl)
641: (cond ((not (eq (car xx) 'elseif))
642: (error "if: missing elseif clause " args)))
643: (setq state 'init))))))))
644:
645: ;--- If :: the same as 'if' but defined for those programs that still
646: ; use it.
647: ;
648: (putd 'If (getd 'if))
649:
650: ;--- defvar :: a macro for declaring a variable special
651: ; a variable declared special with defvar will be special when the
652: ; file containing the variable is compiled and also when the file
653: ; containing the defvar is loaded in. Furthermore, you can specify
654: ; an default value for the variable. It will be set to that value
655: ; iff it is unbound
656: ;
657: (defmacro defvar (variable &optional (initial-value nil iv-p) documentation)
658: (if iv-p
659: then `(progn 'compile
660: (eval-when (eval compile load)
661: (eval '(liszt-declare (special ,variable))))
662: (or (boundp ',variable) (setq ,variable ,initial-value)))
663: else `(eval-when (eval compile load)
664: (eval '(liszt-declare (special ,variable))))))
665:
666:
667:
668:
669: (defmacro list* (&rest forms)
670: (cond ((null forms) nil)
671: ((null (cdr forms)) (car forms))
672: (t (construct-list* forms))))
673:
674: (eval-when (load compile eval)
675: (defun construct-list* (forms)
676: (setq forms (reverse forms))
677: (do ((forms (cddr forms) (cdr forms))
678: (return-form `(cons ,(cadr forms) ,(car forms))
679: `(cons ,(car forms) ,return-form)))
680: ((null forms) return-form))))
681:
682: ;; (<= a b) --> (not (> a b))
683: ;; (<= a b c) --> (not (or (> a b) (> b c)))
684: ;; funny arglist to check for correct number of arguments.
685:
686:
687: (defmacro <= (arg1 arg2 &rest rest &aux result)
688: (setq rest (list* arg1 arg2 rest))
689: (do l rest (cdr l) (null (cdr l))
690: (push `(> ,(car l) ,(cadr l)) result))
691: (cond ((null (cdr result)) `(not ,(car result)))
692: (t `(not (or . ,(nreverse result))))))
693:
694: (defmacro <=& (x y)
695: `(not (>& ,x ,y)))
696:
697: ;; (>= a b) --> (not (< a b))
698: ;; (>= a b c) --> (not (or (< a b) (< b c)))
699: ;; funny arglist to check for correct number of arguments.
700:
701: (defmacro >= (arg1 arg2 &rest rest &aux result)
702: (setq rest (list* arg1 arg2 rest))
703: (do l rest (cdr l) (null (cdr l))
704: (push `(< ,(car l) ,(cadr l)) result))
705: (cond ((null (cdr result)) `(not ,(car result)))
706: (t `(not (or . ,(nreverse result))))))
707:
708:
709: (defmacro >=& (x y)
710: `(not (<& ,x ,y)))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.