diff options
| author | kr.angelov <kr.angelov@gmail.com> | 2012-01-20 13:41:10 +0000 |
|---|---|---|
| committer | kr.angelov <kr.angelov@gmail.com> | 2012-01-20 13:41:10 +0000 |
| commit | 2eee382a62a909d5a3f2f5eda94f30fe68fd5335 (patch) | |
| tree | b0b0d513535895f244214aebf6358e172b8dce6d /src/runtime/c/gu/exn.c | |
| parent | b9728357126f8b9a6311cca17d9f0dcc2a7bfb9b (diff) | |
initial import of the C runtime
Diffstat (limited to 'src/runtime/c/gu/exn.c')
| -rw-r--r-- | src/runtime/c/gu/exn.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/runtime/c/gu/exn.c b/src/runtime/c/gu/exn.c new file mode 100644 index 000000000..7bcfeb088 --- /dev/null +++ b/src/runtime/c/gu/exn.c @@ -0,0 +1,72 @@ +#include <gu/exn.h> +#include <gu/assert.h> + + +GuExn* +gu_new_exn(GuExn* parent, GuKind* catch, GuPool* pool) +{ + return gu_new_s(pool, GuExn, + .state = GU_EXN_OK, + .parent = parent, + .catch = catch, + .caught = NULL, + .data.pool = pool, + .data.data = NULL); +} + +void +gu_exn_block(GuExn* err) +{ + if (err && err->state == GU_EXN_RAISED) { + err->state = GU_EXN_BLOCKED; + } +} + +void +gu_exn_unblock(GuExn* err) +{ + if (err && err->state == GU_EXN_BLOCKED) { + err->state = GU_EXN_RAISED; + } +} + +GuExnData* +gu_exn_raise_debug_(GuExn* base, GuType* type, + const char* filename, const char* func, int lineno) +{ + gu_require(type); + + // TODO: log the error, once there's a system for dumping + // error objects. + + GuExn* err = base; + + while (err && !(err->catch && gu_type_has_kind(type, err->catch))) { + err->state = GU_EXN_RAISED; + err = err->parent; + } + if (!err) { + gu_abort_(GU_ASSERT_ASSERTION, filename, func, lineno, + "Unexpected error raised"); + } + GuExnState old_state = err->state; + err->state = GU_EXN_RAISED; + if (old_state == GU_EXN_OK) { + err->caught = type; + if (err->data.pool) { + return &err->data; + } + } + // Exceptian had already been raised, possibly blocked, or no + // exception value is required. + return NULL; +} + +GuExnData* +gu_exn_raise_(GuExn* base, GuType* type) +{ + return gu_exn_raise_debug_(base, type, NULL, NULL, -1); +} + + +GU_DEFINE_TYPE(GuErrno, signed, _); |
