guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: PLEASE: debugging embedded guile code


From: Neil Jerram
Subject: Re: PLEASE: debugging embedded guile code
Date: 28 Apr 2003 20:21:47 +0100
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7

>>>>> "Bruce" == Bruce Korb <address@hidden> writes:

    Bruce> I guess I'm really lazy.  I'm interested in playing with my project
    Bruce> and I'm completely _un_interested in figuring out the inner workings
    Bruce> of Guile error handling.  But I have a problem.  Sometimes my clients
    Bruce> provide my project with a scheme script that is many lines long.
    Bruce> I merrily hand the whole string off to gh_eval_str() to deal with.
    Bruce> Somewhere in that string, Guile becomes confused and says, "this is
    Bruce> confusing" and calls exit(3C).  My client emails me and says, "Your
    Bruce> program said it was confused but won't tell me where or why."  Well,
    Bruce> I do print out where the Scheme script starts, but not where in the
    Bruce> script the confusion was.  It's adequate for me because I generally
    Bruce> keep my Scheme scripts to under a half dozen lines.  It's a problem.

    Bruce> So, what I would really like:

    Bruce> Explicit, unambiguous directions on exactly how to get the Guile 
library
    Bruce> to print out the same error messages it does when running as part
    Bruce> of the "guile" independent program.  [...]

OK, I understand.  There are three parts to the answer that I think
you need.

1. You want an evaluator with a catch handler,
   e.g. gh_eval_str_with_catch, instead of plain gh_eval_str, which
   just exits.

2. The handler needs to call display-error, which is the function that
   displays all the useful information.

3. In order for display-error to show maximum useful information, the
   port that the source code came from must have a name.
   Unfortunately the current default is that string ports are unnamed.

If I were you, I'd do as much of this as possible in Scheme, e.g.:

(use-modules (ice-9 stack-catch))

(define (eval-client-input str)
  (stack-catch #t
    (lambda ()
      (call-with-input-string str
        (lambda (p)
          (set-port-filename! p "<string port>")
          (list (primitive-eval (read p))))))
    (lambda (key . args)
      ;; [1]
      (apply display-error (fluid-ref the-last-stack)
                           (current-error-port)
                           args)
      (set! stack-saved? #f)
      #f)))

Basic testing...

guile> (eval-client-input "(define foo bar)")
<string port>:1:1: In expression (define foo bar):
<string port>:1:1: Unbound variable: bar
#f
guile> (eval-client-input "(let ((x 1)) (* x x unknown))")
<string port>:1:14: While evaluating arguments to * in expression (* x x ...):
<string port>:1:14: Unbound variable: unknown
#f
guile> (eval-client-input "\
... (for-each (lambda (x)
...             (display (* x x))
...             (newline))
...           number-list)
... ")
<string port>:1:1: While evaluating arguments to for-each in expression 
(for-each
(lambda # # ...) number-list):
<string port>:1:1: Unbound variable: number-list
#f
guile> (eval-client-input "\
... (for-each (lambda (x)
...             (display (* x x))
...             (newline))
...           (cdr number-list))
... ")
<string port>:4:11: While evaluating arguments to cdr in expression (cdr 
number-list):
<string port>:4:11: Unbound variable: number-list
#f

You can call `eval-client-input' from C using scm_c_lookup and
scm_call_1.

Note - the code above assumes that `args' has the right structure (see
doc for display-error), which is true for all the exceptions generated
by Guile itself.  If you want to handle exceptions generated by your
own or your client's code, you need to add code at [1] to identify
non-core exceptions and turn their throw args into suitable parameters
for display-error.

Does this help?

        Neil





reply via email to

[Prev in Thread] Current Thread [Next in Thread]