Repository: lucy-clownfish Updated Branches: refs/heads/master cf8727895 -> 2794cf2eb
Move downcast and certify from Err to Obj The API break shouldn't be a problem. These functions are always invoked via the respective macros. Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/2794cf2e Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/2794cf2e Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/2794cf2e Branch: refs/heads/master Commit: 2794cf2eb9d3bf764d6a452db873e51c5744ae87 Parents: cf87278 Author: Nick Wellnhofer <wellnho...@aevum.de> Authored: Thu Feb 2 15:36:40 2017 +0100 Committer: Nick Wellnhofer <wellnho...@aevum.de> Committed: Thu Feb 2 15:40:46 2017 +0100 ---------------------------------------------------------------------- runtime/core/Clownfish/Err.c | 39 ------------------------ runtime/core/Clownfish/Err.cfh | 37 ---------------------- runtime/core/Clownfish/Obj.c | 43 +++++++++++++++++++++----- runtime/core/Clownfish/Obj.cfh | 42 +++++++++++++++++++++++++ runtime/test/Clownfish/Test/TestErr.c | 49 +----------------------------- runtime/test/Clownfish/Test/TestObj.c | 49 +++++++++++++++++++++++++++++- 6 files changed, 127 insertions(+), 132 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2794cf2e/runtime/core/Clownfish/Err.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Err.c b/runtime/core/Clownfish/Err.c index 7ca59b8..f5ae43d 100644 --- a/runtime/core/Clownfish/Err.c +++ b/runtime/core/Clownfish/Err.c @@ -192,45 +192,6 @@ Err_throw_at(Class *klass, const char *file, int line, Err_do_throw(err); } -// Inlined, slightly optimized version of Obj_is_a. -static CFISH_INLINE bool -SI_obj_is_a(Obj *obj, Class *target_class) { - Class *klass = obj->klass; - - while (klass != NULL) { - if (klass == target_class) { - return true; - } - klass = klass->parent; - } - - return false; -} - -Obj* -Err_downcast(Obj *obj, Class *klass, const char *file, int line, - const char *func) { - if (obj && !SI_obj_is_a(obj, klass)) { - Err_throw_at(ERR, file, line, func, "Can't downcast from %o to %o", - Obj_get_class_name(obj), Class_Get_Name(klass)); - } - return obj; -} - -Obj* -Err_certify(Obj *obj, Class *klass, const char *file, int line, - const char *func) { - if (!obj) { - Err_throw_at(ERR, file, line, func, "Object isn't a %o, it's NULL", - Class_Get_Name(klass)); - } - else if (!SI_obj_is_a(obj, klass)) { - Err_throw_at(ERR, file, line, func, "Can't downcast from %o to %o", - Obj_get_class_name(obj), Class_Get_Name(klass)); - } - return obj; -} - void Err_abstract_method_call(Obj *obj, Class *klass, const char *method_name) { String *class_name = obj ? Obj_get_class_name(obj) : Class_Get_Name(klass); http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2794cf2e/runtime/core/Clownfish/Err.cfh ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Err.cfh b/runtime/core/Clownfish/Err.cfh index a4014c5..1b816c2 100644 --- a/runtime/core/Clownfish/Err.cfh +++ b/runtime/core/Clownfish/Err.cfh @@ -156,32 +156,6 @@ public class Clownfish::Err inherits Clownfish::Obj { make_mess(const char *file, int line, const char *func, const char *pattern, ...); - /** Verify that `obj` is either NULL or inherits from - * `klass`. Throws an exception if the test fails. The following - * convenience macro fills `file`, `line`, and `func` with the - * current code location: - * - * CFISH_DOWNCAST(obj, klass) - * - * @return the object. - */ - public inert nullable Obj* - downcast(Obj *obj, Class *klass, const char *file, int line, - const char *func); - - /** Verify that `obj` is not NULL and inherits from - * `klass`. Throws an exception if the test fails. The following - * convenience macro fills `file`, `line`, and `func` with the - * current code location: - * - * CFISH_CERTIFY(obj, klass) - * - * @return the object. - */ - public inert Obj* - certify(Obj *obj, Class *klass, const char *file, int line, - const char *func); - /** Verify that an object belongs to a subclass and not an abstract class. */ inert inline void @@ -251,15 +225,6 @@ __C__ CFISH_MAKE_MESS(char* format, ...); #endif -#define CFISH_DOWNCAST(_obj, _class) \ - cfish_Err_downcast((cfish_Obj*)(_obj), (_class), \ - __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO) - - -#define CFISH_CERTIFY(_obj, _class) \ - cfish_Err_certify((cfish_Obj*)(_obj), (_class), \ - __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO) - static CFISH_INLINE void cfish_Err_abstract_class_check(cfish_Obj *obj, cfish_Class *klass) { cfish_Class *const my_class = (cfish_Class*)((cfish_Dummy*)obj)->klass; @@ -281,8 +246,6 @@ cfish_Err_abstract_class_check(cfish_Obj *obj, cfish_Class *klass) { #define MAKE_MESS CFISH_MAKE_MESS #define ERR_ADD_FRAME CFISH_ERR_ADD_FRAME #define ERR_FUNC_MACRO CFISH_ERR_FUNC_MACRO - #define DOWNCAST CFISH_DOWNCAST - #define CERTIFY CFISH_CERTIFY #define ABSTRACT_CLASS_CHECK CFISH_ABSTRACT_CLASS_CHECK #endif __END_C__ http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2794cf2e/runtime/core/Clownfish/Obj.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Obj.c b/runtime/core/Clownfish/Obj.c index cd52115..3ea3996 100644 --- a/runtime/core/Clownfish/Obj.c +++ b/runtime/core/Clownfish/Obj.c @@ -31,6 +31,20 @@ #include "Clownfish/Class.h" #include "Clownfish/Util/Memory.h" +static CFISH_INLINE bool +SI_obj_is_a(Obj *obj, Class *ancestor) { + Class *klass = obj->klass; + + while (klass != NULL) { + if (klass == ancestor) { + return true; + } + klass = klass->parent; + } + + return false; +} + Obj* Obj_init(Obj *self) { ABSTRACT_CLASS_CHECK(self, OBJ); @@ -44,16 +58,31 @@ Obj_Destroy_IMP(Obj *self) { bool Obj_is_a(Obj *self, Class *ancestor) { - Class *klass = self ? self->klass : NULL; + return self ? SI_obj_is_a(self, ancestor) : false; +} - while (klass != NULL) { - if (klass == ancestor) { - return true; - } - klass = klass->parent; +Obj* +Obj_downcast(Obj *self, Class *klass, const char *file, int line, + const char *func) { + if (self && !SI_obj_is_a(self, klass)) { + Err_throw_at(ERR, file, line, func, "Can't downcast from %o to %o", + Class_Get_Name(self->klass), Class_Get_Name(klass)); } + return self; +} - return false; +Obj* +Obj_certify(Obj *self, Class *klass, const char *file, int line, + const char *func) { + if (!self) { + Err_throw_at(ERR, file, line, func, "Object isn't a %o, it's NULL", + Class_Get_Name(klass)); + } + else if (!SI_obj_is_a(self, klass)) { + Err_throw_at(ERR, file, line, func, "Can't downcast from %o to %o", + Class_Get_Name(self->klass), Class_Get_Name(klass)); + } + return self; } bool http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2794cf2e/runtime/core/Clownfish/Obj.cfh ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Obj.cfh b/runtime/core/Clownfish/Obj.cfh index 5241a16..a9d1016 100644 --- a/runtime/core/Clownfish/Obj.cfh +++ b/runtime/core/Clownfish/Obj.cfh @@ -78,9 +78,51 @@ public abstract class Clownfish::Obj { public inert bool is_a(nullable Obj *self, nullable Class *ancestor); + /** Verify that `obj` is either NULL or inherits from + * `klass`. Throws an exception if the test fails. The following + * convenience macro fills `file`, `line`, and `func` with the + * current code location: + * + * CFISH_DOWNCAST(obj, klass) + * + * @return the object. + */ + public inert nullable Obj* + downcast(nullable Obj *obj, Class *klass, const char *file, int line, + const char *func); + + /** Verify that `obj` is not NULL and inherits from + * `klass`. Throws an exception if the test fails. The following + * convenience macro fills `file`, `line`, and `func` with the + * current code location: + * + * CFISH_CERTIFY(obj, klass) + * + * @return the object. + */ + public inert Obj* + certify(nullable Obj *obj, Class *klass, const char *file, int line, + const char *func); + /** Generic stringification: "ClassName@hex_mem_address". */ public incremented String* To_String(Obj *self); } +__C__ +#define CFISH_DOWNCAST(_obj, _class) \ + cfish_Obj_downcast((cfish_Obj*)(_obj), (_class), \ + __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO) + + +#define CFISH_CERTIFY(_obj, _class) \ + cfish_Obj_certify((cfish_Obj*)(_obj), (_class), \ + __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO) + +#ifdef CFISH_USE_SHORT_NAMES + #define DOWNCAST CFISH_DOWNCAST + #define CERTIFY CFISH_CERTIFY +#endif +__END_C__ + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2794cf2e/runtime/test/Clownfish/Test/TestErr.c ---------------------------------------------------------------------- diff --git a/runtime/test/Clownfish/Test/TestErr.c b/runtime/test/Clownfish/Test/TestErr.c index 46ecb1e..d22a047 100644 --- a/runtime/test/Clownfish/Test/TestErr.c +++ b/runtime/test/Clownfish/Test/TestErr.c @@ -102,51 +102,6 @@ test_rethrow(TestBatchRunner *runner) { } static void -S_invalid_downcast(void *context) { - Obj *obj = (Obj*)context; - DOWNCAST(obj, ERR); -} - -static void -test_downcast(TestBatchRunner *runner) { - Obj *obj = (Obj*)Str_newf("gamma"); - - TEST_TRUE(runner, DOWNCAST(obj, STRING) != NULL, "downcast"); - - TEST_TRUE(runner, DOWNCAST(NULL, STRING) == NULL, "downcast NULL"); - - Err *error = Err_trap(S_invalid_downcast, obj); - TEST_TRUE(runner, error != NULL, "downcast throws"); - DECREF(error); - - DECREF(obj); -} - -static void -S_invalid_certify(void *context) { - Obj *obj = (Obj*)context; - CERTIFY(obj, ERR); -} - -static void -test_certify(TestBatchRunner *runner) { - Obj *obj = (Obj*)Str_newf("epsilon"); - Err *error; - - TEST_TRUE(runner, CERTIFY(obj, STRING) != NULL, "certify"); - - error = Err_trap(S_invalid_certify, NULL); - TEST_TRUE(runner, error != NULL, "certify NULL"); - DECREF(error); - - error = Err_trap(S_invalid_certify, obj); - TEST_TRUE(runner, error != NULL, "certify throws"); - DECREF(error); - - DECREF(obj); -} - -static void S_err_thread(void *arg) { TestBatchRunner *runner = (TestBatchRunner*)arg; @@ -180,13 +135,11 @@ test_threads(TestBatchRunner *runner) { void TestErr_Run_IMP(TestErr *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 15); + TestBatchRunner_Plan(runner, (TestBatch*)self, 9); test_To_String(runner); test_Cat_Mess(runner); test_Add_Frame(runner); test_rethrow(runner); - test_downcast(runner); - test_certify(runner); test_threads(runner); } http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2794cf2e/runtime/test/Clownfish/Test/TestObj.c ---------------------------------------------------------------------- diff --git a/runtime/test/Clownfish/Test/TestObj.c b/runtime/test/Clownfish/Test/TestObj.c index c4cdafe..51c3848 100644 --- a/runtime/test/Clownfish/Test/TestObj.c +++ b/runtime/test/Clownfish/Test/TestObj.c @@ -102,6 +102,51 @@ test_is_a(TestBatchRunner *runner) { } static void +S_invalid_downcast(void *context) { + Obj *obj = (Obj*)context; + DOWNCAST(obj, ERR); +} + +static void +test_downcast(TestBatchRunner *runner) { + Obj *obj = (Obj*)Str_newf("gamma"); + + TEST_TRUE(runner, DOWNCAST(obj, STRING) != NULL, "downcast"); + + TEST_TRUE(runner, DOWNCAST(NULL, STRING) == NULL, "downcast NULL"); + + Err *error = Err_trap(S_invalid_downcast, obj); + TEST_TRUE(runner, error != NULL, "downcast throws"); + DECREF(error); + + DECREF(obj); +} + +static void +S_invalid_certify(void *context) { + Obj *obj = (Obj*)context; + CERTIFY(obj, ERR); +} + +static void +test_certify(TestBatchRunner *runner) { + Obj *obj = (Obj*)Str_newf("epsilon"); + Err *error; + + TEST_TRUE(runner, CERTIFY(obj, STRING) != NULL, "certify"); + + error = Err_trap(S_invalid_certify, NULL); + TEST_TRUE(runner, error != NULL, "certify NULL"); + DECREF(error); + + error = Err_trap(S_invalid_certify, obj); + TEST_TRUE(runner, error != NULL, "certify throws"); + DECREF(error); + + DECREF(obj); +} + +static void S_attempt_init(void *context) { Obj_init((Obj*)context); } @@ -142,11 +187,13 @@ test_abstract_routines(TestBatchRunner *runner) { void TestObj_Run_IMP(TestObj *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 14); + TestBatchRunner_Plan(runner, (TestBatch*)self, 20); test_refcounts(runner); test_To_String(runner); test_Equals(runner); test_is_a(runner); + test_downcast(runner); + test_certify(runner); test_abstract_routines(runner); }