|
|
1.1 ! root 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: ! 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.