BSD 4_3 development
[unix-history] / usr / lib / lisp / lmhacks.l
CommitLineData
5ffa1c4c
C
1(setq rcs-lmhacks-
2 "$Header: lmhacks.l,v 1.2 83/08/15 22:32:31 jkf Exp $")
3
4;; This file contains miscellaneous functions and macros that
5;; ZetaLisp users often find useful
6
7
8;;; (c) Copyright 1982 Massachusetts Institute of Technology
9
10;; This is a simple multiple value scheme based on the one implemented
11;; in MACLISP. It doesn't clean up after its self properly, so if
12;; you ask for multiple values, you will get them regardless of whether
13;; they are returned.
14
15(environment-maclisp (compile eval) (files struct flavorm))
16
17(declare (macros t))
18
19(defvar si:argn () "Number of arguments returned by last values")
20(defvar si:arg2 () "Second return value")
21(defvar si:arg3 () "Third return value")
22(defvar si:arg4 () "Fourth return value")
23(defvar si:arg5 () "Fifth return value")
24(defvar si:arg6 () "Sixth return value")
25(defvar si:arg7 () "Seventh return value")
26(defvar si:arg8 () "Eigth return value")
27(defvar si:arglist () "Additional return values after the eigth")
28
29(defvar si:return-registers
30 '(si:arg2 si:arg3 si:arg4 si:arg5 si:arg6 si:arg7 si:arg8))
31
32(defmacro values (&rest values)
33 `(prog2 (setq si:argn ,(length values))
34 ,(first values)
35 ,@(do ((vals (cdr values) (cdr vals))
36 (regs si:return-registers (cdr regs))
37 (forms))
38 (nil)
39 (cond ((null vals)
40 (return (reverse forms)))
41 ((null regs)
42 (return
43 `(,@(reverse forms)
44 (setq si:arglist (list ,@vals)))))
45 (t (push `(setq ,(car regs) ,(car vals))
46 forms))))))
47
48(defun values-list (list)
49 (setq si:argn (length list))
50 (do ((vals (cdr list) (cdr vals))
51 (regs si:return-registers (cdr regs)))
52 ((null regs)
53 (if (not (null vals))
54 (setq si:arglist vals))
55 (car list))
56 (set (car regs) (car vals))))
57
58(defmacro multiple-value (vars form)
59 `(progn
60 ,@(if (not (null (car vars)))
61 `((setq ,(car vars) ,form)
62 (if (< si:argn 1) (setq ,(car vars) nil)))
63 `(,form))
64 ,@(do ((vs (cdr vars) (cdr vs))
65 (regs si:return-registers (cdr regs))
66 (i 2 (1+ i))
67 (forms))
68 (nil)
69 (cond ((null vars)
70 (return (reverse forms)))
71 ((null regs)
72 (return
73 (do ((vs vs (cdr vs)))
74 ((null vs) (nreverse forms))
75 (and (not (null (car vs)))
76 (push
77 `(setq ,(car vs)
78 (prog1
79 (if (not (> ,i si:argn))
80 (car si:arglist))
81 (setq si:arglist (cdr si:arglist))))
82 forms)))))
83 ((not (null (car vs)))
84 (push `(setq ,(car vs) (if (not (> ,i si:argn)) ,(car regs))
85 ,(car regs) nil)
86 forms))))))
87
88(defmacro multiple-value-bind (vars form &rest body)
89 `(let ,vars
90 (multiple-value ,vars ,form)
91 ,@body))
92
93(defmacro multiple-value-list (form)
94 `(multiple-value-list-1 ,form))
95
96(defun multiple-value-list-1 (si:arg1)
97 (cond ((= 0 si:argn) ())
98 ((= 1 si:argn)
99 (list si:arg1))
100 ((= 2 si:argn)
101 (list si:arg1 si:arg2))
102 ((= 3 si:argn)
103 (list si:arg1 si:arg2 si:arg3))
104 ((= 4 si:argn)
105 (list si:arg1 si:arg2 si:arg3 si:arg4))
106 ((= 5 si:argn)
107 (list si:arg1 si:arg2 si:arg3 si:arg4 si:arg5))
108 ((= 6 si:argn)
109 (list si:arg1 si:arg2 si:arg3 si:arg4 si:arg5 si:arg6))
110 ((= 7 si:argn)
111 (list si:arg1 si:arg2 si:arg3 si:arg4 si:arg5 si:arg6
112 si:arg7))
113 ((= 8 si:argn)
114 (list si:arg1 si:arg2 si:arg3 si:arg4 si:arg5 si:arg6
115 si:arg7 si:arg8))
116 ((> si:argn 8)
117 (rplacd (nthcdr (- si:argn 9) si:arglist) nil)
118 (list* si:arg1 si:arg2 si:arg3 si:arg4 si:arg5 si:arg6
119 si:arg7 si:arg8 si:arglist))
120 (t (ferror () "Internal error, si:argn = ~D" si:argn))))
121\f
122(defun union (set &rest others)
123 (loop for s in others
124 do (loop for elt in s
125 unless (memq elt set)
126 do (push elt set))
127 finally (return set)))
128
129(defun make-list (length &rest options &aux (iv))
130 (loop for (key val) on options by #'cddr
131 do (selectq key
132 (:initial-value
133 (setq iv val))
134 (:area)
135 (otherwise
136 (error "Illegal parameter to make-list" key))))
137 (loop for i from 1 to length collect iv))
138\f
139;; si:printing-random-object
140;; A macro for aiding in the printing of random objects.
141;; This macro generates a form which: (by default) includes the virtual
142;; address in the printed representation.
143;; Options are :NO-POINTER to suppress the pointer
144;; :TYPEP princs the typep of the object first.
145
146;; Example:
147;; (DEFSELECT ((:PROPERTY HACKER :NAMED-STRUCTURE-INVOKE))
148;; (:PRINT-SELF (HACKER STREAM IGNORE IGNORE)
149;; (SI:PRINTING-RANDOM-OBJECT (HACKER STREAM :TYPEP)
150;; (PRIN1 (HACKER-NAME HACKER) STREAM))))
151;; ==> #<HACKER /"MMcM/" 6172536765>
152
153(defmacro si:printing-random-object ((object stream . options) &body body)
154 (let ((%pointer t)
155 (typep nil))
156 (do ((l options (cdr l)))
157 ((null l))
158 (selectq (car l)
159 (:no-pointer (setq %pointer nil))
160 (:typep (setq typep t))
161 (:fastp (setq l (cdr l))) ; for compatibility sake
162 (otherwise
163 (ferror nil "~S is an unknown keyword in si:printing-random-object"
164 (car l)))))
165 `(progn
166 (patom "#<" ,stream)
167 ,@(and typep
168 `((patom (:typep ,object) ,stream)))
169 ,@(and typep body
170 `((patom " " ,stream)))
171 ,@body
172 ,@(and %pointer
173 `((patom " " ,stream)
174 (patom (maknum ,object) ,stream)))
175 (patom ">" ,stream)
176 ,object)))
177\f
178(defun named-structure-p (x &aux symbol)
179 (cond ((or (and (hunkp x) (atom (setq symbol (cxr 0 x))))
180 (and (vectorp x)
181 (setq symbol (or (and (atom (vprop x)) (vprop x))
182 (and (dtpr (vprop x))
183 (atom (car (vprop x)))
184 (car (vprop x)))))))
185
186 (if (get symbol 'defstruct-description)
187 symbol))))
188
189(defun named-structure-symbol (x)
190 (or (named-structure-p x)
191 (ferror () "~S was supposed to have been a named structure."
192 x)))
193
194(declare (localf named-structure-invoke-internal))
195
196(defun named-structure-invoke (operation struct &rest args)
197 (named-structure-invoke-internal operation struct args t))
198
199(defun named-structure-invoke-carefully (operation struct &rest args)
200 (named-structure-invoke-internal operation struct args nil))
201
202(defun named-structure-invoke-internal (operation struct args error-p)
203 (let (symbol fun)
204 (setq symbol (named-structure-symbol struct))
205 (if (setq fun (get symbol ':named-structure-invoke))
206 then (lexpr-funcall fun operation struct args)
207 else (and error-p
208 (ferror ()
209 "No named structure invoke function for ~S"
210 struct)))))
211
212(defmacro defselect ((function-spec default-handler no-which-operations)
213 &rest args)
214 (let ((name (intern (gensym)))
215 fun-name)
216 `(progn 'compile
217 (defun ,(if (eq (car function-spec) ':property)
218 (cdr function-spec)
219 (ferror () "Can't interpret ~S defselect function spec"
220 function-spec))
221 (operation &rest args &aux temp)
222 (if (setq temp (gethash operation (get ',name 'select-table)))
223 (lexpr-funcall temp args)
224 ,(if default-handler
225 `(lexpr-funcall ,default-handler operation args)
226 `(ferror () "No handler for the ~S method of ~S"
227 operation ',function-spec))))
228 (setf (get ',name 'select-table) (make-hash-table))
229 ,@(do ((args args (cdr args))
230 (form)
231 (forms nil))
232 ((null args) (nreverse forms))
233 (setq form (car args))
234 (cond ((atom (cdr form))
235 (setq fun-name (cdr form)))
236 (t (setq fun-name
237 (intern (concat name (if (atom (car form)) (car form)
238 (caar form)))))
239 (push `(defun ,fun-name ,@(cdr form)) forms)))
240 (if (atom (car form))
241 (push `(puthash ',(car form) ',fun-name
242 (get ',name 'select-table))
243 forms)
244 (mapc #'(lambda (q)
245 (push `(puthash ',q ',fun-name
246 (get ',name 'select-table))
247 forms))
248 (car form))))
249 ,@(and (not no-which-operations)
250 `((defun ,(setq fun-name (intern
251 (concat name '-which-operations)))
252 (&rest args)
253 '(:which-operations ,@(loop for form in args
254 appending (if (atom (car form))
255 (list (car form))
256 (car form)))))
257 (puthash ':which-operations ',fun-name
258 (get ',name 'select-table))))
259 ',function-spec)))
260\f
261(defun :typep (ob &optional (type nil) &aux temp)
262 (cond ((instancep ob)
263 (instance-typep ob type))
264 ((setq temp (named-structure-p ob))
265 (if (null type) temp
266 (if (eq type temp) t
267 (memq type (nth 11. (get temp 'defstruct-description))))))
268 ((hunkp ob)
269 (if (null type) 'hunk (eq type 'hunk)))
270 ((null type)
271 (funcall 'typep ob))
272 (t (eq type (funcall 'typep ob)))))
273
274(defun send-internal (object message &rest args)
275 (declare (special .own-flavor. self))
276 (lexpr-funcall (if (eq self object)
277 (or (gethash message
278 (flavor-method-hash-table .own-flavor.))
279 (flavor-default-handler .own-flavor.))
280 object)
281 message args))
282\f
283;; New printer
284
285(declare (special poport prinlevel prinlength top-level-print))
286
287(defun zprint (x &optional (stream poport))
288 (zprin1 x stream)
289 't)
290
291(defun zprinc (x &optional (stream poport))
292 (zprin1a x stream () (or prinlevel -1)))
293
294(defun zprin1 (x &optional (stream poport))
295 (zprin1a x stream 't (or prinlevel -1)))
296
297(defun zprin1a (ob stream slashifyp level &aux temp)
298 (cond ((null ob) (patom "()" stream))
299 ((setq temp (named-structure-p ob))
300 (or (named-structure-invoke-carefully ':print-self ob stream
301 level slashifyp)
302 (si:printing-random-object (ob stream :typep))))
303 ((instancep ob)
304 (if (get-handler-for ob ':print-self)
305 (send ob ':print-self stream)
306 (si:printing-random-object (ob stream :typep))))
307 ((atom ob)
308 (if slashifyp (xxprint ob stream)
309 (patom ob stream)))
310 ((dtpr ob) (zprint-list ob stream slashifyp (1- level)))
311 ((hunkp ob) (zprint-hunk ob stream slashifyp (1- level)))
312 ((= level 0)
313 (patom "&" stream))
314 (t
315 (if slashifyp (xxprint ob stream)
316 (patom ob stream))))
317 't)
318
319(defun zprint-list (l stream slashifyp level)
320 (tyo #/( stream)
321 (do ((l l (cdr l))
322 (i (or prinlength -1) (1- i))
323 (first t nil))
324 ((not (dtpr l))
325 (cond ((not (null l))
326 (patom " . " stream)
327 (zprin1a l stream slashifyp level)))
328 't)
329 (cond ((= i 0)
330 (patom " ..." stream)
331 (return 't)))
332 (if (not first)
333 (tyo #/ stream))
334 (zprin1a (car l) stream slashifyp level))
335 (tyo #/) stream))
336
337(defun zprint-hunk (l stream slashifyp level)
338 (tyo #/{ stream)
339 (do ((i 0 (1+ i))
340 (lim (hunksize l))
341 (first t nil))
342 ((= i lim)
343 't)
344 (cond ((and (not (null prinlength)) (not (< i prinlength)))
345 (patom " ..." stream)
346 (return 't)))
347 (if (not first)
348 (tyo #/ stream))
349 (zprin1a (cxr i l) stream slashifyp level))
350 (tyo #/} stream))
351
352(eval-when (load eval)
353 (putd 'xxprint (getd 'print))
354 (putd 'xxprinc (getd 'princ)))
355
356(defun new-printer ()
357 (setq top-level-print 'zprint)
358 (putd 'print (getd 'zprint))
359 (putd 'prin1 (getd 'zprin1))
360 't)
361
362(defun old-printer ()
363 (setq top-level-print 'xxprint)
364 (putd 'print (getd 'xxprint))
365 (putd 'princ (getd 'xxprinc))
366 't)
367
368
369
370
371(putprop 'lmhacks t 'version)