[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