[gambit-list] [ANN] Gambit-C v4.4.3 released

Marc Feeley feeley at iro.umontreal.ca
Fri Apr 24 13:01:09 EDT 2009


On 24-Apr-09, at 6:49 AM, Valeriya Pudova wrote:

> Hello good people,
>
> I found that sometime gsi (or gsc) does not report the error location
> refering information. It make hard job to find location of error.
>
> After few tests I found simple code which display this issue.
>
>> (eval '(define (foo) (display (/ 1 0)))) (foo)
> *** ERROR IN foo -- Divide by zero,
> (/ 1 0)
>
> Not (eval) makes the problem, because this  variant works
>
>> (eval '(define (foo)  (/ 1 0))) (foo)
> *** ERROR IN "test2.scm"@1.33 -- Divide by zero
> (/ 1 0)
>
> And not (display):
>
>> (define (foo)  (display (/ 1 0))) (foo)
> *** ERROR IN foo, "test2.scm"@1.25 -- Divide by zero
> (/ 1 0)
>
> Could anybody explain this?
>

The source code location is attached to "source" objects.  These  
source objects are returned by the reader that is called by the "load"  
procedure and the REPL.  The "eval" procedure can accept as its  
parameter expressions that are represented as source objects or pure S- 
expressions, i.e. (nested) Scheme lists, symbols, numbers, etc.  When  
eval creates a continuation for a non-tail procedure call, it leaves  
in the continuation a reference to the expression that corresponds to  
the call (note that in the case of tail procedure calls no  
continuation is created so this information is not saved).  When an  
error is encountered, such as (/ 1 0), the continuation of the  
primitive (here: /) which detected the error is captured and passed to  
the debugger which starts a nested REPL.  The debugger uses this  
continuation to recover the location information for the error  
message.  So the location of the call to / will not be recovered when  
eval was passed a pure S-expression (as in your first test above)  
because the expression saved in the continuation has no source code  
location information attached to it.  In the case of your second test,  
you get the location of the call to foo, because foo has tail- 
called /, so the continuation of / is the continuation created for the  
call to foo (and the call to foo is not inside the S-expression passed  
to eval, i.e. it is a source code object with location information).

The following macro definition might prove useful for debugging:

(##define-syntax attach-this-locat
   (lambda (src)
     (let ((expr (cadr (##source-code src)))
           (locat (##source-locat src)))
       `(##make-source ,expr ',locat))))

The call

(eval (attach-this-locat '(+ 1 (/ 1 0))))

will give a divide-by-zero error with the location of the call to  
attach-this-locat.  This is not perfect, but it at least gives you  
some location information.  It works by extracting the source code  
location from the parameter (i.e. src) and attaching that location to  
the S-expression that is then passed to eval (to turn it into a source  
object).

You may also want to use (declare (not proper-tail-calls)) at the top  
of your code.  It requests that the interpreter and compiler treat  
tail-calls like non-tail-calls, which gives you in error messages the  
location of the last call to the primitive which detected the error.

Marc




More information about the Gambit-list mailing list