summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-05-09 20:24:52 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-05-09 20:24:52 -0700
commit14fddd89cbb63cd6ee99810b6730992a3c8be475 (patch)
tree7947290d288f82cc5b592e1753622692879432d9
parentcc69832ceecf915971cbd09295e5bb4d39fc5de0 (diff)
downloadtxr-14fddd89cbb63cd6ee99810b6730992a3c8be475.tar.gz
txr-14fddd89cbb63cd6ee99810b6730992a3c8be475.tar.bz2
txr-14fddd89cbb63cd6ee99810b6730992a3c8be475.zip
trace: new parameter macro :trace for simple static tracing
Just add :trace to the head of the parameter list, and the function is traced. No dynamic turning on and off though. * autoload.c (trace_set_entries): Trigger autoload on :trace keyword. * stdlib/trace.tl (:trace): New parameter list expander. * txr.1: Documented.
-rw-r--r--autoload.c4
-rw-r--r--stdlib/trace.tl31
-rw-r--r--txr.142
3 files changed, 76 insertions, 1 deletions
diff --git a/autoload.c b/autoload.c
index 86770c8a..84376173 100644
--- a/autoload.c
+++ b/autoload.c
@@ -405,9 +405,13 @@ static val trace_set_entries(val fun)
val name[] = {
lit("trace"), lit("untrace"), nil
};
+ val kname[] = {
+ lit("trace"), nil
+ };
autoload_sys_set(al_fun, sys_name, fun);
autoload_set(al_var, vname, fun);
autoload_set(al_fun, name, fun);
+ autoload_key_set(al_key, kname, fun);
return nil;
}
diff --git a/stdlib/trace.tl b/stdlib/trace.tl
index 683969bc..0ee55275 100644
--- a/stdlib/trace.tl
+++ b/stdlib/trace.tl
@@ -25,6 +25,9 @@
;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
;; POSSIBILITY OF SUCH DAMAGE.
+(compile-only
+ (load-for (struct sys:param-parser-base "param")))
+
(defvar *trace-output* *stdout*)
(defvar sys:*trace-hash* (hash :equal-based))
@@ -122,3 +125,31 @@
(defmacro usr:untrace (. names)
^(sys:untrace ',names))
+
+(define-param-expander :trace (param body menv form)
+ (ignore menv)
+ (let* ((pp (new (fun-param-parser param form)))
+ (args (append pp.req pp.(opt-syms) pp.rest))
+ (name (let* ((anc (dig form))
+ (sls (source-loc-str anc)))
+ (match-case anc
+ ((@(member @type '(flet labels macrolet)) @name)
+ ^(,type ,name ,sls))
+ ((@(or defun defmacro) @name . @nil)
+ ^(,name ,sls))
+ (@nil sls)))))
+ (with-gensyms (abandoned arglist result)
+ (list param
+ ^(let ((,abandoned t)
+ (sys:*trace-level* (succ sys:*trace-level*))
+ (,arglist (list ,*args))
+ ,result)
+ (unwind-protect
+ (progn
+ (sys:trace-enter ',name ,arglist)
+ (set ,result (progn ,*body))
+ (sys:trace-leave ,result)
+ (set ,abandoned nil)
+ ,result)
+ (if ,abandoned
+ (sys:trace-leave :abandoned))))))))
diff --git a/txr.1 b/txr.1
index c1a2cbea..5f3dc45f 100644
--- a/txr.1
+++ b/txr.1
@@ -86888,7 +86888,10 @@ The
.code trace
and
.code untrace
-macros control function tracing.
+macros control dynamic function tracing, which allows
+tracing for named functions to be turned on and off
+without modifying their functions or processing their
+definitions.
When
.code trace
@@ -86969,6 +86972,43 @@ and
functions return
.codn nil .
+.coNP Parameter List Macro @ :trace
+.synb
+.mets (:trace ...)
+.syne
+.desc
+The parameter list macro
+.code :trace
+provides a more static form of function tracing, which cannot
+be turned on and off without changing code and processing the form in which the
+traced function is defined.
+
+When the keyword
+.code :trace
+is inserted as the first element of a parameter list, it triggers a parameter
+list macro which transforms the function into a traced function.
+The function logs information about its execution into the
+.code *trace-output*
+stream in the same way as functions for which tracing has been
+dynamically enabled by the
+.code trace
+macro.
+
+Unlike
+.codn trace ,
+.code :trace
+may be used on anonymous functions created by the
+.code lambda
+operator, functions established by
+.code flet
+and
+.codn labels ,
+as well as
+.code macrolet
+and any other constructs which translate into these which allow for
+.code :trace
+to be inserted into their syntax.
+
.SS* Dynamic Library Access
.coNP Function @ dlopen