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 2011/06/23 01:33:19 UTC

[lucy-commits] svn commit: r1138683 - in /incubator/lucy/trunk/clownfish: lib/Clownfish.xs lib/Clownfish/Binding/Core/Method.pm src/CFCBindMethod.c src/CFCBindMethod.h

Author: marvin
Date: Wed Jun 22 23:33:18 2011
New Revision: 1138683

URL: http://svn.apache.org/viewvc?rev=1138683&view=rev
Log:
Port method_def() and its helper routines from
Clownfish::Binding::Core::Method to C.

Modified:
    incubator/lucy/trunk/clownfish/lib/Clownfish.xs
    incubator/lucy/trunk/clownfish/lib/Clownfish/Binding/Core/Method.pm
    incubator/lucy/trunk/clownfish/src/CFCBindMethod.c
    incubator/lucy/trunk/clownfish/src/CFCBindMethod.h

Modified: incubator/lucy/trunk/clownfish/lib/Clownfish.xs
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/lib/Clownfish.xs?rev=1138683&r1=1138682&r2=1138683&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/lib/Clownfish.xs (original)
+++ incubator/lucy/trunk/clownfish/lib/Clownfish.xs Wed Jun 22 23:33:18 2011
@@ -1723,6 +1723,14 @@ CODE:
 OUTPUT: RETVAL
 
 SV*
+_method_def(meth, klass)
+    CFCMethod *meth;
+    CFCClass  *klass;
+CODE:
+    RETVAL = S_sv_eat_c_string(CFCBindMeth_method_def(meth, klass));
+OUTPUT: RETVAL
+
+SV*
 _callback_obj_def(meth, offset)
     CFCMethod *meth;
     const char *offset;

