Have host language write callbacks. In anticiption of having callback wrappers access the host language C API directly, give responsibility for writing out the callback code to the host language binding.
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/17b608b6 Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/17b608b6 Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/17b608b6 Branch: refs/heads/master Commit: 17b608b676bb1f58ccdeb7488fa373e2b06b63dc Parents: b407d11 Author: Marvin Humphrey <[email protected]> Authored: Fri Nov 9 16:48:18 2012 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Tue Nov 13 17:16:42 2012 -0800 ---------------------------------------------------------------------- clownfish/compiler/perl/lib/Clownfish/CFC.xs | 6 ++ .../compiler/perl/lib/Clownfish/CFC/Perl/Build.pm | 1 + clownfish/compiler/src/CFCBindClass.c | 8 +- clownfish/compiler/src/CFCBindMethod.c | 21 +++++ clownfish/compiler/src/CFCBindMethod.h | 5 + clownfish/compiler/src/CFCPerl.c | 60 +++++++++++++++ clownfish/compiler/src/CFCPerl.h | 5 + 7 files changed, 102 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy/blob/17b608b6/clownfish/compiler/perl/lib/Clownfish/CFC.xs ---------------------------------------------------------------------- diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC.xs b/clownfish/compiler/perl/lib/Clownfish/CFC.xs index f1e834a..fd7012e 100644 --- a/clownfish/compiler/perl/lib/Clownfish/CFC.xs +++ b/clownfish/compiler/perl/lib/Clownfish/CFC.xs @@ -1928,6 +1928,12 @@ PPCODE: CFCPerl_write_bindings(self); void +write_callbacks(self) + CFCPerl *self; +PPCODE: + CFCPerl_write_callbacks(self); + +void write_xs_typemap(self) CFCPerl *self; PPCODE: http://git-wip-us.apache.org/repos/asf/lucy/blob/17b608b6/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm ---------------------------------------------------------------------- diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm b/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm index 099838f..b0fe049 100644 --- a/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm +++ b/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm @@ -322,6 +322,7 @@ sub ACTION_clownfish { if ($modified) { $self->add_to_cleanup($xs_filepath); + $perl_binding->write_callbacks; $perl_binding->write_boot; $perl_binding->write_bindings; $self->_write_pod($perl_binding); http://git-wip-us.apache.org/repos/asf/lucy/blob/17b608b6/clownfish/compiler/src/CFCBindClass.c ---------------------------------------------------------------------- diff --git a/clownfish/compiler/src/CFCBindClass.c b/clownfish/compiler/src/CFCBindClass.c index 03949d7..1eb2560 100644 --- a/clownfish/compiler/src/CFCBindClass.c +++ b/clownfish/compiler/src/CFCBindClass.c @@ -320,12 +320,12 @@ CFCBindClass_to_c_data(CFCBindClass *self) { FREEMEM(method_def); } - // Define callback. + // Declare (but don't define) callback. if ((CFCMethod_public(method) || CFCMethod_abstract(method)) && CFCMethod_novel(method)) { - char *cb_def = CFCBindMeth_callback_def(method); - cb_funcs = CFCUtil_cat(cb_funcs, cb_def, "\n", NULL); - FREEMEM(cb_def); + char *cb_dec = CFCBindMeth_callback_dec(method); + cb_funcs = CFCUtil_cat(cb_funcs, cb_dec, "\n", NULL); + FREEMEM(cb_dec); } // Define MethodSpec struct. http://git-wip-us.apache.org/repos/asf/lucy/blob/17b608b6/clownfish/compiler/src/CFCBindMethod.c ---------------------------------------------------------------------- diff --git a/clownfish/compiler/src/CFCBindMethod.c b/clownfish/compiler/src/CFCBindMethod.c index 02ea167..68ba38a 100644 --- a/clownfish/compiler/src/CFCBindMethod.c +++ b/clownfish/compiler/src/CFCBindMethod.c @@ -336,6 +336,27 @@ CFCBindMeth_abstract_method_def(CFCMethod *method) { } char* +CFCBindMeth_callback_dec(CFCMethod *method) { + CFCType *return_type = CFCMethod_get_return_type(method); + const char *ret_type_str = CFCType_to_c(return_type); + const char *override_sym = CFCMethod_full_override_sym(method); + const char *params = CFCParamList_to_c(CFCMethod_get_param_list(method)); + + char pattern[] = + "%s\n" + "%s(%s);\n"; + size_t size = sizeof(pattern) + + strlen(ret_type_str) + + strlen(override_sym) + + strlen(params); + + char *callback_dec = (char*)MALLOCATE(size); + sprintf(callback_dec, pattern, ret_type_str, override_sym, params); + + return callback_dec; +} + +char* CFCBindMeth_callback_def(CFCMethod *method) { CFCType *return_type = CFCMethod_get_return_type(method); char *params = S_callback_params(method); http://git-wip-us.apache.org/repos/asf/lucy/blob/17b608b6/clownfish/compiler/src/CFCBindMethod.h ---------------------------------------------------------------------- diff --git a/clownfish/compiler/src/CFCBindMethod.h b/clownfish/compiler/src/CFCBindMethod.h index 56956d6..fc15c4f 100644 --- a/clownfish/compiler/src/CFCBindMethod.h +++ b/clownfish/compiler/src/CFCBindMethod.h @@ -57,6 +57,11 @@ CFCBindMeth_spec_def(struct CFCMethod *method); char* CFCBindMeth_abstract_method_def(struct CFCMethod *method); +/** Return C code declaring a callback to the Host for this method. + */ +char* +CFCBindMeth_callback_dec(struct CFCMethod *method); + /** Return C code implementing a callback to the Host for this method. This * code is used when a Host method has overridden a method in a Clownfish * class. http://git-wip-us.apache.org/repos/asf/lucy/blob/17b608b6/clownfish/compiler/src/CFCPerl.c ---------------------------------------------------------------------- diff --git a/clownfish/compiler/src/CFCPerl.c b/clownfish/compiler/src/CFCPerl.c index 52d5cbe..5c28f07 100644 --- a/clownfish/compiler/src/CFCPerl.c +++ b/clownfish/compiler/src/CFCPerl.c @@ -22,8 +22,10 @@ #include "CFCPerl.h" #include "CFCParcel.h" #include "CFCClass.h" +#include "CFCMethod.h" #include "CFCHierarchy.h" #include "CFCUtil.h" +#include "CFCBindMethod.h" #include "CFCPerlClass.h" #include "CFCPerlSub.h" #include "CFCPerlConstructor.h" @@ -497,6 +499,64 @@ CFCPerl_write_bindings(CFCPerl *self) { } void +CFCPerl_write_callbacks(CFCPerl *self) { + CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy); + static const char start[] = + "/* DO NOT EDIT!!!! This is an auto-generated file. */\n" + "\n" + "/* Licensed to the Apache Software Foundation (ASF) under one or more\n" + " * contributor license agreements. See the NOTICE file distributed with\n" + " * this work for additional information regarding copyright ownership.\n" + " * The ASF licenses this file to You under the Apache License, Version 2.0\n" + " * (the \"License\"); you may not use this file except in compliance with\n" + " * the License. You may obtain a copy of the License at\n" + " *\n" + " * http://www.apache.org/licenses/LICENSE-2.0\n" + " *\n" + " * Unless required by applicable law or agreed to in writing, software\n" + " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + " * See the License for the specific language governing permissions and\n" + " * limitations under the License.\n" + " */\n" + "\n" + "#include \"XSBind.h\"\n" + "#include \"parcel.h\"\n" + "#include \"Clownfish/Host.h\"\n" + "\n"; + char *content = CFCUtil_strdup(start); + + for (size_t i = 0; ordered[i] != NULL; i++) { + CFCClass *klass = ordered[i]; + if (CFCClass_inert(klass)) { continue; } + + CFCMethod **fresh_methods = CFCClass_fresh_methods(klass); + for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) { + CFCMethod *method = fresh_methods[meth_num]; + + // Define callback. + if ((CFCMethod_public(method) || CFCMethod_abstract(method)) + && CFCMethod_novel(method)) { + char *cb_def = CFCBindMeth_callback_def(method); + content = CFCUtil_cat(content, cb_def, "\n", NULL); + FREEMEM(cb_def); + } + } + FREEMEM(fresh_methods); + } + + // Write if changed. + const char *src_dest = CFCHierarchy_get_source_dest(self->hierarchy); + char *filepath = CFCUtil_cat(CFCUtil_strdup(""), src_dest, + CFCUTIL_PATH_SEP, "callbacks.c", NULL); + CFCUtil_write_if_changed(filepath, content, strlen(content)); + + FREEMEM(filepath); + FREEMEM(content); + FREEMEM(ordered); +} + +void CFCPerl_write_xs_typemap(CFCPerl *self) { CFCPerlTypeMap_write_xs_typemap(self->hierarchy); } http://git-wip-us.apache.org/repos/asf/lucy/blob/17b608b6/clownfish/compiler/src/CFCPerl.h ---------------------------------------------------------------------- diff --git a/clownfish/compiler/src/CFCPerl.h b/clownfish/compiler/src/CFCPerl.h index 6ea3778..8dfb61f 100644 --- a/clownfish/compiler/src/CFCPerl.h +++ b/clownfish/compiler/src/CFCPerl.h @@ -98,6 +98,11 @@ CFCPerl_write_boot(CFCPerl *self); void CFCPerl_write_bindings(CFCPerl *self); +/** Generate routines which call back from C into Perl for all methods. + */ +void +CFCPerl_write_callbacks(CFCPerl *self); + /** Generate the "typemap" file needed by the XS compiler. */ void
