BSD 4 release
[unix-history] / usr / lib / lisp / machacks.l
CommitLineData
31cef89c
BJ
1(setq |SCCS-machacks| "@(#)machacks.l 1.2 11/7/80")
2
3;; machacks - maclisp compatibility package.
4;; When this file is fasl'ed into a lisp, it will change the syntax to
5;; maclisp's syntax and will define functions know to the standard maclisp.
6;
7; this file will be fasled whenever the -m switch is set for compilation.
8;
9
10(declare (macros t))
11
12;-- macsyma-env
13; This really isn't part of the maclisp compatibility package but we put
14; it here to allow us to bootstrap the macsyma macro packages.
15;
16(def macsyma-env ; put at the beginning of each macsyma file
17 (macro (l) `(include |libmax//prelud.l|)))
18
19(def coutput
20 (lambda (msg)
21 (print msg) ; should go to unfasl port
22 (terpr)))
23
24;--- displace
25; This is useful after a macro has been expanded and you want to save the
26; interpreter the trouble of expanding the macro again.
27; [This is really only useful for interpretation]
28(defun displace (old-form new-form)
29 (cond ((atom old-form)
30 (error '|Not able to displace this form| old-form))
31 ((atom new-form)
32 (rplaca old-form 'progn)
33 (rplacd old-form (list new-form)))
34 (t (rplaca old-form (car new-form))
35 (rplacd old-form (cdr new-form)))))
36
37;--- caseq
38; use is
39; (caseq expr
40; (match1 do1)
41; (match2 do2)
42; (t doifallelsefails))
43(def caseq
44 (macro (form)
45 ((lambda (x)
46 `((lambda (,x)
47 (cond
48 ,@(mapcar '(lambda (ff)
49 (cond ((eq (car ff) 't)
50 `(t ,(cadr ff)))
51 (t `((eq ,x ',(car ff))
52 ,(cadr ff)))))
53 (cddr form))))
54 ,(cadr form)))
55 (gensym 'Z))))
56
57
58
59;A winning macro to store things anywhere: (stolen from AI:ALAN;LSPENV)
60;(SETF (CADR X) 3) --> (RPLACA (CDR X) 3)
61
62(DEFMACRO SETF (EXPR VAL)
63 (COND ((ATOM EXPR)
64 (OR (SYMBOLP EXPR) (ERROR '|-- SETF can't handle this.| EXPR))
65 `(SETQ ,EXPR ,VAL))
66 (T
67 (DO ((Y)) (())
68 (OR (SYMBOLP (CAR EXPR))
69 (ERROR '|-- SETF can't handle this.| EXPR))
70 (AND (SETQ Y (GET (CAR EXPR) 'SETF-EXPAND))
71 (RETURN (FUNCALL Y EXPR VAL)))
72 (OR (SETQ Y (GET (CAR EXPR) 'MACRO))
73 (ERROR '|-- SETF can't handle this.| EXPR))
74 (SETQ EXPR (FUNCALL Y EXPR))))))
75
76(DEFMACRO DEFSETF (NAME VARS &REST BODY)
77 `(DEFPROP ,NAME (LAMBDA ,VARS . ,BODY) SETF-EXPAND))
78
79(DEFSETF CAR (E V) `(RPLACA ,(CADR E) ,V))
80(DEFSETF CAAR (E V) `(RPLACA (CAR ,(CADR E)) ,V))
81(DEFSETF CADR (E V) `(RPLACA (CDR ,(CADR E)) ,V))
82(DEFSETF CAAAR (E V) `(RPLACA (CAAR ,(CADR E)) ,V))
83(DEFSETF CADAR (E V) `(RPLACA (CDAR ,(CADR E)) ,V))
84(DEFSETF CAADR (E V) `(RPLACA (CADR ,(CADR E)) ,V))
85(DEFSETF CADDR (E V) `(RPLACA (CDDR ,(CADR E)) ,V))
86(DEFSETF CAAAAR (E V) `(RPLACA (CAAAR ,(CADR E)) ,V))
87(DEFSETF CADAAR (E V) `(RPLACA (CDAAR ,(CADR E)) ,V))
88(DEFSETF CAADAR (E V) `(RPLACA (CADAR ,(CADR E)) ,V))
89(DEFSETF CADDAR (E V) `(RPLACA (CDDAR ,(CADR E)) ,V))
90(DEFSETF CAAADR (E V) `(RPLACA (CAADR ,(CADR E)) ,V))
91(DEFSETF CADADR (E V) `(RPLACA (CDADR ,(CADR E)) ,V))
92(DEFSETF CAADDR (E V) `(RPLACA (CADDR ,(CADR E)) ,V))
93(DEFSETF CADDDR (E V) `(RPLACA (CDDDR ,(CADR E)) ,V))
94(DEFSETF CDR (E V) `(RPLACD ,(CADR E) ,V))
95(DEFSETF CDAR (E V) `(RPLACD (CAR ,(CADR E)) ,V))
96(DEFSETF CDDR (E V) `(RPLACD (CDR ,(CADR E)) ,V))
97(DEFSETF CDAAR (E V) `(RPLACD (CAAR ,(CADR E)) ,V))
98(DEFSETF CDDAR (E V) `(RPLACD (CDAR ,(CADR E)) ,V))
99(DEFSETF CDADR (E V) `(RPLACD (CADR ,(CADR E)) ,V))
100(DEFSETF CDDDR (E V) `(RPLACD (CDDR ,(CADR E)) ,V))
101(DEFSETF CDAAAR (E V) `(RPLACD (CAAAR ,(CADR E)) ,V))
102(DEFSETF CDDAAR (E V) `(RPLACD (CDAAR ,(CADR E)) ,V))
103(DEFSETF CDADAR (E V) `(RPLACD (CADAR ,(CADR E)) ,V))
104(DEFSETF CDDDAR (E V) `(RPLACD (CDDAR ,(CADR E)) ,V))
105(DEFSETF CDAADR (E V) `(RPLACD (CAADR ,(CADR E)) ,V))
106(DEFSETF CDDADR (E V) `(RPLACD (CDADR ,(CADR E)) ,V))
107(DEFSETF CDADDR (E V) `(RPLACD (CADDR ,(CADR E)) ,V))
108(DEFSETF CDDDDR (E V) `(RPLACD (CDDDR ,(CADR E)) ,V))
109
110(DEFSETF CXR (E V) `(RPLACX ,(CADR E) ,(CADDR E) ,V))
111
112(DEFSETF NTH (E V) `(RPLACA (NTHCDR ,(CADR E) ,(CADDR E)) ,V))
113
114(DEFSETF ARRAYCALL (E V) `(STORE ,E ,V))
115
116(DEFSETF GET (E V) `(PUTPROP ,(CADR E) ,V ,(CADDR E)))
117
118(DEFSETF PLIST (E V) `(SETPLIST ,(CADR E) ,V))
119
120(DEFSETF SYMEVAL (E V) `(SET ,(CADR E) ,V))
121
122(DEFSETF ARG (E V) `(SETARG ,(CADR E) ,V))
123
124(DEFSETF ARGS (E V) `(ARGS ,(CADR E) ,V))
125
126(DEFSETF SFA-GET (E V) `(SFA-STORE ,(CADR E) ,(CADDR E) ,V))
127
128(DEFSETF EXAMINE (E V) `(DEPOSIT ,(CADR E) ,V))
129
130
131(defmacro list* (&rest forms)
132 (cond ((null forms) nil)
133 ((null (cdr forms)) (car forms))
134 (t (construct-list* forms))))
135(defmacro ttf (&rest l) `(list* . , l))
136
137
138(defun construct-list* (forms)
139 (setq forms (reverse forms))
140 (do ((forms (cddr forms) (cdr forms))
141 (return-form `(cons ,(cadr forms) ,(car forms))
142 `(cons ,(car forms) ,return-form)))
143 ((null forms) return-form)))
144
145;; lexpr-funcall is a cross between apply and funcall. The last arguments
146;; is a list of the rest of the arguments
147(defmacro lexpr-funcall (func &rest args)
148 `(apply ,func (list* ,@args)))
149
150; contents of the file libmax;macros all of these functions are
151; (by default) in maclisp
152;; (IF X P Q1 Q2 ...) --> (COND (X P) (T Q1 Q2 ...))
153;; It is important that (IF NIL <FORM>) returns NIL as Macsyma code depends
154;; upon this in places. See also IFN in LIBMAX;MAXMAC.
155
156(DEFMACRO IF (PREDICATE THEN &REST ELSE)
157 (COND ((NULL ELSE) `(COND (,PREDICATE ,THEN)))
158 (T `(COND (,PREDICATE ,THEN) (T . ,ELSE)))))
159
160;; LET, LET*, LIST* are now a part of Multics Lisp. Nobody should miss
161;; the code commented out below.
162;; (LET ((A 3) (B) C) STUFF) --> ((LAMBDA (A B C) STUFF) 3 NIL NIL)
163;; (LET* ((A 3) (B 4)) STUFF) --> ((LAMBDA (A) ((LAMBDA (B) STUFF) 4)) 3)
164
165;; (PUSH X S) --> (SETQ S (CONS X S))
166
167(DEFMACRO PUSH (OBJECT LIST) `(SETF ,LIST (CONS ,OBJECT ,LIST)))
168
169;; (POP S) --> (PROG1 (CAR S) (SETF S (CDR S)))
170;; (POP S V) --> (PROG1 (SETF V (CAR S)) (SETF S (CDR S)))
171;; This relies on the fact that SETF returns the value stored.
172
173(DEFMACRO POP (LIST &OPTIONAL (INTO NIL INTO-P))
174 (COND (INTO-P `(PROG1 (SETF ,INTO (CAR ,LIST))
175 (SETF ,LIST (CDR ,LIST))))
176 (T `(PROG1 (CAR ,LIST)
177 (SETF ,LIST (CDR ,LIST))))))
178
179;; (FOR I m n . BODY) will evaluate BODY with I bound to m,m+1,...,n-1
180;; sequentially. (FOR I 0 n . BODY) --> (DOTIMES (I n) . BODY)
181
182(DEFMACRO FOR (VAR START STOP . BODY)
183 `(DO ,VAR ,START (1+ ,VAR) (= ,VAR ,STOP) ,@BODY))
184
185(DEFMACRO EVENP (X) `(NOT (ODDP ,X)))
186
187; these were grabbed from lspsrc;umlmac.5
188(DEFMACRO WHEN (P . C) `(COND (,P . ,C)))
189(DEFMACRO UNLESS (P . C) `(COND ((NOT ,P) . ,C)))
190(defmacro DOLIST ((var form index) &rest body &aux (dummy (gensym)) decls)
191 (setq decls (cond ((and body
192 (not (atom (car body)))
193 (eq (caar body) 'DECLARE))
194 (prog2 () (cdar body) (pop body)))))
195 (cond (index (setq index (ncons `(,INDEX 0 (1+ ,INDEX)) ))
196 (push `(FIXNUM ,INDEX) decls)))
197 (and decls (setq decls (ncons `(DECLARE ,.decls))))
198 `(DO ((,DUMMY ,FORM (CDR ,DUMMY)) (,VAR) ,.index )
199 ((NULL ,DUMMY))
200 ,@decls
201 (SETQ ,VAR (CAR ,DUMMY)) ,.BODY))
202
203;Repeat a number of times. <count> evaluates to the number of times,
204;and <body> is executed with <var> bound to 0, 1, ...
205;Don't generate dummy variable if <count> is an integer. We could also do this
206;if <count> were a symbol, but the symbol may get clobbered inside the body,
207;so the behavior of the macro would change.
208
209(DEFMACRO DOTIMES (SPEC &REST BODY)
210 (LET (VAR COUNT DUMMY DECLS)
211 (SETQ DECLS `(DECLARE
212 (FIXNUM ,var ) ;LOOP VARIABLE TO BE FILLED IN HERE
213 ,.(cond ((and body
214 (not (atom (car body)))
215 (eq (caar body) 'DECLARE))
216 (prog2 () (cdar body) (pop body))))))
217 (COND ((ATOM SPEC) (SETQ VAR (GENSYM) COUNT SPEC))
218 ('T (DESETQ (VAR COUNT) SPEC)
219 (COND ((NULL VAR) (SETQ VAR (GENSYM))))
220 (COND ((NOT (FIXP COUNT))
221 (SETQ DUMMY `((,(gensym) ,count))
222 COUNT (CAAR DUMMY))))))
223 (SETF (CADADR DECLS) VAR)
224 `(DO ((,var 0 (1+ ,var)) ,.dummy)
225 ((NOT (< ,var ,count)))
226 ,decls
227 ,.body)))
228
229
230;; The following is NOT courtesy AI: LISPM2; LMMAC 118
231;; Theirs is buggy!
232;; PSETQ looks like SETQ but does its work in parallel.
233(DEFMACRO PSETQ (&REST REST)
234 (COND ((CDDR REST)
235 `(SETQ ,(CAR REST)
236 (PROG1 ,(CADR REST) (PSETQ . ,(CDDR REST)))))
237 ;; The last pair. Keep it simple; no superfluous
238 ;; (PROG1 (SETQ...) (PSETQ)).
239 ((CDR REST) `(SETQ . ,REST))
240 (T (error '|Odd number of args to PSETQ| rest 'wrng-no-args))))
241
242
243(defmacro if-for-maclisp-else-lispm (&rest ll) (car ll))
244
245(PROGN 'COMPILE
246 (DEFMACRO LOGAND (&REST FORMS) `(BOOLE 1 . ,FORMS))
247 (DEFMACRO LOGIOR (&REST FORMS) `(BOOLE 7 . ,FORMS))
248 (DEFMACRO LOGXOR (&REST FORMS) `(BOOLE 6 . ,FORMS))
249 )
250
251(DEFMACRO DEFVAR (VARIABLE &OPTIONAL (INITIAL-VALUE NIL IV-P) DOCUMENTATION)
252 DOCUMENTATION ;; Ignored for now.
253 (IF IV-P `(PROGN 'COMPILE
254 (DECLARE (SPECIAL ,VARIABLE))
255 (OR (BOUNDP ',VARIABLE) (SETQ ,VARIABLE ,INITIAL-VALUE)))
256 `(DECLARE (SPECIAL ,VARIABLE))))
257
258(DEFMACRO PSETQ (VAR VALUE . REST)
259 (COND (REST `(SETQ ,VAR (PROG1 ,VALUE (PSETQ . ,REST))))
260 (T `(SETQ ,VAR ,VALUE))))
261
262
263;; (DOTIMES (I N) BODY) evaluates BODY N times, with I bound to 0, 1, ..., N-1.
264;; (DOLIST (X L) BODY) successively binds X to the elements of L, and evaluates
265;; BODY each time.
266
267;; Things to beware of:
268;; [1] This won't work for COUNT being a bignum.
269;; [2] If COUNT is a symbol, somebody could clobber its value inside the body.
270;; [3] Somebody inside of BODY could reference **COUNT**.
271
272(DEFMACRO DOTIMES ((VAR COUNT) . BODY)
273 (IF (OR (FIXP COUNT) (SYMBOLP COUNT))
274 `(DO ((,VAR 0 (1+ ,VAR)))
275 ((>= ,VAR ,COUNT))
276 (DECLARE (FIXNUM ,VAR))
277 . ,BODY)
278 `(DO ((,VAR 0 (1+ ,VAR))
279 (**COUNT** ,COUNT))
280 ((>= ,VAR **COUNT**))
281 (DECLARE (FIXNUM ,VAR **COUNT**))
282 . ,BODY)))
283
284(DEFMACRO DOLIST ((VAR LIST) . BODY)
285 `(DO ((**LIST** ,LIST (CDR **LIST**))
286 (,VAR))
287 ((NULL **LIST**))
288 (SETQ ,VAR (CAR **LIST**))
289 . ,BODY))
290
291;; CASE is apparently missing from ITS MacLisp.
292;; (DEFMACRO SELECT (KEY . FORMS)
293;; (SETQ FORMS
294;; (MAPCAR #'(LAMBDA (FORM) (IF (EQ (CAR FORM) 'OTHERWISE)
295;; (CONS T (CDR FORM)) FORM))
296;; FORMS))
297;; `(CASE ,KEY . ,FORMS))
298
299(DEFMACRO SELECTQ (KEY . FORMS)
300 (SETQ FORMS
301 (MAPCAR '(LAMBDA (FORM) (IF (EQ (CAR FORM) 'OTHERWISE)
302 (CONS T (CDR FORM)) FORM))
303 FORMS))
304 `(CASEQ ,KEY . ,FORMS))
305