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 2016/02/25 00:56:02 UTC

[01/36] lucy-clownfish git commit: Add missing `static` modifier.

Repository: lucy-clownfish
Updated Branches:
  refs/heads/py_exp13 [created] 9d058f4b3


Add missing `static` modifier.


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

Branch: refs/heads/py_exp13
Commit: 4b8d87bcbe098f92e7148ab84e27b619c089218e
Parents: 7c80fb8
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Feb 24 15:19:18 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:19:18 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/4b8d87bc/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index a2b13a4..e17feeb 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -39,7 +39,7 @@ struct CFCPython {
     char *footer;
 };
 
-void
+static void
 S_destroy(CFCPython *self);
 
 static const CFCMeta CFCPYTHON_META = {
@@ -58,7 +58,7 @@ CFCPython_new(CFCHierarchy *hierarchy) {
     return self;
 }
 
-void
+static void
 S_destroy(CFCPython *self) {
     CFCBase_decref((CFCBase*)self->hierarchy);
     FREEMEM(self->header);


[29/36] lucy-clownfish git commit: Add helper for generating arg lists.

Posted by ma...@apache.org.
Add helper for generating arg lists.


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

Branch: refs/heads/py_exp13
Commit: 71c836a2a2329c3a999ce102a6bd38f1b0f08169
Parents: d88c0bf
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 16:08:54 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:36:07 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/71c836a2/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 450c26e..4220aea 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -473,6 +473,26 @@ S_gen_decrefs(CFCParamList *param_list, int first_tick) {
     return decrefs;
 }
 
+static char*
+S_gen_arg_list(CFCParamList *param_list, const char *first_arg) {
+    CFCVariable **vars = CFCParamList_get_variables(param_list);
+    int num_vars = CFCParamList_num_vars(param_list);
+    char *arg_list = CFCUtil_strdup("");
+    for (int i = 0; i < num_vars; i++) {
+        if (i > 0) {
+            arg_list = CFCUtil_cat(arg_list, ", ", NULL);
+        }
+        if (i == 0 && first_arg != NULL) {
+            arg_list = CFCUtil_cat(arg_list, first_arg, NULL);
+        }
+        else {
+            arg_list = CFCUtil_cat(arg_list, CFCVariable_get_name(vars[i]),
+                                   "_ARG", NULL);
+        }
+    }
+    return arg_list;
+}
+
 char*
 CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
     CFCParamList *param_list  = CFCMethod_get_param_list(method);


[11/36] lucy-clownfish git commit: Reuse lower_snake_case code for host aliases.

Posted by ma...@apache.org.
Reuse lower_snake_case code for host aliases.

Method host aliases for both Perl and Python use lower_snake_case, so
share the implementation.


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

Branch: refs/heads/py_exp13
Commit: 3e9cd9e45094eea32150622467b3061e5f3e0409
Parents: 33189df
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 16:13:09 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 runtime/core/Clownfish/Method.c   | 26 ++++++++++++++++++++++++++
 runtime/core/Clownfish/Method.cfh |  6 ++++++
 runtime/perl/xs/XSBind.c          | 24 +-----------------------
 runtime/python/cfext/CFBind.c     |  4 +---
 4 files changed, 34 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e9cd9e4/runtime/core/Clownfish/Method.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Method.c b/runtime/core/Clownfish/Method.c
index c75bd4c..6bf1508 100644
--- a/runtime/core/Clownfish/Method.c
+++ b/runtime/core/Clownfish/Method.c
@@ -21,6 +21,7 @@
 #include "Clownfish/String.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/Class.h"
+#include "Clownfish/CharBuf.h"
 
 Method*
 Method_new(String *name, cfish_method_t callback_func, uint32_t offset) {
@@ -81,4 +82,29 @@ Method_Is_Excluded_From_Host_IMP(Method *self) {
     return self->is_excluded;
 }
 
+String*
+Method_lower_snake_alias(cfish_Method *method) {
+    cfish_String *host_alias = CFISH_Method_Get_Host_Alias(method);
+    if (host_alias) {
+        return (cfish_String*)CFISH_INCREF(host_alias);
+    }
 
+    // Convert to lowercase.
+    cfish_String *name = CFISH_Method_Get_Name(method);
+    cfish_CharBuf *buf = cfish_CB_new(CFISH_Str_Get_Size(name));
+    cfish_StringIterator *iter = CFISH_Str_Top(name);
+    int32_t code_point;
+    while (CFISH_STR_OOB != (code_point = CFISH_StrIter_Next(iter))) {
+        if (code_point > 127) {
+            THROW(CFISH_ERR, "Can't lowercase '%o'", name);
+        }
+        else {
+            CFISH_CB_Cat_Char(buf, tolower(code_point));
+        }
+    }
+    cfish_String *retval = CFISH_CB_Yield_String(buf);
+    CFISH_DECREF(iter);
+    CFISH_DECREF(buf);
+
+    return retval;
+}

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e9cd9e4/runtime/core/Clownfish/Method.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Method.cfh b/runtime/core/Clownfish/Method.cfh
index 3fa8633..2fc4314 100644
--- a/runtime/core/Clownfish/Method.cfh
+++ b/runtime/core/Clownfish/Method.cfh
@@ -53,6 +53,12 @@ final class Clownfish::Method inherits Clownfish::Obj {
 
     public void
     Destroy(Method *self);
+
+    /** Return either a specified host alias or a lower-snake-case version of
+      * the method name.
+      */
+    inert incremented String*
+    lower_snake_alias(Method *method);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e9cd9e4/runtime/perl/xs/XSBind.c
----------------------------------------------------------------------
diff --git a/runtime/perl/xs/XSBind.c b/runtime/perl/xs/XSBind.c
index 813afe0..85bd85b 100644
--- a/runtime/perl/xs/XSBind.c
+++ b/runtime/perl/xs/XSBind.c
@@ -710,29 +710,7 @@ cfish_Class_find_parent_class(cfish_String *class_name) {
 
 cfish_String*
 CFISH_Method_Host_Name_IMP(cfish_Method *self) {
-    cfish_String *host_alias = CFISH_Method_Get_Host_Alias(self);
-    if (host_alias) {
-        return (cfish_String*)CFISH_INCREF(host_alias);
-    }
-
-    // Convert to lowercase.
-    cfish_String *name = CFISH_Method_Get_Name(self);
-    cfish_CharBuf *buf = cfish_CB_new(CFISH_Str_Get_Size(name));
-    cfish_StringIterator *iter = CFISH_Str_Top(name);
-    int32_t code_point;
-    while (CFISH_STR_OOB != (code_point = CFISH_StrIter_Next(iter))) {
-        if (code_point > 127) {
-            THROW(CFISH_ERR, "Can't lowercase '%o'", name);
-        }
-        else {
-            CFISH_CB_Cat_Char(buf, tolower(code_point));
-        }
-    }
-    cfish_String *retval = CFISH_CB_Yield_String(buf);
-    CFISH_DECREF(iter);
-    CFISH_DECREF(buf);
-
-    return retval;
+    return cfish_Method_lower_snake_alias(self);
 }
 
 /***************************** Clownfish::Err *******************************/

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e9cd9e4/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 69ab9bd..99ad069 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -938,9 +938,7 @@ cfish_Class_find_parent_class(cfish_String *class_name) {
 
 cfish_String*
 CFISH_Method_Host_Name_IMP(cfish_Method *self) {
-    CFISH_UNUSED_VAR(self);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_String*);
+    return cfish_Method_lower_snake_alias(self);
 }
 
 /**** Err ******************************************************************/


[23/36] lucy-clownfish git commit: Declare C arg vars in Py glue.

Posted by ma...@apache.org.
Declare C arg vars in Py glue.


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

Branch: refs/heads/py_exp13
Commit: f11b123c496486c51d3a402e16636fc6430fe379
Parents: 74878d3
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 22 19:34:59 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:24:52 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f11b123c/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index fcbeee1..dc98fb4 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -67,6 +67,20 @@ S_build_py_args(CFCParamList *param_list) {
     return py_args;
 }
 
+static char*
+S_gen_decs(CFCParamList *param_list, int first_tick) {
+    char *decs = CFCUtil_strdup("");
+    int num_vars = CFCParamList_num_vars(param_list);
+    CFCVariable **vars = CFCParamList_get_variables(param_list);
+    for (int i = first_tick; i < num_vars; i++) {
+        CFCType *type = CFCVariable_get_type(vars[i]);
+        const char *name = CFCVariable_get_name(vars[i]);
+        decs = CFCUtil_cat(decs, "    ", CFCType_to_c(type), " ", name,
+                           "_ARG = 0;\n", NULL);
+    }
+    return decs;
+}
+
 /* Generate the code which parses arguments passed from Python and converts
  * them to Clownfish-flavored C values.
  */
@@ -286,11 +300,13 @@ S_meth_top(CFCMethod *method) {
         if (!arg_parsing) {
             return NULL;
         }
+        char *decs = S_gen_decs(param_list, 1);
         char pattern[] =
             "(PyObject *self, PyObject *args, PyObject *kwargs) {\n"
+            "%s" // decs
             "%s"
             ;
-        char *result = CFCUtil_sprintf(pattern, arg_parsing);
+        char *result = CFCUtil_sprintf(pattern, decs, arg_parsing);
         FREEMEM(arg_parsing);
         return result;
     }


[02/36] lucy-clownfish git commit: Stub out CFCPyClass.

Posted by ma...@apache.org.
Stub out CFCPyClass.

Stub module for generating Python binding for a Clownfish Class.


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

Branch: refs/heads/py_exp13
Commit: 72102abf76bbf6b86af8fd6b261bf4d040524a64
Parents: 4b8d87b
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Jan 28 14:55:45 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:36 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyClass.c | 68 ++++++++++++++++++++++++++++++++++++++++++
 compiler/src/CFCPyClass.h | 40 +++++++++++++++++++++++++
 2 files changed, 108 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/72102abf/compiler/src/CFCPyClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.c b/compiler/src/CFCPyClass.c
new file mode 100644
index 0000000..8eaa702
--- /dev/null
+++ b/compiler/src/CFCPyClass.c
@@ -0,0 +1,68 @@
+/* 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 CFC_NEED_BASE_STRUCT_DEF 1
+
+#include "CFCBase.h"
+#include "CFCPyClass.h"
+#include "CFCPyMethod.h"
+#include "CFCParcel.h"
+#include "CFCUtil.h"
+#include "CFCClass.h"
+#include "CFCFunction.h"
+#include "CFCMethod.h"
+
+struct CFCPyClass {
+    CFCBase base;
+    CFCParcel *parcel;
+    char *class_name;
+    CFCClass *client;
+    char *pre_code;
+    char *meth_defs;
+};
+
+static void
+S_CFCPyClass_destroy(CFCPyClass *self);
+
+static const CFCMeta CFCPERLCLASS_META = {
+    "Clownfish::CFC::Binding::Python::Class",
+    sizeof(CFCPyClass),
+    (CFCBase_destroy_t)S_CFCPyClass_destroy
+};
+
+CFCPyClass*
+CFCPyClass_new(CFCClass *client) {
+    CFCUTIL_NULL_CHECK(client);
+    CFCPyClass *self = (CFCPyClass*)CFCBase_allocate(&CFCPERLCLASS_META);
+    CFCParcel *parcel = CFCClass_get_parcel(client);
+    self->parcel = (CFCParcel*)CFCBase_incref((CFCBase*)parcel);
+    self->class_name = CFCUtil_strdup(CFCClass_get_name(client));
+    self->client = (CFCClass*)CFCBase_incref((CFCBase*)client);
+    self->pre_code = NULL;
+    self->meth_defs = CFCUtil_strdup("");
+    return self;
+}
+
+static void
+S_CFCPyClass_destroy(CFCPyClass *self) {
+    CFCBase_decref((CFCBase*)self->parcel);
+    CFCBase_decref((CFCBase*)self->client);
+    FREEMEM(self->class_name);
+    FREEMEM(self->pre_code);
+    FREEMEM(self->meth_defs);
+    CFCBase_destroy((CFCBase*)self);
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/72102abf/compiler/src/CFCPyClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.h b/compiler/src/CFCPyClass.h
new file mode 100644
index 0000000..4803833
--- /dev/null
+++ b/compiler/src/CFCPyClass.h
@@ -0,0 +1,40 @@
+/* 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_CFCPYCLASS
+#define H_CFCPYCLASS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct CFCPyClass CFCPyClass;
+struct CFCParcel;
+struct CFCClass;
+
+/** Clownfish::CFC::Binding::Python::Class - Generate Python binding code for a
+ * Clownfish::CFC::Model::Class.
+ */
+
+CFCPyClass*
+CFCPyClass_new(struct CFCClass *client);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_CFCPYCLASS */
+


[08/36] lucy-clownfish git commit: Add registry for CFCPyClass.

Posted by ma...@apache.org.
Add registry for CFCPyClass.

Register CFCPyClass singletons in a crude map.  Also prepare to generate
per-class glue 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/f0048b30
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/f0048b30
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/f0048b30

Branch: refs/heads/py_exp13
Commit: f0048b30e37a52cc7257e6500306b2c00970ec57
Parents: 72102ab
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Jan 28 18:10:01 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyClass.c | 70 ++++++++++++++++++++++++++++++++++++++++++
 compiler/src/CFCPyClass.h | 24 +++++++++++++++
 compiler/src/CFCPython.c  | 32 ++++++++++++++++++-
 3 files changed, 125 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f0048b30/compiler/src/CFCPyClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.c b/compiler/src/CFCPyClass.c
index 8eaa702..e79c2d4 100644
--- a/compiler/src/CFCPyClass.c
+++ b/compiler/src/CFCPyClass.c
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <string.h>
+#include <stdlib.h>
+
 #define CFC_NEED_BASE_STRUCT_DEF 1
 
 #include "CFCBase.h"
@@ -34,6 +37,10 @@ struct CFCPyClass {
     char *meth_defs;
 };
 
+static CFCPyClass **registry = NULL;
+static size_t registry_size = 0;
+static size_t registry_cap  = 0;
+
 static void
 S_CFCPyClass_destroy(CFCPyClass *self);
 
@@ -66,3 +73,66 @@ S_CFCPyClass_destroy(CFCPyClass *self) {
     CFCBase_destroy((CFCBase*)self);
 }
 
+static int
+S_compare_cfcperlclass(const void *va, const void *vb) {
+    CFCPyClass *a = *(CFCPyClass**)va;
+    CFCPyClass *b = *(CFCPyClass**)vb;
+    return strcmp(a->class_name, b->class_name);
+}
+
+void
+CFCPyClass_add_to_registry(CFCPyClass *self) {
+    if (registry_size == registry_cap) {
+        size_t new_cap = registry_cap + 10;
+        registry = (CFCPyClass**)REALLOCATE(registry,
+                                            (new_cap + 1) * sizeof(CFCPyClass*));
+        for (size_t i = registry_cap; i <= new_cap; i++) {
+            registry[i] = NULL;
+        }
+        registry_cap = new_cap;
+    }
+    CFCPyClass *existing = CFCPyClass_singleton(self->class_name);
+    if (existing) {
+        CFCUtil_die("Class '%s' already registered", self->class_name);
+    }
+    registry[registry_size] = (CFCPyClass*)CFCBase_incref((CFCBase*)self);
+    registry_size++;
+    qsort(registry, registry_size, sizeof(CFCPyClass*),
+          S_compare_cfcperlclass);
+}
+
+CFCPyClass*
+CFCPyClass_singleton(const char *class_name) {
+    CFCUTIL_NULL_CHECK(class_name);
+    for (size_t i = 0; i < registry_size; i++) {
+        CFCPyClass *existing = registry[i];
+        if (strcmp(class_name, existing->class_name) == 0) {
+            return existing;
+        }
+    }
+    return NULL;
+}
+
+CFCPyClass**
+CFCPyClass_registry() {
+    if (!registry) {
+        registry = (CFCPyClass**)CALLOCATE(1, sizeof(CFCPyClass*));
+    }
+    return registry;
+}
+
+void
+CFCPyClass_clear_registry(void) {
+    for (size_t i = 0; i < registry_size; i++) {
+        CFCBase_decref((CFCBase*)registry[i]);
+    }
+    FREEMEM(registry);
+    registry_size = 0;
+    registry_cap  = 0;
+    registry      = NULL;
+}
+
+char*
+CFCPyClass_gen_binding_code(CFCPyClass *self) {
+    return CFCUtil_strdup("");
+}

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f0048b30/compiler/src/CFCPyClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.h b/compiler/src/CFCPyClass.h
index 4803833..b905502 100644
--- a/compiler/src/CFCPyClass.h
+++ b/compiler/src/CFCPyClass.h
@@ -32,6 +32,30 @@ struct CFCClass;
 CFCPyClass*
 CFCPyClass_new(struct CFCClass *client);
 
+/** Add a new class binding to the registry.  Each unique parcel/class-name
+  * combination may only be registered once.
+  */
+void
+CFCPyClass_add_to_registry(CFCPyClass *self);
+
+/** Given a class name, return a class binding if one exists.
+  */
+CFCPyClass*
+CFCPyClass_singleton(const char *class_name);
+
+/** All registered class bindings.
+  */
+CFCPyClass**
+CFCPyClass_registry();
+
+/** Release all memory and references held by the registry.
+  */
+void
+CFCPyClass_clear_registry(void);
+
+char*
+CFCPyClass_gen_binding_code(CFCPyClass *self);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f0048b30/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index e17feeb..c7ae4c2 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -24,6 +24,7 @@
 #define CFC_NEED_BASE_STRUCT_DEF
 #include "CFCBase.h"
 #include "CFCPython.h"
+#include "CFCPyClass.h"
 #include "CFCPyMethod.h"
 #include "CFCParcel.h"
 #include "CFCClass.h"
@@ -361,6 +362,30 @@ S_gen_callbacks(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
     return content;
 }
 
+static char*
+S_gen_class_bindings(CFCPython *self, CFCParcel *parcel,
+                     const char *pymod_name, CFCClass **ordered) {
+    char *bindings = CFCUtil_strdup("");
+    for (size_t i = 0; ordered[i] != NULL; i++) {
+        CFCClass *klass = ordered[i];
+        if (CFCClass_included(klass)) {
+            continue;
+        }
+        const char *class_name = CFCClass_get_name(klass);
+        CFCPyClass *class_binding = CFCPyClass_singleton(class_name);
+        if (!class_binding) {
+            // No binding spec'd out, so create one using defaults.
+            class_binding = CFCPyClass_new(klass);
+            CFCPyClass_add_to_registry(class_binding);
+        }
+
+        char *code = CFCPyClass_gen_binding_code(class_binding);
+        bindings = CFCUtil_cat(bindings, code, NULL);
+        FREEMEM(code);
+    }
+    return bindings;
+}
+
 static void
 S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     const char *parcel_name = CFCParcel_get_name(parcel);
@@ -382,6 +407,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     CFCParcel **parcels = CFCParcel_all_parcels();
     char *callbacks          = S_gen_callbacks(self, parcel, ordered);
     char *pound_includes     = CFCUtil_strdup("");
+    char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
@@ -410,6 +436,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "    NULL, NULL, NULL, NULL, NULL\n"
         "};\n"
         "\n"
+        "%s" // class bindings
+        "\n"
         "PyMODINIT_FUNC\n"
         "PyInit__%s(void) {\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
@@ -421,7 +449,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
 
     char *content
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
-                          helper_mod_name, last_component, self->footer);
+                          helper_mod_name, class_bindings, last_component,
+                          self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -429,6 +458,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     FREEMEM(filepath);
 
     FREEMEM(content);
+    FREEMEM(class_bindings);
     FREEMEM(helper_mod_name);
     FREEMEM(pymod_name);
     FREEMEM(pound_includes);


[17/36] lucy-clownfish git commit: Gen list of converter/arg-pointer pairs.

Posted by ma...@apache.org.
Gen list of converter/arg-pointer pairs.

Generate the list of function-pointer/arg-pointer pairs passed which get
passed to `PyArg_ParseTupleAndKeywords`.


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

Branch: refs/heads/py_exp13
Commit: ba87d53627914d6815122d59e9b0ae5afbcf9e23
Parents: 1853cbf
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 13:42:27 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:24:52 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 51 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ba87d536/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 48ef443..c0363a5 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -133,6 +133,53 @@ S_gen_declaration(CFCVariable *var, const char *val) {
     return result;
 }
 
+static char*
+S_gen_target(CFCVariable *var, const char *value) {
+    CFCType *type = CFCVariable_get_type(var);
+    const char *specifier = CFCType_get_specifier(type);
+    const char *micro_sym = CFCVariable_get_name(var);
+    const char *maybe_maybe = "";
+    const char *dest_name;
+    char *var_name = NULL;
+    if (CFCType_is_primitive(type)) {
+        dest_name = CFCType_get_specifier(type);
+        if (value != NULL) {
+            maybe_maybe = "maybe_";
+        }
+        var_name = CFCUtil_sprintf("%s_ARG", CFCVariable_get_name(var));
+    }
+    else if (CFCType_is_object(type)) {
+        if (CFCType_nullable(type) ||
+            (value && strcmp(value, "NULL") == 0)
+           ) {
+            maybe_maybe = "maybe_";
+        }
+        if (strcmp(specifier, "cfish_String") == 0) {
+            dest_name = "string";
+            var_name = CFCUtil_sprintf("%s_ARG", CFCVariable_get_name(var));
+        }
+        else if (strcmp(specifier, "cfish_Hash") == 0) {
+            dest_name = "hash";
+            var_name = CFCUtil_sprintf("%s_ARG", CFCVariable_get_name(var));
+        }
+        else if (strcmp(specifier, "cfish_Vector") == 0) {
+            dest_name = "vec";
+            var_name = CFCUtil_sprintf("%s_ARG", CFCVariable_get_name(var));
+        }
+        else {
+            dest_name = "obj";
+            var_name = CFCUtil_sprintf("wrap_arg_%s", micro_sym);
+        }
+    }
+    else {
+        dest_name = "INVALID";
+    }
+    char *content = CFCUtil_sprintf(", CFBind_%sconvert_%s, &%s",
+                                    maybe_maybe, dest_name, var_name);
+    FREEMEM(var_name);
+    return content;
+}
+
 /* Generate the code which parses arguments passed from Python and converts
  * them to Clownfish-flavored C values.
  */
@@ -169,6 +216,10 @@ S_gen_arg_parsing(CFCParamList *param_list, int first_tick, char **error) {
         char *declaration = S_gen_declaration(var, val);
         declarations = CFCUtil_cat(declarations, declaration, NULL);
         FREEMEM(declaration);
+
+        char *target = S_gen_target(var, val);
+        targets = CFCUtil_cat(targets, target, NULL);
+        FREEMEM(target);
     }
 
     char parse_pattern[] =


[22/36] lucy-clownfish git commit: Detect required arg after optional.

Posted by ma...@apache.org.
Detect required arg after optional.

For now, Clownfish allows required arguments to appear after optional
arguments in a parameter list.  Python does not, so we need to detect
that error case.

Eventually, we'll either fix Clownfish to take on Python's restriction,
or else force the user to create manual glue for problematic methods.


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

Branch: refs/heads/py_exp13
Commit: 74878d3ce0be405b575552dfb25caa6a00e46ba9
Parents: 15602e6
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 11:09:57 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:24:52 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/74878d3c/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index c89d12c..fcbeee1 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -71,7 +71,7 @@ S_build_py_args(CFCParamList *param_list) {
  * them to Clownfish-flavored C values.
  */
 static char*
-S_gen_arg_parsing(CFCParamList *param_list) {
+S_gen_arg_parsing(CFCParamList *param_list, int first_tick, char **error) {
     char *content = NULL;
 
     CFCVariable **vars = CFCParamList_get_variables(param_list);
@@ -84,6 +84,21 @@ S_gen_arg_parsing(CFCParamList *param_list) {
     char *targets      = CFCUtil_strdup("");
     int optional_started = 0;
 
+    for (int i = first_tick; i < num_vars; i++) {
+        const char  *val  = vals[i];
+        if (val == NULL) {
+            if (optional_started) { // problem!
+                *error = "Required after optional param";
+                goto CLEAN_UP_AND_RETURN;
+            }
+        }
+        else {
+            if (!optional_started) {
+                optional_started = 1;
+            }
+        }
+    }
+
     char parse_pattern[] =
         "%s"
         "    char *keywords[] = {%sNULL};\n"
@@ -95,6 +110,7 @@ S_gen_arg_parsing(CFCParamList *param_list) {
     content = CFCUtil_sprintf(parse_pattern, declarations, keywords,
                               format_str, targets);
 
+CLEAN_UP_AND_RETURN:
     FREEMEM(declarations);
     FREEMEM(keywords);
     FREEMEM(format_str);
@@ -262,7 +278,14 @@ S_meth_top(CFCMethod *method) {
         return CFCUtil_sprintf(pattern);
     }
     else {
-        char *arg_parsing = S_gen_arg_parsing(param_list);
+        char *error = NULL;
+        char *arg_parsing = S_gen_arg_parsing(param_list, 1, &error);
+        if (error) {
+            CFCUtil_die("%s in %s", error, CFCMethod_get_name(method));
+        }
+        if (!arg_parsing) {
+            return NULL;
+        }
         char pattern[] =
             "(PyObject *self, PyObject *args, PyObject *kwargs) {\n"
             "%s"


[06/36] lucy-clownfish git commit: Gen list of Py types.

Posted by ma...@apache.org.
Gen list of Py types.

Generate a function which creates two arrays: one of Clownfish Class
objects, and one of their corresponding Python type objects.


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

Branch: refs/heads/py_exp13
Commit: def49238ff3a86cda15baee6cca567d552770be1
Parents: cd5438b
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 14:12:13 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c | 57 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 55 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/def49238/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index c7ae4c2..de19a9c 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -363,6 +363,54 @@ S_gen_callbacks(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
 }
 
 static char*
+S_gen_type_linkups(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
+    char *handles  = CFCUtil_strdup("");
+    char *py_types = CFCUtil_strdup("");
+    int num_items = 0;
+
+    for (size_t i = 0; ordered[i] != NULL; i++) {
+        CFCClass *klass = ordered[i];
+        if (CFCClass_included(klass) || CFCClass_inert(klass)) {
+            continue;
+        }
+        const char *class_var = CFCClass_full_class_var(klass);
+        const char *struct_sym = CFCClass_get_struct_sym(klass);
+        char *handles_temp
+            = CFCUtil_sprintf("%s    handles[%d]  = &%s;\n",
+                              handles, num_items, class_var);
+        char *py_types_temp
+            = CFCUtil_sprintf("%s    py_types[%d] = &%s_pytype_struct;\n",
+                              py_types, num_items, struct_sym);
+        FREEMEM(handles);
+        FREEMEM(py_types);
+        handles  = handles_temp;
+        py_types = py_types_temp;
+        num_items++;
+    }
+
+    char pattern[] =
+        "static void\n"
+        "S_link_py_types(void) {\n"
+        "    const int num_items = %d;\n"
+        "    size_t handles_size  = num_items * sizeof(cfish_Class**);\n"
+        "    size_t py_types_size = num_items * sizeof(PyTypeObject*);\n"
+        "    cfish_Class ***handles  = (cfish_Class***)CFISH_MALLOCATE(handles_size);\n"
+        "    PyTypeObject **py_types = (PyTypeObject**)CFISH_MALLOCATE(py_types_size);\n"
+        "%s\n"
+        "%s\n"
+        "    //CFBind_assoc_py_types(handles, py_types, num_items);\n"
+        "    CFISH_FREEMEM(handles);\n"
+        "    CFISH_FREEMEM(py_types);\n"
+        "}\n"
+        ;
+    char *content = CFCUtil_sprintf(pattern, num_items, handles, py_types);
+
+    FREEMEM(handles);
+    FREEMEM(py_types);
+    return content;
+}
+
+static char*
 S_gen_class_bindings(CFCPython *self, CFCParcel *parcel,
                      const char *pymod_name, CFCClass **ordered) {
     char *bindings = CFCUtil_strdup("");
@@ -406,6 +454,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     CFCClass  **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
     CFCParcel **parcels = CFCParcel_all_parcels();
     char *callbacks          = S_gen_callbacks(self, parcel, ordered);
+    char *type_linkups       = S_gen_type_linkups(self, parcel, ordered);
     char *pound_includes     = CFCUtil_strdup("");
     char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
 
@@ -438,8 +487,11 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "\n"
         "%s" // class bindings
         "\n"
+        "%s" // S_link_py_types function
+        "\n"
         "PyMODINIT_FUNC\n"
         "PyInit__%s(void) {\n"
+        "    S_link_py_types();\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
         "    return module;\n"
         "}\n"
@@ -449,8 +501,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
 
     char *content
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
-                          helper_mod_name, class_bindings, last_component,
-                          self->footer);
+                          helper_mod_name, class_bindings, type_linkups,
+                          last_component, self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -462,6 +514,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     FREEMEM(helper_mod_name);
     FREEMEM(pymod_name);
     FREEMEM(pound_includes);
+    FREEMEM(type_linkups);
     FREEMEM(callbacks);
     FREEMEM(ordered);
 }


[03/36] lucy-clownfish git commit: Given a Class, find its PyTypeObject.

Posted by ma...@apache.org.
Given a Class, find its PyTypeObject.

Cache the PyTypeObject inside the Clownfish Class object, in a
`host_type` member.


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

Branch: refs/heads/py_exp13
Commit: 2b37cc17c94eabbb27efeb090fd5827eac74807a
Parents: d7133b8
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 14:47:34 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 runtime/core/Clownfish/Class.cfh |  1 +
 runtime/python/cfext/CFBind.c    | 43 +++++++++++++++++++++++++++++------
 2 files changed, 37 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b37cc17/runtime/core/Clownfish/Class.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh
index dbb31cb..c87964f 100644
--- a/runtime/core/Clownfish/Class.cfh
+++ b/runtime/core/Clownfish/Class.cfh
@@ -32,6 +32,7 @@ public final class Clownfish::Class inherits Clownfish::Obj {
     int32_t             parcel_id;
     uint32_t            obj_alloc_size;
     uint32_t            class_alloc_size;
+    void               *host_type;
     Method            **methods;
     cfish_method_t[1]   vtable; /* flexible array */
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b37cc17/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 2f8d657..f73b76a 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -50,10 +50,8 @@ S_get_cached_py_type(cfish_Class *klass);
 
 static bool
 S_py_obj_is_a(PyObject *py_obj, cfish_Class *klass) {
-    CFISH_UNUSED_VAR(py_obj);
-    CFISH_UNUSED_VAR(klass);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(bool);
+    PyTypeObject *py_type = S_get_cached_py_type(klass);
+    return !!PyObject_TypeCheck(py_obj, py_type);
 }
 
 void
@@ -859,11 +857,42 @@ CFISH_Obj_To_Host_IMP(cfish_Obj *self) {
 
 /**** Class ****************************************************************/
 
+/* Check the Class object for its associated PyTypeObject, which is stored in
+ * `klass->host_type`.  If it is not there yet, search the class mapping and
+ * cache it in the object.  Return the PyTypeObject.
+ */
 static PyTypeObject*
 S_get_cached_py_type(cfish_Class *self) {
-    // FIXME: dummy implementation
-    CFISH_UNUSED_VAR(self);
-    return NULL;
+    PyTypeObject *py_type = (PyTypeObject*)self->host_type;
+    if (py_type == NULL) {
+        ClassMap *current = klass_map;
+        for (int32_t i = 0; i < current->size; i++) {
+            cfish_Class **handle = current->elems[i].klass_handle;
+            if (handle == NULL || *handle != self) {
+                continue;
+            }
+            py_type = current->elems[i].py_type;
+            Py_INCREF(py_type);
+            if (!cfish_Atomic_cas_ptr((void*volatile*)&self->host_type, py_type, NULL)) {
+                // Lost the race to another thread, so get rid of the refcount.
+                Py_DECREF(py_type);
+            }
+            break;
+        }
+    }
+    if (py_type == NULL) {
+        if (Err_initialized) {
+            CFISH_THROW(CFISH_ERR,
+                        "Can't find a Python type object corresponding to %o",
+                        CFISH_Class_Get_Name(self));
+        }
+        else {
+            fprintf(stderr, "Can't find a Python type corresponding to a "
+                            "Clownfish class\n");
+            exit(1);
+        }
+    }
+    return py_type;
 }
 
 cfish_Obj*


[18/36] lucy-clownfish git commit: Build up the ParseTuple format string.

Posted by ma...@apache.org.
Build up the ParseTuple format string.


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

Branch: refs/heads/py_exp13
Commit: 4cdfb56b6ed149cfef354720e7514d1d23bd8769
Parents: ba87d53
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 13:45:03 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:24:52 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 6 ++++++
 1 file changed, 6 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/4cdfb56b/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index c0363a5..8d6adfb 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -201,6 +201,10 @@ S_gen_arg_parsing(CFCParamList *param_list, int first_tick, char **error) {
         CFCVariable *var  = vars[i];
         const char  *val  = vals[i];
 
+        const char *var_name = CFCVariable_get_name(var);
+        keywords = CFCUtil_cat(keywords, "\"", var_name, "\", ", NULL);
+
+        // Build up ParseTuple format string.
         if (val == NULL) {
             if (optional_started) { // problem!
                 *error = "Required after optional param";
@@ -210,8 +214,10 @@ S_gen_arg_parsing(CFCParamList *param_list, int first_tick, char **error) {
         else {
             if (!optional_started) {
                 optional_started = 1;
+                format_str = CFCUtil_cat(format_str, "|", NULL);
             }
         }
+        format_str = CFCUtil_cat(format_str, "O&", NULL);
 
         char *declaration = S_gen_declaration(var, val);
         declarations = CFCUtil_cat(declarations, declaration, NULL);


[19/36] lucy-clownfish git commit: Gen CFBindArg declarations.

Posted by ma...@apache.org.
Gen CFBindArg declarations.

Generate the declarations for the CFBindArg wrapper structs which are
required by some Python argument conversion routines.


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

Branch: refs/heads/py_exp13
Commit: 1853cbfd000430937312142034090de25de8039f
Parents: f11b123
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 13:38:19 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:24:52 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 58 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1853cbfd/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index dc98fb4..48ef443 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -81,6 +81,58 @@ S_gen_decs(CFCParamList *param_list, int first_tick) {
     return decs;
 }
 
+/* Some of the ParseTuple conversion routines provided by the Python-flavored
+ * CFBind module accept a CFBindArg instead of just a pointer to the value
+ * itself.  This routine generates the declarations for those CFBindArg
+ * variables, as well as handling some default values.
+ */
+static char*
+S_gen_declaration(CFCVariable *var, const char *val) {
+    CFCType *type = CFCVariable_get_type(var);
+    const char *var_name = CFCVariable_get_name(var);
+    const char *type_str = CFCType_to_c(type);
+    char *result = NULL;
+
+    if (CFCType_is_object(type)) {
+        const char *specifier = CFCType_get_specifier(type);
+        if (strcmp(specifier, "cfish_String") == 0) {
+            if (val && strcmp(val, "NULL") != 0) {
+                const char pattern[] =
+                    "    const char arg_%s_DEFAULT[] = %s;\n"
+                    "    %s_ARG = CFISH_SSTR_WRAP_UTF8(\n"
+                    "        arg_%s_DEFAULT, sizeof(arg_%s_DEFAULT) - 1);\n"
+                    ;
+                result = CFCUtil_sprintf(pattern, var_name, val, var_name,
+                                         var_name, var_name);
+            }
+        }
+        else {
+            if (val && strcmp(val, "NULL") != 0) {
+                CFCUtil_die("Can't assign a default of '%s' to a %s",
+                            val, type_str);
+            }
+            if (strcmp(specifier, "cfish_Hash") != 0
+                && strcmp(specifier, "cfish_Vector") != 0
+                ) {
+                const char *class_var = CFCType_get_class_var(type);
+                char pattern[] =
+                    "    CFBindArg wrap_arg_%s = {%s, &%s_ARG};\n"
+                    ;
+                result = CFCUtil_sprintf(pattern, var_name, class_var,
+                                         var_name);
+            }
+        }
+    }
+    else if (CFCType_is_primitive(type)) {
+        ;
+    }
+    else {
+        CFCUtil_die("Unexpected type, can't gen declaration: %s", type_str);
+    }
+
+    return result;
+}
+
 /* Generate the code which parses arguments passed from Python and converts
  * them to Clownfish-flavored C values.
  */
@@ -99,7 +151,9 @@ S_gen_arg_parsing(CFCParamList *param_list, int first_tick, char **error) {
     int optional_started = 0;
 
     for (int i = first_tick; i < num_vars; i++) {
+        CFCVariable *var  = vars[i];
         const char  *val  = vals[i];
+
         if (val == NULL) {
             if (optional_started) { // problem!
                 *error = "Required after optional param";
@@ -111,6 +165,10 @@ S_gen_arg_parsing(CFCParamList *param_list, int first_tick, char **error) {
                 optional_started = 1;
             }
         }
+
+        char *declaration = S_gen_declaration(var, val);
+        declarations = CFCUtil_cat(declarations, declaration, NULL);
+        FREEMEM(declaration);
     }
 
     char parse_pattern[] =


[04/36] lucy-clownfish git commit: Create mapping from Py type to CF Class.

Posted by ma...@apache.org.
Create mapping from Py type to CF Class.

Before initializing Clownfish Class objects, create a mapping which
mates the addresses of Clownfish Class objects to their corresponding
PyTypeObjects.


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

Branch: refs/heads/py_exp13
Commit: d7133b8d149e2090331b767c1f54d5bf118d1a43
Parents: def4923
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 14:37:58 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c      |  2 +-
 runtime/python/cfext/CFBind.c | 63 ++++++++++++++++++++++++++++++++++++++
 runtime/python/cfext/CFBind.h |  7 +++++
 3 files changed, 71 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d7133b8d/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index de19a9c..15f835f 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -398,7 +398,7 @@ S_gen_type_linkups(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
         "    PyTypeObject **py_types = (PyTypeObject**)CFISH_MALLOCATE(py_types_size);\n"
         "%s\n"
         "%s\n"
-        "    //CFBind_assoc_py_types(handles, py_types, num_items);\n"
+        "    CFBind_assoc_py_types(handles, py_types, num_items);\n"
         "    CFISH_FREEMEM(handles);\n"
         "    CFISH_FREEMEM(py_types);\n"
         "}\n"

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d7133b8d/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 48743a7..2f8d657 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -36,6 +36,7 @@
 #include "Clownfish/Num.h"
 #include "Clownfish/String.h"
 #include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Util/Atomic.h"
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/Util/StringHelper.h"
 #include "Clownfish/Vector.h"
@@ -767,6 +768,68 @@ CFBind_maybe_convert_bool(PyObject *py_obj, bool *ptr) {
     return S_convert_bool(py_obj, ptr, true);
 }
 
+typedef struct ClassMapElem {
+    cfish_Class **klass_handle;
+    PyTypeObject *py_type;
+} ClassMapElem;
+
+typedef struct ClassMap {
+    int32_t size;
+    ClassMapElem *elems;
+} ClassMap;
+
+/* Before we can invoke methods on any Clownfish object safely, we must know
+ * about its corresponding Python type object.  This association must be made
+ * early in the bootstrapping process, which is tricky.  We can't use any
+ * of Clownfish's convenient data structures yet!
+ */
+static ClassMap *klass_map = NULL;
+
+static ClassMap*
+S_revise_class_map(ClassMap *current, cfish_Class ***klass_handles,
+                   PyTypeObject **py_types, int32_t num_items) {
+    int32_t num_current = current ? current->size : 0;
+    int32_t total = num_current + num_items;
+    ClassMap *revised = (ClassMap*)malloc(sizeof(ClassMap));
+    revised->elems = (ClassMapElem*)malloc(total * sizeof(ClassMapElem));
+    if (current) {
+        size_t size = num_current * sizeof(ClassMapElem);
+        memcpy(revised->elems, current->elems, size);
+    }
+    for (int32_t i = 0; i < num_items; i++) {
+        revised->elems[i + num_current].klass_handle = klass_handles[i];
+        revised->elems[i + num_current].py_type      = py_types[i];
+    }
+    revised->size = total;
+    return revised;
+}
+
+void
+CFBind_assoc_py_types(cfish_Class ***klass_handles, PyTypeObject **py_types,
+                      int32_t num_items) {
+    while (1) {
+        ClassMap *current = klass_map;
+        ClassMap *revised = S_revise_class_map(current, klass_handles,
+                                               py_types, num_items);
+        if (cfish_Atomic_cas_ptr((void*volatile*)&klass_map, current, revised)) {
+            if (current) {
+                // TODO: Use read locking.  For now we have to leak this
+                // memory to avoid memory errors in case another thread isn't
+                // done reading it yet.
+
+                //free(current->elems);
+                //free(current);
+            }
+            break;
+        }
+        else {
+            // Another thread beat us to it.  Try again.
+            free(revised->elems);
+            free(revised);
+        }
+    }
+}
+
 /**** refcounting **********************************************************/
 
 uint32_t

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d7133b8d/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index 9279510..0064985 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -112,6 +112,13 @@ cfish_Obj*
 CFBind_py_to_cfish_noinc(PyObject *py_obj, cfish_Class *klass,
                          void *allocation);
 
+/** Associate Clownfish classes with Python type objects.  (Internal-only,
+  * used during bootstrapping.)
+  */
+void
+CFBind_assoc_py_types(struct cfish_Class ***klass_handles,
+                      PyTypeObject **py_types, int32_t num_items);
+
 typedef struct CFBindArg {
     cfish_Class *klass;
     void        *ptr;


[09/36] lucy-clownfish git commit: Add classes to Python module object.

Posted by ma...@apache.org.
Add classes to Python module object.

For instance, make `clownfish.String` available on the Python
`clownfish` module object.


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

Branch: refs/heads/py_exp13
Commit: 49972c1cbc6b6f9ae4ad55c6d26b69e491e63741
Parents: 67b7630
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 17:13:37 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c              | 10 +++++++++-
 runtime/python/test/test_clownfish.py |  2 ++
 2 files changed, 11 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/49972c1c/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 068c9c4..d108b69 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -459,6 +459,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
     char *parcel_boots       = CFCUtil_strdup("");
     char *pytype_ready_calls = CFCUtil_strdup("");
+    char *module_adds        = CFCUtil_strdup("");
 
     // Add parcel bootstrapping calls.
     for (size_t i = 0; parcels[i]; ++i) {
@@ -487,6 +488,10 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
                 "    if (PyType_Ready(&", struct_sym,
                 "_pytype_struct) < 0) { return NULL; }\n", NULL);
         }
+
+        module_adds = CFCUtil_cat(module_adds, "    PyModule_AddObject(module, \"",
+                                  struct_sym, "\", (PyObject*)&", struct_sym,
+                                  "_pytype_struct);\n", NULL);
     }
 
     const char pattern[] =
@@ -522,6 +527,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "%s\n" // parcel boots
         "\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
+        "%s\n" // Add types to module
+        "\n"
         "    return module;\n"
         "}\n"
         "\n"
@@ -532,7 +539,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
                           helper_mod_name, class_bindings, type_linkups,
                           last_component, pytype_ready_calls, parcel_boots,
-                          self->footer);
+                          module_adds, self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -540,6 +547,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     FREEMEM(filepath);
 
     FREEMEM(content);
+    FREEMEM(module_adds);
     FREEMEM(pytype_ready_calls);
     FREEMEM(parcel_boots);
     FREEMEM(class_bindings);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/49972c1c/runtime/python/test/test_clownfish.py
----------------------------------------------------------------------
diff --git a/runtime/python/test/test_clownfish.py b/runtime/python/test/test_clownfish.py
index fd124d3..d8f2594 100644
--- a/runtime/python/test/test_clownfish.py
+++ b/runtime/python/test/test_clownfish.py
@@ -21,6 +21,8 @@ class MyTest(unittest.TestCase):
     def testTrue(self):
         self.assertTrue(True, "True should be true")
 
+    def testClassesPresent(self):
+        self.assertIsInstance(clownfish.Hash, type)
 
 if __name__ == '__main__':
     unittest.main()


[27/36] lucy-clownfish git commit: Handle default values for primitive types.

Posted by ma...@apache.org.
Handle default values for primitive types.

Set conversion args to default values prior to Python argument parsing.


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

Branch: refs/heads/py_exp13
Commit: 73635f233dc3a5b1addf17aacdf5773d8fad1113
Parents: 2e4d3d3
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Fri Feb 5 18:03:01 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:36:07 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/73635f23/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index ef8b152..d8128c2 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -124,7 +124,10 @@ S_gen_declaration(CFCVariable *var, const char *val) {
         }
     }
     else if (CFCType_is_primitive(type)) {
-        ;
+        if (val) {
+            char pattern[] = "    %s_ARG = %s;\n";
+            result = CFCUtil_sprintf(pattern, var_name, val);
+        }
     }
     else {
         CFCUtil_die("Unexpected type, can't gen declaration: %s", type_str);


[13/36] lucy-clownfish git commit: Implement Make_Obj and Init_Obj for Python.

Posted by ma...@apache.org.
Implement Make_Obj and Init_Obj for Python.


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

Branch: refs/heads/py_exp13
Commit: 50c98b1faeb6f8966b769ac7dbff811e3808bc1e
Parents: c6c74d2
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 16:47:41 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 runtime/python/cfext/CFBind.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/50c98b1f/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 2471487..a1e47eb 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -930,17 +930,28 @@ S_get_cached_py_type(cfish_Class *self) {
 
 cfish_Obj*
 CFISH_Class_Make_Obj_IMP(cfish_Class *self) {
-    CFISH_UNUSED_VAR(self);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_Obj*);
+    PyTypeObject *py_type = S_get_cached_py_type(self);
+    cfish_Obj *obj = (cfish_Obj*)py_type->tp_alloc(py_type, 0);
+    obj->klass = self;
+    return obj;
 }
 
 cfish_Obj*
 CFISH_Class_Init_Obj_IMP(cfish_Class *self, void *allocation) {
-    CFISH_UNUSED_VAR(self);
-    CFISH_UNUSED_VAR(allocation);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_Obj*);
+    PyTypeObject *py_type = S_get_cached_py_type(self);
+    // It would be nice if we could call PyObject_Init() here and feel
+    // confident that we have performed all Python-specific initialization
+    // under all possible configurations, but that's not possible.  In
+    // addition to setting ob_refcnt and ob_type, PyObject_Init() performs
+    // tracking for heap allocated objects under special builds -- but
+    // Class_Init_Obj() may be called on non-heap memory, such as
+    // stack-allocated Clownfish Strings.  Therefore, we must perform a subset
+    // of tasks selected from PyObject_Init() manually.
+    cfish_Obj *obj = (cfish_Obj*)allocation;
+    obj->ob_base.ob_refcnt = 1;
+    obj->ob_base.ob_type = py_type;
+    obj->klass = self;
+    return obj;
 }
 
 void


[28/36] lucy-clownfish git commit: More liberal Py to Cfish Obj conversion.

Posted by ma...@apache.org.
More liberal Py to Cfish Obj conversion.

When converting a Python argument to Clownfish `Obj*`, allow conversion
from Python dict, list, string, integer, and other types -- instead of
just checking to confirm that the argument is already a Clownfish Obj.


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

Branch: refs/heads/py_exp13
Commit: b05965cafb60362badf530872dc81a304b9db761
Parents: 73635f2
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Sat Feb 6 09:41:59 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:36:07 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c    | 3 ++-
 runtime/python/cfext/CFBind.c | 7 ++++---
 2 files changed, 6 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b05965ca/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index d8128c2..ea97d6a 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -464,7 +464,8 @@ S_gen_decrefs(CFCParamList *param_list, int first_tick) {
         const char *micro_sym = CFCVariable_get_name(var);
         const char *specifier = CFCType_get_specifier(type);
 
-        if (strcmp(specifier, "cfish_String") == 0
+        if (strcmp(specifier, "cfish_Obj") == 0
+             || strcmp(specifier, "cfish_String") == 0
              || strcmp(specifier, "cfish_Vector") == 0
              || strcmp(specifier, "cfish_Hash") == 0
             ) {

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b05965ca/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index a1e47eb..cd77078 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -294,12 +294,13 @@ S_convert_obj(PyObject *py_obj, CFBindArg *arg, bool nullable) {
             return 0;
         }
     }
-    PyTypeObject *py_type = S_get_cached_py_type(arg->klass);
-    if (!PyObject_TypeCheck(py_obj, py_type)) {
+
+    bool success = S_maybe_py_to_cfish(py_obj, arg->klass, true, nullable,
+                                       NULL, arg->ptr);
+    if (!success) {
         PyErr_SetString(PyExc_TypeError, "Invalid argument type");
         return 0;
     }
-    *((PyObject**)arg->ptr) = py_obj;
     return 1;
 }
 


[15/36] lucy-clownfish git commit: Gen stub Py method wrappers.

Posted by ma...@apache.org.
Gen stub Py method wrappers.


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

Branch: refs/heads/py_exp13
Commit: cb25fd0bd79dfcd8097db6bf8c0319cb44a07531
Parents: a158003
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 19:13:00 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:39 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyClass.c  | 17 +++++++++++++++++
 compiler/src/CFCPyMethod.c | 18 ++++++++++++++++++
 compiler/src/CFCPyMethod.h |  3 +++
 3 files changed, 38 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cb25fd0b/compiler/src/CFCPyClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.c b/compiler/src/CFCPyClass.c
index 9f46b60..11a4905 100644
--- a/compiler/src/CFCPyClass.c
+++ b/compiler/src/CFCPyClass.c
@@ -145,6 +145,23 @@ CFCPyClass_gen_binding_code(CFCPyClass *self) {
     char *bindings  = CFCUtil_strdup(self->pre_code ? self->pre_code : "");
     char *meth_defs = CFCUtil_strdup(self->meth_defs);
 
+    // Instance methods.
+    CFCMethod **methods = CFCClass_fresh_methods(klass);
+    for (size_t j = 0; methods[j] != NULL; j++) {
+        CFCMethod *meth = methods[j];
+
+        if (CFCMethod_excluded_from_host(meth)
+            || !CFCMethod_can_be_bound(meth)
+           ) {
+            continue;
+        }
+
+        // Add the function wrapper.
+        char *wrapper = CFCPyMethod_wrapper(meth, klass);
+        bindings = CFCUtil_cat(bindings, wrapper, "\n", NULL);
+        FREEMEM(wrapper);
+    }
+
     // Complete the PyMethodDef array.
     const char *struct_sym = CFCClass_get_struct_sym(klass);
     char *meth_defs_pattern =

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cb25fd0b/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 983df28..0a5cd27 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -215,3 +215,21 @@ S_maybe_unreachable(CFCType *return_type) {
     return return_statement;
 }
 
+char*
+CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
+    char *meth_sym   = CFCMethod_full_method_sym(method, invoker);
+
+    char pattern[] =
+        "static PyObject*\n"
+        "S_%s(PyObject *unused1, PyObject *unused2) {\n"
+        "    CFISH_UNUSED_VAR(unused1);\n"
+        "    CFISH_UNUSED_VAR(unused2);\n"
+        "    Py_RETURN_NONE;\n"
+        "}\n"
+        ;
+    char *wrapper = CFCUtil_sprintf(pattern, meth_sym);
+    FREEMEM(meth_sym);
+
+    return wrapper;
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cb25fd0b/compiler/src/CFCPyMethod.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.h b/compiler/src/CFCPyMethod.h
index 15fa1e6..53768e2 100644
--- a/compiler/src/CFCPyMethod.h
+++ b/compiler/src/CFCPyMethod.h
@@ -31,6 +31,9 @@ struct CFCClass;
 char*
 CFCPyMethod_callback_def(struct CFCMethod *method, struct CFCClass *invoker);
 
+char*
+CFCPyMethod_wrapper(struct CFCMethod *method, struct CFCClass *invoker);
+
 #ifdef __cplusplus
 }
 #endif


[12/36] lucy-clownfish git commit: Invoke `PyType_Ready` for inert classes.

Posted by ma...@apache.org.
Invoke `PyType_Ready` for inert classes.


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

Branch: refs/heads/py_exp13
Commit: c9cbb2dcfd3e9435134bf89812f8d0dad363ae10
Parents: 50c98b1
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 17:03:13 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c9cbb2dc/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 7921fbe..a2d28df 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -457,14 +457,26 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *type_linkups       = S_gen_type_linkups(self, parcel, ordered);
     char *pound_includes     = CFCUtil_strdup("");
     char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
+    char *pytype_ready_calls = CFCUtil_strdup("");
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
         if (CFCClass_included(klass)) { continue; }
+        const char *struct_sym = CFCClass_get_struct_sym(klass);
 
         const char *include_h  = CFCClass_include_h(klass);
         pound_includes = CFCUtil_cat(pound_includes, "#include \"",
                                      include_h, "\"\n", NULL);
+
+        // The PyType_Ready invocations for instantiable classes are handled
+        // via bootstrapping of Clownfish Class objects.  Since inert classes
+        // do not at present have Class objects, we need to handle their
+        // PyType_Ready calls independently.
+        if (CFCClass_inert(klass)) {
+            pytype_ready_calls = CFCUtil_cat(pytype_ready_calls,
+                "    if (PyType_Ready(&", struct_sym,
+                "_pytype_struct) < 0) { return NULL; }\n", NULL);
+        }
     }
 
     const char pattern[] =
@@ -492,6 +504,9 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "PyMODINIT_FUNC\n"
         "PyInit__%s(void) {\n"
         "    cfish_Class_bootstrap_hook1 = CFBind_class_bootstrap_hook1;\n"
+        "\n"
+        "%s\n" // PyType_Ready calls
+        "\n"
         "    S_link_py_types();\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
         "    return module;\n"
@@ -503,7 +518,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *content
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
                           helper_mod_name, class_bindings, type_linkups,
-                          last_component, self->footer);
+                          last_component, pytype_ready_calls, self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -511,6 +526,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     FREEMEM(filepath);
 
     FREEMEM(content);
+    FREEMEM(pytype_ready_calls);
     FREEMEM(class_bindings);
     FREEMEM(helper_mod_name);
     FREEMEM(pymod_name);


[07/36] lucy-clownfish git commit: Gen PyTypeObject structs and empty method lists.

Posted by ma...@apache.org.
Gen PyTypeObject structs and empty method lists.


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

Branch: refs/heads/py_exp13
Commit: cd5438b7e31dab8fdd00cb4da47529fa7e6b3614
Parents: f0048b3
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Jan 28 18:26:45 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyClass.c | 94 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 93 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cd5438b7/compiler/src/CFCPyClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.c b/compiler/src/CFCPyClass.c
index e79c2d4..9f46b60 100644
--- a/compiler/src/CFCPyClass.c
+++ b/compiler/src/CFCPyClass.c
@@ -15,6 +15,7 @@
  */
 
 #include <string.h>
+#include <ctype.h>
 #include <stdlib.h>
 
 #define CFC_NEED_BASE_STRUCT_DEF 1
@@ -44,6 +45,9 @@ static size_t registry_cap  = 0;
 static void
 S_CFCPyClass_destroy(CFCPyClass *self);
 
+static char*
+S_pytype_struct_def(CFCPyClass *self);
+
 static const CFCMeta CFCPERLCLASS_META = {
     "Clownfish::CFC::Binding::Python::Class",
     sizeof(CFCPyClass),
@@ -134,5 +138,93 @@ CFCPyClass_clear_registry(void) {
 
 char*
 CFCPyClass_gen_binding_code(CFCPyClass *self) {
-    return CFCUtil_strdup("");
+    if (!self->client) {
+        CFCUtil_die("No Clownfish class defined for %s", self->class_name);
+    }
+    CFCClass *klass = self->client;
+    char *bindings  = CFCUtil_strdup(self->pre_code ? self->pre_code : "");
+    char *meth_defs = CFCUtil_strdup(self->meth_defs);
+
+    // Complete the PyMethodDef array.
+    const char *struct_sym = CFCClass_get_struct_sym(klass);
+    char *meth_defs_pattern =
+        "static PyMethodDef %s_pymethods[] = {\n"
+        "%s"
+        "   {NULL}\n"
+        "};\n"
+        ;
+    char *meth_defs_array = CFCUtil_sprintf(meth_defs_pattern, struct_sym,
+                                            meth_defs);
+    bindings = CFCUtil_cat(bindings, meth_defs_array, NULL);
+    FREEMEM(meth_defs_array);
+    FREEMEM(meth_defs);
+
+    // PyTypeObject struct def.
+    char *struct_def = S_pytype_struct_def(self);
+    bindings = CFCUtil_cat(bindings, struct_def, NULL);
+    FREEMEM(struct_def);
+
+    return bindings;
+}
+
+static char*
+S_pytype_struct_def(CFCPyClass *self) {
+    CFCClass *klass = self->client;
+    const char *parcel_name = CFCParcel_get_name(self->parcel);
+    char *pymod_name = CFCUtil_strdup(parcel_name);
+    // TODO: Stop lowercasing when parcels are restricted to lowercase.
+    for (int i = 0; pymod_name[i] != '\0'; i++) {
+        pymod_name[i] = tolower(pymod_name[i]);
+    }
+
+    const char *struct_sym = CFCClass_get_struct_sym(klass);
+
+    char pattern[] =
+        "static PyTypeObject %s_pytype_struct = {\n"
+        "    PyVarObject_HEAD_INIT(NULL, 0)\n"
+        "    \"%s.%s\", // tp_name\n"
+        "    0,                                  // tp_basicsize THIS IS A LIE!\n"
+        "    0,                                  // tp_itemsize\n"
+        "    0,                                  // tp_dealloc\n"
+        "    0,                                  // tp_print\n"
+        "    0,                                  // tp_getattr\n"
+        "    0,                                  // tp_setattr\n"
+        "    0,                                  // tp_reserved\n"
+        "    0,                                  // tp_repr\n"
+        "    0,                                  // tp_as_number\n"
+        "    0,                                  // tp_as_sequence\n"
+        "    0,                                  // tp_as_mapping\n"
+        "    0,                                  // tp_hash\n"
+        "    0,                                  // tp_call\n"
+        "    0,                                  // tp_str\n"
+        "    0,                                  // tp_getattro\n"
+        "    0,                                  // tp_setattro\n"
+        "    0,                                  // tp_as_buffer\n"
+        "    Py_TPFLAGS_DEFAULT,                 // tp_flags\n"
+        "    0,                                  // tp_doc\n"
+        "    0,                                  // tp_traverse\n"
+        "    0,                                  // tp_clear\n"
+        "    0,                                  // tp_richcompare\n"
+        "    0,                                  // tp_weaklistoffset\n"
+        "    0,                                  // tp_iter\n"
+        "    0,                                  // tp_iternext\n"
+        "    %s_pymethods,                       // tp_methods\n"
+        "    0,                                  // tp_members\n"
+        "    0,                                  // tp_getset\n"
+        "    0,                                  // tp_base\n"
+        "    0,                                  // tp_dict\n"
+        "    0,                                  // tp_descr_get\n"
+        "    0,                                  // tp_descr_set\n"
+        "    0,                                  // tp_dictoffset\n"
+        "    0,                                  // tp_init\n"
+        "    0,                                  // tp_allow\n"
+        "    0,                                  // tp_new\n"
+        "};\n"
+        ;
+    char *content = CFCUtil_sprintf(pattern, struct_sym, pymod_name,
+                                    struct_sym, struct_sym);
+
+    FREEMEM(pymod_name);
+    return content;
 }
+


[14/36] lucy-clownfish git commit: Tell Python about obj alloc sizes.

Posted by ma...@apache.org.
Tell Python about obj alloc sizes.

As a consequence of Clownfish using Python object allocation internally
under the Python bindings, bootstrapping Clownfish Classes and Python
type objects requires some intricate interplay.


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

Branch: refs/heads/py_exp13
Commit: c6c74d2718fdac87eb9c2330f75eca93dbaa94da
Parents: 3e9cd9e
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 16:43:49 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c         |  1 +
 runtime/core/Clownfish/Class.c   |  4 ++++
 runtime/core/Clownfish/Class.cfh |  8 ++++++++
 runtime/python/cfext/CFBind.c    | 33 +++++++++++++++++++++++++++++++++
 runtime/python/cfext/CFBind.h    |  3 +++
 5 files changed, 49 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 15f835f..7921fbe 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -491,6 +491,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "\n"
         "PyMODINIT_FUNC\n"
         "PyInit__%s(void) {\n"
+        "    cfish_Class_bootstrap_hook1 = CFBind_class_bootstrap_hook1;\n"
         "    S_link_py_types();\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
         "    return module;\n"

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/core/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c
index ba83928..68258c6 100644
--- a/runtime/core/Clownfish/Class.c
+++ b/runtime/core/Clownfish/Class.c
@@ -54,6 +54,7 @@ static int32_t
 S_claim_parcel_id(void);
 
 static LockFreeRegistry *Class_registry;
+cfish_Class_bootstrap_hook1_t cfish_Class_bootstrap_hook1;
 
 void
 Class_bootstrap(const cfish_ClassSpec *specs, size_t num_specs,
@@ -146,6 +147,9 @@ Class_bootstrap(const cfish_ClassSpec *specs, size_t num_specs,
         else {
             klass->obj_alloc_size = ivars_offset + spec->ivars_size;
         }
+        if (cfish_Class_bootstrap_hook1 != NULL) {
+            cfish_Class_bootstrap_hook1(klass);
+        }
 
         klass->flags = 0;
         if (klass == CLASS

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/core/Clownfish/Class.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh
index c87964f..a5c83ab 100644
--- a/runtime/core/Clownfish/Class.cfh
+++ b/runtime/core/Clownfish/Class.cfh
@@ -149,5 +149,13 @@ __C__
 #define CFISH_ALLOCA_OBJ(class) \
     cfish_alloca(CFISH_Class_Get_Obj_Alloc_Size(class))
 
+/** Bootstrapping hook/hack needed by the Python bindings.
+ *
+ * TODO: Refactor this away in favor of a more general solution.
+ */
+typedef void
+(*cfish_Class_bootstrap_hook1_t)(cfish_Class *self);
+extern cfish_Class_bootstrap_hook1_t cfish_Class_bootstrap_hook1;
+
 __END_C__
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 99ad069..2471487 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -857,6 +857,39 @@ CFISH_Obj_To_Host_IMP(cfish_Obj *self) {
 
 /**** Class ****************************************************************/
 
+/* Tell Python about the size of Clownfish objects, by copying
+ * `cfclass->obj_alloc_size` into `pytype->tp_basicsize`.
+ * **THIS MUST BE RUN BEFORE Class_Make_Obj IS CALLED** because under the
+ * Python bindings, Clownfish uses Python object allocation internally.
+ * Furthermore, `tp_basicsize` is supposed to be set before `PyType_Ready()`
+ * is called.
+ *
+ * Ideally we would set `tp_basicsize` from within `Class_register_with_host`,
+ * but it doesn't get called until too late.
+ */
+void
+CFBind_class_bootstrap_hook1(cfish_Class *self) {
+    PyTypeObject *py_type = S_get_cached_py_type(self);
+    if (PyType_HasFeature(py_type, Py_TPFLAGS_READY)) {
+        if (py_type->tp_basicsize != (Py_ssize_t)self->obj_alloc_size) {
+            fprintf(stderr, "PyType for %s readied with wrong alloc size\n",
+                    py_type->tp_name),
+            exit(1);
+        }
+    }
+    else {
+        if (self->parent) {
+            py_type->tp_base = S_get_cached_py_type(self->parent);
+        }
+        py_type->tp_basicsize = self->obj_alloc_size;
+        if (PyType_Ready(py_type) < 0) {
+            fprintf(stderr, "PyType_Ready failed for %s\n",
+                    py_type->tp_name),
+            exit(1);
+        }
+    }
+}
+
 /* Check the Class object for its associated PyTypeObject, which is stored in
  * `klass->host_type`.  If it is not there yet, search the class mapping and
  * cache it in the object.  Return the PyTypeObject.

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index 0064985..9c8d53f 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -219,6 +219,9 @@ CFBind_maybe_convert_float(PyObject *input, float *ptr);
 int
 CFBind_maybe_convert_double(PyObject *input, double *ptr);
 
+void
+CFBind_class_bootstrap_hook1(struct cfish_Class *self);
+
 #ifdef __cplusplus
 }
 #endif


[26/36] lucy-clownfish git commit: Add increfs and decrefs to gen ctor glue.

Posted by ma...@apache.org.
Add increfs and decrefs to gen ctor glue.

Incref decremented args. Signal to CFBind_run_trapped when it needs to
decref some args.


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

Branch: refs/heads/py_exp13
Commit: 2e4d3d3e6292539af7aab6419286ebe1be90e5ba
Parents: a6068b4
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 18:48:50 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:36:07 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2e4d3d3e/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 2f6168a..ef8b152 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -523,6 +523,8 @@ char*
 CFCPyMethod_constructor_wrapper(CFCFunction *init_func, CFCClass *invoker) {
     CFCParamList *param_list  = CFCFunction_get_param_list(init_func);
     char *decs       = S_gen_decs(param_list, 1);
+    char *increfs    = S_gen_arg_increfs(param_list, 1);
+    char *decrefs    = S_gen_decrefs(param_list, 1);
     const char *struct_sym = CFCClass_full_struct_sym(invoker);
     char *error = NULL;
     char *arg_parsing = S_gen_arg_parsing(param_list, 1, &error);
@@ -540,12 +542,16 @@ CFCPyMethod_constructor_wrapper(CFCFunction *init_func, CFCClass *invoker) {
         "S_%s_PY_NEW(PyTypeObject *type, PyObject *args, PyObject *kwargs) {\n"
         "%s" // decs
         "%s" // arg_parsing
+        "%s" // increfs
+        "%s" // decrefs
         "    Py_RETURN_NONE;\n"
         "}\n"
         ;
     char *wrapper = CFCUtil_sprintf(pattern, struct_sym, decs,
-                                    arg_parsing);
+                                    arg_parsing, increfs, decrefs);
 
+    FREEMEM(decrefs);
+    FREEMEM(increfs);
     FREEMEM(decs);
     FREEMEM(arg_parsing);
     return wrapper;


[35/36] lucy-clownfish git commit: Add actual constructor invocation to Py glue.

Posted by ma...@apache.org.
Add actual constructor invocation to Py glue.


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

Branch: refs/heads/py_exp13
Commit: 8b41f26264da06c6b43655a1e939ac1123957d9d
Parents: f624495
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 22 19:40:54 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:41:13 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8b41f262/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index f83fdc0..3d13665 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -586,9 +586,13 @@ CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
 char*
 CFCPyMethod_constructor_wrapper(CFCFunction *init_func, CFCClass *invoker) {
     CFCParamList *param_list  = CFCFunction_get_param_list(init_func);
+    const char *self_type
+        = CFCType_to_c(CFCFunction_get_return_type(init_func));
+    char *func_sym   = CFCFunction_full_func_sym(init_func, invoker);
     char *decs       = S_gen_decs(param_list, 1);
     char *increfs    = S_gen_arg_increfs(param_list, 1);
     char *decrefs    = S_gen_decrefs(param_list, 1);
+    const char *class_var  = CFCClass_full_class_var(invoker);
     const char *struct_sym = CFCClass_full_struct_sym(invoker);
     char *error = NULL;
     char *arg_parsing = S_gen_arg_parsing(param_list, 1, &error);
@@ -600,6 +604,9 @@ CFCPyMethod_constructor_wrapper(CFCFunction *init_func, CFCClass *invoker) {
         CFCUtil_die("Unexpected arg parsing error for %s",
                     CFCClass_get_name(invoker));
     }
+    char *first_arg = CFCUtil_sprintf("(%s)CFISH_Class_Make_Obj(%s)",
+                                      self_type, class_var);
+    char *arg_list = S_gen_arg_list(param_list, first_arg);
 
     char pattern[] =
         "static PyObject*\n"
@@ -607,13 +614,22 @@ CFCPyMethod_constructor_wrapper(CFCFunction *init_func, CFCClass *invoker) {
         "%s" // decs
         "%s" // arg_parsing
         "%s" // increfs
+        "    %s self = NULL;\n"
+        "    CFBIND_TRY(self = %s(%s));\n"
         "%s" // decrefs
-        "    Py_RETURN_NONE;\n"
+        "    if (CFBind_migrate_cferr()) {\n"
+        "        return NULL;\n"
+        "    }\n"
+        "    return (PyObject*)self;\n"
         "}\n"
         ;
     char *wrapper = CFCUtil_sprintf(pattern, struct_sym, decs,
-                                    arg_parsing, increfs, decrefs);
+                                    arg_parsing, increfs, self_type,
+                                    func_sym, arg_list, decrefs);
 
+    FREEMEM(arg_list);
+    FREEMEM(first_arg);
+    FREEMEM(func_sym);
     FREEMEM(decrefs);
     FREEMEM(increfs);
     FREEMEM(decs);


[34/36] lucy-clownfish git commit: Add test for the Py binding of Hash.

Posted by ma...@apache.org.
Add test for the Py binding of Hash.


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

Branch: refs/heads/py_exp13
Commit: 9d058f4b324dabf4f2cdd2ea88f40c9aabe2d622
Parents: 8b41f26
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Feb 10 18:45:50 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:41:13 2016 -0800

----------------------------------------------------------------------
 runtime/python/test/test_hash.py | 102 ++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9d058f4b/runtime/python/test/test_hash.py
----------------------------------------------------------------------
diff --git a/runtime/python/test/test_hash.py b/runtime/python/test/test_hash.py
new file mode 100644
index 0000000..5bfd034
--- /dev/null
+++ b/runtime/python/test/test_hash.py
@@ -0,0 +1,102 @@
+# 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.
+
+import unittest
+import inspect
+import clownfish
+
+class TestHash(unittest.TestCase):
+
+    def testStoreFetch(self):
+        h = clownfish.Hash()
+        h.store("foo", "bar")
+        h.store("foo", "bar")
+        self.assertEqual(h.fetch("foo"), "bar")
+        h.store("nada", None)
+        self.assertEqual(h.fetch("nada"), None)
+
+    def testDelete(self):
+        h = clownfish.Hash()
+        h.store("foo", "bar")
+        got = h.delete("foo")
+        self.assertEqual(h.get_size(), 0)
+        self.assertEqual(got, "bar")
+
+    def testClear(self):
+        h = clownfish.Hash()
+        h.store("foo", 1)
+        h.clear()
+        self.assertEqual(h.get_size(), 0)
+
+    def testHasKey(self):
+        h = clownfish.Hash()
+        h.store("foo", 1)
+        h.store("nada", None)
+        self.assertTrue(h.has_key("foo"))
+        self.assertFalse(h.has_key("bar"))
+        self.assertTrue(h.has_key("nada"))
+
+    def testKeys(self):
+        h = clownfish.Hash()
+        h.store("a", 1)
+        h.store("b", 1)
+        keys = sorted(h.keys())
+        self.assertEqual(keys, ["a", "b"])
+
+    def testValues(self):
+        h = clownfish.Hash()
+        h.store("foo", "a")
+        h.store("bar", "b")
+        got = sorted(h.values())
+        self.assertEqual(got, ["a", "b"])
+
+    def testGetCapacity(self):
+        h = clownfish.Hash(capacity=1)
+        self.assertGreater(h.get_capacity(), 0)
+
+    def testGetSize(self):
+        h = clownfish.Hash()
+        self.assertEqual(h.get_size(), 0)
+        h.store("meep", "moop")
+        self.assertEqual(h.get_size(), 1)
+
+    def testEquals(self):
+        h = clownfish.Hash()
+        other = clownfish.Hash()
+        h.store("a", "foo")
+        other.store("a", "foo")
+        self.assertTrue(h.equals(other))
+        other.store("b", "bar")
+        self.assertFalse(h.equals(other))
+        self.assertTrue(h.equals({"a":"foo"}),
+                        "equals() true against a Python dict")
+        vec = clownfish.Vector()
+        self.assertFalse(h.equals(vec),
+                         "equals() false against conflicting Clownfish type")
+        self.assertFalse(h.equals(1),
+                         "equals() false against conflicting Python type")
+
+    def testIterator(self):
+        h = clownfish.Hash()
+        h.store("a", "foo")
+        i = clownfish.HashIterator(h)
+        self.assertTrue(i.next())
+        self.assertEqual(i.get_key(), "a")
+        self.assertEqual(i.get_value(), "foo")
+        self.assertFalse(i.next())
+
+if __name__ == '__main__':
+    unittest.main()
+


[36/36] lucy-clownfish git commit: Add actual method invocation to Py glue.

Posted by ma...@apache.org.
Add actual method invocation to Py glue.


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

Branch: refs/heads/py_exp13
Commit: f624495ea3f0e80a6d95fb37d51fdb7a2b5b8124
Parents: 674721c
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 22 19:40:17 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:41:13 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 64 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 62 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f624495e/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index ea97d6a..f83fdc0 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -497,24 +497,84 @@ S_gen_arg_list(CFCParamList *param_list, const char *first_arg) {
     return arg_list;
 }
 
+static char*
+S_gen_meth_invocation(CFCMethod *method, CFCClass *invoker) {
+    CFCParamList *param_list = CFCMethod_get_param_list(method);
+    char *full_meth = CFCMethod_full_method_sym(method, invoker);
+    char *meth_type_c = CFCMethod_full_typedef(method, invoker);
+    const char *class_var = CFCClass_full_class_var(invoker);
+    char *first_arg
+        = CFCUtil_sprintf("(%s*)self", CFCClass_full_struct_sym(invoker));
+    char *arg_list = S_gen_arg_list(param_list, first_arg);
+
+    CFCType *return_type = CFCMethod_get_return_type(method);
+    char *maybe_declare;
+    const char *maybe_assign;
+    if (CFCType_is_void(return_type)) {
+        maybe_declare = CFCUtil_strdup("");
+        maybe_assign = "";
+    }
+    else {
+        maybe_declare = CFCUtil_sprintf("    %s retvalCF;\n",
+                                        CFCType_to_c(return_type));
+        maybe_assign = "retvalCF = ";
+    }
+
+    const char pattern[] =
+        "%s"
+        "    %s method = CFISH_METHOD_PTR(%s, %s);\n"
+        "    CFBIND_TRY(%smethod(%s));\n"
+        ;
+    char *content
+        = CFCUtil_sprintf(pattern, maybe_declare, meth_type_c, class_var,
+                          full_meth, maybe_assign, arg_list);
+
+    FREEMEM(arg_list);
+    FREEMEM(first_arg);
+    FREEMEM(maybe_declare);
+    FREEMEM(full_meth);
+    FREEMEM(meth_type_c);
+    return content;
+}
+
 char*
 CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
     CFCParamList *param_list  = CFCMethod_get_param_list(method);
+    CFCType      *return_type = CFCMethod_get_return_type(method);
     char *meth_sym   = CFCMethod_full_method_sym(method, invoker);
     char *meth_top   = S_meth_top(method);
     char *increfs    = S_gen_arg_increfs(param_list, 1);
     char *decrefs    = S_gen_decrefs(param_list, 1);
+    char *invocation = S_gen_meth_invocation(method, invoker);
+    char *ret;
+    if (CFCType_is_void(return_type)) {
+        ret = CFCUtil_strdup("    Py_RETURN_NONE;\n");
+    }
+    else if (CFCType_incremented(return_type)) {
+        ret = CFCUtil_strdup("    return CFBind_cfish_to_py_zeroref((cfish_Obj*)retvalCF);\n");
+    }
+    else {
+        char *conv = CFCPyTypeMap_c_to_py(return_type, "retvalCF");
+        ret = CFCUtil_sprintf("    return %s;\n", conv);
+        FREEMEM(conv);
+    }
 
     char pattern[] =
         "static PyObject*\n"
         "S_%s%s"
         "%s" // increfs
+        "%s" // invocation
         "%s" // decrefs
-        "    Py_RETURN_NONE;\n"
+        "    if (CFBind_migrate_cferr()) {\n"
+        "        return NULL;\n"
+        "    }\n"
+        "%s" // ret
         "}\n"
         ;
     char *wrapper = CFCUtil_sprintf(pattern, meth_sym, meth_top,
-                                    increfs, decrefs);
+                                    increfs, invocation, decrefs, ret);
+    FREEMEM(ret);
+    FREEMEM(invocation);
     FREEMEM(decrefs);
     FREEMEM(increfs);
     FREEMEM(meth_sym);


[16/36] lucy-clownfish git commit: Add CFCPyMethod and CFCPyClass to CFC.h.

Posted by ma...@apache.org.
Add CFCPyMethod and CFCPyClass to CFC.h.


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

Branch: refs/heads/py_exp13
Commit: a15800378cb8f27b2a572961d67fc833a136ea08
Parents: 49972c1
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 18:17:59 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:39 2016 -0800

----------------------------------------------------------------------
 compiler/include/CFC.h | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a1580037/compiler/include/CFC.h
----------------------------------------------------------------------
diff --git a/compiler/include/CFC.h b/compiler/include/CFC.h
index 1bdc968..fdd34c8 100644
--- a/compiler/include/CFC.h
+++ b/compiler/include/CFC.h
@@ -58,6 +58,8 @@
 #include "CFCPerlTypeMap.h"
 
 #include "CFCPython.h"
+#include "CFCPyClass.h"
+#include "CFCPyMethod.h"
 
 #include "CFCRuby.h"
 


[20/36] lucy-clownfish git commit: Consider num args in Py binding.

Posted by ma...@apache.org.
Consider num args in Py binding.

For generated CPython method glue code, support keyword args if the
method takes arguments.


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

Branch: refs/heads/py_exp13
Commit: 6a50d2179d0464048f54f021eff3e70029b6162d
Parents: cb25fd0
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 10:39:32 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:24:52 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/6a50d217/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 0a5cd27..863a0cb 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -215,20 +215,40 @@ S_maybe_unreachable(CFCType *return_type) {
     return return_statement;
 }
 
+static char*
+S_meth_top(CFCMethod *method) {
+    CFCParamList *param_list = CFCMethod_get_param_list(method);
+
+    if (CFCParamList_num_vars(param_list) == 1) {
+        char pattern[] =
+            "(PyObject *self, PyObject *unused) {\n"
+            "    CFISH_UNUSED_VAR(unused);\n"
+            ;
+        return CFCUtil_sprintf(pattern);
+    }
+    else {
+        char pattern[] =
+            "(PyObject *self, PyObject *args, PyObject *kwargs) {\n"
+            ;
+        char *result = CFCUtil_sprintf(pattern);
+        return result;
+    }
+}
+
 char*
 CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
     char *meth_sym   = CFCMethod_full_method_sym(method, invoker);
+    char *meth_top   = S_meth_top(method);
 
     char pattern[] =
         "static PyObject*\n"
-        "S_%s(PyObject *unused1, PyObject *unused2) {\n"
-        "    CFISH_UNUSED_VAR(unused1);\n"
-        "    CFISH_UNUSED_VAR(unused2);\n"
+        "S_%s%s"
         "    Py_RETURN_NONE;\n"
         "}\n"
         ;
-    char *wrapper = CFCUtil_sprintf(pattern, meth_sym);
+    char *wrapper = CFCUtil_sprintf(pattern, meth_sym, meth_top);
     FREEMEM(meth_sym);
+    FREEMEM(meth_top);
 
     return wrapper;
 }


[10/36] lucy-clownfish git commit: Bootstrap Clownfish parcels in Python build.

Posted by ma...@apache.org.
Bootstrap Clownfish parcels in Python build.

Finally, the Python implementation is complete enough that we can run
the bootstrapping for the Clownfish parcel.


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

Branch: refs/heads/py_exp13
Commit: 67b76306dd136fe88a392d4d489bfd26f0f2f750
Parents: c9cbb2d
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 17:08:27 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/67b76306/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index a2d28df..068c9c4 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -457,8 +457,18 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *type_linkups       = S_gen_type_linkups(self, parcel, ordered);
     char *pound_includes     = CFCUtil_strdup("");
     char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
+    char *parcel_boots       = CFCUtil_strdup("");
     char *pytype_ready_calls = CFCUtil_strdup("");
 
+    // Add parcel bootstrapping calls.
+    for (size_t i = 0; parcels[i]; ++i) {
+        if (!CFCParcel_included(parcels[i])) {
+            const char *prefix = CFCParcel_get_prefix(parcels[i]);
+            parcel_boots = CFCUtil_cat(parcel_boots, "    ", prefix,
+                                       "bootstrap_parcel();\n", NULL);
+        }
+    }
+
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
         if (CFCClass_included(klass)) { continue; }
@@ -508,6 +518,9 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "%s\n" // PyType_Ready calls
         "\n"
         "    S_link_py_types();\n"
+        "\n"
+        "%s\n" // parcel boots
+        "\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
         "    return module;\n"
         "}\n"
@@ -518,7 +531,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *content
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
                           helper_mod_name, class_bindings, type_linkups,
-                          last_component, pytype_ready_calls, self->footer);
+                          last_component, pytype_ready_calls, parcel_boots,
+                          self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -527,6 +541,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
 
     FREEMEM(content);
     FREEMEM(pytype_ready_calls);
+    FREEMEM(parcel_boots);
     FREEMEM(class_bindings);
     FREEMEM(helper_mod_name);
     FREEMEM(pymod_name);


[33/36] lucy-clownfish git commit: Test err handling in Py glue.

Posted by ma...@apache.org.
Test err handling in Py glue.

Check that a Clownfish exception gets transformed into a Python
exception.


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

Branch: refs/heads/py_exp13
Commit: 674721cc3e0f7fac030cf75fcdcfc4ee3d2f539f
Parents: b05965c
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 22 18:29:02 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:36:08 2016 -0800

----------------------------------------------------------------------
 runtime/python/test/test_err.py | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/674721cc/runtime/python/test/test_err.py
----------------------------------------------------------------------
diff --git a/runtime/python/test/test_err.py b/runtime/python/test/test_err.py
new file mode 100644
index 0000000..a553d74
--- /dev/null
+++ b/runtime/python/test/test_err.py
@@ -0,0 +1,31 @@
+# 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.
+
+import unittest
+import clownfish
+import sys
+
+class TestErr(unittest.TestCase):
+
+    def testErrorHandling(self):
+        vec = clownfish.Vector()
+        try:
+            vec.grow(sys.maxsize)
+        except RuntimeError as e:
+            self.assertTrue(str(e).find("overflow") != -1)
+
+if __name__ == '__main__':
+    unittest.main()
+


[25/36] lucy-clownfish git commit: Prepare decrefs to run in Py glue.

Posted by ma...@apache.org.
Prepare decrefs to run in Py glue.


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

Branch: refs/heads/py_exp13
Commit: d88c0bf5c19a22b655bb5c59a6f2a0d2c366f85c
Parents: a9daf3c
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 15:46:23 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:35:27 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d88c0bf5/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 5464dbb..450c26e 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -447,22 +447,51 @@ S_gen_arg_increfs(CFCParamList *param_list, int first_tick) {
     return content;
 }
 
+// Prep refcount decrement calls to follow the Clownfish subroutine
+// invocation.
+static char*
+S_gen_decrefs(CFCParamList *param_list, int first_tick) {
+    CFCVariable **vars = CFCParamList_get_variables(param_list);
+    int num_vars = CFCParamList_num_vars(param_list);
+    char *decrefs = CFCUtil_strdup("");
+
+    for (int i = first_tick; i < num_vars; i++) {
+        CFCVariable *var = vars[i];
+        CFCType *type = CFCVariable_get_type(var);
+        const char *micro_sym = CFCVariable_get_name(var);
+        const char *specifier = CFCType_get_specifier(type);
+
+        if (strcmp(specifier, "cfish_String") == 0
+             || strcmp(specifier, "cfish_Vector") == 0
+             || strcmp(specifier, "cfish_Hash") == 0
+            ) {
+            decrefs = CFCUtil_cat(decrefs, "    CFISH_DECREF(", micro_sym,
+                                  "_ARG);\n", NULL);
+        }
+    }
+
+    return decrefs;
+}
+
 char*
 CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
     CFCParamList *param_list  = CFCMethod_get_param_list(method);
     char *meth_sym   = CFCMethod_full_method_sym(method, invoker);
     char *meth_top   = S_meth_top(method);
     char *increfs    = S_gen_arg_increfs(param_list, 1);
+    char *decrefs    = S_gen_decrefs(param_list, 1);
 
     char pattern[] =
         "static PyObject*\n"
         "S_%s%s"
         "%s" // increfs
+        "%s" // decrefs
         "    Py_RETURN_NONE;\n"
         "}\n"
         ;
     char *wrapper = CFCUtil_sprintf(pattern, meth_sym, meth_top,
-                                    increfs);
+                                    increfs, decrefs);
+    FREEMEM(decrefs);
     FREEMEM(increfs);
     FREEMEM(meth_sym);
     FREEMEM(meth_top);


[32/36] lucy-clownfish git commit: Gen arg parsing for Py constructor glue.

Posted by ma...@apache.org.
Gen arg parsing for Py constructor glue.


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

Branch: refs/heads/py_exp13
Commit: a6068b41523b9c216bb63ace4d66f9f5cccf1477
Parents: 5443a74
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 18:43:41 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:36:07 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a6068b41/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index c93252e..2f6168a 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -521,19 +521,33 @@ CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
 
 char*
 CFCPyMethod_constructor_wrapper(CFCFunction *init_func, CFCClass *invoker) {
+    CFCParamList *param_list  = CFCFunction_get_param_list(init_func);
+    char *decs       = S_gen_decs(param_list, 1);
     const char *struct_sym = CFCClass_full_struct_sym(invoker);
+    char *error = NULL;
+    char *arg_parsing = S_gen_arg_parsing(param_list, 1, &error);
+    if (error) {
+        CFCUtil_die("%s in constructor for %s", error,
+                    CFCClass_get_name(invoker));
+    }
+    if (!arg_parsing) {
+        CFCUtil_die("Unexpected arg parsing error for %s",
+                    CFCClass_get_name(invoker));
+    }
 
     char pattern[] =
         "static PyObject*\n"
         "S_%s_PY_NEW(PyTypeObject *type, PyObject *args, PyObject *kwargs) {\n"
-        "    CFISH_UNUSED_VAR(type);\n"
-        "    CFISH_UNUSED_VAR(args);\n"
-        "    CFISH_UNUSED_VAR(kwargs);\n"
+        "%s" // decs
+        "%s" // arg_parsing
         "    Py_RETURN_NONE;\n"
         "}\n"
         ;
-    char *wrapper = CFCUtil_sprintf(pattern, struct_sym);
+    char *wrapper = CFCUtil_sprintf(pattern, struct_sym, decs,
+                                    arg_parsing);
 
+    FREEMEM(decs);
+    FREEMEM(arg_parsing);
     return wrapper;
 }
 


[05/36] lucy-clownfish git commit: Stub out some placeholders for Py bindings.

Posted by ma...@apache.org.
Stub out some placeholders for Py bindings.

Subclassing from Python won't be supported until these are fully
implemented.


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

Branch: refs/heads/py_exp13
Commit: 33189df152305583c976b2701396eff940b992a1
Parents: 2b37cc1
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 15:49:29 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 runtime/python/cfext/CFBind.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/33189df1/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index f73b76a..69ab9bd 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -912,23 +912,26 @@ CFISH_Class_Init_Obj_IMP(cfish_Class *self, void *allocation) {
 
 void
 cfish_Class_register_with_host(cfish_Class *singleton, cfish_Class *parent) {
+    // FIXME
     CFISH_UNUSED_VAR(singleton);
     CFISH_UNUSED_VAR(parent);
-    CFISH_THROW(CFISH_ERR, "TODO");
 }
 
 cfish_Vector*
 cfish_Class_fresh_host_methods(cfish_String *class_name) {
+    // FIXME Scan Python class for host methods which override.  Until this is
+    // implemented, it will be impossible to override Clownfish methods from
+    // Python.
     CFISH_UNUSED_VAR(class_name);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_Vector*);
+    return cfish_Vec_new(0);
 }
 
 cfish_String*
 cfish_Class_find_parent_class(cfish_String *class_name) {
+    // FIXME Until this is implemented, subclassing from Python will be
+    // impossible.
     CFISH_UNUSED_VAR(class_name);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_String*);
+    return NULL;
 }
 
 /**** Method ***************************************************************/


[31/36] lucy-clownfish git commit: Stub out generated Python constructors.

Posted by ma...@apache.org.
Stub out generated Python constructors.


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

Branch: refs/heads/py_exp13
Commit: 5443a74386b0bd6217d12c16a5ef9265c99d78c7
Parents: d8ced59
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 17:50:12 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:36:07 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyClass.c  | 23 +++++++++++++++++++++--
 compiler/src/CFCPyMethod.c | 18 ++++++++++++++++++
 compiler/src/CFCPyMethod.h |  7 +++++++
 3 files changed, 46 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5443a743/compiler/src/CFCPyClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.c b/compiler/src/CFCPyClass.c
index 529c6cf..0fe168e 100644
--- a/compiler/src/CFCPyClass.c
+++ b/compiler/src/CFCPyClass.c
@@ -145,6 +145,14 @@ CFCPyClass_gen_binding_code(CFCPyClass *self) {
     char *bindings  = CFCUtil_strdup(self->pre_code ? self->pre_code : "");
     char *meth_defs = CFCUtil_strdup(self->meth_defs);
 
+    // Constructor.
+    CFCFunction *init_func = CFCClass_function(klass, "init");
+    if (init_func && CFCFunction_can_be_bound(init_func)) {
+        char *wrapper = CFCPyMethod_constructor_wrapper(init_func, klass);
+        bindings = CFCUtil_cat(bindings, wrapper, "\n", NULL);
+        FREEMEM(wrapper);
+    }
+
     // Instance methods.
     CFCMethod **methods = CFCClass_fresh_methods(klass);
     for (size_t j = 0; methods[j] != NULL; j++) {
@@ -201,6 +209,16 @@ S_pytype_struct_def(CFCPyClass *self) {
 
     const char *struct_sym = CFCClass_get_struct_sym(klass);
 
+    char *tp_new;
+    CFCFunction *init_func = CFCClass_function(klass, "init");
+    if (init_func && CFCFunction_can_be_bound(init_func)) {
+        tp_new = CFCUtil_sprintf("S_%s_PY_NEW",
+                                 CFCClass_full_struct_sym(klass));
+    }
+    else {
+        tp_new = CFCUtil_strdup("0");
+    }
+
     char pattern[] =
         "static PyTypeObject %s_pytype_struct = {\n"
         "    PyVarObject_HEAD_INIT(NULL, 0)\n"
@@ -240,12 +258,13 @@ S_pytype_struct_def(CFCPyClass *self) {
         "    0,                                  // tp_dictoffset\n"
         "    0,                                  // tp_init\n"
         "    0,                                  // tp_allow\n"
-        "    0,                                  // tp_new\n"
+        "    %s,                                 // tp_new\n"
         "};\n"
         ;
     char *content = CFCUtil_sprintf(pattern, struct_sym, pymod_name,
-                                    struct_sym, struct_sym);
+                                    struct_sym, struct_sym, tp_new);
 
+    FREEMEM(tp_new);
     FREEMEM(pymod_name);
     return content;
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5443a743/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 1291568..c93252e 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -520,6 +520,24 @@ CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
 }
 
 char*
+CFCPyMethod_constructor_wrapper(CFCFunction *init_func, CFCClass *invoker) {
+    const char *struct_sym = CFCClass_full_struct_sym(invoker);
+
+    char pattern[] =
+        "static PyObject*\n"
+        "S_%s_PY_NEW(PyTypeObject *type, PyObject *args, PyObject *kwargs) {\n"
+        "    CFISH_UNUSED_VAR(type);\n"
+        "    CFISH_UNUSED_VAR(args);\n"
+        "    CFISH_UNUSED_VAR(kwargs);\n"
+        "    Py_RETURN_NONE;\n"
+        "}\n"
+        ;
+    char *wrapper = CFCUtil_sprintf(pattern, struct_sym);
+
+    return wrapper;
+}
+
+char*
 CFCPyMethod_pymethoddef(CFCMethod *method, CFCClass *invoker) {
     CFCParamList *param_list = CFCMethod_get_param_list(method);
     const char *flags = CFCParamList_num_vars(param_list) == 1

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5443a743/compiler/src/CFCPyMethod.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.h b/compiler/src/CFCPyMethod.h
index b3d6808..f85844f 100644
--- a/compiler/src/CFCPyMethod.h
+++ b/compiler/src/CFCPyMethod.h
@@ -21,6 +21,7 @@
 extern "C" {
 #endif
 
+struct CFCFunction;
 struct CFCMethod;
 struct CFCClass;
 
@@ -39,6 +40,12 @@ CFCPyMethod_pymethoddef(struct CFCMethod *method, struct CFCClass *invoker);
 char*
 CFCPyMethod_wrapper(struct CFCMethod *method, struct CFCClass *invoker);
 
+/** Generate glue code for a constructor.
+  */
+char*
+CFCPyMethod_constructor_wrapper(struct CFCFunction *init_func,
+                                struct CFCClass *invoker);
+
 #ifdef __cplusplus
 }
 #endif


[30/36] lucy-clownfish git commit: Register PyMethodDefs for glued methods.

Posted by ma...@apache.org.
Register PyMethodDefs for glued methods.

Create PyMethodDef entries for each wrapped Clownfish method.


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

Branch: refs/heads/py_exp13
Commit: d8ced59cb135f628c0266e6aff0141152280f603
Parents: 71c836a
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 17:13:28 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:36:07 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyClass.c             |  5 +++++
 compiler/src/CFCPyMethod.c            | 21 +++++++++++++++++++++
 compiler/src/CFCPyMethod.h            |  5 +++++
 runtime/python/test/test_clownfish.py |  2 ++
 4 files changed, 33 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d8ced59c/compiler/src/CFCPyClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.c b/compiler/src/CFCPyClass.c
index 11a4905..529c6cf 100644
--- a/compiler/src/CFCPyClass.c
+++ b/compiler/src/CFCPyClass.c
@@ -160,6 +160,11 @@ CFCPyClass_gen_binding_code(CFCPyClass *self) {
         char *wrapper = CFCPyMethod_wrapper(meth, klass);
         bindings = CFCUtil_cat(bindings, wrapper, "\n", NULL);
         FREEMEM(wrapper);
+
+        // Add PyMethodDef entry.
+        char *meth_def = CFCPyMethod_pymethoddef(meth, klass);
+        meth_defs = CFCUtil_cat(meth_defs, "    ", meth_def, "\n", NULL);
+        FREEMEM(meth_def);
     }
 
     // Complete the PyMethodDef array.

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d8ced59c/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 4220aea..1291568 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -519,3 +519,24 @@ CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
     return wrapper;
 }
 
+char*
+CFCPyMethod_pymethoddef(CFCMethod *method, CFCClass *invoker) {
+    CFCParamList *param_list = CFCMethod_get_param_list(method);
+    const char *flags = CFCParamList_num_vars(param_list) == 1
+                        ? "METH_NOARGS"
+                        : "METH_KEYWORDS|METH_VARARGS";
+    char *meth_sym = CFCMethod_full_method_sym(method, invoker);
+    char *micro_sym = CFCUtil_strdup(CFCSymbol_get_name((CFCSymbol*)method));
+    for (int i = 0; micro_sym[i] != 0; i++) {
+        micro_sym[i] = tolower(micro_sym[i]);
+    }
+
+    char pattern[] =
+        "{\"%s\", (PyCFunction)S_%s, %s, NULL},";
+    char *py_meth_def = CFCUtil_sprintf(pattern, micro_sym, meth_sym, flags);
+
+    FREEMEM(meth_sym);
+    FREEMEM(micro_sym);
+    return py_meth_def;
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d8ced59c/compiler/src/CFCPyMethod.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.h b/compiler/src/CFCPyMethod.h
index 53768e2..b3d6808 100644
--- a/compiler/src/CFCPyMethod.h
+++ b/compiler/src/CFCPyMethod.h
@@ -31,6 +31,11 @@ struct CFCClass;
 char*
 CFCPyMethod_callback_def(struct CFCMethod *method, struct CFCClass *invoker);
 
+/** Generate a PyMethodDef entry for an instance method.
+  */
+char*
+CFCPyMethod_pymethoddef(struct CFCMethod *method, struct CFCClass *invoker);
+
 char*
 CFCPyMethod_wrapper(struct CFCMethod *method, struct CFCClass *invoker);
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d8ced59c/runtime/python/test/test_clownfish.py
----------------------------------------------------------------------
diff --git a/runtime/python/test/test_clownfish.py b/runtime/python/test/test_clownfish.py
index d8f2594..f7908ca 100644
--- a/runtime/python/test/test_clownfish.py
+++ b/runtime/python/test/test_clownfish.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 
 import unittest
+import inspect
 import clownfish
 
 class MyTest(unittest.TestCase):
@@ -23,6 +24,7 @@ class MyTest(unittest.TestCase):
 
     def testClassesPresent(self):
         self.assertIsInstance(clownfish.Hash, type)
+        self.assertTrue(inspect.ismethoddescriptor(clownfish.Hash.store))
 
 if __name__ == '__main__':
     unittest.main()


[24/36] lucy-clownfish git commit: Incref `decremented` args in Py glue.

Posted by ma...@apache.org.
Incref `decremented` args in Py glue.

For args that are specified as `decremented` in the Clownfish method
signature, add an INCREF in the glue 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/a9daf3cf
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/a9daf3cf
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/a9daf3cf

Branch: refs/heads/py_exp13
Commit: a9daf3cf7bb82ee5c9f51a83b5f3d166fb35de6d
Parents: 4cdfb56
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 15:44:10 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:32:30 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a9daf3cf/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 8d6adfb..5464dbb 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -427,18 +427,43 @@ S_meth_top(CFCMethod *method) {
     }
 }
 
+static char*
+S_gen_arg_increfs(CFCParamList *param_list, int first_tick) {
+    CFCVariable **vars = CFCParamList_get_variables(param_list);
+    int num_vars = CFCParamList_num_vars(param_list);
+    char *content = CFCUtil_strdup("");
+    for (int i = first_tick;i < num_vars; i++) {
+        CFCType *type = CFCVariable_get_type(vars[i]);
+        if (CFCType_decremented(type)) {
+            const char *name = CFCVariable_get_name(vars[i]);
+            const char *specifier = CFCType_get_specifier(type);
+            char pattern[] =
+                "    %s_ARG = (%s*)CFISH_INCREF(%s_ARG);\n";
+            char *incref = CFCUtil_sprintf(pattern, name, specifier, name);
+            content = CFCUtil_cat(content, incref, NULL);
+            FREEMEM(incref);
+        }
+    }
+    return content;
+}
+
 char*
 CFCPyMethod_wrapper(CFCMethod *method, CFCClass *invoker) {
+    CFCParamList *param_list  = CFCMethod_get_param_list(method);
     char *meth_sym   = CFCMethod_full_method_sym(method, invoker);
     char *meth_top   = S_meth_top(method);
+    char *increfs    = S_gen_arg_increfs(param_list, 1);
 
     char pattern[] =
         "static PyObject*\n"
         "S_%s%s"
+        "%s" // increfs
         "    Py_RETURN_NONE;\n"
         "}\n"
         ;
-    char *wrapper = CFCUtil_sprintf(pattern, meth_sym, meth_top);
+    char *wrapper = CFCUtil_sprintf(pattern, meth_sym, meth_top,
+                                    increfs);
+    FREEMEM(increfs);
     FREEMEM(meth_sym);
     FREEMEM(meth_top);
 


[21/36] lucy-clownfish git commit: Prepare to parse Python meth args.

Posted by ma...@apache.org.
Prepare to parse Python meth args.

Stub out data structures into which we will read arguments from Python.


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

Branch: refs/heads/py_exp13
Commit: 15602e67deb05b28329c9eaf0612a739547ddf8b
Parents: 6a50d21
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 2 11:03:02 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:24:52 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyMethod.c | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/15602e67/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 863a0cb..c89d12c 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -67,6 +67,41 @@ S_build_py_args(CFCParamList *param_list) {
     return py_args;
 }
 
+/* Generate the code which parses arguments passed from Python and converts
+ * them to Clownfish-flavored C values.
+ */
+static char*
+S_gen_arg_parsing(CFCParamList *param_list) {
+    char *content = NULL;
+
+    CFCVariable **vars = CFCParamList_get_variables(param_list);
+    const char **vals = CFCParamList_get_initial_values(param_list);
+    int num_vars = CFCParamList_num_vars(param_list);
+
+    char *declarations = CFCUtil_strdup("");
+    char *keywords     = CFCUtil_strdup("");
+    char *format_str   = CFCUtil_strdup("");
+    char *targets      = CFCUtil_strdup("");
+    int optional_started = 0;
+
+    char parse_pattern[] =
+        "%s"
+        "    char *keywords[] = {%sNULL};\n"
+        "    char *fmt = \"%s\";\n"
+        "    int ok = PyArg_ParseTupleAndKeywords(args, kwargs, fmt,\n"
+        "        keywords%s);\n"
+        "    if (!ok) { return NULL; }\n"
+        ;
+    content = CFCUtil_sprintf(parse_pattern, declarations, keywords,
+                              format_str, targets);
+
+    FREEMEM(declarations);
+    FREEMEM(keywords);
+    FREEMEM(format_str);
+    FREEMEM(targets);
+    return content;
+}
+
 static char*
 S_build_pymeth_invocation(CFCMethod *method) {
     CFCType *return_type = CFCMethod_get_return_type(method);
@@ -227,10 +262,13 @@ S_meth_top(CFCMethod *method) {
         return CFCUtil_sprintf(pattern);
     }
     else {
+        char *arg_parsing = S_gen_arg_parsing(param_list);
         char pattern[] =
             "(PyObject *self, PyObject *args, PyObject *kwargs) {\n"
+            "%s"
             ;
-        char *result = CFCUtil_sprintf(pattern);
+        char *result = CFCUtil_sprintf(pattern, arg_parsing);
+        FREEMEM(arg_parsing);
         return result;
     }
 }