Commit | Line | Data |
---|---|---|
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 |