;;;; basic environmental stuff ;;;; This software is part of the SBCL system. See the README file for ;;;; more information. ;;;; This software is derived from software originally released by Xerox ;;;; Corporation. Copyright and release statements follow. Later modifications ;;;; to the software are in the public domain and are provided with ;;;; absolutely no warranty. See the COPYING and CREDITS files for more ;;;; information. ;;;; copyright information from original PCL sources: ;;;; ;;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation. ;;;; All rights reserved. ;;;; ;;;; Use and copying of this software and preparation of derivative works based ;;;; upon this software are permitted. Any distribution of this software or ;;;; derivative works must comply with all applicable United States export ;;;; control laws. ;;;; ;;;; This software is made available AS IS, and Xerox Corporation makes no ;;;; warranty about the software, its performance or its conformity to any ;;;; specification. (in-package "SB-PCL") ;;; FIXME: This stuff isn't part of the ANSI spec, and isn't even ;;; exported from PCL, but it looks as though it might be useful, ;;; so I don't want to just delete it. Perhaps it should go in ;;; a "contrib" directory eventually? #| (defun parse-method-or-spec (spec &optional (errorp t)) (let (gf method name temp) (if (method-p spec) (setq method spec gf (method-generic-function method) temp (and gf (generic-function-name gf)) name (if temp (make-method-spec temp (method-qualifiers method) (unparse-specializers (method-specializers method))) (make-symbol (format nil "~S" method)))) (let ((gf-spec (car spec))) (multiple-value-bind (quals specls) (parse-defmethod (cdr spec)) (and (setq gf (and (or errorp (fboundp gf-spec)) (gdefinition gf-spec))) (let ((nreq (compute-discriminating-function-arglist-info gf))) (setq specls (append (parse-specializers specls) (make-list (- nreq (length specls)) :initial-element *the-class-t*))) (and (setq method (get-method gf quals specls errorp)) (setq name (make-method-spec gf-spec quals (unparse-specializers specls))))))))) (values gf method name))) ;;; TRACE-METHOD and UNTRACE-METHOD accept method specs as arguments. A ;;; method-spec should be a list like: ;;; ( qualifiers* (specializers*)) ;;; where should be either a symbol or a list ;;; of (SETF ). ;;; ;;; For example, to trace the method defined by: ;;; ;;; (defmethod foo ((x spaceship)) 'ss) ;;; ;;; You should say: ;;; ;;; (trace-method '(foo (spaceship))) ;;; ;;; You can also provide a method object in the place of the method ;;; spec, in which case that method object will be traced. ;;; ;;; For UNTRACE-METHOD, if an argument is given, that method is untraced. ;;; If no argument is given, all traced methods are untraced. (defclass traced-method (method) ((method :initarg :method) (function :initarg :function :reader method-function) (generic-function :initform nil :accessor method-generic-function))) (defmethod method-lambda-list ((m traced-method)) (with-slots (method) m (method-lambda-list method))) (defmethod method-specializers ((m traced-method)) (with-slots (method) m (method-specializers method))) (defmethod method-qualifiers ((m traced-method)) (with-slots (method) m (method-qualifiers method))) (defmethod accessor-method-slot-name ((m traced-method)) (with-slots (method) m (accessor-method-slot-name method))) (defvar *traced-methods* ()) (defun trace-method (spec &rest options) (multiple-value-bind (gf omethod name) (parse-method-or-spec spec) (let* ((tfunction (trace-method-internal (method-function omethod) name options)) (tmethod (make-instance 'traced-method :method omethod :function tfunction))) (remove-method gf omethod) (add-method gf tmethod) (pushnew tmethod *traced-methods*) tmethod))) (defun untrace-method (&optional spec) (flet ((untrace-1 (m) (let ((gf (method-generic-function m))) (when gf (remove-method gf m) (add-method gf (slot-value m 'method)) (setq *traced-methods* (remove m *traced-methods*)))))) (if (not (null spec)) (multiple-value-bind (gf method) (parse-method-or-spec spec) (declare (ignore gf)) (if (memq method *traced-methods*) (untrace-1 method) (error "~S is not a traced method?" method))) (dolist (m *traced-methods*) (untrace-1 m))))) (defun trace-method-internal (ofunction name options) (eval `(untrace ,name)) (setf (fdefinition name) ofunction) (eval `(trace ,name ,@options)) (fdefinition name)) |# #| ;;;; Helper for slightly newer trace implementation, based on ;;;; breakpoint stuff. The above is potentially still useful, so it's ;;;; left in, commented. ;;; (this turned out to be a roundabout way of doing things) (defun list-all-maybe-method-names (gf) (let (result) (dolist (method (generic-function-methods gf) (nreverse result)) (let ((spec (nth-value 2 (parse-method-or-spec method)))) (push spec result) (push (list* 'fast-method (cdr spec)) result))))) |# ;;;; MAKE-LOAD-FORM ;; Overwrite the old bootstrap non-generic MAKE-LOAD-FORM function with a ;; shiny new generic function. (fmakunbound 'make-load-form) (defgeneric make-load-form (object &optional environment)) ;; Link bootstrap-time how-to-dump-it information into the shiny new ;; CLOS system. (defmethod make-load-form ((obj sb-sys:structure!object) &optional (env nil env-p)) (if env-p (sb-sys:structure!object-make-load-form obj env) (sb-sys:structure!object-make-load-form obj))) (defmethod make-load-form ((object wrapper) &optional env) (declare (ignore env)) (let ((pname (classoid-proper-name (layout-classoid object)))) (unless pname (error "can't dump wrapper for anonymous class:~% ~S" (layout-classoid object))) `(classoid-layout (find-classoid ',pname)))) (defmethod make-load-form ((object structure-object) &optional env) (declare (ignore env)) (error "~@" object 'make-load-form)) (defmethod make-load-form ((object standard-object) &optional env) (declare (ignore env)) (error "~@" object 'make-load-form)) (defmethod make-load-form ((object condition) &optional env) (declare (ignore env)) (error "~@" object 'make-load-form)) (defun make-load-form-saving-slots (object &key (slot-names nil slot-names-p) environment) (declare (ignore environment)) (let ((class (class-of object))) (collect ((inits)) (dolist (slot (class-slots class)) (let ((slot-name (slot-definition-name slot))) (when (or (memq slot-name slot-names) (and (not slot-names-p) (eq :instance (slot-definition-allocation slot)))) (if (slot-boundp-using-class class object slot) (let ((value (slot-value-using-class class object slot))) (if (typep object 'structure-object) ;; low-level but less noisy initializer form ;; FIXME: why not go class->layout->info == dd? (let* ((dd (find-defstruct-description (class-name class))) (dsd (find slot-name (dd-slots dd) :key #'dsd-name))) (inits `(,(slot-setter-lambda-form dd dsd) ',value ,object))) (inits `(setf (slot-value ,object ',slot-name) ',value)))) (inits `(slot-makunbound ,object ',slot-name)))))) (values `(allocate-instance (find-class ',(class-name class))) `(progn ,@(inits))))))