You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2016/02/25 00:07:33 UTC

[06/20] lucy-clownfish git commit: Implement Clownfish exceptions using `longjmp`.

Implement Clownfish exceptions using `longjmp`.

Though Python uses exceptions, executing exceptions from the Python C
API requires setting thread-local error information and indicating an
error condition to the Python interpreter by returning NULL from the
glue function.  So Clownfish has to have its own independent exception
handling.


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/eccf1b64
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/eccf1b64
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/eccf1b64

Branch: refs/heads/master
Commit: eccf1b645bb9042825d84bbe4db4041ad63e2fc1
Parents: 7910ca9
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Fri Jan 22 15:40:08 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:02 2016 -0800

----------------------------------------------------------------------
 runtime/python/cfext/CFBind.c | 66 +++++++++++++++++++++++++++-----------
 1 file changed, 48 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/eccf1b64/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 6b13120..3c4bb4b 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -19,6 +19,8 @@
 #define C_CFISH_METHOD
 #define C_CFISH_ERR
 
+#include <setjmp.h>
+
 #include "charmony.h"
 #include "CFBind.h"
 
@@ -36,6 +38,8 @@
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/Vector.h"
 
+static bool Err_initialized;
+
 /**** refcounting **********************************************************/
 
 uint32_t
@@ -114,48 +118,74 @@ CFISH_Method_Host_Name_IMP(cfish_Method *self) {
 
 /**** Err ******************************************************************/
 
+/* TODO: Thread safety? */
+static cfish_Err *current_error;
+static cfish_Err *thrown_error;
+static jmp_buf  *current_env;
+
 void
-cfish_Err_init_class() {
-    CFISH_THROW(CFISH_ERR, "TODO");
+cfish_Err_init_class(void) {
+    Err_initialized = true;
 }
 
 cfish_Err*
 cfish_Err_get_error() {
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_Err*);
+    return current_error;
 }
 
 void
 cfish_Err_set_error(cfish_Err *error) {
-    CFISH_UNUSED_VAR(error);
-    CFISH_THROW(CFISH_ERR, "TODO");
+    if (current_error) {
+        CFISH_DECREF(current_error);
+    }
+    current_error = error;
 }
 
 void
 cfish_Err_do_throw(cfish_Err *error) {
-    CFISH_UNUSED_VAR(error);
-    CFISH_THROW(CFISH_ERR, "TODO");
+    if (current_env) {
+        thrown_error = error;
+        longjmp(*current_env, 1);
+    }
+    else {
+        cfish_String *message = CFISH_Err_Get_Mess(error);
+        char *utf8 = CFISH_Str_To_Utf8(message);
+        fprintf(stderr, "%s", utf8);
+        CFISH_FREEMEM(utf8);
+        exit(EXIT_FAILURE);
+    }
 }
 
 void
 cfish_Err_throw_mess(cfish_Class *klass, cfish_String *message) {
-    CFISH_UNUSED_VAR(klass);
-    CFISH_UNUSED_VAR(message);
-    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNUSED_VAR(klass); // TODO use klass
+    cfish_Err *err = cfish_Err_new(message);
+    cfish_Err_do_throw(err);
 }
 
 void
 cfish_Err_warn_mess(cfish_String *message) {
-    CFISH_UNUSED_VAR(message);
-    CFISH_THROW(CFISH_ERR, "TODO");
+    char *utf8 = CFISH_Str_To_Utf8(message);
+    fprintf(stderr, "%s", utf8);
+    CFISH_FREEMEM(utf8);
+    CFISH_DECREF(message);
 }
 
 cfish_Err*
-cfish_Err_trap(CFISH_Err_Attempt_t routine, void *routine_context) {
-    CFISH_UNUSED_VAR(routine);
-    CFISH_UNUSED_VAR(routine_context);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_Err*);
+cfish_Err_trap(CFISH_Err_Attempt_t routine, void *context) {
+    jmp_buf  env;
+    jmp_buf *prev_env = current_env;
+    current_env = &env;
+
+    if (!setjmp(env)) {
+        routine(context);
+    }
+
+    current_env = prev_env;
+
+    cfish_Err *error = thrown_error;
+    thrown_error = NULL;
+    return error;
 }
 
 /**** TestUtils ************************************************************/