Errors, Assertions, and Traces
Errors and Warnings
Bigloo permits to signal an error via theerror
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 -- 4Switching 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, preferwith-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 towith-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.
&exceptionclass
(class &exception (fname read-only (default #f)) (location read-only (default #f)))
.keep
&error::&exceptionclass
(class &error::&exception (proc read-only) (msg read-only) (obj read-only))
.keep
&type-error::&errorclass
(class &type-error::&error (type read-only))
.keep
&io-error::&errorclass
(class &io-error::&error)
.keep
&io-port-error::&io-errorclass
(class &io-port-error::&io-error)
.keep
&io-read-error::&io-errorclass
(class &io-read-error::&io-port-error)
.keep
&io-write-error::&io-port-errorclass
(class &io-write-error::&io-port-error)
.keep
&io-closed-error::&io-port-errorclass
(class &io-closed-error::&io-port-error)
.keep
&io-file-not-found-error::&io-errorclass
(class &io-file-not-found-error::&io-error)
.keep
&io-parse-error::&io-errorclass
(class &io-parse-error::&io-error)
.keep
&io-unknown-host-error::&io-errorclass
(class &io-unknown-host-error::&io-error)
.keep
&io-malformed-url-error::&io-errorclass
(class &io-malformed-url-error::&io-error)
.keep
&http-error::&errorclass
(class &http-error::&error)
.keep
&http-redirection-error::&http-errorclass
(class &http-redirection-error::&http-error)
.keep
&http-status-error::&http-errorclass
(class &http-status-error::&http-error)
.keep
&http-redirection::&http-errorclass
(class &http-redirection::&exception (port::input-port read-only) (url::bstring read-only))
.keep
process-exception::&errorclass
(class &process-exception::&error)
.keep
&warning::&exceptionclass
(class &warning::&exception (args read-only))
.keep
&eval-warning::&warningclass
(class &warning::&warning)
.keep
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 ⇒ #fThe 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 userdisplay
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=0Traces 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 thebigloo-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