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/01/05 00:33:49 UTC

[5/8] lucy-clownfish git commit: Simplify abstract method call errors

Simplify abstract method call errors

There's no need to declare abstract method implementations in the class
headers. In the parcel.c files, they can be simply defined as void
functions taking only a cfish_Obj parameter.

To reduce code size, the abstract method implementations call a helper
function in Err.


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

Branch: refs/heads/optimize_autogen
Commit: cd8f180e3305fe5562c734af225e66c2fe7b3f61
Parents: b92cfa9
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Nov 30 22:11:04 2014 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Jan 4 23:59:59 2015 +0100

----------------------------------------------------------------------
 compiler/src/CFCBindClass.c      |  1 +
 compiler/src/CFCBindCore.c       |  1 -
 compiler/src/CFCBindMethod.c     | 71 ++++-------------------------------
 runtime/core/Clownfish/Err.c     |  7 ++++
 runtime/core/Clownfish/Err.cfh   |  6 +++
 runtime/perl/t/binding/019-obj.t |  6 ++-
 6 files changed, 26 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cd8f180e/compiler/src/CFCBindClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindClass.c b/compiler/src/CFCBindClass.c
index eba1c10..4900111 100644
--- a/compiler/src/CFCBindClass.c
+++ b/compiler/src/CFCBindClass.c
@@ -627,6 +627,7 @@ S_sub_declarations(CFCBindClass *self) {
     }
     for (int i = 0; fresh_methods[i] != NULL; i++) {
         CFCMethod *method = fresh_methods[i];
+        if (CFCMethod_abstract(method)) { continue; }
         char *dec = CFCBindMeth_imp_declaration(method);
         if (CFCMethod_final(method)) {
             declarations = CFCUtil_cat(declarations, PREFIX, "VISIBLE ", NULL);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cd8f180e/compiler/src/CFCBindCore.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindCore.c b/compiler/src/CFCBindCore.c
index 75953c9..c6adf01 100644
--- a/compiler/src/CFCBindCore.c
+++ b/compiler/src/CFCBindCore.c
@@ -432,7 +432,6 @@ S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
         "#include <stdio.h>\n"
         "#include <stdlib.h>\n"
         "\n"
-        "#define C_CFISH_CLASS\n"            // Needed for abstract methods.
         "%s"
         "\n"
         "#include \"callbacks.h\"\n"

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cd8f180e/compiler/src/CFCBindMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindMethod.c b/compiler/src/CFCBindMethod.c
index 58de50d..0aec672 100644
--- a/compiler/src/CFCBindMethod.c
+++ b/compiler/src/CFCBindMethod.c
@@ -34,20 +34,6 @@ S_final_method_def(CFCMethod *method, CFCClass *klass);
 static char*
 S_virtual_method_def(CFCMethod *method, CFCClass *klass);
 
-/* Take a NULL-terminated list of CFCVariables and build up a string of
- * directives like:
- *
- *     UNUSED_VAR(var1);
- *     UNUSED_VAR(var2);
- */
-static char*
-S_build_unused_vars(CFCVariable **vars);
-
-/* Create an unreachable return statement if necessary, in order to thwart
- * compiler warnings. */
-static char*
-S_maybe_unreachable(CFCType *return_type);
-
 char*
 CFCBindMeth_method_def(CFCMethod *method, CFCClass *klass) {
     if (CFCMethod_final(method)) {
@@ -218,64 +204,21 @@ CFCBindMeth_inherited_spec_def(CFCMethod *method, CFCClass *klass) {
     return def;
 }
 
-static char*
-S_build_unused_vars(CFCVariable **vars) {
-    char *unused = CFCUtil_strdup("");
-
-    for (int i = 0; vars[i] != NULL; i++) {
-        const char *var_name = CFCVariable_micro_sym(vars[i]);
-        size_t size = strlen(unused) + strlen(var_name) + 80;
-        unused = (char*)REALLOCATE(unused, size);
-        strcat(unused, "\n    CFISH_UNUSED_VAR(");
-        strcat(unused, var_name);
-        strcat(unused, ");");
-    }
-
-    return unused;
-}
-
-static char*
-S_maybe_unreachable(CFCType *return_type) {
-    char *return_statement;
-    if (CFCType_is_void(return_type)) {
-        return_statement = CFCUtil_strdup("");
-    }
-    else {
-        const char *ret_type_str = CFCType_to_c(return_type);
-        char pattern[] = "\n    CFISH_UNREACHABLE_RETURN(%s);";
-        return_statement = CFCUtil_sprintf(pattern, ret_type_str);
-    }
-    return return_statement;
-}
-
 char*
 CFCBindMeth_abstract_method_def(CFCMethod *method) {
-    CFCParamList *param_list = CFCMethod_get_param_list(method);
-    const char *params = CFCParamList_to_c(param_list);
+    CFCType    *type          = CFCMethod_self_type(method);
     const char *full_func_sym = CFCMethod_imp_func(method);
-    const char *class_var
-        = CFCType_get_class_var(CFCMethod_self_type(method));
-    CFCType    *return_type  = CFCMethod_get_return_type(method);
-    const char *ret_type_str = CFCType_to_c(return_type);
-    const char *macro_sym    = CFCMethod_get_macro_sym(method);
-
-    // Thwart compiler warnings.
-    CFCVariable **param_vars = CFCParamList_get_variables(param_list);
-    char *unused = S_build_unused_vars(param_vars + 1);
-    char *return_statement = S_maybe_unreachable(return_type);
+    const char *class_var     = CFCType_get_class_var(type);
+    const char *macro_sym     = CFCMethod_get_macro_sym(method);
 
     char pattern[] =
-        "%s\n"
-        "%s(%s) {\n"
-        "    cfish_String *klass = self ? CFISH_Obj_Get_Class_Name((cfish_Obj*)self) : %s->name;%s\n"
-        "    CFISH_THROW(CFISH_ERR, \"Abstract method '%s' not defined by %%o\", klass);%s\n"
+        "void\n"
+        "%s(cfish_Obj *self) {\n"
+        "    cfish_Err_abstract_method_call(self, %s, \"%s\");\n"
         "}\n";
     char *abstract_def
-        = CFCUtil_sprintf(pattern, ret_type_str, full_func_sym, params,
-                          class_var, unused, macro_sym, return_statement);
+        = CFCUtil_sprintf(pattern, full_func_sym, class_var, macro_sym);
 
-    FREEMEM(unused);
-    FREEMEM(return_statement);
     return abstract_def;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cd8f180e/runtime/core/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Err.c b/runtime/core/Clownfish/Err.c
index 5c3add2..e195b3b 100644
--- a/runtime/core/Clownfish/Err.c
+++ b/runtime/core/Clownfish/Err.c
@@ -231,6 +231,13 @@ Err_certify(Obj *obj, Class *klass, const char *file, int line,
     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);
+    THROW(ERR, "Abstract method '%s' not defined by %o", method_name,
+          class_name);
+}
+
 #ifdef CHY_HAS_WINDOWS_H
 
 #include <windows.h>

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cd8f180e/runtime/core/Clownfish/Err.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Err.cfh b/runtime/core/Clownfish/Err.cfh
index 60f6ecb..24b7558 100644
--- a/runtime/core/Clownfish/Err.cfh
+++ b/runtime/core/Clownfish/Err.cfh
@@ -162,6 +162,12 @@ public class Clownfish::Err inherits Clownfish::Obj {
     inert inline void
     abstract_class_check(Obj *obj, Class *klass);
 
+    /** Throw an error after abstract method `method_name` was called on
+     * object `obj` of class `klass`.
+     */
+    inert void
+    abstract_method_call(Obj *obj, Class *klass, const char *method_name);
+
     /** On Windows, return a newly allocated buffer containing the string
      * description for the the last error in the thread.
      */

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cd8f180e/runtime/perl/t/binding/019-obj.t
----------------------------------------------------------------------
diff --git a/runtime/perl/t/binding/019-obj.t b/runtime/perl/t/binding/019-obj.t
index 9d3b846..89d1ce3 100644
--- a/runtime/perl/t/binding/019-obj.t
+++ b/runtime/perl/t/binding/019-obj.t
@@ -16,7 +16,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 20;
+use Test::More tests => 21;
 
 package TestObj;
 use base qw( Clownfish::Obj );
@@ -91,6 +91,10 @@ ok( !$object->is_a("thing"),             "custom is_a wrong" );
 eval { my $another_obj = TestObj->new( kill_me_now => 1 ) };
 like( $@, qr/kill_me_now/, "reject bad param" );
 
+eval { $object->to_i64 };
+like( $@, qr/Abstract method 'To_I64' not defined by TestObj/,
+      "calling an abstract method throws" );
+
 my $stringified_perl_obj = "$object";
 require Clownfish::Hash;
 my $hash = Clownfish::Hash->new;