1
/*===========================================================================
2
* FileName : operations-srfi34.c
3
* About : Exception Handling for Programs
5
* Copyright (C) 2005 by Kazuki Ohta (mover@hct.zaq.ne.jp)
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
* 3. Neither the name of authors nor the names of its contributors
19
* may be used to endorse or promote products derived from this software
20
* without specific prior written permission.
22
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
23
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
26
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
===========================================================================*/
35
/*=======================================
37
=======================================*/
40
/*=======================================
42
=======================================*/
43
#include "sigscheme.h"
44
#include "sigschemeinternal.h"
46
/*=======================================
47
File Local Struct Declarations
48
=======================================*/
50
/*=======================================
51
File Local Macro Declarations
52
=======================================*/
53
#define CONTINUATION_JMPENV SCM_CONTINUATION_OPAQUE0
54
#define CONTINUATION_SET_JMPENV SCM_CONTINUATION_SET_OPAQUE0
56
/*=======================================
58
=======================================*/
59
ScmObj scm_exception_handlers = NULL;
60
ScmObj scm_exception_continuations = NULL;
62
static ScmObj exception_thrown_obj = NULL;
64
/*=======================================
65
File Local Function Declarations
66
=======================================*/
67
static ScmObj guard_handle_clauses(ScmObj clauses, ScmObj env);
69
/*=======================================
70
Function Implementations
71
=======================================*/
72
void SigScm_Initialize_SRFI34(void)
74
/*=======================================================================
76
=======================================================================*/
77
Scm_RegisterProcedureFixed2("with-exception-handler", ScmOp_SRFI34_with_exception_handler);
78
Scm_RegisterSyntaxVariadic1("guard" , ScmExp_SRFI34_guard);
79
Scm_RegisterProcedureFixed1("raise" , ScmOp_SRFI34_raise);
80
scm_exception_handlers = SCM_FALSE;
81
scm_exception_continuations = SCM_FALSE;
82
SigScm_GC_Protect(&scm_exception_handlers);
83
SigScm_GC_Protect(&scm_exception_continuations);
87
* FIXME: Reimplement with dynamic-wind as "Reference Implementation" of
88
* SRFI-34 does, without direct use of setjmp/longjmp
90
ScmObj ScmOp_SRFI34_with_exception_handler(ScmObj handler, ScmObj thunk)
93
ScmObj ret = SCM_FALSE;
94
ScmObj cont = Scm_NewContinuation();
95
DECLARE_FUNCTION("with-exception-handler", ProcedureFixed2);
97
ASSERT_PROCEDUREP(handler);
98
ASSERT_PROCEDUREP(thunk);
100
CONTINUATION_SET_JMPENV(cont, &jmpenv);
101
if (setjmp(CONTINUATION_JMPENV(cont))) {
102
ret = Scm_call(CURRENT_EXCEPTION_HANDLER(), LIST_1(exception_thrown_obj));
103
POP_EXCEPTION_CONTINUATION();
104
POP_EXCEPTION_HANDLER();
105
exception_thrown_obj = SCM_FALSE; /* make sweepable */
109
PUSH_EXCEPTION_HANDLER(handler);
110
PUSH_EXCEPTION_CONTINUATION(cont);
111
ret = Scm_call(thunk, SCM_NULL);
112
POP_EXCEPTION_CONTINUATION();
113
POP_EXCEPTION_HANDLER();
119
* FIXME: Reimplement with dynamic-wind, Scm_CallWithCurrentContinuation() and
120
* Scm_CallContinuation() as "Reference Implementation" of SRFI-34 does,
121
* without direct use of setjmp/longjmp
123
ScmObj ScmExp_SRFI34_guard(ScmObj var_and_clauses, ScmObj body, ScmObj env)
125
/* (guard (var clauses) body) */
127
ScmObj var = SCM_FALSE;
128
ScmObj clauses = SCM_FALSE;
129
ScmObj expr = SCM_FALSE;
130
ScmObj cont = Scm_NewContinuation();
131
DECLARE_FUNCTION("guard", SyntaxVariadic1);
133
ASSERT_CONSP(var_and_clauses);
135
var = CAR(var_and_clauses);
136
clauses = CDR(var_and_clauses);
140
/* check if return from "raise" */
141
CONTINUATION_SET_JMPENV(cont, &jmpenv);
142
if (setjmp(CONTINUATION_JMPENV(cont))) {
143
POP_EXCEPTION_CONTINUATION();
144
env = Scm_ExtendEnvironment(LIST_1(var), LIST_1(exception_thrown_obj), env);
145
return guard_handle_clauses(clauses, env);
148
PUSH_EXCEPTION_CONTINUATION(cont);
149
while (!NO_MORE_ARG(body)) {
150
expr = POP_ARG(body);
151
expr = EVAL(expr, env);
153
POP_EXCEPTION_CONTINUATION();
159
* - Simplify with ScmExp_cond()
161
static ScmObj guard_handle_clauses(ScmObj clauses, ScmObj env)
163
ScmObj thrown = exception_thrown_obj;
164
ScmObj clause = SCM_FALSE;
165
ScmObj test = SCM_FALSE;
166
ScmObj exps = SCM_FALSE;
167
ScmObj proc = SCM_FALSE;
168
ScmObj ret = SCM_FALSE;
169
DECLARE_INTERNAL_FUNCTION("guard");
172
exception_thrown_obj = SCM_FALSE;
174
/* handle "cond" like clause */
175
for (; !NULLP(clauses); clauses = CDR(clauses)) {
176
clause = CAR(clauses);
178
ERR_OBJ("bad clause ", clause);
184
test = EVAL(test, env);
188
* if the selected <clause> contains only the <test> and no <expression>s,
189
* then the value of the <test> is returned as the result.
195
* If the selected <clause> uses the => alternate form, then the <expression>
196
* is evaluated. Its value must be a procedure that accepts one argument;
197
* this procedure is then called on the value of the <test> and the value
198
* returned by this procedure is returned by the guard expression.
200
/* FIXME: remove expensive Scm_Intern() */
201
if (EQ(Scm_Intern("=>"), CAR(exps))) {
202
proc = EVAL(CADR(exps), env);
203
if (FALSEP(ScmOp_procedurep(proc)))
204
ERR_OBJ("the value of exp after => must be the procedure but got ", proc);
206
return Scm_call(proc, LIST_1(test));
209
for (; !NULLP(exps); exps = CDR(exps))
210
ret = EVAL(CAR(exps), env);
216
/* "reraise" exception */
217
if (NULLP(CURRENT_EXCEPTION_CONTINUATION()))
218
ERR("guard: cannot reraise exception");
219
ScmOp_SRFI34_raise(thrown);
221
/* never reaches here */
227
* - Reimplement with dynamic-wind as "Reference Implementation" of SRFI-34
228
* does, without direct use of setjmp/longjmp
229
* - Cause error when the current exception handler returns, as "Reference
230
* Implementation" of SRFI-34 does. current implementation allows writing
231
* unspecified behavior
233
ScmObj ScmOp_SRFI34_raise(ScmObj obj)
236
DECLARE_FUNCTION("raise", ProcedureFixed1);
238
exception_thrown_obj = obj;
240
env = CONTINUATION_JMPENV(CURRENT_EXCEPTION_CONTINUATION());
243
/* never reaches here */