Modified: incubator/lucy/trunk/clownfish/lib/Clownfish/Binding/Core/Method.pm
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/lib/Clownfish/Binding/Core/Method.pm?rev=1138683&r1=1138682&r2=1138683&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/lib/Clownfish/Binding/Core/Method.pm (original)
+++ incubator/lucy/trunk/clownfish/lib/Clownfish/Binding/Core/Method.pm Wed Jun 22 23:33:18 2011
@@ -21,67 +21,8 @@ use Clownfish::Util qw( a_isa_b );
 use Carp;
 
 sub method_def {
-    my ( undef,   %args )  = @_;
-    my ( $method, $class ) = @args{qw( method class )};
-    confess("Not a Method")
-        unless a_isa_b( $method, "Clownfish::Method" );
-    confess("Not a Class")
-        unless a_isa_b( $class, "Clownfish::Class" );
-    if ( $method->final ) {
-        return _final_method_def( $method, $class );
-    }
-    else {
-        return _virtual_method_def( $method, $class );
-    }
-}
-
-sub _virtual_method_def {
-    my ( $method, $class ) = @_;
-    my $cnick           = $class->get_cnick;
-    my $param_list      = $method->get_param_list;
-    my $invoker_struct  = $class->full_struct_sym;
-    my $common_struct   = $method->self_type->get_specifier;
-    my $full_method_sym = $method->full_method_sym($cnick);
-    my $full_offset_sym = $method->full_offset_sym($cnick);
-    my $typedef         = $method->full_typedef;
-    my $arg_names       = $param_list->name_list;
-    $arg_names =~ s/\s*\w+/self/;
-
-    # Prepare the parameter list for the inline function.
-    my $params = $param_list->to_c;
-    $params =~ s/^.*?\*\s*\w+/const $invoker_struct *self/
-        or confess("no match: $params");
-
-    # Prepare a return statement... or not.
-    my $return_type = $method->get_return_type->to_c;
-    my $maybe_return = $method->get_return_type->is_void ? '' : 'return ';
-
-    return <<END_STUFF;
-extern size_t $full_offset_sym;
-static CHY_INLINE $return_type
-$full_method_sym($params) {
-    char *const method_address = *(char**)self + $full_offset_sym;
-    const $typedef method = *(($typedef*)method_address);
-    ${maybe_return}method(($common_struct*)$arg_names);
-}
-END_STUFF
-}
-
-# Create a macro definition that aliases to a function name directly, since
-# this method may not be overridden.
-sub _final_method_def {
-    my ( $method, $class ) = @_;
-    my $cnick           = $class->get_cnick;
-    my $macro_sym       = $method->get_macro_sym;
-    my $self_type       = $method->self_type->to_c;
-    my $full_method_sym = $method->full_method_sym($cnick);
-    my $full_func_sym   = $method->full_func_sym;
-    my $arg_names       = $method->get_param_list->name_list;
-
-    return <<END_STUFF;
-#define $full_method_sym($arg_names) \\
-    $full_func_sym(($self_type)$arg_names)
-END_STUFF
+    my ( undef, %args ) = @_;
+    return _method_def( @args{qw( method class )} );
 }
 
 sub callback_obj_def {

Modified: incubator/lucy/trunk/clownfish/src/CFCBindMethod.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/src/CFCBindMethod.c?rev=1138683&r1=1138682&r2=1138683&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/src/CFCBindMethod.c (original)
+++ incubator/lucy/trunk/clownfish/src/CFCBindMethod.c Wed Jun 22 23:33:18 2011
@@ -24,6 +24,15 @@
 #include "CFCType.h"
 #include "CFCVariable.h"
 #include "CFCSymbol.h"
+#include "CFCClass.h"
+
+/* Create a macro definition that aliases to a function name directly, since
+ * this method may not be overridden. */
+static char*
+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:
@@ -70,6 +79,111 @@ static char*
 S_obj_callback_def(CFCMethod *method, const char *callback_params);
 
 char*
+CFCBindMeth_method_def(CFCMethod *method, CFCClass *klass) {
+    if (CFCMethod_final(method)) {
+        return S_final_method_def(method, klass);
+    }
+    else {
+        return S_virtual_method_def(method, klass);
+    }
+}
+
+/* Create a macro definition that aliases to a function name directly, since
+ * this method may not be overridden. */
+static char*
+S_final_method_def(CFCMethod *method, CFCClass *klass) {
+    const char *cnick = CFCClass_get_cnick(klass);
+    const char *self_type = CFCType_to_c(CFCMethod_self_type(method));
+    size_t meth_sym_size = CFCMethod_full_method_sym(method, cnick, NULL, 0);
+    char *full_meth_sym = (char*)MALLOCATE(meth_sym_size);
+    CFCMethod_full_method_sym(method, cnick, full_meth_sym, meth_sym_size);
+    const char *full_func_sym = CFCMethod_implementing_func_sym(method);
+    const char *arg_names 
+        = CFCParamList_name_list(CFCMethod_get_param_list(method));
+
+    char pattern[] = "#define %s(%s) \\\n    %s((%s)%s)\n";
+    size_t size = sizeof(pattern)
+                  + strlen(full_meth_sym)
+                  + strlen(arg_names)
+                  + strlen(full_func_sym)
+                  + strlen(self_type)
+                  + strlen(arg_names)
+                  + 20;
+    char *method_def = (char*)MALLOCATE(size);
+    sprintf(method_def, pattern, full_meth_sym, arg_names, full_func_sym,
+            self_type, arg_names);
+
+    FREEMEM(full_meth_sym);
+    return method_def;
+}
+
+static char*
+S_virtual_method_def(CFCMethod *method, CFCClass *klass) {
+    const char *cnick = CFCClass_get_cnick(klass);
+    CFCParamList *param_list = CFCMethod_get_param_list(method);
+    const char *invoker_struct = CFCClass_full_struct_sym(klass);
+    const char *common_struct 
+        = CFCType_get_specifier(CFCMethod_self_type(method));
+    const char *typedef_str = CFCMethod_full_typedef(method);
+
+    size_t meth_sym_size = CFCMethod_full_method_sym(method, cnick, NULL, 0);
+    char *full_meth_sym = (char*)MALLOCATE(meth_sym_size);
+    CFCMethod_full_method_sym(method, cnick, full_meth_sym, meth_sym_size);
+
+    size_t offset_sym_size = CFCMethod_full_offset_sym(method, cnick, NULL, 0);
+    char *full_offset_sym = (char*)MALLOCATE(offset_sym_size);
+    CFCMethod_full_offset_sym(method, cnick, full_offset_sym, offset_sym_size);
+
+    // Prepare parameter lists, minus invoker.  The invoker gets forced to
+    // "self" later.
+    const char *arg_names_minus_invoker = CFCParamList_name_list(param_list);
+    const char *params_minus_invoker    = CFCParamList_to_c(param_list);
+    while (*arg_names_minus_invoker && *arg_names_minus_invoker != ',') {
+        arg_names_minus_invoker++;
+    }
+    while (*params_minus_invoker && *params_minus_invoker != ',') {
+        params_minus_invoker++;
+    }
+
+    // Prepare a return statement... or not.
+    CFCType *return_type = CFCMethod_get_return_type(method);
+    const char *ret_type_str = CFCType_to_c(return_type);
+    const char *maybe_return = CFCType_is_void(return_type) ? "" : "return ";
+
+    const char pattern[] = 
+        "extern size_t %s;\n"
+        "static CHY_INLINE %s\n"
+        "%s(const %s *self%s) {\n"
+        "    char *const method_address = *(char**)self + %s;\n"
+        "    const %s method = *((%s*)method_address);\n"
+        "    %smethod((%s*)self%s);\n"
+        "}\n";
+
+    size_t size = sizeof(pattern)
+                  + strlen(full_offset_sym)
+                  + strlen(ret_type_str)
+                  + strlen(full_meth_sym)
+                  + strlen(invoker_struct)
+                  + strlen(params_minus_invoker)
+                  + strlen(full_offset_sym)
+                  + strlen(typedef_str)
+                  + strlen(typedef_str)
+                  + strlen(maybe_return)
+                  + strlen(common_struct)
+                  + strlen(arg_names_minus_invoker)
+                  + 40;
+    char *method_def = (char*)MALLOCATE(size);
+    sprintf(method_def, pattern, full_offset_sym, ret_type_str,
+            full_meth_sym, invoker_struct, params_minus_invoker,
+            full_offset_sym, typedef_str, typedef_str, maybe_return,
+            common_struct, arg_names_minus_invoker);
+
+    FREEMEM(full_offset_sym);
+    FREEMEM(full_meth_sym);
+    return method_def;
+}
+
+char*
 CFCBindMeth_typdef_dec(struct CFCMethod *method) {
     const char *params = CFCParamList_to_c(CFCMethod_get_param_list(method));
     const char *ret_type = CFCType_to_c(CFCMethod_get_return_type(method));

Modified: incubator/lucy/trunk/clownfish/src/CFCBindMethod.h
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/src/CFCBindMethod.h?rev=1138683&r1=1138682&r2=1138683&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/src/CFCBindMethod.h (original)
+++ incubator/lucy/trunk/clownfish/src/CFCBindMethod.h Wed Jun 22 23:33:18 2011
@@ -22,6 +22,10 @@ extern "C" {
 #endif
 
 struct CFCMethod;
+struct CFCClass;
+
+char*
+CFCBindMeth_method_def(struct CFCMethod *method, struct CFCClass *klass);
 
 char*
 CFCBindMeth_typdef_dec(struct CFCMethod *method);