Trace/Untrace Macro

The Trace/Untrace Macro-

Trace (and its counterpart Untrace) is a Common Lisp macro that, given one or many function-names of symbols, will cause the functions to be "traced". Whenever a traced function is invoked, information about the call, about the arguments passed, and about any eventually returned values is printed to trace output. If trace is used with no function-names, no tracing action is performed; instead, a list of the functions currently being traced is returned.

Example:

CL-USER 1 > (defun bar (x) (car x))
BAR

CL-USER 2 > (trace bar)
(BAR)

CL-USER 3 > (bar '(1 2 3 4 5 6 7 8))
0 BAR > ...
 >> X : (1 2 3 4 5 6 7 8)
0 BAR < ...
 << VALUE-0 : 1
1

The idea-

The idea here was to use Java Dynamic Proxies to intercept, and temporarily replace CommonLisp? functions so they may be traced. The Java Dynamic Proxy class uses the Reflection library to intercept method invocations, so we could inject output into the intercepted invocations. This was an experimental project, as we werent sure if Java's Proxy class could properly mimic all the different types of CLForJava? functions. There are 3 different types of functions to worry about in the CLForJava? system: (1) Java-defined functions, (2) Lisp-compiled functions, and (3) Lisp-on-the-fly functions.

The source-

The source for this macro is several locations:

/src/java/lisp/system/function/TraceHelper.java - The code that, given a single/list of function symbols, replaces their function with a created proxy function.

/src/java/lisp/system/function/TraceMap.java - Code that maintains a Hash Map of traced functions and helper functions.

/src/java/lisp/system/function/TraceProxy.java - Class that actually creates, and manipulates output of proxy functions.

/src/java/lisp/system/function/UntraceHelper.java - The code that, given a single/list of traced function symbols, replaces their proxy function with the original function.

/src/lisp/MacrosAndFunctions/Misc-Macros.lsp - Contains the macro declaration for Trace and Untrace

What works -

Trace and Untrace work on all 3 types of ClForJava? functions (stated above) when simply traced and called. Trace and Untrace mimic LispWorks? output exactily.

What doesn't work -

1. After a function has been traced, you can't use it when defining another function.

Example:

(trace car)

=> (CAR)

(defun foo (x) (car x))

=> explosion

We are not exactily sure why this is happening, but we have a hunch: When the defun expression is evaluated by Eval.java, the function munging field is not present for the proxied class (as it is for the original function class) and a FIELD_NOT_FOUND exception is thrown.

2. The Function Field in /src/java/lisp/extensions/type/CommonLispFunctions.java can't be replaced by a proxied functions. This can't be set because the proxied function is not actually and 'instanceof' the original function class, only its implemented interfaces. The solution to this is to change every function to an interface that contains a static inner class defining the function.

RyanMoore - 2010-12-14

Topic revision: r1 - 2010-12-14 - 15:27:35 - RyanMoore
 
Home
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback