Re: proper stack traces

Matthias Radestock <[email protected]> Wed, 15 Mar 2006 07:46:04 +0000
Newsgroups gmane.comp.java.sisc.devel
Message-ID <[email protected]>
Matt Hellige <[email protected]> writes:

> I don't have any specific examples, although I noticed a bug opened
> recently that captures a few of the common cases (where call info
> seems to be lost inside of "let" and perhaps other forms).

Matt,

thanks for your comments.

As I noted in my original message, the procedure name will only be
recorded if it is a global var rather than a lexical var or other
expression, and that is actually the correct behaviour. We still get
source locations.

One thing we could try is to record the name of the surrounding
top-level procedure at the call location, which is what you get in Java
stack traces. However, that is actually surprisingly hard to do
automatically and doesn't gain the user any new information - they can
always go to the source location and read the code to find the
surrounding proc - it just improves the "at-a-glance" readability of the
trace.

The stack traces, and indeed the current error messages, are almost
completely useless without source location information. Unfortunately,
source transformations really mess with that. Every piece of code
undergoes three transformations:
- macro expansion
- optimisation
- optimistic optimisation

The stack tracer deals with the latter by unoptimising any code executed
while stack tracing is enabled, and I have taken great care to ensure
that the source location information produced this way is identical to
what is produced if the code is not optimistically optimised in the
first place.

That leaves macro transformation and optimisation as the culprits for
incorrect/absent source location info. They all *propagate* source
location information. However, when they introduce new code then the
location information of that will point either to the location of the
macro or be absent altogether. Take for example

(import* misc define-simple-syntax)
(define-simple-syntax (call fn . args) (fn . args))

(define (bar x)
  (if (zero? x)
      (/ 1 0)
      (bar (- x 1))))

(define (baz x)
  (if (zero? x)
      (/ 1 0)
      (call baz (- x 1))))

Calling 'bar' produces

Error in /: division by zero.
------------------
stack-test1.scm:6:7: <call to />
5 repetitions of ...
  stack-test1.scm:7:7: <call to bar>
console:131:1: <call to bar>

...which is fine. By contrast, calling 'baz' produces

stack-test1.scm:11:7: <call to />
5 repetitions of ...
  ?:?:?: <call to baz>
console:150:1: <call to baz>

...which is missing the source location information of the recursive
call to baz.

Fortunately it is quite rare for macros to produce procedure
applications, so we don't run into this problem very often.

Correcting it would involve annotating macro-produced expressions with
both the macro source location and the macro invocation location, with
several such locations recorded in cases of nested macro expansion.

That requires major surgery on the macro expander though which we will
probably not do until we've switched to a different expander.



Matthias



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642