[plt-scheme] Source location infromation and tracebacks (was: match-lambda and source location)

From: Jakub Piotr Cłapa (jpc-ml at zenburn.net)
Date: Sun Jan 4 13:16:20 EST 2009

On 1/3/09 8:11 PM, Matthew Flatt wrote:
> At Sat, 03 Jan 2009 00:54:53 +0100, Jakub Piotr Cłapa wrote:
>> match-lambda creates a lambda without overriding syntax information.
>> This greatly reduces the information content in stack traces.
>> OTOH overriding the source information for the lambda keyword greatly
>> reduces the clarity of the macro code...
> I don't understand what you mean. Can you provide an example, describe
> how it behaves, and describe how it should behave instead?

Ok. I think I misinterpreted the problem since I last stumbled upon it. 
Here is the test case:

(define test-1
     [(list a b) #t]))

(define (test-2 l)
   (match l
     [(list a b) #t]))

Notice the difference in tracebacks between (test-1 #t) and (test-2 #t).
This is as far as I (now) understand related to source location 
information of the match form.

The problem with readability of the macros was in my own code:

(define-syntax (on-notif stx)
   (syntax-case stx ()
     [(on-notif (notif arg ...)
        expr expr+ ...)
      (with-syntax ([fun (datum->syntax #'here
                                        (syntax-e #'(lambda (arg ...)
                                                      expr expr+ ...))
            #;(** 'notif (list fun (notif-observers notif)))
            (notif-add-observer! notif fun)))]))

Not very pretty and AFAIR I had to datum->syntax the whole expression 
and not only the lambda keyword... Is there a better way to solve this? 
(I wanted to differentiate the resulting closures when they were printed)

> I may misunderstand this part, too, but I think the first half is what
> Errortrace (in the "errortrace" collection) does. It instruments code
> to push continuation marks that indicates source locations, and then
> the exception handler collects the marks to reconstruct a stack trace.
> Errortrace doesn't try to track tail calls beyond the immediate one.

1. My (uneducated) idea was to add a note every time the source location 
info suggests that we changed from macro generated code to user code and 
vice versa.

2. Tracing several previous tail calls could ease the debugging of loops 
and should be possible without breaking the space efficiency of tail calls.

This would provide for Scheme loops what tracebacks provide for normal 
function calls. An answer to the question: How I got here? This is 
something that Scheme style iteration could do much better than an 
average imperative loop.

A related concern is that even when tail calls are not used for looping 
we sometimes loose information:
(define (sqrt-inv a)
   (let ([inv (/ a)])
     (sqrt inv)))

(define (do-b b)
   (sqrt-inv (* 2 b)))

(define (do-c c)
   (if (< c 0)
       (do-b c)))

When we call (do-c 0) we don't get any of the do- functions in the 

I have only limited knowledge of how continuation marks (and the 
traceback machinery) work in PLT Scheme so I apologize if my remarks are 
not very good.

Jakub Piotr Cłapa

Posted on the users mailing list.