Exceptions!!!
This commit is contained in:
+39
-5
@@ -2,7 +2,6 @@
|
||||
#define INCLUDED_STACK_H
|
||||
|
||||
#include "base.h"
|
||||
#include "list.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdnoreturn.h>
|
||||
@@ -49,8 +48,8 @@ struct _StackFrame {
|
||||
} unwind_protect;
|
||||
struct {
|
||||
jmp_buf *target;
|
||||
LispVal **variable;
|
||||
LispVal *exceptions; // list of exception symbols to catch
|
||||
size_t datum; // extra value to identify this case
|
||||
} condition_case;
|
||||
struct {
|
||||
LispVal *symbol;
|
||||
@@ -72,6 +71,7 @@ struct UnwindInformation {
|
||||
struct {
|
||||
LispVal *name;
|
||||
LispVal *data;
|
||||
size_t handler_datum;
|
||||
} exception;
|
||||
};
|
||||
};
|
||||
@@ -110,6 +110,24 @@ static ALWAYS_INLINE StackFrame *LISP_STACK_REF(void) {
|
||||
return &the_stack.frames[the_stack.depth - 1];
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE LispVal *EXCEPTION_NAME(void) {
|
||||
assert(the_stack.unwind_info.set
|
||||
&& the_stack.unwind_info.cause == UNWIND_EXCEPTION);
|
||||
return the_stack.unwind_info.exception.name;
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE LispVal *EXCEPTION_DATA(void) {
|
||||
assert(the_stack.unwind_info.set
|
||||
&& the_stack.unwind_info.cause == UNWIND_EXCEPTION);
|
||||
return the_stack.unwind_info.exception.data;
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE size_t EXCEPTION_HANDLER_DATUM(void) {
|
||||
assert(the_stack.unwind_info.set
|
||||
&& the_stack.unwind_info.cause == UNWIND_EXCEPTION);
|
||||
return the_stack.unwind_info.exception.handler_datum;
|
||||
}
|
||||
|
||||
// functions
|
||||
void push_call_frame(LispVal *name, LispVal *args);
|
||||
// replace the args in the top stack frame with ARGS and mark them as evaluated
|
||||
@@ -121,8 +139,7 @@ void set_stack_evaluated_args(StackFrame *restrict ref, LispVal *fobj,
|
||||
void push_unwind_protect_frame(jmp_buf *buf);
|
||||
|
||||
// condition case
|
||||
void push_condition_case_frame(jmp_buf *buf, LispVal **variable,
|
||||
LispVal *exceptions);
|
||||
void push_condition_case_frame(jmp_buf *buf, LispVal *exceptions, size_t datum);
|
||||
|
||||
// local references
|
||||
void push_local_reference_frame(void);
|
||||
@@ -153,6 +170,8 @@ static ALWAYS_INLINE LispVal *UNWIND_AND_RETURN(StackFrame *frame,
|
||||
}
|
||||
noreturn void continue_unwinding(void);
|
||||
|
||||
noreturn void lisp_signal(LispVal *name, LispVal *data);
|
||||
|
||||
#define UNWIND_PROTECT(body, cleanup) \
|
||||
{ \
|
||||
jmp_buf _internal_jb; \
|
||||
@@ -162,8 +181,23 @@ noreturn void continue_unwinding(void);
|
||||
{body}; \
|
||||
unwind_to(_internal_target); \
|
||||
} else { \
|
||||
cleanup \
|
||||
{cleanup}; \
|
||||
continue_unwinding(); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define CONDITION_CASE(exceptions, body, handler) \
|
||||
{ \
|
||||
jmp_buf _internal_jb; \
|
||||
StackFrame *_internal_target = LISP_STACK_REF(); \
|
||||
if (setjmp(_internal_jb) == 0) { \
|
||||
push_condition_case_frame(&_internal_jb, exceptions, 0); \
|
||||
{body}; \
|
||||
unwind_to(_internal_target); \
|
||||
} else { \
|
||||
{handler}; \
|
||||
unwind_to(_internal_target); \
|
||||
} \
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user