Errors, Assertions, and Traces

Errors and Warnings

Bigloo permits to signal an error via the error function. Errors are implemented by the means of exceptions (see with-exception-handler, with-handler, and raise forms). Assertions allow the checking of predicates at certain points in programs.

typeof objbigloo procedure

Returns a string which is the name of the dynamic type of obj.
.keep

error proc msg objbigloo procedure

This form signals an error by calling the current error handler with proc, msg and obj as arguments.

(define (foo l)
   (if (not (pair? l))
       (error "foo" "argument not a pair" l)
       (car l)))

(foo 4)
error--> *** ERROR:bigloo:foo:
         argument not a pair -- 4
Switching on the -g compilation switch enables stack dumping when the error function is invoked. That is, when a program is compiled with -g and when, at runtime, the shell variable BIGLOOSTACKDEPTH is set and contains a number, an execution stack of depth BIGLOOSTACKDEPTH is printed when an error is raised.
.keep

error/location proc msg obj file locationbigloo procedure

This form signals an error by calling the current error handler with proc, msg and obj as arguments. The error is prompted in file, at character position location.

(define (foo l)
   (if (not (pair? l))
       (error/location
         "foo" "argument not a pair" l "foo.scm" 115)
       (car l)))

(foo 4)
error--> File "foo.scm", line 4, character 115:
         #       (car l)))
         #       ^
         # *** ERROR:bigloo:foo
         # argument not a pair -- 4
             0. FOO
             1. DYNAMIC-WIND
             2. INTERP
             3. ENGINE
             4. MAIN
.keep

get-trace-stack sizebigloo procedure

dump-trace-stack output-port sizebigloo procedure

Switching on the -g compilation switch enables stack dumping Compiler Description. That is, the list of the pending calls can be dumped by the runtime-system. The function get-trace-stack builds such a trace. The list built by get-trace-stack only contains the size top most pending calls. The function dump-trace-stack displays a representation of this stack on the output-port.

.keep

warning/location file location [arg]...bigloo procedure

This form signals a warning. That is, is arg are displayed on the standard error port. The warning is prompted in file at character position location.

(define (foo l)
   (if (not (pair? l))
       (begin
          (warning/location
            "foo.scm" 154 "foo:" "argument not a pair -- " l)
          '())
       (car l)))

(foo 4)
 File "foo.scm", line 6, character 154:
   #       (car l)))
   #       ^
   # *** WARNING:bigloo:foo:
   argument not a pair -- 4
 '()
.keep

exception-notify excbigloo procedure

error-notify errbigloo procedure

warning-notify errbigloo procedure

Display a message describing the error or warning on the default error port.
.keep

Exceptions

current-exception-handlerSRFI-18 function

Returns the current exception handler with is a 0-ary procedure.
.keep

with-exception-handler handler thunkSRFI-18 function

Returns the result(s) of calling thunk with no arguments. The handler, which must be a procedure, is installed as the current exception handler in the dynamic environment in effect during the call to thunk. When possible, prefer with-handler to with-exception-handler because the former provides better debugging support and because its semantics is more intuitive.
.keep

with-handler handler bodybigloo form

Returns the result(s) of evaluating body. The handler, which must be a procedure, is installed as the current exception handler in the dynamic environment in effect during the evaluation of body. Contrarily to with-exception-handler, if an exception is raised, the handler is invoked and the value of the with-handler form is the value produced by invoking the handler. The handler is executed in the continuation of the with-handler form.

JVM note: When executed within a JVM, the form with-handler also catches Java exceptions.

Important note: Since Bigloo version 3.2c, error handlers are executed after the execution stack is unwound. Hence, error handlers are executed after protected blocks. For instance in the following code:

(with-handler 
   (lambda (e) action)
   (unwind-protect
      body
      protect))
The action is executed after protect.

.keep

raise objSRFI-18 function

Calls the current exception handler with obj as the single argument. obj may be any Scheme object. Note that invoking the current handler does not escape from the current computation. It is up the to handler to perform the escape. It an error, signaled by the runtime system, if the current exception handler returns.

(define (f n)
  (if (< n 0) (raise "negative arg") (sqrt n))))

(define (g)
  (bind-exit (return)
    (with-exception-handler
      (lambda (exc)
        (return
          (if (string? exc)
              (string-append "error: " exc)
              "unknown error")))
      (lambda ()
        (write (f 4.))
        (write (f -1.))
        (write (f 9.))))))

(g)   2. and returns "error: negative arg"
.keep
The standard Bigloo runtime system uses the following classes for signaling errors and warnings:

Deprecated try form

try exp handlerbigloo syntax

This form is deprecated. As much as possible, it should be replaced with true exceptions (i.e., with-exception-handler and raise). The argument exp is evaluated. If an error is raised, the handler is called. The argument handler is a procedure of four arguments. Its first argument is the continuation of try. The other arguments are proc, mes and obj. Invoking the first argument will resume after the error.

