You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2015/05/30 13:55:57 UTC

[1/3] lucy-clownfish git commit: Factor out thread-local storage code

Repository: lucy-clownfish
Updated Branches:
  refs/heads/master dafc3801b -> 13a9ccce3


Factor out thread-local storage code


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

Branch: refs/heads/master
Commit: 76980a516626770f60083dbd8cdec55317b85b35
Parents: dafc380
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun May 10 21:11:50 2015 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat May 30 13:34:19 2015 +0200

----------------------------------------------------------------------
 runtime/c/src/Clownfish/Err.c | 149 +++++--------------------------------
 runtime/c/src/tls.c           | 140 ++++++++++++++++++++++++++++++++++
 runtime/c/src/tls.h           |  53 +++++++++++++
 3 files changed, 212 insertions(+), 130 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/76980a51/runtime/c/src/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Err.c b/runtime/c/src/Clownfish/Err.c
index 1956293..07a5233 100644
--- a/runtime/c/src/Clownfish/Err.c
+++ b/runtime/c/src/Clownfish/Err.c
@@ -23,150 +23,39 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "tls.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/String.h"
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/Class.h"
 
-typedef struct {
-    Err *current_error;
-    Err *thrown_error;
-    jmp_buf *current_env;
-} cfish_ErrGlobals;
-
-/**************************** No thread support ****************************/
-#ifdef CFISH_NOTHREADS
-
-static cfish_ErrGlobals err_globals;
-
-void
-Err_init_class() {
-}
-
-static cfish_ErrGlobals*
-S_get_globals() {
-    return &err_globals;
-}
-
-/********************************** Windows ********************************/
-#elif defined(CHY_HAS_WINDOWS_H)
-
-#include <windows.h>
-
-static DWORD err_globals_tls_index;
-
-void
-Err_init_class() {
-    err_globals_tls_index = TlsAlloc();
-    if (err_globals_tls_index == TLS_OUT_OF_INDEXES) {
-        fprintf(stderr, "TlsAlloc failed (TLS_OUT_OF_INDEXES)\n");
-        abort();
-    }
-}
-
-static cfish_ErrGlobals*
-S_get_globals() {
-    cfish_ErrGlobals *globals
-        = (cfish_ErrGlobals*)TlsGetValue(err_globals_tls_index);
-
-    if (!globals) {
-        globals = (cfish_ErrGlobals*)CALLOCATE(1, sizeof(cfish_ErrGlobals));
-        if (!TlsSetValue(err_globals_tls_index, globals)) {
-            fprintf(stderr, "TlsSetValue failed: %d\n", GetLastError());
-            abort();
-        }
-    }
-
-    return globals;
-}
-
-BOOL WINAPI
-DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved) {
-    if (reason == DLL_THREAD_DETACH) {
-        cfish_ErrGlobals *globals
-            = (cfish_ErrGlobals*)TlsGetValue(err_globals_tls_index);
-
-        if (globals) {
-            DECREF(globals->current_error);
-            FREEMEM(globals);
-        }
-    }
-
-    return TRUE;
-}
-
-/******************************** pthreads *********************************/
-#elif defined(CHY_HAS_PTHREAD_H)
-
-#include <pthread.h>
-
-static pthread_key_t err_globals_key;
-
-static void
-S_destroy_globals(void *globals);
-
 void
 Err_init_class() {
-    int error = pthread_key_create(&err_globals_key, S_destroy_globals);
-    if (error) {
-        fprintf(stderr, "pthread_key_create failed: %d\n", error);
-        abort();
-    }
-}
-
-static cfish_ErrGlobals*
-S_get_globals() {
-    cfish_ErrGlobals *globals
-        = (cfish_ErrGlobals*)pthread_getspecific(err_globals_key);
-
-    if (!globals) {
-        globals = (cfish_ErrGlobals*)CALLOCATE(1, sizeof(cfish_ErrGlobals));
-        int error = pthread_setspecific(err_globals_key, globals);
-        if (error) {
-            fprintf(stderr, "pthread_setspecific failed: %d\n", error);
-            abort();
-        }
-    }
-
-    return globals;
+    Tls_init();
 }
 
