|
|
1.1 root 1: (setq rcs-lmhacks-
2: "$Header: /usr/lib/lisp/RCS/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:
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:
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:
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:
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:
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)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.