summaryrefslogtreecommitdiff
path: root/src/runtime/c/gu/exn.c
diff options
context:
space:
mode:
authorkr.angelov <kr.angelov@gmail.com>2012-01-20 13:41:10 +0000
committerkr.angelov <kr.angelov@gmail.com>2012-01-20 13:41:10 +0000
commit2eee382a62a909d5a3f2f5eda94f30fe68fd5335 (patch)
treeb0b0d513535895f244214aebf6358e172b8dce6d /src/runtime/c/gu/exn.c
parentb9728357126f8b9a6311cca17d9f0dcc2a7bfb9b (diff)
initial import of the C runtime
Diffstat (limited to 'src/runtime/c/gu/exn.c')
-rw-r--r--src/runtime/c/gu/exn.c72
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, _);