-static void
-S_destroy_globals(void *arg) {
-    cfish_ErrGlobals *globals = (cfish_ErrGlobals*)arg;
-    DECREF(globals->current_error);
-    FREEMEM(globals);
-}
-
-/****************** No support for thread-local storage ********************/
-#else
-
-#error "No support for thread-local storage."
-
-#endif
-
 Err*
 Err_get_error() {
-    return S_get_globals()->current_error;
+    return Tls_get_err_context()->current_error;
 }
 
 void
 Err_set_error(Err *error) {
-    cfish_ErrGlobals *globals = S_get_globals();
+    ErrContext *context = Tls_get_err_context();
 
-    if (globals->current_error) {
-        DECREF(globals->current_error);
+    if (context->current_error) {
+        DECREF(context->current_error);
     }
-    globals->current_error = error;
+    context->current_error = error;
 }
 
 void
 Err_do_throw(Err *error) {
-    cfish_ErrGlobals *globals = S_get_globals();
+    ErrContext *context = Tls_get_err_context();
 
-    if (globals->current_env) {
-        globals->thrown_error = error;
-        longjmp(*globals->current_env, 1);
+    if (context->current_env) {
+        context->thrown_error = error;
+        longjmp(*context->current_env, 1);
     }
     else {
         String *message = Err_Get_Mess(error);
@@ -193,21 +82,21 @@ Err_warn_mess(String *message) {
 }
 
 Err*
-Err_trap(Err_Attempt_t routine, void *context) {
-    cfish_ErrGlobals *globals = S_get_globals();
+Err_trap(Err_Attempt_t routine, void *routine_context) {
+    ErrContext *err_context = Tls_get_err_context();
 
     jmp_buf  env;
-    jmp_buf *prev_env = globals->current_env;
-    globals->current_env = &env;
+    jmp_buf *prev_env = err_context->current_env;
+    err_context->current_env = &env;
 
     if (!setjmp(env)) {
-        routine(context);
+        routine(routine_context);
     }
 
-    globals->current_env = prev_env;
+    err_context->current_env = prev_env;
 
-    Err *error = globals->thrown_error;
-    globals->thrown_error = NULL;
+    Err *error = err_context->thrown_error;
+    err_context->thrown_error = NULL;
     return error;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/76980a51/runtime/c/src/tls.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/tls.c b/runtime/c/src/tls.c
new file mode 100644
index 0000000..b550f13
--- /dev/null
+++ b/runtime/c/src/tls.c
@@ -0,0 +1,140 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFISH_USE_SHORT_NAMES
+
+#include "charmony.h"
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tls.h"
+
+#include "Clownfish/Util/Memory.h"
+
+/**************************** No thread support ****************************/
+#ifdef CFISH_NOTHREADS
+
+static ErrContext err_context;
+
+void
+Tls_init() {
+}
+
+ErrContext*
+Tls_get_err_context() {
+    return &err_context;
+}
+
+/********************************** Windows ********************************/
+#elif defined(CHY_HAS_WINDOWS_H)
+
+#include <windows.h>
+
+static DWORD err_context_tls_index;
+
+void
+Tls_init() {
+    err_context_tls_index = TlsAlloc();
+    if (err_context_tls_index == TLS_OUT_OF_INDEXES) {
+        fprintf(stderr, "TlsAlloc failed (TLS_OUT_OF_INDEXES)\n");
+        abort();
+    }
+}
+
+ErrContext*
+Tls_get_err_context() {
+    ErrContext *context
+        = (ErrContext*)TlsGetValue(err_context_tls_index);
+
+    if (!context) {
+        context = (ErrContext*)CALLOCATE(1, sizeof(ErrContext));
+        if (!TlsSetValue(err_context_tls_index, context)) {
+            fprintf(stderr, "TlsSetValue failed: %d\n", GetLastError());
+            abort();
+        }
+    }
+
+    return context;
+}
+
+BOOL WINAPI
+DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved) {
+    if (reason == DLL_THREAD_DETACH) {
+        ErrContext *context
+            = (ErrContext*)TlsGetValue(err_context_tls_index);
+
+        if (context) {
+            DECREF(context->current_error);
+            FREEMEM(context);
+        }
+    }
+
+    return TRUE;
+}
+
+/******************************** pthreads *********************************/
+#elif defined(CHY_HAS_PTHREAD_H)
+
+#include <pthread.h>
+
+static pthread_key_t err_context_key;
+
+static void
+S_destroy_context(void *context);
+
+void
+Tls_init() {
+    int error = pthread_key_create(&err_context_key, S_destroy_context);
+    if (error) {
+        fprintf(stderr, "pthread_key_create failed: %d\n", error);
+        abort();
+    }
+}
+
+ErrContext*
+Tls_get_err_context() {
+    ErrContext *context
+        = (ErrContext*)pthread_getspecific(err_context_key);
+
+    if (!context) {
+        context = (ErrContext*)CALLOCATE(1, sizeof(ErrContext));
+        int error = pthread_setspecific(err_context_key, context);
+        if (error) {
+            fprintf(stderr, "pthread_setspecific failed: %d\n", error);
+            abort();
+        }
+    }
+
+    return context;
+}
+
+static void
+S_destroy_context(void *arg) {
+    ErrContext *context = (ErrContext*)arg;
+    DECREF(context->current_error);
+    FREEMEM(context);
+}
+
+/****************** No support for thread-local storage ********************/
+#else
+
+#error "No support for thread-local storage."
+
+#endif
+
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/76980a51/runtime/c/src/tls.h
----------------------------------------------------------------------
diff --git a/runtime/c/src/tls.h b/runtime/c/src/tls.h
new file mode 100644
index 0000000..a430690
--- /dev/null
+++ b/runtime/c/src/tls.h
@@ -0,0 +1,53 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef H_CLOWNFISH_TLS
+#define H_CLOWNFISH_TLS 1
+
+#include "charmony.h"
+
+#include <setjmp.h>
+
+#include "Clownfish/Err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    Err *current_error;
+    Err *thrown_error;
+    jmp_buf *current_env;
+} cfish_ErrContext;
+
+void
+cfish_Tls_init(void);
+
+cfish_ErrContext*
+cfish_Tls_get_err_context();
+
+#ifdef CFISH_USE_SHORT_NAMES
+  #define ErrContext            cfish_ErrContext
+  #define Tls_init              cfish_Tls_init
+  #define Tls_get_err_context   cfish_Tls_get_err_context
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_CLOWNFISH_TLS */
+


[3/3] lucy-clownfish git commit: Change error messages in C bindings

Posted by nw...@apache.org.
Change error messages in C bindings


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

Branch: refs/heads/master
Commit: 13a9ccce33f2d121a7a13063fbaae09f67a70c12
Parents: 6a696e8
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat May 30 13:48:51 2015 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat May 30 13:48:51 2015 +0200

----------------------------------------------------------------------
 runtime/c/src/clownfish.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/13a9ccce/runtime/c/src/clownfish.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/clownfish.c b/runtime/c/src/clownfish.c
index d9baa11..6917ec2 100644
--- a/runtime/c/src/clownfish.c
+++ b/runtime/c/src/clownfish.c
@@ -121,7 +121,7 @@ cfish_dec_refcount(void *vself) {
 void*
 Obj_To_Host_IMP(Obj *self) {
     UNUSED_VAR(self);
-    THROW(ERR, "TODO");
+    THROW(ERR, "Obj_To_Host not supported in C bindings");
     UNREACHABLE_RETURN(void*);
 }
 
@@ -148,7 +148,7 @@ Obj*
 Class_Foster_Obj_IMP(Class *self, void *host_obj) {
     UNUSED_VAR(self);
     UNUSED_VAR(host_obj);
-    THROW(ERR, "TODO");
+    THROW(ERR, "Class_Foster_Obj not supported in C bindings");
     UNREACHABLE_RETURN(Obj*);
 }
 
@@ -167,7 +167,7 @@ Class_fresh_host_methods(String *class_name) {
 String*
 Class_find_parent_class(String *class_name) {
     UNUSED_VAR(class_name);
-    THROW(ERR, "TODO");
+    THROW(ERR, "Class_find_parent_class not supported in C bindings");
     UNREACHABLE_RETURN(String*);
 }
 


[2/3] lucy-clownfish git commit: Consolidate C bindings implementation

Posted by nw...@apache.org.
Consolidate C bindings implementation

Move all the method implementations into src/clownfish.c.


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

Branch: refs/heads/master
Commit: 6a696e8a760c9e0835b497dc94c298c5f056ea7b
Parents: 76980a5
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat May 30 13:46:54 2015 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat May 30 13:46:54 2015 +0200

----------------------------------------------------------------------
 runtime/c/src/Clownfish/Class.c                 |  74 ----
 runtime/c/src/Clownfish/Err.c                   | 102 ------
 runtime/c/src/Clownfish/Method.c                |  27 --
 runtime/c/src/Clownfish/Obj.c                   | 185 ----------
 runtime/c/src/Clownfish/TestHarness/TestUtils.c |  38 ---
 runtime/c/src/clownfish.c                       | 342 +++++++++++++++++++
 6 files changed, 342 insertions(+), 426 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/6a696e8a/runtime/c/src/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Class.c b/runtime/c/src/Clownfish/Class.c
deleted file mode 100644
index 0b1491a..0000000
--- a/runtime/c/src/Clownfish/Class.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define CFISH_USE_SHORT_NAMES
-#define C_CFISH_OBJ
-#define C_CFISH_CLASS
-
-#include <string.h>
-
-#include "charmony.h"
-
-#include "Clownfish/Class.h"
-#include "Clownfish/String.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Util/Memory.h"
-#include "Clownfish/Vector.h"
-
-Obj*
-Class_Make_Obj_IMP(Class *self) {
-    Obj *obj = (Obj*)Memory_wrapped_calloc(self->obj_alloc_size, 1);
-    obj->klass = self;
-    obj->refcount = 1;
-    return obj;
-}
-
-Obj*
-Class_Init_Obj_IMP(Class *self, void *allocation) {
-    memset(allocation, 0, self->obj_alloc_size);
-    Obj *obj = (Obj*)allocation;
-    obj->klass = self;
-    obj->refcount = 1;
-    return obj;
-}
-
-Obj*
-Class_Foster_Obj_IMP(Class *self, void *host_obj) {
-    UNUSED_VAR(self);
-    UNUSED_VAR(host_obj);
-    THROW(ERR, "TODO");
-    UNREACHABLE_RETURN(Obj*);
-}
-
-void
-Class_register_with_host(Class *singleton, Class *parent) {
-    UNUSED_VAR(singleton);
-    UNUSED_VAR(parent);
-}
-
-Vector*
-Class_fresh_host_methods(String *class_name) {
-    UNUSED_VAR(class_name);
-    return Vec_new(0);
-}
-
-String*
-Class_find_parent_class(String *class_name) {
-    UNUSED_VAR(class_name);
-    THROW(ERR, "TODO");
-    UNREACHABLE_RETURN(String*);
-}
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/6a696e8a/runtime/c/src/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Err.c b/runtime/c/src/Clownfish/Err.c
deleted file mode 100644
index 07a5233..0000000
--- a/runtime/c/src/Clownfish/Err.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define CFISH_USE_SHORT_NAMES
-#define C_CFISH_ERR
-
-#include "charmony.h"
-
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "tls.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/String.h"
-#include "Clownfish/Util/Memory.h"
-#include "Clownfish/Class.h"
-
-void
-Err_init_class() {
-    Tls_init();
-}
-
-Err*
-Err_get_error() {
-    return Tls_get_err_context()->current_error;
-}
-
-void
-Err_set_error(Err *error) {
-    ErrContext *context = Tls_get_err_context();
-
-    if (context->current_error) {
-        DECREF(context->current_error);
-    }
-    context->current_error = error;
-}
-
-void
-Err_do_throw(Err *error) {
-    ErrContext *context = Tls_get_err_context();
-
-    if (context->current_env) {
-        context->thrown_error = error;
-        longjmp(*context->current_env, 1);
-    }
-    else {
-        String *message = Err_Get_Mess(error);
-        char *utf8 = Str_To_Utf8(message);
-        fprintf(stderr, "%s", utf8);
-        FREEMEM(utf8);
-        exit(EXIT_FAILURE);
-    }
-}
-
-void
-Err_throw_mess(Class *klass, String *message) {
-    UNUSED_VAR(klass);
-    Err *err = Err_new(message);
-    Err_do_throw(err);
-}
-
-void
-Err_warn_mess(String *message) {
-    char *utf8 = Str_To_Utf8(message);
-    fprintf(stderr, "%s", utf8);
-    FREEMEM(utf8);
-    DECREF(message);
-}
-
-Err*
-Err_trap(Err_Attempt_t routine, void *routine_context) {
-    ErrContext *err_context = Tls_get_err_context();
-
-    jmp_buf  env;
-    jmp_buf *prev_env = err_context->current_env;
-    err_context->current_env = &env;
-
-    if (!setjmp(env)) {
-        routine(routine_context);
-    }
-
-    err_context->current_env = prev_env;
-
-    Err *error = err_context->thrown_error;
-    err_context->thrown_error = NULL;
-    return error;
-}
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/6a696e8a/runtime/c/src/Clownfish/Method.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Method.c b/runtime/c/src/Clownfish/Method.c
deleted file mode 100644
index 25e3b28..0000000
--- a/runtime/c/src/Clownfish/Method.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define CFISH_USE_SHORT_NAMES
-#define C_CFISH_METHOD
-
-#include "Clownfish/Method.h"
-#include "Clownfish/String.h"
-
-String*
-Method_Host_Name_IMP(Method *self) {
-    return (String*)INCREF(self->name);
-}
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/6a696e8a/runtime/c/src/Clownfish/Obj.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Obj.c b/runtime/c/src/Clownfish/Obj.c
deleted file mode 100644
index a037ff1..0000000
--- a/runtime/c/src/Clownfish/Obj.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_CFISH_OBJ
-#define C_CFISH_CLASS
-#define CFISH_USE_SHORT_NAMES
-
-#include "charmony.h"
-
-#include "Clownfish/Obj.h"
-#include "Clownfish/Class.h"
-#include "Clownfish/Blob.h"
-#include "Clownfish/ByteBuf.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Hash.h"
-#include "Clownfish/Num.h"
-#include "Clownfish/String.h"
-#include "Clownfish/Vector.h"
-
-static CFISH_INLINE bool
-SI_immortal(cfish_Class *klass) {
-    if (klass == CFISH_CLASS
-        || klass == CFISH_METHOD
-        || klass == CFISH_BOOLNUM
-       ){
-        return true;
-    }
-    return false;
-}
-
-static CFISH_INLINE bool
-SI_is_string_type(cfish_Class *klass) {
-    if (klass == CFISH_STRING) {
-        return true;
-    }
-    return false;
-}
-
-uint32_t
-cfish_get_refcount(void *vself) {
-    cfish_Obj *self = (cfish_Obj*)vself;
-    return self->refcount;
-}
-
-Obj*
-cfish_inc_refcount(void *vself) {
-    Obj *self = (Obj*)vself;
-
-    // Handle special cases.
-    cfish_Class *const klass = self->klass;
-    if (klass->flags & CFISH_fREFCOUNTSPECIAL) {
-        if (SI_is_string_type(klass)) {
-            // Only copy-on-incref Strings get special-cased.  Ordinary
-            // strings fall through to the general case.
-            if (CFISH_Str_Is_Copy_On_IncRef((cfish_String*)self)) {
-                const char *utf8 = CFISH_Str_Get_Ptr8((cfish_String*)self);
-                size_t size = CFISH_Str_Get_Size((cfish_String*)self);
-                return (cfish_Obj*)cfish_Str_new_from_trusted_utf8(utf8, size);
-            }
-        }
-        else if (SI_immortal(klass)) {
-            return self;
-        }
-    }
-
-    self->refcount++;
-    return self;
-}
-
-uint32_t
-cfish_dec_refcount(void *vself) {
-    cfish_Obj *self = (Obj*)vself;
-    cfish_Class *klass = self->klass;
-    if (klass->flags & CFISH_fREFCOUNTSPECIAL) {
-        if (SI_immortal(klass)) {
-            return self->refcount;
-        }
-    }
-
-    uint32_t modified_refcount = INT32_MAX;
-    switch (self->refcount) {
-        case 0:
-            THROW(ERR, "Illegal refcount of 0");
-            break; // useless
-        case 1:
-            modified_refcount = 0;
-            Obj_Destroy(self);
-            break;
-        default:
-            modified_refcount = --self->refcount;
-            break;
-    }
-    return modified_refcount;
-}
-
-void*
-Obj_To_Host_IMP(Obj *self) {
-    UNUSED_VAR(self);
-    THROW(ERR, "TODO");
-    UNREACHABLE_RETURN(void*);
-}
-
-void*
-Str_To_Host_IMP(String *self) {
-    Str_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(STRING, CFISH_Str_To_Host);
-    return super_to_host(self);
-}
-
-void*
-Blob_To_Host_IMP(Blob *self) {
-    Blob_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(BLOB, CFISH_Blob_To_Host);
-    return super_to_host(self);
-}
-
-void*
-BB_To_Host_IMP(ByteBuf *self) {
-    BB_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(BYTEBUF, CFISH_BB_To_Host);
-    return super_to_host(self);
-}
-
-void*
-Vec_To_Host_IMP(Vector *self) {
-    Vec_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(VECTOR, CFISH_Vec_To_Host);
-    return super_to_host(self);
-}
-
-void*
-Hash_To_Host_IMP(Hash *self) {
-    Hash_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(HASH, CFISH_Hash_To_Host);
-    return super_to_host(self);
-}
-
-void*
-Float32_To_Host_IMP(Float32 *self) {
-    Float32_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(FLOAT32, CFISH_Float32_To_Host);
-    return super_to_host(self);
-}
-
-void*
-Float64_To_Host_IMP(Float64 *self) {
-    Float64_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(FLOAT64, CFISH_Float64_To_Host);
-    return super_to_host(self);
-}
-
-void*
-Int32_To_Host_IMP(Integer32 *self) {
-    Int32_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(INTEGER32, CFISH_Int32_To_Host);
-    return super_to_host(self);
-}
-
-void*
-Int64_To_Host_IMP(Integer64 *self) {
-    Int64_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(INTEGER64, CFISH_Int64_To_Host);
-    return super_to_host(self);
-}
-
-void*
-Bool_To_Host_IMP(BoolNum *self) {
-    Bool_To_Host_t super_to_host
-        = SUPER_METHOD_PTR(BOOLNUM, CFISH_Bool_To_Host);
-    return super_to_host(self);
-}
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/6a696e8a/runtime/c/src/Clownfish/TestHarness/TestUtils.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/TestHarness/TestUtils.c b/runtime/c/src/Clownfish/TestHarness/TestUtils.c
deleted file mode 100644
index e862423..0000000
--- a/runtime/c/src/Clownfish/TestHarness/TestUtils.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define CFISH_USE_SHORT_NAMES
-
-#include "charmony.h"
-
-#include "Clownfish/TestHarness/TestUtils.h"
-
-void*
-cfish_TestUtils_clone_host_runtime() {
-    return NULL;
-}
-
-void
-cfish_TestUtils_set_host_runtime(void *runtime) {
-    UNUSED_VAR(runtime);
-}
-
-void
-cfish_TestUtils_destroy_host_runtime(void *runtime) {
-    UNUSED_VAR(runtime);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/6a696e8a/runtime/c/src/clownfish.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/clownfish.c b/runtime/c/src/clownfish.c
new file mode 100644
index 0000000..d9baa11
--- /dev/null
+++ b/runtime/c/src/clownfish.c
@@ -0,0 +1,342 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define C_CFISH_CLASS
+#define C_CFISH_METHOD
+#define C_CFISH_OBJ
+#define CFISH_USE_SHORT_NAMES
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "charmony.h"
+
+#include "tls.h"
+#include "Clownfish/Obj.h"
+#include "Clownfish/Class.h"
+#include "Clownfish/Blob.h"
+#include "Clownfish/ByteBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Hash.h"
+#include "Clownfish/Method.h"
+#include "Clownfish/Num.h"
+#include "Clownfish/String.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Util/Memory.h"
+#include "Clownfish/Vector.h"
+
+/**** Obj ******************************************************************/
+
+static CFISH_INLINE bool
+SI_immortal(cfish_Class *klass) {
+    if (klass == CFISH_CLASS
+        || klass == CFISH_METHOD
+        || klass == CFISH_BOOLNUM
+       ){
+        return true;
+    }
+    return false;
+}
+
+static CFISH_INLINE bool
+SI_is_string_type(cfish_Class *klass) {
+    if (klass == CFISH_STRING) {
+        return true;
+    }
+    return false;
+}
+
+uint32_t
+cfish_get_refcount(void *vself) {
+    cfish_Obj *self = (cfish_Obj*)vself;
+    return self->refcount;
+}
+
+Obj*
+cfish_inc_refcount(void *vself) {
+    Obj *self = (Obj*)vself;
+
+    // Handle special cases.
+    cfish_Class *const klass = self->klass;
+    if (klass->flags & CFISH_fREFCOUNTSPECIAL) {
+        if (SI_is_string_type(klass)) {
+            // Only copy-on-incref Strings get special-cased.  Ordinary
+            // strings fall through to the general case.
+            if (CFISH_Str_Is_Copy_On_IncRef((cfish_String*)self)) {
+                const char *utf8 = CFISH_Str_Get_Ptr8((cfish_String*)self);
+                size_t size = CFISH_Str_Get_Size((cfish_String*)self);
+                return (cfish_Obj*)cfish_Str_new_from_trusted_utf8(utf8, size);
+            }
+        }
+        else if (SI_immortal(klass)) {
+            return self;
+        }
+    }
+
+    self->refcount++;
+    return self;
+}
+
+uint32_t
+cfish_dec_refcount(void *vself) {
+    cfish_Obj *self = (Obj*)vself;
+    cfish_Class *klass = self->klass;
+    if (klass->flags & CFISH_fREFCOUNTSPECIAL) {
+        if (SI_immortal(klass)) {
+            return self->refcount;
+        }
+    }
+
+    uint32_t modified_refcount = INT32_MAX;
+    switch (self->refcount) {
+        case 0:
+            THROW(ERR, "Illegal refcount of 0");
+            break; // useless
+        case 1:
+            modified_refcount = 0;
+            Obj_Destroy(self);
+            break;
+        default:
+            modified_refcount = --self->refcount;
+            break;
+    }
+    return modified_refcount;
+}
+
+void*
+Obj_To_Host_IMP(Obj *self) {
+    UNUSED_VAR(self);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(void*);
+}
+
+/**** Class ****************************************************************/
+
+Obj*
+Class_Make_Obj_IMP(Class *self) {
+    Obj *obj = (Obj*)Memory_wrapped_calloc(self->obj_alloc_size, 1);
+    obj->klass = self;
+    obj->refcount = 1;
+    return obj;
+}
+
+Obj*
+Class_Init_Obj_IMP(Class *self, void *allocation) {
+    memset(allocation, 0, self->obj_alloc_size);
+    Obj *obj = (Obj*)allocation;
+    obj->klass = self;
+    obj->refcount = 1;
+    return obj;
+}
+
+Obj*
+Class_Foster_Obj_IMP(Class *self, void *host_obj) {
+    UNUSED_VAR(self);
+    UNUSED_VAR(host_obj);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(Obj*);
+}
+
+void
+Class_register_with_host(Class *singleton, Class *parent) {
+    UNUSED_VAR(singleton);
+    UNUSED_VAR(parent);
+}
+
+Vector*
+Class_fresh_host_methods(String *class_name) {
+    UNUSED_VAR(class_name);
+    return Vec_new(0);
+}
+
+String*
+Class_find_parent_class(String *class_name) {
+    UNUSED_VAR(class_name);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(String*);
+}
+
+/**** Method ***************************************************************/
+
+String*
+Method_Host_Name_IMP(Method *self) {
+    return (String*)INCREF(self->name);
+}
+
+/**** Err ******************************************************************/
+
+void
+Err_init_class() {
+    Tls_init();
+}
+
+Err*
+Err_get_error() {
+    return Tls_get_err_context()->current_error;
+}
+
+void
+Err_set_error(Err *error) {
+    ErrContext *context = Tls_get_err_context();
+
+    if (context->current_error) {
+        DECREF(context->current_error);
+    }
+    context->current_error = error;
+}
+
+void
+Err_do_throw(Err *error) {
+    ErrContext *context = Tls_get_err_context();
+
+    if (context->current_env) {
+        context->thrown_error = error;
+        longjmp(*context->current_env, 1);
+    }
+    else {
+        String *message = Err_Get_Mess(error);
+        char *utf8 = Str_To_Utf8(message);
+        fprintf(stderr, "%s", utf8);
+        FREEMEM(utf8);
+        exit(EXIT_FAILURE);
+    }
+}
+
+void
+Err_throw_mess(Class *klass, String *message) {
+    UNUSED_VAR(klass);
+    Err *err = Err_new(message);
+    Err_do_throw(err);
+}
+
+void
+Err_warn_mess(String *message) {
+    char *utf8 = Str_To_Utf8(message);
+    fprintf(stderr, "%s", utf8);
+    FREEMEM(utf8);
+    DECREF(message);
+}
+
+Err*
+Err_trap(Err_Attempt_t routine, void *routine_context) {
+    ErrContext *err_context = Tls_get_err_context();
+
+    jmp_buf  env;
+    jmp_buf *prev_env = err_context->current_env;
+    err_context->current_env = &env;
+
+    if (!setjmp(env)) {
+        routine(routine_context);
+    }
+
+    err_context->current_env = prev_env;
+
+    Err *error = err_context->thrown_error;
+    err_context->thrown_error = NULL;
+    return error;
+}
+
+/**** TestUtils ************************************************************/
+
+void*
+cfish_TestUtils_clone_host_runtime() {
+    return NULL;
+}
+
+void
+cfish_TestUtils_set_host_runtime(void *runtime) {
+    UNUSED_VAR(runtime);
+}
+
+void
+cfish_TestUtils_destroy_host_runtime(void *runtime) {
+    UNUSED_VAR(runtime);
+}
+
+/**** To_Host methods ******************************************************/
+
+void*
+Str_To_Host_IMP(String *self) {
+    Str_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(STRING, CFISH_Str_To_Host);
+    return super_to_host(self);
+}
+
+void*
+Blob_To_Host_IMP(Blob *self) {
+    Blob_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(BLOB, CFISH_Blob_To_Host);
+    return super_to_host(self);
+}
+
+void*
+BB_To_Host_IMP(ByteBuf *self) {
+    BB_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(BYTEBUF, CFISH_BB_To_Host);
+    return super_to_host(self);
+}
+
+void*
+Vec_To_Host_IMP(Vector *self) {
+    Vec_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(VECTOR, CFISH_Vec_To_Host);
+    return super_to_host(self);
+}
+
+void*
+Hash_To_Host_IMP(Hash *self) {
+    Hash_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(HASH, CFISH_Hash_To_Host);
+    return super_to_host(self);
+}
+
+void*
+Float32_To_Host_IMP(Float32 *self) {
+    Float32_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(FLOAT32, CFISH_Float32_To_Host);
+    return super_to_host(self);
+}
+
+void*
+Float64_To_Host_IMP(Float64 *self) {
+    Float64_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(FLOAT64, CFISH_Float64_To_Host);
+    return super_to_host(self);
+}
+
+void*
+Int32_To_Host_IMP(Integer32 *self) {
+    Int32_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(INTEGER32, CFISH_Int32_To_Host);
+    return super_to_host(self);
+}
+
+void*
+Int64_To_Host_IMP(Integer64 *self) {
+    Int64_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(INTEGER64, CFISH_Int64_To_Host);
+    return super_to_host(self);
+}
+
+void*
+Bool_To_Host_IMP(BoolNum *self) {
+    Bool_To_Host_t super_to_host
+        = SUPER_METHOD_PTR(BOOLNUM, CFISH_Bool_To_Host);
+    return super_to_host(self);
+}
+