16. Bigloo The Programming Language (4.6a) User manual for version 4.6a January 2025 -- Errors, Assertions, and Traces

main page

top: | Bigloo The Programming Language (4.6a) User manual for version 4.6a January 2025

Errors, Assertions, and Traces

Chapters

### 16.1 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 obj | bigloo procedure

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

error proc msg obj | bigloo 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.

error/location proc msg obj file location | bigloo 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

get-trace-stack size | bigloo procedure

dump-trace-stack output-port size | bigloo 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`.

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
    => '()

exception-notify exc | bigloo procedure

error-notify err | bigloo procedure

warning-notify err | bigloo procedure

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

### 16.2 Exceptions

current-exception-handler | SRFI-18 function

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

with-exception-handler handler thunk | SRFI-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.

with-handler handler body | bigloo 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`.

raise obj | SRFI-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"

The standard Bigloo runtime system uses the following classes for signaling errors and warnings.

&exception | class

    (class &exception
       (fname read-only (default #f))
       (location read-only (default #f)))

&error::&exception | class

    (class &error::&exception
       (proc read-only)
       (msg read-only)
       (obj read-only))

&type-error::&error | class

    (class &type-error::&error
       (type read-only))

&io-error::&error | class

    (class &io-error::&error)

&io-port-error::&io-error | class

    (class &io-port-error::&io-error)

&io-read-error::&io-error | class

    (class &io-read-error::&io-port-error)

&io-write-error::&io-port-error | class

    (class &io-write-error::&io-port-error)

&io-closed-error::&io-port-error | class

    (class &io-closed-error::&io-port-error)

&io-file-not-found-error::&io-error | class

    (class &io-file-not-found-error::&io-error)

&io-parse-error::&io-error | class

    (class &io-parse-error::&io-error)

&io-unknown-host-error::&io-error | class

    (class &io-unknown-host-error::&io-error)

&io-malformed-url-error::&io-error | class

    (class &io-malformed-url-error::&io-error)

&http-error::&error | class

    (class &http-error::&error)

&http-redirection-error::&http-error | class

    (class &http-redirection-error::&http-error)

&http-status-error::&http-error | class

    (class &http-status-error::&http-error)

&http-redirection::&http-error | class

    (class &http-redirection::&exception
      (port::input-port read-only)
      (url::bstring read-only))

process-exception::&error | class

    (class &process-exception::&error)

&warning::&exception | class

    (class &warning::&exception
       (args read-only))

&eval-warning::&warning | class

    (class &warning::&warning)

### 16.3 Deprecated try form

try exp handler | bigloo 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

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
    => '()

### 16.4 Assertions

assert (var...) s-expression | bigloo 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
    -----------------------

    *:=>

### 16.5 Tracing

Bigloo provides a trace facility whose is intended for simple debugging tasks. It is a replacement for user `display`s 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 . body | bigloo 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).

trace-item . args | bigloo function

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

trace-bold s | bigloo function

trace-string s | bigloo function

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

trace-color color . args | bigloo 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).

trace-margin | bigloo 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 "="))
                    ...))

trace-port | bigloo function

trace-port-set! | bigloo function

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

This Html page has been produced by Skribe.
Last update Mon Jan 27 07:55:49 2025.