"$Header: /usr/lib/lisp/lmhacks.l,v 1.1 83/01/29 18:38:35 jkf Exp $")
;; This file contains miscellaneous functions and macros that
;; ZetaLisp users often find useful
;;; (c) Copyright 1982 Massachusetts Institute of Technology
;; This is a simple multiple value scheme based on the one implemented
;; in MACLISP. It doesn't clean up after its self properly, so if
;; you ask for multiple values, you will get them regardless of whether
(environment-maclisp (compile eval) (files struct flavorm))
(defvar si:argn () "Number of arguments returned by last values")
(defvar si:arg2 () "Second return value")
(defvar si:arg3 () "Third return value")
(defvar si:arg4 () "Fourth return value")
(defvar si:arg5 () "Fifth return value")
(defvar si:arg6 () "Sixth return value")
(defvar si:arg7 () "Seventh return value")
(defvar si:arg8 () "Eigth return value")
(defvar si:arglist () "Additional return values after the eigth")
(defvar si:return-registers
'(si:arg2 si:arg3 si:arg4 si:arg5 si:arg6 si:arg7 si:arg8))
(defmacro values (&rest values)
`(prog2 (setq si:argn ,(length values))
,@(do ((vals (cdr values) (cdr vals))
(regs si:return-registers (cdr regs))
(return (reverse forms)))
(setq si:arglist (list ,@vals)))))
(t (push `(setq ,(car regs) ,(car vals))
(defun values-list (list)
(setq si:argn (length list))
(do ((vals (cdr list) (cdr vals))
(regs si:return-registers (cdr regs)))
(set (car regs) (car vals))))
(defmacro multiple-value (vars form)
,@(if (not (null (car vars)))
`((setq ,(car vars) ,form)
(if (< si:argn 1) (setq ,(car vars) nil)))
,@(do ((vs (cdr vars) (cdr vs))
(regs si:return-registers (cdr regs))
(return (reverse forms)))
((null vs) (nreverse forms))
(and (not (null (car vs)))
(setq si:arglist (cdr si:arglist))))
(push `(setq ,(car vs) (if (not (> ,i si:argn)) ,(car regs))
(defmacro multiple-value-bind (vars form &rest body)
(multiple-value ,vars ,form)
(defmacro multiple-value-list (form)
`(multiple-value-list-1 ,form))
(defun multiple-value-list-1 (si:arg1)
(list si:arg1 si:arg2 si:arg3))
(list si:arg1 si:arg2 si:arg3 si:arg4))
(list si:arg1 si:arg2 si:arg3 si:arg4 si:arg5))
(list si:arg1 si:arg2 si:arg3 si:arg4 si:arg5 si:arg6))
(list si:arg1 si:arg2 si:arg3 si:arg4 si:arg5 si:arg6
(list si:arg1 si:arg2 si:arg3 si:arg4 si:arg5 si:arg6
(rplacd (nthcdr (- si:argn 9) si:arglist) nil)
(list* si:arg1 si:arg2 si:arg3 si:arg4 si:arg5 si:arg6
si:arg7 si:arg8 si:arglist))
(t (ferror () "Internal error, si:argn = ~D" si:argn))))
(defun union (set &rest others)
(defun make-list (length &rest options &aux (iv))
(loop for (key val) on options by #'cddr
(error "Illegal parameter to make-list" key))))
(loop for i from 1 to length collect iv))
;; si:printing-random-object
;; A macro for aiding in the printing of random objects.
;; This macro generates a form which: (by default) includes the virtual
;; address in the printed representation.
;; Options are :NO-POINTER to suppress the pointer
;; :TYPEP princs the typep of the object first.
;; (DEFSELECT ((:PROPERTY HACKER :NAMED-STRUCTURE-INVOKE))
;; (:PRINT-SELF (HACKER STREAM IGNORE IGNORE)
;; (SI:PRINTING-RANDOM-OBJECT (HACKER STREAM :TYPEP)
;; (PRIN1 (HACKER-NAME HACKER) STREAM))))
;; ==> #<HACKER /"MMcM/" 6172536765>
(defmacro si:printing-random-object ((object stream . options) &body body)
(do ((l options (cdr l)))
(:no-pointer (setq %pointer nil))
(:fastp (setq l (cdr l))) ; for compatibility sake
(ferror nil "~S is an unknown keyword in si:printing-random-object"
`((patom (:typep ,object) ,stream)))
(patom (maknum ,object) ,stream)))
(defun named-structure-p (x &aux symbol)
(cond ((and (hunkp x) (atom (setq symbol (cxr 0 x))))
(if (get symbol 'defstruct-description)
(defun named-structure-symbol (x)
(or (named-structure-p x)
(ferror () "~S was supposed to have been a named structure."
(declare (localf named-structure-invoke-internal))
(defun named-structure-invoke (operation struct &rest args)
(named-structure-invoke-internal operation struct args t))
(defun named-structure-invoke-carefully (operation struct &rest args)
(named-structure-invoke-internal operation struct args nil))
(defun named-structure-invoke-internal (operation struct args error-p)
(setq symbol (named-structure-symbol struct))
(if (setq fun (get symbol ':named-structure-invoke))
then (lexpr-funcall fun operation struct args)
"No named structure invoke function for ~S"
(defmacro defselect ((function-spec default-handler no-which-operations)
(let ((name (intern (gensym)))
(defun ,(if (eq (car function-spec) ':property)
(ferror () "Can't interpret ~S defselect function spec"
(operation &rest args &aux temp)
(if (setq temp (gethash operation (get ',name 'select-table)))
(lexpr-funcall temp args)
`(lexpr-funcall ,default-handler operation args)
`(ferror () "No handler for the ~S method of ~S"
operation ',function-spec))))
(setf (get ',name 'select-table) (make-hash-table))
,@(do ((args args (cdr args))
((null args) (nreverse forms))
(setq fun-name (cdr form)))
(intern (concat name (if (atom (car form)) (car form)
(push `(defun ,fun-name ,@(cdr form)) forms)))
(push `(puthash ',(car form) ',fun-name
(get ',name 'select-table))
(push `(puthash ',q ',fun-name
(get ',name 'select-table))
,@(and (not no-which-operations)
`((defun ,(setq fun-name (intern
(concat name '-which-operations)))
'(:which-operations ,@(loop for form in args
appending (if (atom (car form))
(puthash ':which-operations ',fun-name
(get ',name 'select-table))))
(defun :typep (ob &optional (type nil) &aux temp)
(instance-typep ob type))
((setq temp (named-structure-p ob))
(memq type (nth 11. (get temp 'defstruct-description))))))
(if (null type) 'hunk (eq type 'hunk)))
(t (eq type (funcall 'typep ob)))))
(defun send-internal (object message &rest args)
(declare (special .own-flavor. self))
(lexpr-funcall (if (eq self object)
(flavor-method-hash-table .own-flavor.))
(flavor-default-handler .own-flavor.))
(declare (special poport prinlevel prinlength top-level-print))
(defun zprint (x &optional (stream poport))
(defun zprinc (x &optional (stream poport))
(zprin1a x stream () (or prinlevel -1)))
(defun zprin1 (x &optional (stream poport))
(zprin1a x stream 't (or prinlevel -1)))
(defun zprin1a (ob stream slashifyp level &aux temp)
(cond ((null ob) (patom "()" stream))
((setq temp (named-structure-p ob))
(or (named-structure-invoke-carefully ':print-self ob stream
(si:printing-random-object (ob stream :typep))))
(if (get-handler-for ob ':print-self)
(send ob ':print-self stream)
(si:printing-random-object (ob stream :typep))))
(if slashifyp (xxprint ob stream)
((dtpr ob) (zprint-list ob stream slashifyp (1- level)))
((hunkp ob) (zprint-hunk ob stream slashifyp (1- level)))
(if slashifyp (xxprint ob stream)
(defun zprint-list (l stream slashifyp level)
(i (or prinlength -1) (1- i))
(zprin1a l stream slashifyp level)))
(zprin1a (car l) stream slashifyp level))
(defun zprint-hunk (l stream slashifyp level)
(cond ((and (not (null prinlength)) (not (< i prinlength)))
(zprin1a (cxr i l) stream slashifyp level))
(putd 'xxprint (getd 'print))
(putd 'xxprinc (getd 'princ)))
(setq top-level-print 'zprint)
(putd 'print (getd 'zprint))
(putd 'prin1 (getd 'zprin1))
(setq top-level-print 'xxprint)
(putd 'print (getd 'xxprint))
(putd 'princ (getd 'xxprinc))
(putprop 'lmhacks t 'version)