Exceptions!!!

This commit is contained in:
2026-09-02 01:54:14 -07:00
parent 17c11d90ea
commit 07060a17fe
13 changed files with 396 additions and 60 deletions
+39 -5
View File
@@ -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