diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-07-31 17:33:59 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-07-31 17:40:55 -0700 |
commit | 0b38bc996c4c7e2693931bbd5103c7772b56b4bd (patch) | |
tree | 8e74fd6b7efc3a0fb87037b2bb58b9d8c6129339 /unwind.h | |
parent | 2f5e7a5b96039b7a00543b4056bab7ec85c8db4b (diff) | |
download | txr-0b38bc996c4c7e2693931bbd5103c7772b56b4bd.tar.gz txr-0b38bc996c4c7e2693931bbd5103c7772b56b4bd.tar.bz2 txr-0b38bc996c4c7e2693931bbd5103c7772b56b4bd.zip |
txr-015 2009-10-15txr-015
Diffstat (limited to 'unwind.h')
-rw-r--r-- | unwind.h | 92 |
1 files changed, 90 insertions, 2 deletions
@@ -24,10 +24,16 @@ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +#ifdef __GNUC__ +#define noreturn __attribute__((noreturn)) +#else +#define noreturn +#endif + typedef union uw_frame uw_frame_t; typedef enum uw_frtype uw_frtype_t; -enum uw_frtype { UW_BLOCK, UW_ENV }; +enum uw_frtype { UW_BLOCK, UW_ENV, UW_CATCH }; struct uw_common { uw_frame_t *up; @@ -48,20 +54,42 @@ struct uw_dynamic_env { obj_t *func_bindings; }; +struct uw_catch { + uw_frame_t *up; + uw_frtype_t type; + obj_t *matches; + obj_t *sym; + obj_t *exception; + uw_frame_t *cont; + int visible; + jmp_buf jb; +}; + union uw_frame { struct uw_common uw; struct uw_block bl; struct uw_dynamic_env ev; + struct uw_catch ca; }; -void uw_init(void); void uw_push_block(uw_frame_t *, obj_t *tag); void uw_push_env(uw_frame_t *); obj_t *uw_get_func(obj_t *sym); obj_t *uw_set_func(obj_t *sym, obj_t *value); obj_t *uw_block_return(obj_t *tag, obj_t *result); +void uw_push_catch(uw_frame_t *, obj_t *matches); +noreturn obj_t *uw_throw(obj_t *sym, obj_t *exception); +noreturn obj_t *uw_throwf(obj_t *sym, const char *fmt, ...); +noreturn obj_t *uw_errorf(const char *fmt, ...); +noreturn obj_t *uw_throwcf(obj_t *sym, const char *fmt, ...); +noreturn obj_t *uw_errorcf(const char *fmt, ...); +void uw_register_subtype(obj_t *sub, obj_t *super); +obj_t *uw_exception_subtype_p(obj_t *sub, obj_t *sup); +void uw_continue(uw_frame_t *curr, uw_frame_t *target); void uw_pop_frame(uw_frame_t *); +void uw_init(void); +noreturn obj_t *type_mismatch(const char *, ...); #define uw_block_begin(TAG, RESULTVAR) \ obj_t *RESULTVAR = nil; \ @@ -85,3 +113,63 @@ void uw_pop_frame(uw_frame_t *); #define uw_env_end \ uw_pop_frame(&uw_env); \ } + +#define uw_catch_begin(MATCHES, SYMVAR, \ + EXCVAR) \ + obj_t *SYMVAR = nil; \ + obj_t *EXCVAR = nil; \ + { \ + uw_frame_t uw_catch; \ + uw_push_catch(&uw_catch, MATCHES); \ + switch (setjmp(uw_catch.ca.jb)) { \ + case 0: + +#define uw_do_unwind \ + goto uw_unwind_label + +#define uw_catch(SYMVAR, EXCVAR) \ + break; \ + case 2: \ + EXCVAR = uw_catch.ca.exception; \ + SYMVAR = uw_catch.ca.sym; \ + +#define uw_unwind \ + break; \ + uw_unwind_label: \ + case 1: + +#define uw_catch_end \ + default: \ + break; \ + } \ + if (uw_catch.ca.cont) \ + uw_continue(&uw_catch, \ + uw_catch.ca.cont); \ + uw_pop_frame(&uw_catch); \ + } + +#define internal_error(STR) \ + uw_throwcf(internal_err, \ + "%s:%d %s", __FILE__, \ + __LINE__, STR) + +#define type_assert(EXPR, ARGS) \ + if (!(EXPR)) type_mismatch ARGS + +#define bug_unless(EXPR) \ + if (!(EXPR)) \ + internal_error("assertion " \ + #EXPR \ + " failed") + +#define numeric_assert(EXPR) \ + if (!(EXPR)) \ + uw_throwcf(numeric_err, "%s", \ + "assertion " #EXPR \ + " failed") + +#define range_bug_unless(EXPR) \ + if (!(EXPR)) \ + uw_throwcf(range_err, "%s", \ + "assertion" #EXPR \ + " failed") |