* Multiple Values:: Returning and accepting multiple values.
* Exceptions:: Throwing and catching exceptions.
* Error Reporting:: Procedures for signaling errors.
-* Dynamic Wind:: Guarding against non-local entrance/exit.
-* Frames:: Another way to handle non-localness
+* Dynamic Wind:: Dealing with non-local entrance/exit.
* Handling Errors:: How to handle errors in C code.
@end menu
the value of @var{test}. The result of this procedure application is
then the result of the @code{cond}-expression.
+@cindex SRFI-61
+@cindex general cond clause
+@cindex multiple values and cond
+One additional @code{cond}-clause is available as an extension to
+standard Scheme:
+
+@lisp
+(@var{test} @var{guard} => @var{expression})
+@end lisp
+
+where @var{guard} and @var{expression} must evaluate to procedures.
+For this clause type, @var{test} may return multiple values, and
+@code{cond} ignores its boolean state; instead, @code{cond} evaluates
+@var{guard} and applies the resulting procedure to the value(s) of
+@var{test}, as if @var{guard} were the @var{consumer} argument of
+@code{call-with-values}. Iff the result of that procedure call is a
+true value, it evaluates @var{expression} and applies the resulting
+procedure to the value(s) of @var{test}, in the same manner as the
+@var{guard} was called.
+
The @var{test} of the last @var{clause} may be the symbol @code{else}.
Then, if none of the preceding @var{test}s is true, the
@var{expression}s following the @code{else} are evaluated to produce the
@code{dynamic-wind} (@pxref{Dynamic Wind}) can be used to ensure setup
and cleanup code is run when a program locus is resumed or abandoned
-through the continuation mechanism. C code can use @dfn{frames}
-(@pxref{Frames}).
+through the continuation mechanism.
@sp 1
Continuations are a powerful mechanism, and can be used to implement
@end deffn
In addition to the fundamental procedures described above, Guile has a
-module which exports a syntax called @code{receive}, which is much more
-convenient. If you want to use it in your programs, you have to load
-the module @code{(ice-9 receive)} with the statement
+module which exports a syntax called @code{receive}, which is much
+more convenient. This is in the @code{(ice-9 receive)} and is the
+same as specified by SRFI-8 (@pxref{SRFI-8}).
@lisp
(use-modules (ice-9 receive))
@end lisp
@deffn {library syntax} receive formals expr body @dots{}
-Evaluate the expression @var{expr}, and bind the result values (zero or
-more) to the formal arguments in the formal argument list @var{formals}.
-@var{formals} must have the same syntax like the formal argument list
-used in @code{lambda} (@pxref{Lambda}). After binding the variables,
-the expressions in @var{body} @dots{} are evaluated in order.
+Evaluate the expression @var{expr}, and bind the result values (zero
+or more) to the formal arguments in @var{formals}. @var{formals} is a
+list of symbols, like the argument list in a @code{lambda}
+(@pxref{Lambda}). After binding the variables, the expressions in
+@var{body} @dots{} are evaluated in order, the return value is the
+result from the last expression.
+
+For example getting results from @code{partition} in SRFI-1
+(@pxref{SRFI-1}),
+
+@example
+(receive (odds evens)
+ (partition odd? '(7 4 2 8 3))
+ (display odds)
+ (display " and ")
+ (display evens))
+@print{} (7 3) and (4 2 8)
+@end example
+
@end deffn
@menu
* Exception Terminology:: Different ways to say the same thing.
* Catch:: Setting up to catch exceptions.
-* Throw:: Throwing an exception.
+* Throw Handlers:: Adding extra handling to a throw.
* Lazy Catch:: Catch without unwinding the stack.
+* Throw:: Throwing an exception.
* Exception Implementation:: How Guile implements exceptions.
@end menu
@code{catch} is used to set up a target for a possible non-local jump.
The arguments of a @code{catch} expression are a @dfn{key}, which
restricts the set of exceptions to which this @code{catch} applies, a
-thunk that specifies the code to execute and a @dfn{handler} procedure
-that says what to do if an exception is thrown while executing the code.
-Note that if the execution thunk executes @dfn{normally}, which means
-without throwing any exceptions, the handler procedure is not called at
-all.
+thunk that specifies the code to execute and one or two @dfn{handler}
+procedures that say what to do if an exception is thrown while executing
+the code. If the execution thunk executes @dfn{normally}, which means
+without throwing any exceptions, the handler procedures are not called
+at all.
When an exception is thrown using the @code{throw} function, the first
argument of the @code{throw} is a symbol that indicates the type of the
corresponds to the number of arguments in all @code{throw} expressions
that can be caught by this @code{catch}.
-@deffn {Scheme Procedure} catch key thunk handler
+The fourth, optional argument of a @code{catch} expression is another
+handler procedure, called the @dfn{pre-unwind} handler. It differs from
+the third argument in that if an exception is thrown, it is called,
+@emph{before} the third argument handler, in exactly the dynamic context
+of the @code{throw} expression that threw the exception. This means
+that it is useful for capturing or displaying the stack at the point of
+the @code{throw}, or for examining other aspects of the dynamic context,
+such as fluid values, before the context is unwound back to that of the
+prevailing @code{catch}.
+
+@deffn {Scheme Procedure} catch key thunk handler [pre-unwind-handler]
+@deffnx {C Function} scm_catch_with_pre_unwind_handler (key, thunk, handler, pre_unwind_handler)
@deffnx {C Function} scm_catch (key, thunk, handler)
Invoke @var{thunk} in the dynamic context of @var{handler} for
exceptions matching @var{key}. If thunk throws to the symbol
If the key is @code{#t}, then a throw to @emph{any} symbol will
match this call to @code{catch}.
+
+If a @var{pre-unwind-handler} is given and @var{thunk} throws
+an exception that matches @var{key}, Guile calls the
+@var{pre-unwind-handler} before unwinding the dynamic state and
+invoking the main @var{handler}. @var{pre-unwind-handler} should
+be a procedure with the same signature as @var{handler}, that
+is @code{(lambda (key . args))}. It is typically used to save
+the stack at the point where the exception occurred, but can also
+query other parts of the dynamic state at that point, such as
+fluid values.
+
+A @var{pre-unwind-handler} can exit either normally or non-locally.
+If it exits normally, Guile unwinds the stack and dynamic context
+and then calls the normal (third argument) handler. If it exits
+non-locally, that exit determines the continuation.
@end deffn
-If the handler procedure needs to match a variety of @code{throw}
+If a handler procedure needs to match a variety of @code{throw}
expressions with varying numbers of arguments, you should write it like
this:
another, but should be specified by the documentation for each exception
type.
-Note that, once the handler procedure is invoked, the catch that led to
-the handler procedure being called is no longer active. Therefore, if
-the handler procedure itself throws an exception, that exception can
-only be caught by another active catch higher up the call stack, if
-there is one.
+Note that, once the normal (post-unwind) handler procedure is invoked,
+the catch that led to the handler procedure being called is no longer
+active. Therefore, if the handler procedure itself throws an exception,
+that exception can only be caught by another active catch higher up the
+call stack, if there is one.
@sp 1
-@deftypefn {C Function} SCM scm_internal_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data)
-The above @code{scm_catch} takes Scheme procedures as body and handler
-arguments. @code{scm_internal_catch} is an equivalent taking C
-functions.
-
-@var{body} is called as @code{@var{body} (@var{body_data})} with a
-catch on exceptions of the given @var{tag} type. If an exception is
-caught, @var{handler} is called @code{@var{handler}
-(@var{handler_data}, @var{key}, @var{args})}. @var{key} and
-@var{args} are the @code{SCM} key and argument list from the
-@code{throw}.
+@deftypefn {C Function} SCM scm_c_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data, scm_t_catch_handler pre_unwind_handler, void *pre_unwind_handler_data)
+@deftypefnx {C Function} SCM scm_internal_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data)
+The above @code{scm_catch_with_pre_unwind_handler} and @code{scm_catch}
+take Scheme procedures as body and handler arguments.
+@code{scm_c_catch} and @code{scm_internal_catch} are equivalents taking
+C functions.
+
+@var{body} is called as @code{@var{body} (@var{body_data})} with a catch
+on exceptions of the given @var{tag} type. If an exception is caught,
+@var{pre_unwind_handler} and @var{handler} are called as
+@code{@var{handler} (@var{handler_data}, @var{key}, @var{args})}.
+@var{key} and @var{args} are the @code{SCM} key and argument list from
+the @code{throw}.
@tpindex scm_t_catch_body
@tpindex scm_t_catch_handler
@end deftypefn
-@node Throw
-@subsubsection Throwing Exceptions
-
-The @code{throw} primitive is used to throw an exception. One argument,
-the @var{key}, is mandatory, and must be a symbol; it indicates the type
-of exception that is being thrown. Following the @var{key},
-@code{throw} accepts any number of additional arguments, whose meaning
-depends on the exception type. The documentation for each possible type
-of exception should specify the additional arguments that are expected
-for that kind of exception.
-
-@deffn {Scheme Procedure} throw key . args
-@deffnx {C Function} scm_throw (key, args)
-Invoke the catch form matching @var{key}, passing @var{args} to the
-@var{handler}.
+@node Throw Handlers
+@subsubsection Throw Handlers
-@var{key} is a symbol. It will match catches of the same symbol or of
-@code{#t}.
+It's sometimes useful to be able to intercept an exception that is being
+thrown, but without changing where in the dynamic context that exception
+will eventually be caught. This could be to clean up some related state
+or to pass information about the exception to a debugger, for example.
+The @code{with-throw-handler} procedure provides a way to do this.
-If there is no handler at all, Guile prints an error and then exits.
+@deffn {Scheme Procedure} with-throw-handler key thunk handler
+@deffnx {C Function} scm_with_throw_handler (key, thunk, handler)
+Add @var{handler} to the dynamic context as a throw handler
+for key @var{key}, then invoke @var{thunk}.
@end deffn
-When an exception is thrown, it will be caught by the innermost
-@code{catch} expression that applies to the type of the thrown
-exception; in other words, the innermost @code{catch} whose @var{key} is
-@code{#t} or is the same symbol as that used in the @code{throw}
-expression. Once Guile has identified the appropriate @code{catch}, it
-handles the exception by applying that @code{catch} expression's handler
-procedure to the arguments of the @code{throw}.
-
-If there is no appropriate @code{catch} for a thrown exception, Guile
-prints an error to the current error port indicating an uncaught
-exception, and then exits. In practice, it is quite difficult to
-observe this behaviour, because Guile when used interactively installs a
-top level @code{catch} handler that will catch all exceptions and print
-an appropriate error message @emph{without} exiting. For example, this
-is what happens if you try to throw an unhandled exception in the
-standard Guile REPL; note that Guile's command loop continues after the
-error message:
-
-@lisp
-guile> (throw 'badex)
-<unnamed port>:3:1: In procedure gsubr-apply @dots{}
-<unnamed port>:3:1: unhandled-exception: badex
-ABORT: (misc-error)
-guile>
-@end lisp
-
-The default uncaught exception behaviour can be observed by evaluating a
-@code{throw} expression from the shell command line:
-
-@example
-$ guile -c "(begin (throw 'badex) (display \"here\\n\"))"
-guile: uncaught throw to badex: ()
-$
-@end example
+@deftypefn {C Function} SCM scm_c_with_throw_handler (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data, int lazy_catch_p)
+The above @code{scm_with_throw_handler} takes Scheme procedures as body
+(thunk) and handler arguments. @code{scm_c_with_throw_handler} is an
+equivalent taking C functions. See @code{scm_c_catch} (@pxref{Catch})
+for a description of the parameters, the behaviour however of course
+follows @code{with-throw-handler}.
+@end deftypefn
-@noindent
-That Guile exits immediately following the uncaught exception
-is shown by the absence of any output from the @code{display}
-expression, because Guile never gets to the point of evaluating that
-expression.
+If @var{thunk} throws an exception, Guile handles that exception by
+invoking the innermost @code{catch} or throw handler whose key matches
+that of the exception. When the innermost thing is a throw handler,
+Guile calls the specified handler procedure using @code{(apply
+@var{handler} key args)}. The handler procedure may either return
+normally or exit non-locally. If it returns normally, Guile passes the
+exception on to the next innermost @code{catch} or throw handler. If it
+exits non-locally, that exit determines the continuation.
+
+The behaviour of a throw handler is very similar to that of a
+@code{catch} expression's optional pre-unwind handler. In particular, a
+throw handler's handler procedure is invoked in the exact dynamic
+context of the @code{throw} expression, just as a pre-unwind handler is.
+@code{with-throw-handler} may be seen as a half-@code{catch}: it does
+everything that a @code{catch} would do until the point where
+@code{catch} would start unwinding the stack and dynamic context, but
+then it rethrows to the next innermost @code{catch} or throw handler
+instead.
@node Lazy Catch
@subsubsection Catch Without Unwinding
+Before version 1.8, Guile's closest equivalent to
+@code{with-throw-handler} was @code{lazy-catch}. From version 1.8
+onwards we recommend using @code{with-throw-handler} because its
+behaviour is more useful than that of @code{lazy-catch}, but
+@code{lazy-catch} is still supported as well.
+
A @dfn{lazy catch} is used in the same way as a normal @code{catch},
with @var{key}, @var{thunk} and @var{handler} arguments specifying the
exception type, normal case code and handler procedure, but differs in
@deffnx {C Function} scm_lazy_catch (key, thunk, handler)
This behaves exactly like @code{catch}, except that it does
not unwind the stack before invoking @var{handler}.
-The @var{handler} procedure is not allowed to return:
-it must throw to another catch, or otherwise exit non-locally.
+If the @var{handler} procedure returns normally, Guile
+rethrows the same exception again to the next innermost catch,
+lazy-catch or throw handler. If the @var{handler} exits
+non-locally, that exit determines the continuation.
@end deffn
@deftypefn {C Function} SCM scm_internal_lazy_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data)
follows @code{lazy-catch}.
@end deftypefn
-Typically, @var{handler} should save any desired state associated with
-the stack at the point where the corresponding @code{throw} occurred,
-and then throw an exception itself --- usually the same exception as the
-one it caught. If @var{handler} is invoked and does @emph{not} throw an
-exception, Guile itself throws an exception with key @code{misc-error}.
+Typically @var{handler} is used to display a backtrace of the stack at
+the point where the corresponding @code{throw} occurred, or to save off
+this information for possible display later.
Not unwinding the stack means that throwing an exception that is caught
by a @code{lazy-catch} is @emph{almost} equivalent to calling the
state of the call stack at the exact point where an exception or an
error is thrown. For an example of this, see REFFIXME:stack-catch.
+It should be obvious from the above that @code{lazy-catch} is very
+similar to @code{with-throw-handler}. In fact Guile implements
+@code{lazy-catch} in exactly the same way as @code{with-throw-handler},
+except with a flag set to say ``where there are slight differences
+between what @code{with-throw-handler} and @code{lazy-catch} would do,
+do what @code{lazy-catch} has always done''. There are two such
+differences:
+
+@enumerate
+@item
+@code{with-throw-handler} handlers execute in the full dynamic context
+of the originating @code{throw} call. @code{lazy-catch} handlers
+execute in the dynamic context of the @code{lazy-catch} expression,
+excepting only that the stack has not yet been unwound from the point of
+the @code{throw} call.
+
+@item
+If a @code{with-throw-handler} handler throws to a key that does not
+match the @code{with-throw-handler} expression's @var{key}, the new
+throw may be handled by a @code{catch} or throw handler that is _closer_
+to the throw than the first @code{with-throw-handler}. If a
+@code{lazy-catch} handler throws, it will always be handled by a
+@code{catch} or throw handler that is higher up the dynamic context than
+the first @code{lazy-catch}.
+@end enumerate
+
+Here is an example to illustrate the second difference:
+
+@lisp
+(catch 'a
+ (lambda ()
+ (with-throw-handler 'b
+ (lambda ()
+ (catch 'a
+ (lambda ()
+ (throw 'b))
+ inner-handler))
+ (lambda (key . args)
+ (throw 'a))))
+ outer-handler)
+@end lisp
+
+@noindent
+This code will call @code{inner-handler} and then continue with the
+continuation of the inner @code{catch}. If the
+@code{with-throw-handler} was changed to @code{lazy-catch}, however, the
+code would call @code{outer-handler} and then continue with the
+continuation of the outer @code{catch}.
+
+Modulo these two differences, any statements in the previous and
+following subsections about throw handlers apply to lazy catches as
+well.
+
+
+@node Throw
+@subsubsection Throwing Exceptions
+
+The @code{throw} primitive is used to throw an exception. One argument,
+the @var{key}, is mandatory, and must be a symbol; it indicates the type
+of exception that is being thrown. Following the @var{key},
+@code{throw} accepts any number of additional arguments, whose meaning
+depends on the exception type. The documentation for each possible type
+of exception should specify the additional arguments that are expected
+for that kind of exception.
+
+@deffn {Scheme Procedure} throw key . args
+@deffnx {C Function} scm_throw (key, args)
+Invoke the catch form matching @var{key}, passing @var{args} to the
+@var{handler}.
+
+@var{key} is a symbol. It will match catches of the same symbol or of
+@code{#t}.
+
+If there is no handler at all, Guile prints an error and then exits.
+@end deffn
+
+When an exception is thrown, it will be caught by the innermost
+@code{catch} or throw handler that applies to the type of the thrown
+exception; in other words, whose @var{key} is either @code{#t} or the
+same symbol as that used in the @code{throw} expression. Once Guile has
+identified the appropriate @code{catch} or throw handler, it handles the
+exception by applying the relevant handler procedure(s) to the arguments
+of the @code{throw}.
+
+If there is no appropriate @code{catch} or throw handler for a thrown
+exception, Guile prints an error to the current error port indicating an
+uncaught exception, and then exits. In practice, it is quite difficult
+to observe this behaviour, because Guile when used interactively
+installs a top level @code{catch} handler that will catch all exceptions
+and print an appropriate error message @emph{without} exiting. For
+example, this is what happens if you try to throw an unhandled exception
+in the standard Guile REPL; note that Guile's command loop continues
+after the error message:
+
+@lisp
+guile> (throw 'badex)
+<unnamed port>:3:1: In procedure gsubr-apply @dots{}
+<unnamed port>:3:1: unhandled-exception: badex
+ABORT: (misc-error)
+guile>
+@end lisp
+
+The default uncaught exception behaviour can be observed by evaluating a
+@code{throw} expression from the shell command line:
+
+@example
+$ guile -c "(begin (throw 'badex) (display \"here\\n\"))"
+guile: uncaught throw to badex: ()
+$
+@end example
+
+@noindent
+That Guile exits immediately following the uncaught exception
+is shown by the absence of any output from the @code{display}
+expression, because Guile never gets to the point of evaluating that
+expression.
+
@node Exception Implementation
@subsubsection How Guile Implements Exceptions
@deffn {Scheme Procedure} strerror err
@deffnx {C Function} scm_strerror (err)
-Return the Unix error message corresponding to @var{err}, which
-must be an integer value.
+Return the Unix error message corresponding to @var{err}, an integer
+@code{errno} value.
+
+When @code{setlocale} has been called (@pxref{Locales}), the message
+is in the language and charset of @code{LC_MESSAGES}. (This is done
+by the C library.)
@end deffn
@c begin (scm-doc-string "boot-9.scm" "false-if-exception")
@node Dynamic Wind
@subsection Dynamic Wind
-@rnindex dynamic-wind
-@deffn {Scheme Procedure} dynamic-wind in_guard thunk out_guard
-@deffnx {C Function} scm_dynamic_wind (in_guard, thunk, out_guard)
-All three arguments must be 0-argument procedures.
-@var{in_guard} is called, then @var{thunk}, then
-@var{out_guard}.
-
-If, any time during the execution of @var{thunk}, the
-dynamic extent of the @code{dynamic-wind} expression is escaped
-non-locally, @var{out_guard} is called. If the dynamic extent of
-the dynamic-wind is re-entered, @var{in_guard} is called. Thus
-@var{in_guard} and @var{out_guard} may be called any number of
-times.
-@lisp
-(define x 'normal-binding)
-@result{} x
-(define a-cont (call-with-current-continuation
- (lambda (escape)
- (let ((old-x x))
- (dynamic-wind
- ;; in-guard:
- ;;
- (lambda () (set! x 'special-binding))
-
- ;; thunk
- ;;
- (lambda () (display x) (newline)
- (call-with-current-continuation escape)
- (display x) (newline)
- x)
-
- ;; out-guard:
- ;;
- (lambda () (set! x old-x)))))))
-
-;; Prints:
-special-binding
-;; Evaluates to:
-@result{} a-cont
-x
-@result{} normal-binding
-(a-cont #f)
-;; Prints:
-special-binding
-;; Evaluates to:
-@result{} a-cont ;; the value of the (define a-cont...)
-x
-@result{} normal-binding
-a-cont
-@result{} special-binding
-@end lisp
-@end deffn
-
-@node Frames
-@subsection Frames
-
For Scheme code, the fundamental procedure to react to non-local entry
-and exits of dynamic contexts is @code{dynamic-wind}. C code could use
-@code{scm_internal_dynamic_wind}, but since C does not allow the
-convenient construction of anonymous procedures that close over lexical
-variables, this will be, well, inconvenient. Instead, C code can use
-@dfn{frames}.
-
-Guile offers the functions @code{scm_frame_begin} and
-@code{scm_frame_end} to delimit a dynamic extent. Within this dynamic
-extent, which is called a @dfn{frame}, you can perform various
-@dfn{frame actions} that control what happens when the frame is entered
-or left. For example, you can register a cleanup routine with
-@code{scm_frame_unwind} that is executed when the frame is left. There are
-several other more specialized frame actions as well, for example to
-temporarily block the execution of asyncs or to temporarily change the
-current output port. They are described elsewhere in this manual.
+and exits of dynamic contexts is @code{dynamic-wind}. C code could
+use @code{scm_internal_dynamic_wind}, but since C does not allow the
+convenient construction of anonymous procedures that close over
+lexical variables, this will be, well, inconvenient.
+
+Therefore, Guile offers the functions @code{scm_dynwind_begin} and
+@code{scm_dynwind_end} to delimit a dynamic extent. Within this
+dynamic extent, which is called a @dfn{dynwind context}, you can
+perform various @dfn{dynwind actions} that control what happens when
+the dynwind context is entered or left. For example, you can register
+a cleanup routine with @code{scm_dynwind_unwind_handler} that is
+executed when the context is left. There are several other more
+specialized dynwind actions as well, for example to temporarily block
+the execution of asyncs or to temporarily change the current output
+port. They are described elsewhere in this manual.
Here is an example that shows how to prevent memory leaks.
@{
char *c_s1, *c_s2, *c_res;
- scm_frame_begin (0);
+ scm_dynwind_begin (0);
c_s1 = scm_to_locale_string (s1);
- /* Call 'free (c_s1)' when the frame is left.
+ /* Call 'free (c_s1)' when the dynwind context is left.
*/
- scm_frame_unwind_handler (free, c_s1, SCM_F_WIND_EXPLICITLY);
+ scm_dynwind_unwind_handler (free, c_s1, SCM_F_WIND_EXPLICITLY);
c_s2 = scm_to_locale_string (s2);
/* Same as above, but more concisely.
*/
- scm_frame_free (c_s2);
+ scm_dynwind_free (c_s2);
c_res = foo (c_s1, c_s2);
if (c_res == NULL)
scm_memory_error ("foo");
- scm_frame_end ();
+ scm_dynwind_end ();
return scm_take_locale_string (res);
@}
@end example
-@deftp {C Type} scm_t_frame_flags
+@rnindex dynamic-wind
+@deffn {Scheme Procedure} dynamic-wind in_guard thunk out_guard
+@deffnx {C Function} scm_dynamic_wind (in_guard, thunk, out_guard)
+All three arguments must be 0-argument procedures.
+@var{in_guard} is called, then @var{thunk}, then
+@var{out_guard}.
+
+If, any time during the execution of @var{thunk}, the
+dynamic extent of the @code{dynamic-wind} expression is escaped
+non-locally, @var{out_guard} is called. If the dynamic extent of
+the dynamic-wind is re-entered, @var{in_guard} is called. Thus
+@var{in_guard} and @var{out_guard} may be called any number of
+times.
+
+@lisp
+(define x 'normal-binding)
+@result{} x
+(define a-cont
+ (call-with-current-continuation
+ (lambda (escape)
+ (let ((old-x x))
+ (dynamic-wind
+ ;; in-guard:
+ ;;
+ (lambda () (set! x 'special-binding))
+
+ ;; thunk
+ ;;
+ (lambda () (display x) (newline)
+ (call-with-current-continuation escape)
+ (display x) (newline)
+ x)
+
+ ;; out-guard:
+ ;;
+ (lambda () (set! x old-x)))))))
+;; Prints:
+special-binding
+;; Evaluates to:
+@result{} a-cont
+x
+@result{} normal-binding
+(a-cont #f)
+;; Prints:
+special-binding
+;; Evaluates to:
+@result{} a-cont ;; the value of the (define a-cont...)
+x
+@result{} normal-binding
+a-cont
+@result{} special-binding
+@end lisp
+@end deffn
+
+@deftp {C Type} scm_t_dynwind_flags
This is an enumeration of several flags that modify the behavior of
-@code{scm_begin_frame}. The flags are listed in the following table.
+@code{scm_dynwind_begin}. The flags are listed in the following
+table.
@table @code
-@item SCM_F_FRAME_REWINDABLE
-The frame is @dfn{rewindable}. This means that it can be reentered
-non-locally (via the invokation of a continuation). The default is that
-a frame can not be reentered non-locally.
+@item SCM_F_DYNWIND_REWINDABLE
+The dynamic context is @dfn{rewindable}. This means that it can be
+reentered non-locally (via the invokation of a continuation). The
+default is that a dynwind context can not be reentered non-locally.
@end table
@end deftp
-@deftypefn {C Function} void scm_frame_begin (scm_t_frame_flags flags)
-The function @code{scm_begin_frame} starts a new frame and makes it the
-`current' one.
+@deftypefn {C Function} void scm_dynwind_begin (scm_t_dynwind_flags flags)
+The function @code{scm_dynwind_begin} starts a new dynamic context and
+makes it the `current' one.
-The @var{flags} argument determines the default behavior of the frame.
-For normal frames, use 0. This will result in a frame that can not be
-reentered with a captured continuation. When you are prepared to handle
-reentries, include @code{SCM_F_FRAME_REWINDABLE} in @var{flags}.
+The @var{flags} argument determines the default behavior of the
+context. Normally, use 0. This will result in a context that can not
+be reentered with a captured continuation. When you are prepared to
+handle reentries, include @code{SCM_F_DYNWIND_REWINDABLE} in
+@var{flags}.
Being prepared for reentry means that the effects of unwind handlers
can be undone on reentry. In the example above, we want to prevent a
back on reentry. Thus reentry can not be allowed.
The consequence is that continuations become less useful when
-non-reenterable frames are captured, but you don't need to worry about
-that too much.
-
-The frame is ended either implicitly when a non-local exit happens, or
-explicitly with @code{scm_end_frame}. You must make sure that a frame
-is indeed ended properly. If you fail to call @code{scm_end_frame}
-for each @code{scm_begin_frame}, the behavior is undefined.
+non-reenterable contexts are captured, but you don't need to worry
+about that too much.
+
+The context is ended either implicitly when a non-local exit happens,
+or explicitly with @code{scm_dynwind_end}. You must make sure that a
+dynwind context is indeed ended properly. If you fail to call
+@code{scm_dynwind_end} for each @code{scm_dynwind_begin}, the behavior
+is undefined.
@end deftypefn
-@deftypefn {C Function} void scm_frame_end ()
-End the current frame explicitly and make the previous frame current.
+@deftypefn {C Function} void scm_dynwind_end ()
+End the current dynamic context explicitly and make the previous one
+current.
@end deftypefn
@deftp {C Type} scm_t_wind_flags
This is an enumeration of several flags that modify the behavior of
-@code{scm_on_unwind_handler} and @code{scm_on_rewind_handler}. The
-flags are listed in the following table.
+@code{scm_dynwind_unwind_handler} and
+@code{scm_dynwind_rewind_handler}. The flags are listed in the
+following table.
@table @code
@item SCM_F_WIND_EXPLICITLY
@vindex SCM_F_WIND_EXPLICITLY
-The registered action is also carried out when the frame is entered or
-left locally.
+The registered action is also carried out when the dynwind context is
+entered or left locally.
@end table
@end deftp
-@deftypefn {C Function} void scm_frame_unwind_handler (void (*func)(void *), void *data, scm_t_wind_flags flags)
-@deftypefnx {C Function} void scm_frame_unwind_handler_with_scm (void (*func)(SCM), SCM data, scm_t_wind_flags flags)
+@deftypefn {C Function} void scm_dynwind_unwind_handler (void (*func)(void *), void *data, scm_t_wind_flags flags)
+@deftypefnx {C Function} void scm_dynwind_unwind_handler_with_scm (void (*func)(SCM), SCM data, scm_t_wind_flags flags)
Arranges for @var{func} to be called with @var{data} as its arguments
-when the current frame ends implicitly. If @var{flags} contains
-@code{SCM_F_WIND_EXPLICITLY}, @var{func} is also called when the frame
-ends explicitly with @code{scm_frame_end}.
+when the current context ends implicitly. If @var{flags} contains
+@code{SCM_F_WIND_EXPLICITLY}, @var{func} is also called when the
+context ends explicitly with @code{scm_dynwind_end}.
-The function @code{scm_frame_unwind_handler_with_scm} takes care that
+The function @code{scm_dynwind_unwind_handler_with_scm} takes care that
@var{data} is protected from garbage collection.
@end deftypefn
-@deftypefn {C Function} void scm_frame_rewind_handler (void (*func)(void *), void *data, scm_t_wind_flags flags)
-@deftypefnx {C Function} void scm_frame_rewind_handler_with_scm (void (*func)(SCM), SCM data, scm_t_wind_flags flags)
+@deftypefn {C Function} void scm_dynwind_rewind_handler (void (*func)(void *), void *data, scm_t_wind_flags flags)
+@deftypefnx {C Function} void scm_dynwind_rewind_handler_with_scm (void (*func)(SCM), SCM data, scm_t_wind_flags flags)
Arrange for @var{func} to be called with @var{data} as its argument when
-the current frame is restarted by rewinding the stack. When @var{flags}
+the current context is restarted by rewinding the stack. When @var{flags}
contains @code{SCM_F_WIND_EXPLICITLY}, @var{func} is called immediately
as well.
-The function @code{scm_frame_rewind_handler_with_scm} takes care that
+The function @code{scm_dynwind_rewind_handler_with_scm} takes care that
@var{data} is protected from garbage collection.
@end deftypefn
+@deftypefn {C Function} void scm_dynwind_free (void *mem)
+Arrange for @var{mem} to be freed automatically whenever the current
+context is exited, whether normally or non-locally.
+@code{scm_dynwind_free (mem)} is an equivalent shorthand for
+@code{scm_dynwind_unwind_handler (free, mem, SCM_F_WIND_EXPLICITLY)}.
+@end deftypefn
+
@node Handling Errors
@subsection How to Handle Errors
can be @code{NULL} to give the effect of @code{#f} described above.
@deftypefn {C Function} SCM scm_error (SCM @var{key}, char *@var{subr}, char *@var{message}, SCM @var{args}, SCM @var{rest})
-Throw an error, as per @code{scm-error} above.
+Throw an error, as per @code{scm-error} (@pxref{Error Reporting}).
@end deftypefn
@deftypefn {C Function} void scm_syserror (char *@var{subr})