X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fmisc.lisp;h=a0400676d1f63a8026f26eb7f16b2bebe2776adf;hb=e1301bcded5eed2d9259d7688edf03892468fe2b;hp=b3b24c147bf7a29ff4f71d736f9d0337c776e918;hpb=f6799959f40b3d376479da75797d95f8943afc57;p=jscl.git diff --git a/src/misc.lisp b/src/misc.lisp index b3b24c1..a040067 100644 --- a/src/misc.lisp +++ b/src/misc.lisp @@ -13,6 +13,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with JSCL. If not, see . +(/debug "loading misc.lisp!") + (defparameter *features* '(:jscl :common-lisp)) (defun lisp-implementation-type () @@ -26,3 +28,56 @@ (prog1 (progn ,form) (setq ,end (get-internal-real-time)) (format t "Execution took ~a seconds.~%" (/ (- ,end ,start) 1000.0)))))) + + +;;;; TRACE + +;;; This trace implementation works on symbols, replacing the function +;;; with a wrapper. So it will not trace calls to the function if they +;;; got the function object before it was traced. + +;;; An alist of the form (NAME FUNCTION), where NAME is the name of a +;;; function, and FUNCTION is the function traced. +(defvar *traced-functions* nil) +(defvar *trace-level* 0) + +(defun trace-report-call (name args) + (dotimes (i *trace-level*) (write-string " ")) + (format t "~a: ~S~%" *trace-level* (cons name args))) + +(defun trace-report-return (name values) + (dotimes (i *trace-level*) (write-string " ")) + (format t "~a: ~S returned " *trace-level* name) + (dolist (value values) (format t "~S " value)) + (format t "~%")) + +(defun trace-functions (names) + (if (null names) + (mapcar #'car *traced-functions*) + (dolist (name names names) + (if (find name *traced-functions* :key #'car) + (format t "`~S' is already traced.~%" name) + (let ((func (fdefinition name))) + (fset name (lambda (&rest args) + (let (values) + (trace-report-call name args) + (let ((*trace-level* (+ *trace-level* 1))) + (setq values (multiple-value-list (apply func args)))) + (trace-report-return name values) + (values-list values)))) + (push (cons name func) *traced-functions*)))))) + +(defun untrace-functions (names) + (when (null names) + (setq names (mapcar #'car *traced-functions*))) + (dolist (name names) + (let ((func (cdr (find name *traced-functions* :key #'car)))) + (if func + (fset name func) + (format t "~S is not being traced.~%" name))))) + +(defmacro trace (&rest names) + `(trace-functions ',names)) + +(defmacro untrace (&rest names) + `(untrace-functions ',names))