From c333031197d39d776282d07cfc079a159126d8a4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20V=C3=A1zquez?= Date: Wed, 15 May 2013 10:10:37 +0100 Subject: [PATCH] Simple TRACE utility --- src/misc.lisp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/toplevel.lisp | 5 +++-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/misc.lisp b/src/misc.lisp index b3b24c1..3f4c5de 100644 --- a/src/misc.lisp +++ b/src/misc.lisp @@ -26,3 +26,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)) diff --git a/src/toplevel.lisp b/src/toplevel.lisp index d148a47..ed0abfe 100644 --- a/src/toplevel.lisp +++ b/src/toplevel.lisp @@ -75,8 +75,9 @@ second set setf setq seventh sixth some string string-upcase string= stringp sublis subseq subst symbol-function symbol-name symbol-package symbol-plist symbol-value symbolp t tagbody tailp tenth third throw - time tree-equal truncate unless unwind-protect values values-list variable - vector-push-extend warn when write-line write-string zerop)) + time trace tree-equal truncate unless untrace unwind-protect values + values-list variable vector-push-extend warn when write-line write-string + zerop)) (setq *package* *user-package*) -- 1.7.10.4