(let ((handler (lambda (escape proc mes obj)
                  (print "***ERROR:" proc ":" mes " -- " obj)
                  (escape #f))))
   (try (car 1) handler))
    ***ERROR:CAR:not a pair -- 1
    #f
The argument handler is not evaluated in the dynamic scope of its try form. That is:

(let ((handler (lambda (escape proc mes obj)
                  (escape (car obj)))))
   (try (car 1) handler))
   error--> *** ERROR:bigloo:CAR
            Type `PAIR' expected, `BINT' provided -- 1
.keep
Some library functions exist to help in writing handlers:

warning [arg]...bigloo procedure

This form signals a warning. That is, is arg are displayed on the standard error port.

(define (foo l)
   (if (not (pair? l))
       (begin
          (warning "foo:" "argument not a pair -- " l)
          '())
       (car l)))

(foo 4)
 *** WARNING:bigloo:foo:
   argument not a pair -- 4
 '()
.keep

Assertions

assert (var...) s-expressionbigloo syntax

Assertions can be enabled or disabled using Bigloo's compilation flags -g flag to enable them). If the assertions are disabled they are not evaluated. If an assertion is evaluated, if the expression exp does not evaluate to #t, an error is signaled and the interpreter is launched in an environment where var... are bound to their current values.

Assertion forms are legal expressions which always evaluate to the unspecified object.

Here is an example of assertion usage:

(module foo
   (eval (export foo)))

(define (foo x y)
   [assert (x y) (< x y)]
   (labels ((gee (t)
                 [assert (t) (>= t 0)]
                 (let ((res (+ x t)))
                    [assert (res t) (> res 10)]
                    res)))
      (set! x (gee y))
      [assert (x) (> x 10)]
      x))

(repl)
This module is compiled with the -g flag to enable assertions, then the produced executable is run:

$ a.out

1:=> (foo 1 2)

File "foo.scm", line 9, character 158: # [assert (res t) (> res 10)] # ^ # *** ERROR:bigloo:assert # assertion failed -- (BEGIN (> RES 10)) 0. GEE 1. FOO ----------------------- Variables' value are : RES : 3 T : 2 ----------------------- *:=> ^D File "foo.scm", line 12, character 228: # [assert (x) (> x 10)] # ^ # *** ERROR:bigloo:assert # assertion failed -- (BEGIN (> X 10)) 0. FOO ----------------------- Variables' value are : X : 3 -----------------------

*:=> 3 1:=> (foo 1 2) File "foo.scm", line 9, character 158: # [assert (res t) (> res 10)] # ^ # *** ERROR:bigloo:assert # assertion failed -- (BEGIN (> RES 10)) 0. GEE 1. FOO ----------------------- Variables' value are : RES : 3 T : 2 -----------------------

*:=>
.keep

Tracing

Bigloo provides a trace facility whose is intended for simple debugging tasks. It is a replacement for user displays that clutters the source code. Here is a typical example using it:

(define (foo x)
   (with-trace 1 'foo
      (let loop ((n x))
         (with-trace 2 'loop
            (trace-item "n=" n)
            (when (> n 0)
               (let liip ((m n))
                  (with-trace 2 'liip
                     (trace-item "m=" m))
                  (when (> m 0)
                     (liip (- m 1))))
               (loop (- n 1)))))))

(foo 3)
which produces the following output:

+ foo
  |--+ loop
  |  |- n=3
  |  |--+ liip
  |  |  |- m=3
  |  |--+ liip
  |  |  |- m=2
  |  |--+ liip
  |  |  |- m=1
  |  |--+ liip
  |  |  |- m=0
  |  |--+ loop
  |  |  |- n=2
  |  |  |--+ liip
  |  |  |  |- m=2
  |  |  |--+ liip
  |  |  |  |- m=1
  |  |  |--+ liip
  |  |  |  |- m=0
  |  |  |--+ loop
  |  |  |  |- n=1
  |  |  |  |--+ liip
  |  |  |  |  |- m=1
  |  |  |  |--+ liip
  |  |  |  |  |- m=0
  |  |  |  |--+ loop
  |  |  |  |  |- n=0
Traces generation is controlled by a set of functions and parameters (see Parameters). The functions are described in this chapter.

with-trace level label . bodybigloo syntax

The variable level is the level of a trace. It is a positive integer. It enables simple filtering for traces. A trace is displayed if and only if the debugging level used to compile or to execute the program is greater than the trace level. The variable label is a label, .e.i., an identifier denoting the trace. This identifier will be displayed in debug mode. The variable body is the body of the form, that is, the expression to be evaluated.

Unless a trace is activated (with-trace lv la body) (when its level lv is greater than the current debug level) is equivalent to (begin body). When traces are activated, before executing body.

The debugging level is controlled by two parameters: bigloo-debug and bigloo-compiler-debug (see Parameters).

.keep

trace-item . argsbigloo function

This function displays all its arguments. It has to be used nested in a with-trace form.
.keep

trace-bold sbigloo function

trace-string sbigloo function

These two functions are provided for convenience. They returns strings made of their parameters.
.keep

trace-color color . argsbigloo function

The color argument is a positive integer. This function returns a string which is the representation of args and that appears on the terminal in color color.

Colors can be enable or disabled using the bigloo-trace-color parameter (see Parameters).
.keep

trace-marginbigloo function

trace-margin-set!bigloo function

The trace-margin parameter is used to control the characters that are displayed in the margin of a trace. Usual applications should not use this. However, it may be convenient to set the margin by hands in some context. For instance, it can be used to distinguished threads in a multi-threaded application such as:

(make-thread (lambda () 
                (trace-margin-set! (trace-color 1 "="))
                ...))
(make-thread (lambda () 
                (trace-margin-set! (trace-color 2 "="))
                ...))
.keep

trace-portbigloo function

trace-port-set!bigloo function

These functions return and set the output port used by traces.
.keep