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/09 18:11:18 UTC

[01/12] lucy-clownfish git commit: Add CFCPyTypeMap.

Repository: lucy-clownfish
Updated Branches:
  refs/heads/master c75ee9248 -> 9debabe4d


Add CFCPyTypeMap.

Only include a C-to-Python conversion routine for now.


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

Branch: refs/heads/master
Commit: d4f52d9c6a8c956727e1e530860424fa8ae18cc7
Parents: 11d08c5
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Sat Dec 20 16:31:19 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 09:58:12 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyTypeMap.c | 71 ++++++++++++++++++++++++++++++++++++++++
 compiler/src/CFCPyTypeMap.h | 43 ++++++++++++++++++++++++
 2 files changed, 114 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d4f52d9c/compiler/src/CFCPyTypeMap.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyTypeMap.c b/compiler/src/CFCPyTypeMap.c
new file mode 100644
index 0000000..016d3dc
--- /dev/null
+++ b/compiler/src/CFCPyTypeMap.c
@@ -0,0 +1,71 @@
+/* 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.
+ */
+
+#include <string.h>
+
+#include "CFCPyTypeMap.h"
+#include "CFCType.h"
+#include "CFCUtil.h"
+
+char*
+CFCPyTypeMap_c_to_py(CFCType *type, const char *cf_var) {
+    const char *type_str = CFCType_to_c(type);
+    char *result = NULL;
+
+    if (CFCType_is_object(type)) {
+        result = CFCUtil_sprintf("CFBind_cfish_to_py((cfish_Obj*)%s)", cf_var);
+    }
+    else if (CFCType_is_primitive(type)) {
+        const char *specifier = CFCType_get_specifier(type);
+
+        if (strcmp(specifier, "double") == 0
+            || strcmp(specifier, "float") == 0
+           ) {
+            result = CFCUtil_sprintf("PyFloat_FromDouble(%s)", cf_var);
+        }
+        else if (strcmp(specifier, "int") == 0
+                 || strcmp(specifier, "short") == 0
+                 || strcmp(specifier, "long") == 0
+                 || strcmp(specifier, "char") == 0 // OK if char is unsigned
+                 || strcmp(specifier, "int8_t") == 0
+                 || strcmp(specifier, "int16_t") == 0
+                 || strcmp(specifier, "int32_t") == 0
+                ) {
+            result = CFCUtil_sprintf("PyLong_FromLong(%s)", cf_var);
+        }
+        else if (strcmp(specifier, "int64_t") == 0) {
+            result = CFCUtil_sprintf("PyLong_FromLongLong(%s)", cf_var);
+        }
+        else if (strcmp(specifier, "uint8_t") == 0
+                 || strcmp(specifier, "uint16_t") == 0
+                 || strcmp(specifier, "uint32_t") == 0
+                ) {
+            result = CFCUtil_sprintf("PyLong_FromUnsignedLong(%s)", cf_var);
+        }
+        else if (strcmp(specifier, "uint64_t") == 0) {
+            result = CFCUtil_sprintf("PyLong_FromUnsignedLongLong(%s)", cf_var);
+        }
+        else if (strcmp(specifier, "size_t") == 0) {
+            result = CFCUtil_sprintf("PyLong_FromSize_t(%s)", cf_var);
+        }
+        else if (strcmp(specifier, "bool") == 0) {
+            result = CFCUtil_sprintf("PyBool_FromLong(%s)", cf_var);
+        }
+    }
+
+    return result;
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d4f52d9c/compiler/src/CFCPyTypeMap.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyTypeMap.h b/compiler/src/CFCPyTypeMap.h
new file mode 100644
index 0000000..da14829
--- /dev/null
+++ b/compiler/src/CFCPyTypeMap.h
@@ -0,0 +1,43 @@
+/* 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_CFCPYTYPEMAP
+#define H_CFCPYTYPEMAP
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct CFCType;
+struct CFCParcel;
+
+/** Return an expression converts from a variable of type `type` to a
+ * PyObject*.
+ * 
+ * @param type A Clownfish::CFC::Model::Type, which will be used to select the
+ * mapping code.
+ * @param cf_var The name of the variable from which we are extracting a
+ * value.
+ */ 
+char*
+CFCPyTypeMap_c_to_py(struct CFCType *type, const char *cf_var);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_CFCPYTYPEMAP */
+


[05/12] lucy-clownfish git commit: Regen charmonizer for Python details.

Posted by ma...@apache.org.
Regen charmonizer for Python details.


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

Branch: refs/heads/master
Commit: 1cf2a6d7d9d895879e4224cf9d3008426af7402b
Parents: 1f30f3e
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Dec 16 09:55:52 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 09:58:13 2016 -0800

----------------------------------------------------------------------
 runtime/common/charmonizer.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1cf2a6d7/runtime/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.c b/runtime/common/charmonizer.c
index c0a75ad..e9e571a 100644
--- a/runtime/common/charmonizer.c
+++ b/runtime/common/charmonizer.c
@@ -8183,7 +8183,16 @@ cfish_MakeFile_new(chaz_CLI *cli) {
         self->host_src_dir = "ext";
         self->autogen_src_files = go_autogen_src_files;
     }
-    else if (strcmp(chaz_CLI_strval(cli, "host"), "perl") == 0) {
+    else if (chaz_CLI_defined(cli, "enable-python")) {
+        static const char *python_autogen_src_files[] = {
+            "cfish_parcel",
+            "testcfish_parcel",
+            NULL
+        };
+        self->host_src_dir = "cfext";
+        self->autogen_src_files = python_autogen_src_files;
+    }
+    else if (chaz_CLI_defined(cli, "enable-perl")) {
         static const char *perl_autogen_src_files[] = {
             "boot",
             "callbacks",


[08/12] lucy-clownfish git commit: Add CFBind containing stubs.

Posted by ma...@apache.org.
Add CFBind containing stubs.

Stub out the Clownfish runtime's host-specific functions.


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

Branch: refs/heads/master
Commit: fb4cc37143198a96e17cd9096543e8b2afa5c591
Parents: 5b1631a
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 20 14:02:31 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 10:23:20 2016 -0800

----------------------------------------------------------------------
 runtime/python/cfext/CFBind.c | 241 +++++++++++++++++++++++++++++++++++++
 runtime/python/cfext/CFBind.h |  32 +++++
 2 files changed, 273 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/fb4cc371/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
new file mode 100644
index 0000000..a386e4c
--- /dev/null
+++ b/runtime/python/cfext/CFBind.c
@@ -0,0 +1,241 @@
+/* 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 C_CFISH_OBJ
+#define C_CFISH_CLASS
+#define C_CFISH_METHOD
+#define C_CFISH_ERR
+
+#include "charmony.h"
+#include "CFBind.h"
+
+#include "Clownfish/Obj.h"
+#include "Clownfish/Class.h"
+#include "Clownfish/Blob.h"
+#include "Clownfish/Boolean.h"
+#include "Clownfish/ByteBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Hash.h"
+#include "Clownfish/Method.h"
+#include "Clownfish/Num.h"
+#include "Clownfish/String.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Util/Memory.h"
+#include "Clownfish/Vector.h"
+
+/**** refcounting **********************************************************/
+
+uint32_t
+cfish_get_refcount(void *vself) {
+    CFISH_UNUSED_VAR(vself);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(uint32_t);
+}
+
+cfish_Obj*
+cfish_inc_refcount(void *vself) {
+    CFISH_UNUSED_VAR(vself);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(cfish_Obj*);
+}
+
+uint32_t
+cfish_dec_refcount(void *vself) {
+    CFISH_UNUSED_VAR(vself);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(uint32_t);
+}
+
+/**** Obj ******************************************************************/
+
+void*
+CFISH_Obj_To_Host_IMP(cfish_Obj *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+
+/**** Class ****************************************************************/
+
+cfish_Obj*
+CFISH_Class_Make_Obj_IMP(cfish_Class *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(cfish_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*);
+}
+
+void
+cfish_Class_register_with_host(cfish_Class *singleton, cfish_Class *parent) {
+    CFISH_UNUSED_VAR(singleton);
+    CFISH_UNUSED_VAR(parent);
+    CFISH_THROW(CFISH_ERR, "TODO");
+}
+
+cfish_Vector*
+cfish_Class_fresh_host_methods(cfish_String *class_name) {
+    CFISH_UNUSED_VAR(class_name);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(cfish_Vector*);
+}
+
+cfish_String*
+cfish_Class_find_parent_class(cfish_String *class_name) {
+    CFISH_UNUSED_VAR(class_name);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(cfish_String*);
+}
+
+/**** Method ***************************************************************/
+
+cfish_String*
+CFISH_Method_Host_Name_IMP(cfish_Method *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(cfish_String*);
+}
+
+/**** Err ******************************************************************/
+
+void
+cfish_Err_init_class() {
+    CFISH_THROW(CFISH_ERR, "TODO");
+}
+
+cfish_Err*
+cfish_Err_get_error() {
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(cfish_Err*);
+}
+
+void
+cfish_Err_set_error(cfish_Err *error) {
+    CFISH_UNUSED_VAR(error);
+    CFISH_THROW(CFISH_ERR, "TODO");
+}
+
+void
+cfish_Err_do_throw(cfish_Err *error) {
+    CFISH_UNUSED_VAR(error);
+    CFISH_THROW(CFISH_ERR, "TODO");
+}
+
+void
+cfish_Err_throw_mess(cfish_Class *klass, cfish_String *message) {
+    CFISH_UNUSED_VAR(klass);
+    CFISH_UNUSED_VAR(message);
+    CFISH_THROW(CFISH_ERR, "TODO");
+}
+
+void
+cfish_Err_warn_mess(cfish_String *message) {
+    CFISH_UNUSED_VAR(message);
+    CFISH_THROW(CFISH_ERR, "TODO");
+}
+
+cfish_Err*
+cfish_Err_trap(CFISH_Err_Attempt_t routine, void *routine_context) {
+    CFISH_UNUSED_VAR(routine);
+    CFISH_UNUSED_VAR(routine_context);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(cfish_Err*);
+}
+
+/**** TestUtils ************************************************************/
+
+void*
+cfish_TestUtils_clone_host_runtime() {
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+
+void
+cfish_TestUtils_set_host_runtime(void *runtime) {
+    CFISH_UNUSED_VAR(runtime);
+    CFISH_THROW(CFISH_ERR, "TODO");
+}
+
+void
+cfish_TestUtils_destroy_host_runtime(void *runtime) {
+    CFISH_UNUSED_VAR(runtime);
+    CFISH_THROW(CFISH_ERR, "TODO");
+}
+
+/**** To_Host methods ******************************************************/
+
+void*
+CFISH_Str_To_Host_IMP(cfish_String *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+
+void*
+CFISH_Blob_To_Host_IMP(cfish_Blob *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+
+void*
+CFISH_BB_To_Host_IMP(cfish_ByteBuf *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+
+void*
+CFISH_Vec_To_Host_IMP(cfish_Vector *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+
+void*
+CFISH_Hash_To_Host_IMP(cfish_Hash *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+
+void*
+CFISH_Float_To_Host_IMP(cfish_Float *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+
+void*
+CFISH_Int_To_Host_IMP(cfish_Integer *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+
+void*
+CFISH_Bool_To_Host_IMP(cfish_Boolean *self) {
+    CFISH_UNUSED_VAR(self);
+    CFISH_THROW(CFISH_ERR, "TODO");
+    CFISH_UNREACHABLE_RETURN(void*);
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/fb4cc371/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
new file mode 100644
index 0000000..810f201
--- /dev/null
+++ b/runtime/python/cfext/CFBind.h
@@ -0,0 +1,32 @@
+/* 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_CFISH_PY_CFBIND
+#define H_CFISH_PY_CFBIND 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cfish_platform.h"
+#include "Python.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // H_CFISH_PY_CFBIND
+


[03/12] lucy-clownfish git commit: Move `cfc` Python module to top level.

Posted by ma...@apache.org.
Move `cfc` Python module to top level.

Moving the `cfc` module out from underneath `clownfish` gives the
runtime full control over what ends up in the `clownfish` module.


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

Branch: refs/heads/master
Commit: 11d08c5b0a8a724ad7fd5ac7f10fb9ee065eea89
Parents: 47234c3
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Dec 29 19:31:16 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 09:58:12 2016 -0800

----------------------------------------------------------------------
 compiler/python/setup.py                      |   8 +-
 compiler/python/src/cfc/__init__.py           |  29 ++
 compiler/python/src/cfc/_cfc.c                | 400 +++++++++++++++++++++
 compiler/python/src/clownfish/_cfc.c          | 400 ---------------------
 compiler/python/src/clownfish/cfc/__init__.py |  29 --
 compiler/python/test/test_cfc.py              |   2 +-
 6 files changed, 434 insertions(+), 434 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/11d08c5b/compiler/python/setup.py
----------------------------------------------------------------------
diff --git a/compiler/python/setup.py b/compiler/python/setup.py
index e140161..7d8017e 100644
--- a/compiler/python/setup.py
+++ b/compiler/python/setup.py
@@ -53,7 +53,7 @@ CHARMONY_H_PATH      = 'charmony.h'
 LIBCFC_NAME          = 'libcfc.a' # TODO portability
 LIBCFC_PATH          = os.path.abspath(os.path.join(os.curdir, LIBCFC_NAME))
 
-c_filepaths = [os.path.join('src', 'clownfish', '_cfc.c')]
+c_filepaths = [os.path.join('src', 'cfc', '_cfc.c')]
 paths_to_clean = [
     CHARMONIZER_EXE_PATH,
     CHARMONY_H_PATH,
@@ -111,7 +111,7 @@ class libcfc(_Command):
         self.run_command('charmony')
         subprocess.check_call([make_command, '-j', 'static'])
         # Touch Python binding file if the library has changed.
-        cfc_c = os.path.join('src', 'clownfish', '_cfc.c')
+        cfc_c = os.path.join('src', 'cfc', '_cfc.c')
         if newer_group(['libcfc.a'], cfc_c):
             os.utime(cfc_c, None)
 
@@ -161,7 +161,7 @@ class test(_Command):
         # restore sys.path
         sys.path = orig_sys_path
 
-cfc_extension = Extension('clownfish._cfc',
+cfc_extension = Extension('cfc._cfc',
                           define_macros = [('CFCPYTHON', None)],
                           include_dirs = [
                               CFC_INCLUDE_DIR,
@@ -177,7 +177,7 @@ setup(name = 'clownfish-cfc',
       author = 'Apache Lucy Project',
       author_email = 'dev at lucy dot apache dot org',
       url = 'http://lucy.apache.org',
-      packages = ['clownfish.cfc',
+      packages = ['cfc',
                  ],
       cmdclass = {
           'build': my_build,

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/11d08c5b/compiler/python/src/cfc/__init__.py
----------------------------------------------------------------------
diff --git a/compiler/python/src/cfc/__init__.py b/compiler/python/src/cfc/__init__.py
new file mode 100644
index 0000000..05afcc5
--- /dev/null
+++ b/compiler/python/src/cfc/__init__.py
@@ -0,0 +1,29 @@
+# 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 cfc._cfc
+from cfc._cfc import *
+import site
+import os.path
+
+def _get_inc_dirs():
+    dirs = []
+    for path in site.getsitepackages():
+        path = os.path.join(path, "clownfish/_include")
+        dirs.append(path)
+    return dirs
+
+cfc._cfc._get_inc_dirs = _get_inc_dirs
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/11d08c5b/compiler/python/src/cfc/_cfc.c
----------------------------------------------------------------------
diff --git a/compiler/python/src/cfc/_cfc.c b/compiler/python/src/cfc/_cfc.c
new file mode 100644
index 0000000..d20b5fa
--- /dev/null
+++ b/compiler/python/src/cfc/_cfc.c
@@ -0,0 +1,400 @@
+/* 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.
+ */
+
+#include "Python.h"
+#include "CFC.h"
+
+typedef struct {
+    PyObject_HEAD
+    void *cfc_obj;
+} CFCPyWrapper;
+
+static PyModuleDef cfc_module_def = {
+    PyModuleDef_HEAD_INIT,
+    "cfc._cfc",
+    "CFC: Clownfish compiler",
+    -1,
+    NULL, NULL, NULL, NULL, NULL
+};
+
+static PyModuleDef cfc_model_module_def = {
+    PyModuleDef_HEAD_INIT,
+    "cfc.model",
+    "CFC classes which model language constructs",
+    -1,
+    NULL, NULL, NULL, NULL, NULL
+};
+
+static PyModuleDef cfc_binding_module_def = {
+    PyModuleDef_HEAD_INIT,
+    "cfc.binding",
+    "CFC components which generate bindings",
+    -1,
+    NULL, NULL, NULL, NULL, NULL
+};
+
+static PyObject *cfc_module;
+static PyObject *cfc_model_module;
+static PyObject *cfc_binding_module;
+
+static PyObject*
+S_wrap_cfcbase(PyTypeObject *type, void *cfc_obj) {
+    if (cfc_obj == NULL) {
+        Py_RETURN_NONE;
+    }
+    CFCPyWrapper *wrapper = (CFCPyWrapper*)type->tp_alloc(type, 0);
+    if (wrapper == NULL) {
+        PyErr_SetString(PyExc_RuntimeError, "Failed to allocate object");
+        return NULL;
+    }
+    wrapper->cfc_obj = cfc_obj;
+    return (PyObject*)wrapper;
+}
+
+static void
+S_CFCBase_dealloc(CFCPyWrapper *wrapper) {
+    CFCBase *temp = (CFCBase*)wrapper->cfc_obj;
+    wrapper->cfc_obj = NULL;
+    CFCBase_decref(temp);
+    Py_TYPE(wrapper)->tp_free(wrapper);
+}
+
+void*
+S_to_cfc_something(PyObject *wrapper, const char *class_name) {
+    if (wrapper == NULL || wrapper == Py_None) {
+        return NULL;
+    }
+    CFCBase *obj = (CFCBase*)((CFCPyWrapper*)wrapper)->cfc_obj;
+    if (strcmp(CFCBase_get_cfc_class(obj), class_name) != 0) {
+        CFCUtil_die("Object is not a %s, it's a %s", class_name,
+                    CFCBase_get_cfc_class(obj));
+    }
+    return obj;
+}
+
+static CFCHierarchy*
+S_to_Hierarchy(PyObject *wrapper) {
+    return (CFCHierarchy*)S_to_cfc_something(wrapper,
+        "Clownfish::CFC::Model::Hierarchy");
+}
+
+static CFCParcel*
+S_to_Parcel(PyObject *wrapper) {
+    return (CFCParcel*)S_to_cfc_something(wrapper,
+        "Clownfish::CFC::Model::Parcel");
+}
+
+static CFCBindCore*
+S_to_BindCore(PyObject *wrapper) {
+    return (CFCBindCore*)S_to_cfc_something(wrapper,
+        "Clownfish::CFC::Binding::Core");
+}
+
+static PyTypeObject *Hierarchy_pytype;
+static PyTypeObject *Parcel_pytype;
+static PyTypeObject *BindCore_pytype;
+
+/***************************** CFCHierarchy *****************************/
+
+static PyObject*
+S_CFCHierarchy_new(PyTypeObject *type, PyObject *args,
+                   PyObject *keyword_args) {
+    char *dest = NULL;
+    char *keywords[] = {"dest", NULL};
+    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "|s",
+                                             keywords, &dest);
+    if (!result) { return NULL; }
+    if (!dest) {
+        PyErr_SetString(PyExc_TypeError, "Missing required arg 'dest'");
+        return NULL;
+    }
+    PyObject *inc_func = PyObject_GetAttrString(cfc_module, "_get_inc_dirs");
+    PyObject *dirs = NULL;
+    if (PyCallable_Check(inc_func)) {
+        dirs = PyObject_CallObject(inc_func, NULL);
+    }
+    if (dirs == NULL || !PyList_Check(dirs)) {
+        Py_XDECREF(inc_func);
+        Py_XDECREF(dirs);
+        PyErr_SetString(PyExc_RuntimeError, "_get_inc_dirs failed");
+        return NULL;
+    }
+    CFCHierarchy *hierarchy = CFCHierarchy_new(dest);
+    for (Py_ssize_t i = 0, max = PyList_Size(dirs); i < max; i++) {
+        PyObject *dir = PyList_GetItem(dirs, i);
+        if (PyUnicode_Check(dir)) {
+            char *dir_utf8 = PyUnicode_AsUTF8(dir);
+            CFCHierarchy_add_include_dir(hierarchy, dir_utf8);
+        }
+        else {
+            PyErr_SetString(PyExc_RuntimeError, "not a string");
+            return NULL;
+        }
+    }
+
+    Py_XDECREF(inc_func);
+    Py_XDECREF(dirs);
+
+    return S_wrap_cfcbase(Hierarchy_pytype, hierarchy);
+}
+
+static PyObject*
+S_CFCHierarchy_build(PyObject *wrapper, PyObject *unused) {
+    CHY_UNUSED_VAR(unused);
+    CFCHierarchy_build(S_to_Hierarchy(wrapper));
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+S_CFCHierarchy_add_include_dir(PyObject *wrapper, PyObject *dir) {
+    CFCHierarchy_add_include_dir(S_to_Hierarchy(wrapper),
+                                 PyUnicode_AsUTF8(dir));
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+S_CFCHierarchy_add_source_dir(PyObject *wrapper, PyObject *dir) {
+    CFCHierarchy_add_source_dir(S_to_Hierarchy(wrapper),
+                                PyUnicode_AsUTF8(dir));
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+S_CFCHierarchy_write_log(PyObject *wrapper, PyObject *unused) {
+    CHY_UNUSED_VAR(unused);
+    CFCHierarchy_write_log(S_to_Hierarchy(wrapper));
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef hierarchy_methods[] = {
+    {"add_include_dir", (PyCFunction)S_CFCHierarchy_add_include_dir, METH_O,      NULL},
+    {"add_source_dir",  (PyCFunction)S_CFCHierarchy_add_source_dir,  METH_O,      NULL},
+    {"build",           (PyCFunction)S_CFCHierarchy_build,           METH_NOARGS, NULL},
+    {"write_log",       (PyCFunction)S_CFCHierarchy_write_log,       METH_NOARGS, NULL},
+    {NULL}
+};
+
+static PyTypeObject Hierarchy_pytype_struct = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "cfc.model.Hierarchy",              // tp_name
+    sizeof(CFCPyWrapper),               // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)S_CFCBase_dealloc,      // tp_dealloc
+    0,                                  // tp_print
+    0,                                  // tp_getattr
+    0,                                  // tp_setattr
+    0,                                  // tp_reserved
+    0,                                  // tp_repr
+    0,                                  // tp_as_number
+    0,                                  // tp_as_sequence
+    0,                                  // tp_as_mapping
+    0,                                  // tp_hash
+    0,                                  // tp_call
+    0,                                  // tp_str
+    0,                                  // tp_getattro
+    0,                                  // tp_setattro
+    0,                                  // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "CFCHierarchy",                     // tp_doc
+    0,                                  // tp_traverse
+    0,                                  // tp_clear
+    0,                                  // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    0,                                  // tp_iter
+    0,                                  // tp_iternext
+    hierarchy_methods,                  // tp_methods
+    0,                                  // tp_members
+    0,                                  // tp_getset
+    0,                                  // tp_base
+    0,                                  // tp_dict
+    0,                                  // tp_descr_get
+    0,                                  // tp_descr_set
+    0,                                  // tp_dictoffset
+    0,                                  // tp_init
+    0,                                  // tp_allow
+    (newfunc)S_CFCHierarchy_new         // tp_new
+};
+
+/***************************** CFCParcel *****************************/
+
+PyObject*
+S_CFCParcel_fetch(PyObject *ignored, PyObject *name) {
+    CFCParcel *parcel = CFCParcel_fetch(PyUnicode_AsUTF8(name));
+    return S_wrap_cfcbase(Parcel_pytype, parcel);
+}
+
+static PyMethodDef parcel_methods[] = {
+    {"fetch", (PyCFunction)S_CFCParcel_fetch, METH_STATIC, NULL},
+    {NULL}
+};
+
+static PyTypeObject Parcel_pytype_struct = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "cfc.model.Parcel",                 // tp_name
+    sizeof(CFCPyWrapper),               // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)S_CFCBase_dealloc,      // tp_dealloc
+    0,                                  // tp_print
+    0,                                  // tp_getattr
+    0,                                  // tp_setattr
+    0,                                  // tp_reserved
+    0,                                  // tp_repr
+    0,                                  // tp_as_number
+    0,                                  // tp_as_sequence
+    0,                                  // tp_as_mapping
+    0,                                  // tp_hash
+    0,                                  // tp_call
+    0,                                  // tp_str
+    0,                                  // tp_getattro
+    0,                                  // tp_setattro
+    0,                                  // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "CFCParcel",                        // tp_doc
+    0,                                  // tp_traverse
+    0,                                  // tp_clear
+    0,                                  // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    0,                                  // tp_iter
+    0,                                  // tp_iternext
+    parcel_methods,                     // tp_methods
+    0,                                  // tp_members
+    0,                                  // tp_getset
+    0,                                  // tp_base
+    0,                                  // tp_dict
+    0,                                  // tp_descr_get
+    0,                                  // tp_descr_set
+    0,                                  // tp_dictoffset
+    0,                                  // tp_init
+    0,                                  // tp_allow
+    0                                   // tp_new
+};
+
+/***************************** CFCBindCore *****************************/
+
+static PyObject*
+S_CFCBindCore_new(PyTypeObject *type, PyObject *args,
+                   PyObject *keyword_args) {
+    PyObject *hierarchy_wrapped;
+    char *header = "";
+    char *footer = "";
+    char *keywords[] = {"hierarchy", "header", "footer", NULL};
+    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "O!|ss",
+                                             keywords, Hierarchy_pytype,
+                                             &hierarchy_wrapped, &header,
+                                             &footer);
+    if (!result) { return NULL; }
+    CFCHierarchy *hierarchy = S_to_Hierarchy(hierarchy_wrapped);
+    CFCBindCore *obj = CFCBindCore_new(hierarchy, header, footer);
+    return S_wrap_cfcbase(BindCore_pytype, obj);
+}
+
+static PyObject*
+S_CFCBindCore_write_all_modified(PyObject *wrapper, PyObject *args) {
+    int modified = 0;
+    int result = PyArg_ParseTuple(args, "|p", &modified);
+    if (!result) { return NULL; }
+    CFCBindCore_write_all_modified(S_to_BindCore(wrapper), modified);
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef bindcore_methods[] = {
+    {"write_all_modified", (PyCFunction)S_CFCBindCore_write_all_modified, METH_VARARGS, NULL},
+    {NULL}
+};
+
+static PyTypeObject BindCore_pytype_struct = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "cfc.binding.BindCore",             // tp_name
+    sizeof(CFCPyWrapper),               // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)S_CFCBase_dealloc,      // tp_dealloc
+    0,                                  // tp_print
+    0,                                  // tp_getattr
+    0,                                  // tp_setattr
+    0,                                  // tp_reserved
+    0,                                  // tp_repr
+    0,                                  // tp_as_number
+    0,                                  // tp_as_sequence
+    0,                                  // tp_as_mapping
+    0,                                  // tp_hash
+    0,                                  // tp_call
+    0,                                  // tp_str
+    0,                                  // tp_getattro
+    0,                                  // tp_setattro
+    0,                                  // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "CFCBindCore",                      // tp_doc
+    0,                                  // tp_traverse
+    0,                                  // tp_clear
+    0,                                  // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    0,                                  // tp_iter
+    0,                                  // tp_iternext
+    bindcore_methods,                   // tp_methods
+    0,                                  // tp_members
+    0,                                  // tp_getset
+    0,                                  // tp_base
+    0,                                  // tp_dict
+    0,                                  // tp_descr_get
+    0,                                  // tp_descr_set
+    0,                                  // tp_dictoffset
+    0,                                  // tp_init
+    0,                                  // tp_allow
+    (newfunc)S_CFCBindCore_new          // tp_new
+};
+
+/******************************* common ******************************/
+
+PyMODINIT_FUNC
+PyInit__cfc(void) {
+    // Initialize Python type objects.
+    Hierarchy_pytype = &Hierarchy_pytype_struct;
+    Parcel_pytype    = &Parcel_pytype_struct;
+    BindCore_pytype  = &BindCore_pytype_struct;
+    if (PyType_Ready(Hierarchy_pytype) < 0) {
+        return NULL;
+    }
+    if (PyType_Ready(Parcel_pytype) < 0) {
+        return NULL;
+    }
+    if (PyType_Ready(BindCore_pytype) < 0) {
+        return NULL;
+    }
+
+    // Initialize modules.
+    cfc_module = PyModule_Create(&cfc_module_def);
+    cfc_model_module = PyModule_Create(&cfc_model_module_def);
+    cfc_binding_module = PyModule_Create(&cfc_binding_module_def);
+    PyModule_AddObject(cfc_module, "model", (PyObject*)cfc_model_module);
+    PyModule_AddObject(cfc_module, "binding", (PyObject*)cfc_binding_module);
+
+    // Add type objects to "model" module.
+    Py_INCREF(Hierarchy_pytype);
+    PyModule_AddObject(cfc_model_module, "Hierarchy",
+                       (PyObject*)Hierarchy_pytype);
+    Py_INCREF(Parcel_pytype);
+    PyModule_AddObject(cfc_model_module, "Parcel",
+                       (PyObject*)Parcel_pytype);
+
+    // Add type objects to "binding" module.
+    Py_INCREF(BindCore_pytype);
+    PyModule_AddObject(cfc_binding_module, "BindCore",
+                       (PyObject*)BindCore_pytype);
+
+    return cfc_module;
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/11d08c5b/compiler/python/src/clownfish/_cfc.c
----------------------------------------------------------------------
diff --git a/compiler/python/src/clownfish/_cfc.c b/compiler/python/src/clownfish/_cfc.c
deleted file mode 100644
index 706943f..0000000
--- a/compiler/python/src/clownfish/_cfc.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/* 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.
- */
-
-#include "Python.h"
-#include "CFC.h"
-
-typedef struct {
-    PyObject_HEAD
-    void *cfc_obj;
-} CFCPyWrapper;
-
-static PyModuleDef cfc_module_def = {
-    PyModuleDef_HEAD_INIT,
-    "clownfish._cfc",
-    "CFC: Clownfish compiler",
-    -1,
-    NULL, NULL, NULL, NULL, NULL
-};
-
-static PyModuleDef cfc_model_module_def = {
-    PyModuleDef_HEAD_INIT,
-    "clownfish.cfc.model",
-    "CFC classes which model language constructs",
-    -1,
-    NULL, NULL, NULL, NULL, NULL
-};
-
-static PyModuleDef cfc_binding_module_def = {
-    PyModuleDef_HEAD_INIT,
-    "clownfish.cfc.binding",
-    "CFC components which generate bindings",
-    -1,
-    NULL, NULL, NULL, NULL, NULL
-};
-
-static PyObject *cfc_module;
-static PyObject *cfc_model_module;
-static PyObject *cfc_binding_module;
-
-static PyObject*
-S_wrap_cfcbase(PyTypeObject *type, void *cfc_obj) {
-    if (cfc_obj == NULL) {
-        Py_RETURN_NONE;
-    }
-    CFCPyWrapper *wrapper = (CFCPyWrapper*)type->tp_alloc(type, 0);
-    if (wrapper == NULL) {
-        PyErr_SetString(PyExc_RuntimeError, "Failed to allocate object");
-        return NULL;
-    }
-    wrapper->cfc_obj = cfc_obj;
-    return (PyObject*)wrapper;
-}
-
-static void
-S_CFCBase_dealloc(CFCPyWrapper *wrapper) {
-    CFCBase *temp = (CFCBase*)wrapper->cfc_obj;
-    wrapper->cfc_obj = NULL;
-    CFCBase_decref(temp);
-    Py_TYPE(wrapper)->tp_free(wrapper);
-}
-
-void*
-S_to_cfc_something(PyObject *wrapper, const char *class_name) {
-    if (wrapper == NULL || wrapper == Py_None) {
-        return NULL;
-    }
-    CFCBase *obj = (CFCBase*)((CFCPyWrapper*)wrapper)->cfc_obj;
-    if (strcmp(CFCBase_get_cfc_class(obj), class_name) != 0) {
-        CFCUtil_die("Object is not a %s, it's a %s", class_name,
-                    CFCBase_get_cfc_class(obj));
-    }
-    return obj;
-}
-
-static CFCHierarchy*
-S_to_Hierarchy(PyObject *wrapper) {
-    return (CFCHierarchy*)S_to_cfc_something(wrapper,
-        "Clownfish::CFC::Model::Hierarchy");
-}
-
-static CFCParcel*
-S_to_Parcel(PyObject *wrapper) {
-    return (CFCParcel*)S_to_cfc_something(wrapper,
-        "Clownfish::CFC::Model::Parcel");
-}
-
-static CFCBindCore*
-S_to_BindCore(PyObject *wrapper) {
-    return (CFCBindCore*)S_to_cfc_something(wrapper,
-        "Clownfish::CFC::Binding::Core");
-}
-
-static PyTypeObject *Hierarchy_pytype;
-static PyTypeObject *Parcel_pytype;
-static PyTypeObject *BindCore_pytype;
-
-/***************************** CFCHierarchy *****************************/
-
-static PyObject*
-S_CFCHierarchy_new(PyTypeObject *type, PyObject *args,
-                   PyObject *keyword_args) {
-    char *dest = NULL;
-    char *keywords[] = {"dest", NULL};
-    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "|s",
-                                             keywords, &dest);
-    if (!result) { return NULL; }
-    if (!dest) {
-        PyErr_SetString(PyExc_TypeError, "Missing required arg 'dest'");
-        return NULL;
-    }
-    PyObject *inc_func = PyObject_GetAttrString(cfc_module, "_get_inc_dirs");
-    PyObject *dirs = NULL;
-    if (PyCallable_Check(inc_func)) {
-        dirs = PyObject_CallObject(inc_func, NULL);
-    }
-    if (dirs == NULL || !PyList_Check(dirs)) {
-        Py_XDECREF(inc_func);
-        Py_XDECREF(dirs);
-        PyErr_SetString(PyExc_RuntimeError, "_get_inc_dirs failed");
-        return NULL;
-    }
-    CFCHierarchy *hierarchy = CFCHierarchy_new(dest);
-    for (Py_ssize_t i = 0, max = PyList_Size(dirs); i < max; i++) {
-        PyObject *dir = PyList_GetItem(dirs, i);
-        if (PyUnicode_Check(dir)) {
-            char *dir_utf8 = PyUnicode_AsUTF8(dir);
-            CFCHierarchy_add_include_dir(hierarchy, dir_utf8);
-        }
-        else {
-            PyErr_SetString(PyExc_RuntimeError, "not a string");
-            return NULL;
-        }
-    }
-
-    Py_XDECREF(inc_func);
-    Py_XDECREF(dirs);
-
-    return S_wrap_cfcbase(Hierarchy_pytype, hierarchy);
-}
-
-static PyObject*
-S_CFCHierarchy_build(PyObject *wrapper, PyObject *unused) {
-    CHY_UNUSED_VAR(unused);
-    CFCHierarchy_build(S_to_Hierarchy(wrapper));
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-S_CFCHierarchy_add_include_dir(PyObject *wrapper, PyObject *dir) {
-    CFCHierarchy_add_include_dir(S_to_Hierarchy(wrapper),
-                                 PyUnicode_AsUTF8(dir));
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-S_CFCHierarchy_add_source_dir(PyObject *wrapper, PyObject *dir) {
-    CFCHierarchy_add_source_dir(S_to_Hierarchy(wrapper),
-                                PyUnicode_AsUTF8(dir));
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-S_CFCHierarchy_write_log(PyObject *wrapper, PyObject *unused) {
-    CHY_UNUSED_VAR(unused);
-    CFCHierarchy_write_log(S_to_Hierarchy(wrapper));
-    Py_RETURN_NONE;
-}
-
-static PyMethodDef hierarchy_methods[] = {
-    {"add_include_dir", (PyCFunction)S_CFCHierarchy_add_include_dir, METH_O,      NULL},
-    {"add_source_dir",  (PyCFunction)S_CFCHierarchy_add_source_dir,  METH_O,      NULL},
-    {"build",           (PyCFunction)S_CFCHierarchy_build,           METH_NOARGS, NULL},
-    {"write_log",       (PyCFunction)S_CFCHierarchy_write_log,       METH_NOARGS, NULL},
-    {NULL}
-};
-
-static PyTypeObject Hierarchy_pytype_struct = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "clownfish.cfc.model.Hierarchy",    // tp_name
-    sizeof(CFCPyWrapper),               // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)S_CFCBase_dealloc,      // tp_dealloc
-    0,                                  // tp_print
-    0,                                  // tp_getattr
-    0,                                  // tp_setattr
-    0,                                  // tp_reserved
-    0,                                  // tp_repr
-    0,                                  // tp_as_number
-    0,                                  // tp_as_sequence
-    0,                                  // tp_as_mapping
-    0,                                  // tp_hash
-    0,                                  // tp_call
-    0,                                  // tp_str
-    0,                                  // tp_getattro
-    0,                                  // tp_setattro
-    0,                                  // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "CFCHierarchy",                     // tp_doc
-    0,                                  // tp_traverse
-    0,                                  // tp_clear
-    0,                                  // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    0,                                  // tp_iter
-    0,                                  // tp_iternext
-    hierarchy_methods,                  // tp_methods
-    0,                                  // tp_members
-    0,                                  // tp_getset
-    0,                                  // tp_base
-    0,                                  // tp_dict
-    0,                                  // tp_descr_get
-    0,                                  // tp_descr_set
-    0,                                  // tp_dictoffset
-    0,                                  // tp_init
-    0,                                  // tp_allow
-    (newfunc)S_CFCHierarchy_new         // tp_new
-};
-
-/***************************** CFCParcel *****************************/
-
-PyObject*
-S_CFCParcel_fetch(PyObject *ignored, PyObject *name) {
-    CFCParcel *parcel = CFCParcel_fetch(PyUnicode_AsUTF8(name));
-    return S_wrap_cfcbase(Parcel_pytype, parcel);
-}
-
-static PyMethodDef parcel_methods[] = {
-    {"fetch", (PyCFunction)S_CFCParcel_fetch, METH_STATIC, NULL},
-    {NULL}
-};
-
-static PyTypeObject Parcel_pytype_struct = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "clownfish.cfc.model.Parcel",       // tp_name
-    sizeof(CFCPyWrapper),               // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)S_CFCBase_dealloc,      // tp_dealloc
-    0,                                  // tp_print
-    0,                                  // tp_getattr
-    0,                                  // tp_setattr
-    0,                                  // tp_reserved
-    0,                                  // tp_repr
-    0,                                  // tp_as_number
-    0,                                  // tp_as_sequence
-    0,                                  // tp_as_mapping
-    0,                                  // tp_hash
-    0,                                  // tp_call
-    0,                                  // tp_str
-    0,                                  // tp_getattro
-    0,                                  // tp_setattro
-    0,                                  // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "CFCParcel",                        // tp_doc
-    0,                                  // tp_traverse
-    0,                                  // tp_clear
-    0,                                  // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    0,                                  // tp_iter
-    0,                                  // tp_iternext
-    parcel_methods,                     // tp_methods
-    0,                                  // tp_members
-    0,                                  // tp_getset
-    0,                                  // tp_base
-    0,                                  // tp_dict
-    0,                                  // tp_descr_get
-    0,                                  // tp_descr_set
-    0,                                  // tp_dictoffset
-    0,                                  // tp_init
-    0,                                  // tp_allow
-    0                                   // tp_new
-};
-
-/***************************** CFCBindCore *****************************/
-
-static PyObject*
-S_CFCBindCore_new(PyTypeObject *type, PyObject *args,
-                   PyObject *keyword_args) {
-    PyObject *hierarchy_wrapped;
-    char *header = "";
-    char *footer = "";
-    char *keywords[] = {"hierarchy", "header", "footer", NULL};
-    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "O!|ss",
-                                             keywords, Hierarchy_pytype,
-                                             &hierarchy_wrapped, &header,
-                                             &footer);
-    if (!result) { return NULL; }
-    CFCHierarchy *hierarchy = S_to_Hierarchy(hierarchy_wrapped);
-    CFCBindCore *obj = CFCBindCore_new(hierarchy, header, footer);
-    return S_wrap_cfcbase(BindCore_pytype, obj);
-}
-
-static PyObject*
-S_CFCBindCore_write_all_modified(PyObject *wrapper, PyObject *args) {
-    int modified = 0;
-    int result = PyArg_ParseTuple(args, "|p", &modified);
-    if (!result) { return NULL; }
-    CFCBindCore_write_all_modified(S_to_BindCore(wrapper), modified);
-    Py_RETURN_NONE;
-}
-
-static PyMethodDef bindcore_methods[] = {
-    {"write_all_modified", (PyCFunction)S_CFCBindCore_write_all_modified, METH_VARARGS, NULL},
-    {NULL}
-};
-
-static PyTypeObject BindCore_pytype_struct = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "clownfish.cfc.binding.BindCore",   // tp_name
-    sizeof(CFCPyWrapper),               // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)S_CFCBase_dealloc,      // tp_dealloc
-    0,                                  // tp_print
-    0,                                  // tp_getattr
-    0,                                  // tp_setattr
-    0,                                  // tp_reserved
-    0,                                  // tp_repr
-    0,                                  // tp_as_number
-    0,                                  // tp_as_sequence
-    0,                                  // tp_as_mapping
-    0,                                  // tp_hash
-    0,                                  // tp_call
-    0,                                  // tp_str
-    0,                                  // tp_getattro
-    0,                                  // tp_setattro
-    0,                                  // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "CFCBindCore",                      // tp_doc
-    0,                                  // tp_traverse
-    0,                                  // tp_clear
-    0,                                  // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    0,                                  // tp_iter
-    0,                                  // tp_iternext
-    bindcore_methods,                   // tp_methods
-    0,                                  // tp_members
-    0,                                  // tp_getset
-    0,                                  // tp_base
-    0,                                  // tp_dict
-    0,                                  // tp_descr_get
-    0,                                  // tp_descr_set
-    0,                                  // tp_dictoffset
-    0,                                  // tp_init
-    0,                                  // tp_allow
-    (newfunc)S_CFCBindCore_new          // tp_new
-};
-
-/******************************* common ******************************/
-
-PyMODINIT_FUNC
-PyInit__cfc(void) {
-    // Initialize Python type objects.
-    Hierarchy_pytype = &Hierarchy_pytype_struct;
-    Parcel_pytype    = &Parcel_pytype_struct;
-    BindCore_pytype  = &BindCore_pytype_struct;
-    if (PyType_Ready(Hierarchy_pytype) < 0) {
-        return NULL;
-    }
-    if (PyType_Ready(Parcel_pytype) < 0) {
-        return NULL;
-    }
-    if (PyType_Ready(BindCore_pytype) < 0) {
-        return NULL;
-    }
-
-    // Initialize modules.
-    cfc_module = PyModule_Create(&cfc_module_def);
-    cfc_model_module = PyModule_Create(&cfc_model_module_def);
-    cfc_binding_module = PyModule_Create(&cfc_binding_module_def);
-    PyModule_AddObject(cfc_module, "model", (PyObject*)cfc_model_module);
-    PyModule_AddObject(cfc_module, "binding", (PyObject*)cfc_binding_module);
-
-    // Add type objects to "model" module.
-    Py_INCREF(Hierarchy_pytype);
-    PyModule_AddObject(cfc_model_module, "Hierarchy",
-                       (PyObject*)Hierarchy_pytype);
-    Py_INCREF(Parcel_pytype);
-    PyModule_AddObject(cfc_model_module, "Parcel",
-                       (PyObject*)Parcel_pytype);
-
-    // Add type objects to "binding" module.
-    Py_INCREF(BindCore_pytype);
-    PyModule_AddObject(cfc_binding_module, "BindCore",
-                       (PyObject*)BindCore_pytype);
-
-    return cfc_module;
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/11d08c5b/compiler/python/src/clownfish/cfc/__init__.py
----------------------------------------------------------------------
diff --git a/compiler/python/src/clownfish/cfc/__init__.py b/compiler/python/src/clownfish/cfc/__init__.py
deleted file mode 100644
index f7f3e0b..0000000
--- a/compiler/python/src/clownfish/cfc/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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 clownfish._cfc
-from clownfish._cfc import *
-import site
-import os.path
-
-def _get_inc_dirs():
-    dirs = []
-    for path in site.getsitepackages():
-        path = os.path.join(path, "clownfish/_include")
-        dirs.append(path)
-    return dirs
-
-clownfish._cfc._get_inc_dirs = _get_inc_dirs
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/11d08c5b/compiler/python/test/test_cfc.py
----------------------------------------------------------------------
diff --git a/compiler/python/test/test_cfc.py b/compiler/python/test/test_cfc.py
index c4091d8..5ac2b8f 100644
--- a/compiler/python/test/test_cfc.py
+++ b/compiler/python/test/test_cfc.py
@@ -1,5 +1,5 @@
 import unittest
-import clownfish.cfc
+import cfc
 
 class MyTest(unittest.TestCase):
 


[11/12] lucy-clownfish git commit: Build py C extension for runtime.

Posted by ma...@apache.org.
Build py C extension for runtime.


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

Branch: refs/heads/master
Commit: bebd2447680dc23be903dfb8000158725699014d
Parents: 49361b7
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Jan 19 20:44:50 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 10:23:21 2016 -0800

----------------------------------------------------------------------
 runtime/python/setup.py                  | 67 +++++++++++++++++++++++++--
 runtime/python/src/clownfish/__init__.py |  3 ++
 2 files changed, 66 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bebd2447/runtime/python/setup.py
----------------------------------------------------------------------
diff --git a/runtime/python/setup.py b/runtime/python/setup.py
index fdaa593..dbc41f5 100644
--- a/runtime/python/setup.py
+++ b/runtime/python/setup.py
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from distutils.core import setup
+from distutils.core import setup, Extension
 from distutils.command.build import build as _build
 from distutils.command.clean import clean as _clean
 from distutils.cmd import Command as _Command
@@ -21,16 +21,25 @@ from distutils.dep_util import newer_group
 import distutils.ccompiler
 import os
 import glob
+import platform
 import shutil
 import subprocess
 import sysconfig
 import sys
 import unittest
 
+def ext_build_dir(base):
+    """Returns the build directory for compiled extensions"""
+    pattern = "lib.{platform}-{version[0]}.{version[1]}"
+    dirname = pattern.format(platform=sysconfig.get_platform(),
+                             version=sys.version_info)
+    return os.path.join(base, 'build', dirname)
+
 # Get a compiler object and and strings representing the compiler type and
 # CFLAGS.  Add the Python headers include dir to CFLAGS.
 compiler = distutils.ccompiler.new_compiler()
 cflags = sysconfig.get_config_var('CFLAGS')
+cflags = cflags + " -I" + sysconfig.get_path('include')
 compiler_type = distutils.ccompiler.get_default_compiler()
 
 # There's no public way to get a string representing the compiler executable
@@ -48,12 +57,20 @@ CHARMONIZER_C        = os.path.join(COMMON_SOURCE_DIR, 'charmonizer.c')
 CHARMONIZER_EXE_NAME = compiler.executable_filename('charmonizer')
 CHARMONIZER_EXE_PATH = os.path.join(os.curdir, CHARMONIZER_EXE_NAME)
 CHARMONY_H_PATH      = 'charmony.h'
-
-c_filepaths = []
+LIBCLOWNFISH_NAME    = 'libclownfish.a' # TODO portability
+LIBCLOWNFISH_PATH    = os.path.abspath(os.path.join(os.curdir, LIBCLOWNFISH_NAME))
+AUTOGEN_INCLUDE      = os.path.join('autogen', 'include')
+CFC_DIR              = os.path.join(BASE_DIR, 'compiler', 'python')
+CFC_BUILD_DIR        = ext_build_dir(os.path.join(CFC_DIR))
+PY_BINDING_DIR       = os.path.abspath(os.curdir)
+BINDING_FILE         = '_clownfish.c'
+
+c_filepaths = [BINDING_FILE]
 paths_to_clean = [
     CHARMONIZER_EXE_PATH,
     CHARMONY_H_PATH,
     '_charm*',
+    BINDING_FILE,
 ]
 
 def _quotify(text):
@@ -97,6 +114,35 @@ class charmony(_Command):
             print(" ".join(command))
             subprocess.check_call(command)
 
+class libclownfish(_Command):
+    description = "Build the Clownfish runtime core as a static archive."
+    user_options = []
+    def initialize_options(self):
+        pass
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        self.run_command('charmony')
+        self.run_cfc()
+        subprocess.check_call([make_command, '-j', 'static'])
+
+    def run_cfc(self):
+        sys.path.append(CFC_DIR)
+        sys.path.append(CFC_BUILD_DIR)
+        import cfc
+        hierarchy = cfc.model.Hierarchy(dest="autogen")
+        hierarchy.add_source_dir(CORE_SOURCE_DIR)
+        hierarchy.build()
+        header = "Autogenerated by setup.py"
+        core_binding = cfc.binding.BindCore(hierarchy=hierarchy, header=header)
+        modified = core_binding.write_all_modified()
+        if modified:
+            py_binding = cfc.binding.Python(hierarchy=hierarchy)
+            py_binding.set_header(header)
+            py_binding.write_bindings(parcel="Clownfish", dest=PY_BINDING_DIR)
+            hierarchy.write_log()
+
 class my_clean(_clean):
     def run(self):
         _clean.run(self)
@@ -113,6 +159,7 @@ class my_clean(_clean):
 class my_build(_build):
     def run(self):
         self.run_command('charmony')
+        self.run_command('libclownfish')
         _build.run(self)
 
 class test(_Command):
@@ -142,6 +189,16 @@ class test(_Command):
         # restore sys.path
         sys.path = orig_sys_path
 
+clownfish_extension = Extension('clownfish._clownfish',
+                                 include_dirs = [
+                                    CORE_SOURCE_DIR,
+                                    AUTOGEN_INCLUDE,
+                                    CFEXT_DIR,
+                                    os.curdir,
+                                 ],
+                                 extra_link_args = [LIBCLOWNFISH_PATH],
+                                 sources = c_filepaths)
+
 setup(name = 'clownfish',
       version = '0.4.0',
       description = 'Clownfish runtime',
@@ -154,7 +211,9 @@ setup(name = 'clownfish',
           'build': my_build,
           'clean': my_clean,
           'charmony': charmony,
+          'libclownfish': libclownfish,
           'test': test,
       },
-      package_dir={'': 'src'},)
+      package_dir={'': 'src'},
+      ext_modules = [clownfish_extension])
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bebd2447/runtime/python/src/clownfish/__init__.py
----------------------------------------------------------------------
diff --git a/runtime/python/src/clownfish/__init__.py b/runtime/python/src/clownfish/__init__.py
index 09697dc..5c3afae 100644
--- a/runtime/python/src/clownfish/__init__.py
+++ b/runtime/python/src/clownfish/__init__.py
@@ -13,3 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import clownfish._clownfish
+from clownfish._clownfish import *
+


[09/12] lucy-clownfish git commit: Gen stub Python extension file.

Posted by ma...@apache.org.
Gen stub Python extension file.

Generate a Python extension file, which is a stub for now.


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

Branch: refs/heads/master
Commit: 5b1631a961a49ac7f593c963c313fa6c3b5b8456
Parents: 856d7c1
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Jan 19 19:30:08 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 10:23:20 2016 -0800

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


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5b1631a9/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 729570a..2c57eb0 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -108,8 +108,68 @@ S_write_hostdefs(CFCPython *self) {
     FREEMEM(content);
 }
 
+static void
+S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
+    const char *parcel_name = CFCParcel_get_name(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 *last_dot = strrchr(pymod_name, '.');
+    const char *last_component = last_dot != NULL
+                                 ? last_dot + 1
+                                 : pymod_name;
+    char *helper_mod_name = CFCUtil_sprintf("%s._%s", pymod_name, last_component);
+    for (int i = 0; helper_mod_name[i] != '\0'; i++) {
+        helper_mod_name[i] = tolower(helper_mod_name[i]);
+    }
+
+    const char pattern[] =
+        "%s\n"
+        "\n"
+        "#include \"Python.h\"\n"
+        "#include \"cfish_parcel.h\"\n"
+        "#include \"CFBind.h\"\n"
+        "\n"
+        "static PyModuleDef module_def = {\n"
+        "    PyModuleDef_HEAD_INIT,\n"
+        "    \"%s\",\n" // module name
+        "    NULL,\n" // docstring
+        "    -1,\n"
+        "    NULL, NULL, NULL, NULL, NULL\n"
+        "};\n"
+        "\n"
+        "PyMODINIT_FUNC\n"
+        "PyInit__%s(void) {\n"
+        "    PyObject *module = PyModule_Create(&module_def);\n"
+        "    return module;\n"
+        "}\n"
+        "\n"
+        "%s\n"
+        "\n";
+
+    char *content
+        = CFCUtil_sprintf(pattern, self->header,
+                          helper_mod_name, last_component, self->footer);
+
+    char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
+                                     last_component);
+    CFCUtil_write_if_changed(filepath, content, strlen(content));
+    FREEMEM(filepath);
+
+    FREEMEM(content);
+    FREEMEM(helper_mod_name);
+    FREEMEM(pymod_name);
+}
+
 void
 CFCPython_write_bindings(CFCPython *self, const char *parcel_name, const char *dest) {
+    CFCParcel *parcel = CFCParcel_fetch(parcel_name);
+    if (parcel == NULL) {
+        CFCUtil_die("Unknown parcel: %s", parcel_name);
+    }
     S_write_hostdefs(self);
+    S_write_module_file(self, parcel, dest);
 }
 


[06/12] lucy-clownfish git commit: Add Python-specific details to charmonizer.

Posted by ma...@apache.org.
Add Python-specific details to charmonizer.


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

Branch: refs/heads/master
Commit: 1f30f3e7ef58c4ad84452be7d6da59d1f35b5304
Parents: d4f52d9
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Dec 16 09:54:46 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 09:58:13 2016 -0800

----------------------------------------------------------------------
 runtime/common/charmonizer.main | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1f30f3e7/runtime/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.main b/runtime/common/charmonizer.main
index dd919c6..7ddf0d7 100644
--- a/runtime/common/charmonizer.main
+++ b/runtime/common/charmonizer.main
@@ -288,7 +288,16 @@ cfish_MakeFile_new(chaz_CLI *cli) {
         self->host_src_dir = "ext";
         self->autogen_src_files = go_autogen_src_files;
     }
-    else if (strcmp(chaz_CLI_strval(cli, "host"), "perl") == 0) {
+    else if (chaz_CLI_defined(cli, "enable-python")) {
+        static const char *python_autogen_src_files[] = {
+            "cfish_parcel",
+            "testcfish_parcel",
+            NULL
+        };
+        self->host_src_dir = "cfext";
+        self->autogen_src_files = python_autogen_src_files;
+    }
+    else if (chaz_CLI_defined(cli, "enable-perl")) {
         static const char *perl_autogen_src_files[] = {
             "boot",
             "callbacks",


[04/12] lucy-clownfish git commit: Add CFCPython.

Posted by ma...@apache.org.
Add CFCPython.

Start with writing cfish_hostdefs.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/b10130e0
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/b10130e0
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/b10130e0

Branch: refs/heads/master
Commit: b10130e067253b05cb57c213157d6e901805eebe
Parents: 1cf2a6d
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Dec 18 18:43:29 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 09:58:13 2016 -0800

----------------------------------------------------------------------
 compiler/include/CFC.h         |   2 +
 compiler/python/src/cfc/_cfc.c | 125 ++++++++++++++++++++++++++++++++++--
 compiler/src/CFCPython.c       | 115 +++++++++++++++++++++++++++++++++
 compiler/src/CFCPython.h       |  63 ++++++++++++++++++
 4 files changed, 300 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b10130e0/compiler/include/CFC.h
----------------------------------------------------------------------
diff --git a/compiler/include/CFC.h b/compiler/include/CFC.h
index 9d1c222..1bdc968 100644
--- a/compiler/include/CFC.h
+++ b/compiler/include/CFC.h
@@ -57,5 +57,7 @@
 #include "CFCPerlPod.h"
 #include "CFCPerlTypeMap.h"
 
+#include "CFCPython.h"
+
 #include "CFCRuby.h"
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b10130e0/compiler/python/src/cfc/_cfc.c
----------------------------------------------------------------------
diff --git a/compiler/python/src/cfc/_cfc.c b/compiler/python/src/cfc/_cfc.c
index d20b5fa..24e45a4 100644
--- a/compiler/python/src/cfc/_cfc.c
+++ b/compiler/python/src/cfc/_cfc.c
@@ -103,9 +103,16 @@ S_to_BindCore(PyObject *wrapper) {
         "Clownfish::CFC::Binding::Core");
 }
 
+static CFCPython*
+S_to_BindPython(PyObject *wrapper) {
+    return (CFCPython*)S_to_cfc_something(wrapper,
+        "Clownfish::CFC::Binding::Python");
+}
+
 static PyTypeObject *Hierarchy_pytype;
 static PyTypeObject *Parcel_pytype;
 static PyTypeObject *BindCore_pytype;
+static PyTypeObject *BindPython_pytype;
 
 /***************************** CFCHierarchy *****************************/
 
@@ -173,6 +180,13 @@ S_CFCHierarchy_add_source_dir(PyObject *wrapper, PyObject *dir) {
 }
 
 static PyObject*
+S_CFCHierarchy_get_dest(PyObject *wrapper, PyObject *unused) {
+    CHY_UNUSED_VAR(unused);
+    const char *dest = CFCHierarchy_get_dest(S_to_Hierarchy(wrapper));
+    return PyUnicode_DecodeASCII(dest, strlen(dest), NULL);
+}
+
+static PyObject*
 S_CFCHierarchy_write_log(PyObject *wrapper, PyObject *unused) {
     CHY_UNUSED_VAR(unused);
     CFCHierarchy_write_log(S_to_Hierarchy(wrapper));
@@ -183,6 +197,7 @@ static PyMethodDef hierarchy_methods[] = {
     {"add_include_dir", (PyCFunction)S_CFCHierarchy_add_include_dir, METH_O,      NULL},
     {"add_source_dir",  (PyCFunction)S_CFCHierarchy_add_source_dir,  METH_O,      NULL},
     {"build",           (PyCFunction)S_CFCHierarchy_build,           METH_NOARGS, NULL},
+    {"get_dest",        (PyCFunction)S_CFCHierarchy_get_dest,        METH_NOARGS, NULL},
     {"write_log",       (PyCFunction)S_CFCHierarchy_write_log,       METH_NOARGS, NULL},
     {NULL}
 };
@@ -306,8 +321,13 @@ S_CFCBindCore_write_all_modified(PyObject *wrapper, PyObject *args) {
     int modified = 0;
     int result = PyArg_ParseTuple(args, "|p", &modified);
     if (!result) { return NULL; }
-    CFCBindCore_write_all_modified(S_to_BindCore(wrapper), modified);
-    Py_RETURN_NONE;
+    modified = CFCBindCore_write_all_modified(S_to_BindCore(wrapper), modified);
+    if (modified) {
+        Py_RETURN_TRUE;
+    }
+    else {
+        Py_RETURN_FALSE;
+    }
 }
 
 static PyMethodDef bindcore_methods[] = {
@@ -356,14 +376,103 @@ static PyTypeObject BindCore_pytype_struct = {
     (newfunc)S_CFCBindCore_new          // tp_new
 };
 
+/***************************** CFCPython *****************************/
+
+static PyObject*
+S_CFCPython_new(PyTypeObject *type, PyObject *args, PyObject *keyword_args) {
+    PyObject *hierarchy_wrapped;
+    char *keywords[] = {"hierarchy", NULL};
+    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "O!",
+                                             keywords, Hierarchy_pytype,
+                                             &hierarchy_wrapped);
+    if (!result) { return NULL; }
+    CFCHierarchy *hierarchy = S_to_Hierarchy(hierarchy_wrapped);
+    CFCPython *obj = CFCPython_new(hierarchy);
+    return S_wrap_cfcbase(BindPython_pytype, obj);
+}
+
+static PyObject*
+S_CFCPython_set_header(PyObject *wrapper, PyObject *header) {
+    CFCPython_set_header(S_to_BindPython(wrapper), PyUnicode_AsUTF8(header));
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+S_CFCPython_set_footer(PyObject *wrapper, PyObject *footer) {
+    CFCPython_set_footer(S_to_BindPython(wrapper), PyUnicode_AsUTF8(footer));
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+S_CFCPython_write_bindings(PyObject *wrapper, PyObject *args,
+                           PyObject *keyword_args) {
+    char *parcel;
+    char *dest;
+    char *keywords[] = {"parcel", "dest", NULL};
+    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "ss",
+                                             keywords, &parcel, &dest);
+    if (!result) { return NULL; }
+    CFCPython_write_bindings(S_to_BindPython(wrapper), parcel, dest);
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef bindpython_methods[] = {
+    {"set_header",     (PyCFunction)S_CFCPython_set_header,     METH_O, NULL},
+    {"set_footer",     (PyCFunction)S_CFCPython_set_footer,     METH_O, NULL},
+    {"write_bindings", (PyCFunction)S_CFCPython_write_bindings, METH_KEYWORDS|METH_VARARGS, NULL},
+    {NULL}
+};
+
+static PyTypeObject BindPython_pytype_struct = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "cfc.binding.Python",               // tp_name
+    sizeof(CFCPyWrapper),               // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)S_CFCBase_dealloc,      // tp_dealloc
+    0,                                  // tp_print
+    0,                                  // tp_getattr
+    0,                                  // tp_setattr
+    0,                                  // tp_reserved
+    0,                                  // tp_repr
+    0,                                  // tp_as_number
+    0,                                  // tp_as_sequence
+    0,                                  // tp_as_mapping
+    0,                                  // tp_hash
+    0,                                  // tp_call
+    0,                                  // tp_str
+    0,                                  // tp_getattro
+    0,                                  // tp_setattro
+    0,                                  // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "CFCBindPython",                    // tp_doc
+    0,                                  // tp_traverse
+    0,                                  // tp_clear
+    0,                                  // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    0,                                  // tp_iter
+    0,                                  // tp_iternext
+    bindpython_methods,                   // tp_methods
+    0,                                  // tp_members
+    0,                                  // tp_getset
+    0,                                  // tp_base
+    0,                                  // tp_dict
+    0,                                  // tp_descr_get
+    0,                                  // tp_descr_set
+    0,                                  // tp_dictoffset
+    0,                                  // tp_init
+    0,                                  // tp_allow
+    (newfunc)S_CFCPython_new            // tp_new
+};
+
 /******************************* common ******************************/
 
 PyMODINIT_FUNC
 PyInit__cfc(void) {
     // Initialize Python type objects.
-    Hierarchy_pytype = &Hierarchy_pytype_struct;
-    Parcel_pytype    = &Parcel_pytype_struct;
-    BindCore_pytype  = &BindCore_pytype_struct;
+    Hierarchy_pytype  = &Hierarchy_pytype_struct;
+    Parcel_pytype     = &Parcel_pytype_struct;
+    BindCore_pytype   = &BindCore_pytype_struct;
+    BindPython_pytype = &BindPython_pytype_struct;
     if (PyType_Ready(Hierarchy_pytype) < 0) {
         return NULL;
     }
@@ -373,6 +482,9 @@ PyInit__cfc(void) {
     if (PyType_Ready(BindCore_pytype) < 0) {
         return NULL;
     }
+    if (PyType_Ready(BindPython_pytype) < 0) {
+        return NULL;
+    }
 
     // Initialize modules.
     cfc_module = PyModule_Create(&cfc_module_def);
@@ -393,6 +505,9 @@ PyInit__cfc(void) {
     Py_INCREF(BindCore_pytype);
     PyModule_AddObject(cfc_binding_module, "BindCore",
                        (PyObject*)BindCore_pytype);
+    Py_INCREF(BindCore_pytype);
+    PyModule_AddObject(cfc_binding_module, "Python",
+                       (PyObject*)BindPython_pytype);
 
     return cfc_module;
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b10130e0/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
new file mode 100644
index 0000000..729570a
--- /dev/null
+++ b/compiler/src/CFCPython.c
@@ -0,0 +1,115 @@
+/* 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.
+ */
+
+#include "charmony.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#define CFC_NEED_BASE_STRUCT_DEF
+#include "CFCBase.h"
+#include "CFCPython.h"
+#include "CFCParcel.h"
+#include "CFCClass.h"
+#include "CFCMethod.h"
+#include "CFCHierarchy.h"
+#include "CFCUtil.h"
+#include "CFCBindCore.h"
+
+struct CFCPython {
+    CFCBase base;
+    CFCHierarchy *hierarchy;
+    char *header;
+    char *footer;
+};
+
+void
+S_destroy(CFCPython *self);
+
+static const CFCMeta CFCPYTHON_META = {
+    "Clownfish::CFC::Binding::Python",
+    sizeof(CFCPython),
+    (CFCBase_destroy_t)S_destroy
+};
+
+CFCPython*
+CFCPython_new(CFCHierarchy *hierarchy) {
+    CFCUTIL_NULL_CHECK(hierarchy);
+    CFCPython *self = (CFCPython*)CFCBase_allocate(&CFCPYTHON_META);
+    self->hierarchy  = (CFCHierarchy*)CFCBase_incref((CFCBase*)hierarchy);
+    self->header     = CFCUtil_strdup("");
+    self->footer     = CFCUtil_strdup("");
+    return self;
+}
+
+void
+S_destroy(CFCPython *self) {
+    CFCBase_decref((CFCBase*)self->hierarchy);
+    FREEMEM(self->header);
+    FREEMEM(self->footer);
+    CFCBase_destroy((CFCBase*)self);
+}
+
+void
+CFCPython_set_header(CFCPython *self, const char *header) {
+    CFCUTIL_NULL_CHECK(header);
+    free(self->header);
+    self->header = CFCUtil_make_c_comment(header);
+}
+
+void
+CFCPython_set_footer(CFCPython *self, const char *footer) {
+    CFCUTIL_NULL_CHECK(footer);
+    free(self->footer);
+    self->footer = CFCUtil_make_c_comment(footer);
+}
+
+static void
+S_write_hostdefs(CFCPython *self) {
+    const char pattern[] =
+        "%s\n"
+        "\n"
+        "#ifndef H_CFISH_HOSTDEFS\n"
+        "#define H_CFISH_HOSTDEFS 1\n"
+        "\n"
+        "#include \"Python.h\"\n"
+        "\n"
+        "#define CFISH_OBJ_HEAD \\\n"
+        "    PyObject_HEAD\n"
+        "\n"
+        "#endif /* H_CFISH_HOSTDEFS */\n"
+        "\n"
+        "%s\n";
+    char *content
+        = CFCUtil_sprintf(pattern, self->header, self->footer);
+
+    // Write if the content has changed.
+    const char *inc_dest = CFCHierarchy_get_include_dest(self->hierarchy);
+    char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "cfish_hostdefs.h",
+                                     inc_dest);
+    CFCUtil_write_if_changed(filepath, content, strlen(content));
+
+    FREEMEM(filepath);
+    FREEMEM(content);
+}
+
+void
+CFCPython_write_bindings(CFCPython *self, const char *parcel_name, const char *dest) {
+    S_write_hostdefs(self);
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b10130e0/compiler/src/CFCPython.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.h b/compiler/src/CFCPython.h
new file mode 100644
index 0000000..6fa846a
--- /dev/null
+++ b/compiler/src/CFCPython.h
@@ -0,0 +1,63 @@
+/* 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_CFCPYTHON
+#define H_CFCPYTHON
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct CFCPython CFCPython;
+struct CFCParcel;
+struct CFCHierarchy;
+
+/** Clownfish::CFC::Binding::Python - Python bindings for a
+ * Clownfish::CFC::Model::Hierarchy.
+ *
+ * Clownfish::CFC::Binding::Python presents an interface for auto-generating
+ * Python C API code to bind to a Clownfish class hierarchy.
+ */
+
+/**
+ * @param hierarchy A CFCHierarchy.
+ */
+
+CFCPython*
+CFCPython_new(struct CFCHierarchy *hierarchy);
+
+/** Set the text which will be prepended to generated C files -- for
+ * instance, an "autogenerated file" warning.
+ */
+void
+CFCPython_set_header(CFCPython *self, const char *header);
+
+/** Set the text which will be appended to the end of generated C files.
+ */
+void
+CFCPython_set_footer(CFCPython *self, const char *footer);
+
+/** Generate Python bindings for the specified parcel.
+ */
+void
+CFCPython_write_bindings(CFCPython *self, const char *parcel, const char *dest);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_CFCPYTHON */
+


[07/12] lucy-clownfish git commit: Start runtime Python bindings.

Posted by ma...@apache.org.
Start runtime Python bindings.

Add setup.py which only runs charmonizer and cleanup targets.  Add a
stub __init__.py file.


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

Branch: refs/heads/master
Commit: 856d7c1d84c619bcaa44cc992e575e8052af630a
Parents: b10130e
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Jan 19 18:25:51 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 10:23:08 2016 -0800

----------------------------------------------------------------------
 runtime/python/setup.py                  | 130 ++++++++++++++++++++++++++
 runtime/python/src/clownfish/__init__.py |  15 +++
 2 files changed, 145 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/856d7c1d/runtime/python/setup.py
----------------------------------------------------------------------
diff --git a/runtime/python/setup.py b/runtime/python/setup.py
new file mode 100644
index 0000000..a522cb9
--- /dev/null
+++ b/runtime/python/setup.py
@@ -0,0 +1,130 @@
+# 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.
+
+from distutils.core import setup
+from distutils.command.build import build as _build
+from distutils.command.clean import clean as _clean
+from distutils.cmd import Command as _Command
+from distutils.dep_util import newer_group
+import distutils.ccompiler
+import os
+import glob
+import shutil
+import subprocess
+import sysconfig
+
+# Get a compiler object and and strings representing the compiler type and
+# CFLAGS.  Add the Python headers include dir to CFLAGS.
+compiler = distutils.ccompiler.new_compiler()
+cflags = sysconfig.get_config_var('CFLAGS')
+compiler_type = distutils.ccompiler.get_default_compiler()
+
+# There's no public way to get a string representing the compiler executable
+# out of distutils, but the member variable has been in the same place for a
+# long time, so violating encapsulation may be ok.
+compiler_name = " ".join(compiler.compiler)
+make_command = "make" # TODO portability
+
+BASE_DIR        = os.path.abspath(os.path.join(os.pardir, os.pardir))
+PARENT_DIR      = os.path.abspath(os.pardir)
+CORE_SOURCE_DIR = os.path.join(PARENT_DIR, 'core')
+CFEXT_DIR       = 'cfext'
+COMMON_SOURCE_DIR    = os.path.join(PARENT_DIR, 'common')
+CHARMONIZER_C        = os.path.join(COMMON_SOURCE_DIR, 'charmonizer.c')
+CHARMONIZER_EXE_NAME = compiler.executable_filename('charmonizer')
+CHARMONIZER_EXE_PATH = os.path.join(os.curdir, CHARMONIZER_EXE_NAME)
+CHARMONY_H_PATH      = 'charmony.h'
+
+c_filepaths = []
+paths_to_clean = [
+    CHARMONIZER_EXE_PATH,
+    CHARMONY_H_PATH,
+    '_charm*',
+]
+
+def _quotify(text):
+    text = text.replace('\\', '\\\\')
+    text = text.replace('"', '\\"')
+    return '"' + text + '"'
+
+class charmony(_Command):
+    description = "Build and run charmonizer"
+    user_options = []
+    def initialize_options(self):
+        pass
+    def finalize_options(self):
+        pass
+    def run(self):
+        # Compile charmonizer.
+        if newer_group([CHARMONIZER_C], CHARMONIZER_EXE_PATH):
+            command = [compiler_name]
+            if compiler_type == 'msvc':
+                command.append('/Fe' + CHARMONIZER_EXE_PATH)
+            else:
+                command.extend(['-o', CHARMONIZER_EXE_PATH])
+            command.append(CHARMONIZER_C)
+            print(" ".join(command))
+            subprocess.check_call(command)
+
+        # Run charmonizer.
+        if newer_group([CHARMONIZER_EXE_PATH], CHARMONY_H_PATH):
+            command = [
+                CHARMONIZER_EXE_PATH,
+                '--cc=' + _quotify(compiler_name),
+                '--enable-c',
+                '--enable-python',
+                '--host=python',
+                '--enable-makefile',
+                '--',
+                cflags
+            ]
+            if 'CHARM_VALGRIND' in os.environ:
+                command[0:0] = "valgrind", "--leak-check=yes";
+            print(" ".join(command))
+            subprocess.check_call(command)
+
+class my_clean(_clean):
+    def run(self):
+        _clean.run(self)
+        if os.path.isfile("Makefile"):
+            subprocess.check_call([make_command, 'distclean'])
+        for elem in paths_to_clean:
+            for path in glob.glob(elem):
+                print("removing " + path)
+                if os.path.isdir(path):
+                    shutil.rmtree(path)
+                else:
+                    os.unlink(path)
+
+class my_build(_build):
+    def run(self):
+        self.run_command('charmony')
+        _build.run(self)
+
+setup(name = 'clownfish',
+      version = '0.4.0',
+      description = 'Clownfish runtime',
+      author = 'Apache Lucy Project',
+      author_email = 'dev at lucy dot apache dot org',
+      url = 'http://lucy.apache.org',
+      packages = ['clownfish',
+                 ],
+      cmdclass = {
+          'build': my_build,
+          'clean': my_clean,
+          'charmony': charmony,
+      },
+      package_dir={'': 'src'},)
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/856d7c1d/runtime/python/src/clownfish/__init__.py
----------------------------------------------------------------------
diff --git a/runtime/python/src/clownfish/__init__.py b/runtime/python/src/clownfish/__init__.py
new file mode 100644
index 0000000..09697dc
--- /dev/null
+++ b/runtime/python/src/clownfish/__init__.py
@@ -0,0 +1,15 @@
+# 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.
+


[12/12] lucy-clownfish git commit: Merge branch 'CLOWNFISH-66-stub-py-runtime'

Posted by ma...@apache.org.
Merge branch 'CLOWNFISH-66-stub-py-runtime'

Stub out Python bindings for the Clownfish runtime.

* Compile the core runtime code into a static archive.
* Stub out Python versions of host-specific functions.
* Define the hostdefs for Python.
* Autogenerate a C module file.
* Add a simple Python test file which loads the module.
* Add `setup.py` with `build`, `test`, and `clean` targets.

To test, run `python3 setup.py test` under `compiler/python`, then again
under `runtime/python`. Afterwards, clean up using `python3 setup.py
clean --all`.

The build is fragile and incomplete, but the test passes on OS X with
Python 3.5.1.

This closes #55.


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

Branch: refs/heads/master
Commit: 9debabe4dba6fce1d0c54f898d302fbfb5d151e7
Parents: c75ee92 bebd244
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Feb 9 09:07:33 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 9 09:07:33 2016 -0800

----------------------------------------------------------------------
 compiler/include/CFC.h                    |   2 +
 compiler/python/clownfish/_cfc.c          | 400 -------------------
 compiler/python/clownfish/cfc/__init__.py |  29 --
 compiler/python/setup.py                  |   9 +-
 compiler/python/src/cfc/__init__.py       |  29 ++
 compiler/python/src/cfc/_cfc.c            | 515 +++++++++++++++++++++++++
 compiler/python/test/test_cfc.py          |   2 +-
 compiler/src/CFCPyTypeMap.c               |  71 ++++
 compiler/src/CFCPyTypeMap.h               |  43 +++
 compiler/src/CFCPython.c                  | 175 +++++++++
 compiler/src/CFCPython.h                  |  63 +++
 runtime/common/charmonizer.c              |  11 +-
 runtime/common/charmonizer.main           |  11 +-
 runtime/python/cfext/CFBind.c             | 241 ++++++++++++
 runtime/python/cfext/CFBind.h             |  32 ++
 runtime/python/setup.py                   | 219 +++++++++++
 runtime/python/src/clownfish/__init__.py  |  18 +
 runtime/python/test/test_clownfish.py     |  27 ++
 18 files changed, 1461 insertions(+), 436 deletions(-)
----------------------------------------------------------------------



[02/12] lucy-clownfish git commit: Move Python files under `src`.

Posted by ma...@apache.org.
Move Python files under `src`.

Moving the Python source directory into `src` means that the files are
no longer findable by python running in the python/ directory because
the current directory is on sys.path.  In later versions of Python, this
becomes an issue because the source dir (which does not contain any
shared objects) shadows the build directory (where shared objects get put).


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

Branch: refs/heads/master
Commit: 47234c3d8f223d05930e2cb72de1ad01c8c9ed32
Parents: c75ee92
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Dec 29 19:18:51 2014 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 09:58:12 2016 -0800

----------------------------------------------------------------------
 compiler/python/clownfish/_cfc.c              | 400 ---------------------
 compiler/python/clownfish/cfc/__init__.py     |  29 --
 compiler/python/setup.py                      |   5 +-
 compiler/python/src/clownfish/_cfc.c          | 400 +++++++++++++++++++++
 compiler/python/src/clownfish/cfc/__init__.py |  29 ++
 5 files changed, 432 insertions(+), 431 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/47234c3d/compiler/python/clownfish/_cfc.c
----------------------------------------------------------------------
diff --git a/compiler/python/clownfish/_cfc.c b/compiler/python/clownfish/_cfc.c
deleted file mode 100644
index 706943f..0000000
--- a/compiler/python/clownfish/_cfc.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/* 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.
- */
-
-#include "Python.h"
-#include "CFC.h"
-
-typedef struct {
-    PyObject_HEAD
-    void *cfc_obj;
-} CFCPyWrapper;
-
-static PyModuleDef cfc_module_def = {
-    PyModuleDef_HEAD_INIT,
-    "clownfish._cfc",
-    "CFC: Clownfish compiler",
-    -1,
-    NULL, NULL, NULL, NULL, NULL
-};
-
-static PyModuleDef cfc_model_module_def = {
-    PyModuleDef_HEAD_INIT,
-    "clownfish.cfc.model",
-    "CFC classes which model language constructs",
-    -1,
-    NULL, NULL, NULL, NULL, NULL
-};
-
-static PyModuleDef cfc_binding_module_def = {
-    PyModuleDef_HEAD_INIT,
-    "clownfish.cfc.binding",
-    "CFC components which generate bindings",
-    -1,
-    NULL, NULL, NULL, NULL, NULL
-};
-
-static PyObject *cfc_module;
-static PyObject *cfc_model_module;
-static PyObject *cfc_binding_module;
-
-static PyObject*
-S_wrap_cfcbase(PyTypeObject *type, void *cfc_obj) {
-    if (cfc_obj == NULL) {
-        Py_RETURN_NONE;
-    }
-    CFCPyWrapper *wrapper = (CFCPyWrapper*)type->tp_alloc(type, 0);
-    if (wrapper == NULL) {
-        PyErr_SetString(PyExc_RuntimeError, "Failed to allocate object");
-        return NULL;
-    }
-    wrapper->cfc_obj = cfc_obj;
-    return (PyObject*)wrapper;
-}
-
-static void
-S_CFCBase_dealloc(CFCPyWrapper *wrapper) {
-    CFCBase *temp = (CFCBase*)wrapper->cfc_obj;
-    wrapper->cfc_obj = NULL;
-    CFCBase_decref(temp);
-    Py_TYPE(wrapper)->tp_free(wrapper);
-}
-
-void*
-S_to_cfc_something(PyObject *wrapper, const char *class_name) {
-    if (wrapper == NULL || wrapper == Py_None) {
-        return NULL;
-    }
-    CFCBase *obj = (CFCBase*)((CFCPyWrapper*)wrapper)->cfc_obj;
-    if (strcmp(CFCBase_get_cfc_class(obj), class_name) != 0) {
-        CFCUtil_die("Object is not a %s, it's a %s", class_name,
-                    CFCBase_get_cfc_class(obj));
-    }
-    return obj;
-}
-
-static CFCHierarchy*
-S_to_Hierarchy(PyObject *wrapper) {
-    return (CFCHierarchy*)S_to_cfc_something(wrapper,
-        "Clownfish::CFC::Model::Hierarchy");
-}
-
-static CFCParcel*
-S_to_Parcel(PyObject *wrapper) {
-    return (CFCParcel*)S_to_cfc_something(wrapper,
-        "Clownfish::CFC::Model::Parcel");
-}
-
-static CFCBindCore*
-S_to_BindCore(PyObject *wrapper) {
-    return (CFCBindCore*)S_to_cfc_something(wrapper,
-        "Clownfish::CFC::Binding::Core");
-}
-
-static PyTypeObject *Hierarchy_pytype;
-static PyTypeObject *Parcel_pytype;
-static PyTypeObject *BindCore_pytype;
-
-/***************************** CFCHierarchy *****************************/
-
-static PyObject*
-S_CFCHierarchy_new(PyTypeObject *type, PyObject *args,
-                   PyObject *keyword_args) {
-    char *dest = NULL;
-    char *keywords[] = {"dest", NULL};
-    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "|s",
-                                             keywords, &dest);
-    if (!result) { return NULL; }
-    if (!dest) {
-        PyErr_SetString(PyExc_TypeError, "Missing required arg 'dest'");
-        return NULL;
-    }
-    PyObject *inc_func = PyObject_GetAttrString(cfc_module, "_get_inc_dirs");
-    PyObject *dirs = NULL;
-    if (PyCallable_Check(inc_func)) {
-        dirs = PyObject_CallObject(inc_func, NULL);
-    }
-    if (dirs == NULL || !PyList_Check(dirs)) {
-        Py_XDECREF(inc_func);
-        Py_XDECREF(dirs);
-        PyErr_SetString(PyExc_RuntimeError, "_get_inc_dirs failed");
-        return NULL;
-    }
-    CFCHierarchy *hierarchy = CFCHierarchy_new(dest);
-    for (Py_ssize_t i = 0, max = PyList_Size(dirs); i < max; i++) {
-        PyObject *dir = PyList_GetItem(dirs, i);
-        if (PyUnicode_Check(dir)) {
-            char *dir_utf8 = PyUnicode_AsUTF8(dir);
-            CFCHierarchy_add_include_dir(hierarchy, dir_utf8);
-        }
-        else {
-            PyErr_SetString(PyExc_RuntimeError, "not a string");
-            return NULL;
-        }
-    }
-
-    Py_XDECREF(inc_func);
-    Py_XDECREF(dirs);
-
-    return S_wrap_cfcbase(Hierarchy_pytype, hierarchy);
-}
-
-static PyObject*
-S_CFCHierarchy_build(PyObject *wrapper, PyObject *unused) {
-    CHY_UNUSED_VAR(unused);
-    CFCHierarchy_build(S_to_Hierarchy(wrapper));
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-S_CFCHierarchy_add_include_dir(PyObject *wrapper, PyObject *dir) {
-    CFCHierarchy_add_include_dir(S_to_Hierarchy(wrapper),
-                                 PyUnicode_AsUTF8(dir));
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-S_CFCHierarchy_add_source_dir(PyObject *wrapper, PyObject *dir) {
-    CFCHierarchy_add_source_dir(S_to_Hierarchy(wrapper),
-                                PyUnicode_AsUTF8(dir));
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-S_CFCHierarchy_write_log(PyObject *wrapper, PyObject *unused) {
-    CHY_UNUSED_VAR(unused);
-    CFCHierarchy_write_log(S_to_Hierarchy(wrapper));
-    Py_RETURN_NONE;
-}
-
-static PyMethodDef hierarchy_methods[] = {
-    {"add_include_dir", (PyCFunction)S_CFCHierarchy_add_include_dir, METH_O,      NULL},
-    {"add_source_dir",  (PyCFunction)S_CFCHierarchy_add_source_dir,  METH_O,      NULL},
-    {"build",           (PyCFunction)S_CFCHierarchy_build,           METH_NOARGS, NULL},
-    {"write_log",       (PyCFunction)S_CFCHierarchy_write_log,       METH_NOARGS, NULL},
-    {NULL}
-};
-
-static PyTypeObject Hierarchy_pytype_struct = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "clownfish.cfc.model.Hierarchy",    // tp_name
-    sizeof(CFCPyWrapper),               // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)S_CFCBase_dealloc,      // tp_dealloc
-    0,                                  // tp_print
-    0,                                  // tp_getattr
-    0,                                  // tp_setattr
-    0,                                  // tp_reserved
-    0,                                  // tp_repr
-    0,                                  // tp_as_number
-    0,                                  // tp_as_sequence
-    0,                                  // tp_as_mapping
-    0,                                  // tp_hash
-    0,                                  // tp_call
-    0,                                  // tp_str
-    0,                                  // tp_getattro
-    0,                                  // tp_setattro
-    0,                                  // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "CFCHierarchy",                     // tp_doc
-    0,                                  // tp_traverse
-    0,                                  // tp_clear
-    0,                                  // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    0,                                  // tp_iter
-    0,                                  // tp_iternext
-    hierarchy_methods,                  // tp_methods
-    0,                                  // tp_members
-    0,                                  // tp_getset
-    0,                                  // tp_base
-    0,                                  // tp_dict
-    0,                                  // tp_descr_get
-    0,                                  // tp_descr_set
-    0,                                  // tp_dictoffset
-    0,                                  // tp_init
-    0,                                  // tp_allow
-    (newfunc)S_CFCHierarchy_new         // tp_new
-};
-
-/***************************** CFCParcel *****************************/
-
-PyObject*
-S_CFCParcel_fetch(PyObject *ignored, PyObject *name) {
-    CFCParcel *parcel = CFCParcel_fetch(PyUnicode_AsUTF8(name));
-    return S_wrap_cfcbase(Parcel_pytype, parcel);
-}
-
-static PyMethodDef parcel_methods[] = {
-    {"fetch", (PyCFunction)S_CFCParcel_fetch, METH_STATIC, NULL},
-    {NULL}
-};
-
-static PyTypeObject Parcel_pytype_struct = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "clownfish.cfc.model.Parcel",       // tp_name
-    sizeof(CFCPyWrapper),               // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)S_CFCBase_dealloc,      // tp_dealloc
-    0,                                  // tp_print
-    0,                                  // tp_getattr
-    0,                                  // tp_setattr
-    0,                                  // tp_reserved
-    0,                                  // tp_repr
-    0,                                  // tp_as_number
-    0,                                  // tp_as_sequence
-    0,                                  // tp_as_mapping
-    0,                                  // tp_hash
-    0,                                  // tp_call
-    0,                                  // tp_str
-    0,                                  // tp_getattro
-    0,                                  // tp_setattro
-    0,                                  // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "CFCParcel",                        // tp_doc
-    0,                                  // tp_traverse
-    0,                                  // tp_clear
-    0,                                  // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    0,                                  // tp_iter
-    0,                                  // tp_iternext
-    parcel_methods,                     // tp_methods
-    0,                                  // tp_members
-    0,                                  // tp_getset
-    0,                                  // tp_base
-    0,                                  // tp_dict
-    0,                                  // tp_descr_get
-    0,                                  // tp_descr_set
-    0,                                  // tp_dictoffset
-    0,                                  // tp_init
-    0,                                  // tp_allow
-    0                                   // tp_new
-};
-
-/***************************** CFCBindCore *****************************/
-
-static PyObject*
-S_CFCBindCore_new(PyTypeObject *type, PyObject *args,
-                   PyObject *keyword_args) {
-    PyObject *hierarchy_wrapped;
-    char *header = "";
-    char *footer = "";
-    char *keywords[] = {"hierarchy", "header", "footer", NULL};
-    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "O!|ss",
-                                             keywords, Hierarchy_pytype,
-                                             &hierarchy_wrapped, &header,
-                                             &footer);
-    if (!result) { return NULL; }
-    CFCHierarchy *hierarchy = S_to_Hierarchy(hierarchy_wrapped);
-    CFCBindCore *obj = CFCBindCore_new(hierarchy, header, footer);
-    return S_wrap_cfcbase(BindCore_pytype, obj);
-}
-
-static PyObject*
-S_CFCBindCore_write_all_modified(PyObject *wrapper, PyObject *args) {
-    int modified = 0;
-    int result = PyArg_ParseTuple(args, "|p", &modified);
-    if (!result) { return NULL; }
-    CFCBindCore_write_all_modified(S_to_BindCore(wrapper), modified);
-    Py_RETURN_NONE;
-}
-
-static PyMethodDef bindcore_methods[] = {
-    {"write_all_modified", (PyCFunction)S_CFCBindCore_write_all_modified, METH_VARARGS, NULL},
-    {NULL}
-};
-
-static PyTypeObject BindCore_pytype_struct = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "clownfish.cfc.binding.BindCore",   // tp_name
-    sizeof(CFCPyWrapper),               // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)S_CFCBase_dealloc,      // tp_dealloc
-    0,                                  // tp_print
-    0,                                  // tp_getattr
-    0,                                  // tp_setattr
-    0,                                  // tp_reserved
-    0,                                  // tp_repr
-    0,                                  // tp_as_number
-    0,                                  // tp_as_sequence
-    0,                                  // tp_as_mapping
-    0,                                  // tp_hash
-    0,                                  // tp_call
-    0,                                  // tp_str
-    0,                                  // tp_getattro
-    0,                                  // tp_setattro
-    0,                                  // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "CFCBindCore",                      // tp_doc
-    0,                                  // tp_traverse
-    0,                                  // tp_clear
-    0,                                  // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    0,                                  // tp_iter
-    0,                                  // tp_iternext
-    bindcore_methods,                   // tp_methods
-    0,                                  // tp_members
-    0,                                  // tp_getset
-    0,                                  // tp_base
-    0,                                  // tp_dict
-    0,                                  // tp_descr_get
-    0,                                  // tp_descr_set
-    0,                                  // tp_dictoffset
-    0,                                  // tp_init
-    0,                                  // tp_allow
-    (newfunc)S_CFCBindCore_new          // tp_new
-};
-
-/******************************* common ******************************/
-
-PyMODINIT_FUNC
-PyInit__cfc(void) {
-    // Initialize Python type objects.
-    Hierarchy_pytype = &Hierarchy_pytype_struct;
-    Parcel_pytype    = &Parcel_pytype_struct;
-    BindCore_pytype  = &BindCore_pytype_struct;
-    if (PyType_Ready(Hierarchy_pytype) < 0) {
-        return NULL;
-    }
-    if (PyType_Ready(Parcel_pytype) < 0) {
-        return NULL;
-    }
-    if (PyType_Ready(BindCore_pytype) < 0) {
-        return NULL;
-    }
-
-    // Initialize modules.
-    cfc_module = PyModule_Create(&cfc_module_def);
-    cfc_model_module = PyModule_Create(&cfc_model_module_def);
-    cfc_binding_module = PyModule_Create(&cfc_binding_module_def);
-    PyModule_AddObject(cfc_module, "model", (PyObject*)cfc_model_module);
-    PyModule_AddObject(cfc_module, "binding", (PyObject*)cfc_binding_module);
-
-    // Add type objects to "model" module.
-    Py_INCREF(Hierarchy_pytype);
-    PyModule_AddObject(cfc_model_module, "Hierarchy",
-                       (PyObject*)Hierarchy_pytype);
-    Py_INCREF(Parcel_pytype);
-    PyModule_AddObject(cfc_model_module, "Parcel",
-                       (PyObject*)Parcel_pytype);
-
-    // Add type objects to "binding" module.
-    Py_INCREF(BindCore_pytype);
-    PyModule_AddObject(cfc_binding_module, "BindCore",
-                       (PyObject*)BindCore_pytype);
-
-    return cfc_module;
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/47234c3d/compiler/python/clownfish/cfc/__init__.py
----------------------------------------------------------------------
diff --git a/compiler/python/clownfish/cfc/__init__.py b/compiler/python/clownfish/cfc/__init__.py
deleted file mode 100644
index f7f3e0b..0000000
--- a/compiler/python/clownfish/cfc/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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 clownfish._cfc
-from clownfish._cfc import *
-import site
-import os.path
-
-def _get_inc_dirs():
-    dirs = []
-    for path in site.getsitepackages():
-        path = os.path.join(path, "clownfish/_include")
-        dirs.append(path)
-    return dirs
-
-clownfish._cfc._get_inc_dirs = _get_inc_dirs
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/47234c3d/compiler/python/setup.py
----------------------------------------------------------------------
diff --git a/compiler/python/setup.py b/compiler/python/setup.py
index ccfba55..e140161 100644
--- a/compiler/python/setup.py
+++ b/compiler/python/setup.py
@@ -53,7 +53,7 @@ CHARMONY_H_PATH      = 'charmony.h'
 LIBCFC_NAME          = 'libcfc.a' # TODO portability
 LIBCFC_PATH          = os.path.abspath(os.path.join(os.curdir, LIBCFC_NAME))
 
-c_filepaths = [os.path.join('clownfish', '_cfc.c')]
+c_filepaths = [os.path.join('src', 'clownfish', '_cfc.c')]
 paths_to_clean = [
     CHARMONIZER_EXE_PATH,
     CHARMONY_H_PATH,
@@ -111,7 +111,7 @@ class libcfc(_Command):
         self.run_command('charmony')
         subprocess.check_call([make_command, '-j', 'static'])
         # Touch Python binding file if the library has changed.
-        cfc_c = os.path.join('clownfish', '_cfc.c')
+        cfc_c = os.path.join('src', 'clownfish', '_cfc.c')
         if newer_group(['libcfc.a'], cfc_c):
             os.utime(cfc_c, None)
 
@@ -186,5 +186,6 @@ setup(name = 'clownfish-cfc',
           'libcfc': libcfc,
           'test': test,
       },
+      package_dir={'': 'src'},
       ext_modules = [cfc_extension])
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/47234c3d/compiler/python/src/clownfish/_cfc.c
----------------------------------------------------------------------
diff --git a/compiler/python/src/clownfish/_cfc.c b/compiler/python/src/clownfish/_cfc.c
new file mode 100644
index 0000000..706943f
--- /dev/null
+++ b/compiler/python/src/clownfish/_cfc.c
@@ -0,0 +1,400 @@
+/* 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.
+ */
+
+#include "Python.h"
+#include "CFC.h"
+
+typedef struct {
+    PyObject_HEAD
+    void *cfc_obj;
+} CFCPyWrapper;
+
+static PyModuleDef cfc_module_def = {
+    PyModuleDef_HEAD_INIT,
+    "clownfish._cfc",
+    "CFC: Clownfish compiler",
+    -1,
+    NULL, NULL, NULL, NULL, NULL
+};
+
+static PyModuleDef cfc_model_module_def = {
+    PyModuleDef_HEAD_INIT,
+    "clownfish.cfc.model",
+    "CFC classes which model language constructs",
+    -1,
+    NULL, NULL, NULL, NULL, NULL
+};
+
+static PyModuleDef cfc_binding_module_def = {
+    PyModuleDef_HEAD_INIT,
+    "clownfish.cfc.binding",
+    "CFC components which generate bindings",
+    -1,
+    NULL, NULL, NULL, NULL, NULL
+};
+
+static PyObject *cfc_module;
+static PyObject *cfc_model_module;
+static PyObject *cfc_binding_module;
+
+static PyObject*
+S_wrap_cfcbase(PyTypeObject *type, void *cfc_obj) {
+    if (cfc_obj == NULL) {
+        Py_RETURN_NONE;
+    }
+    CFCPyWrapper *wrapper = (CFCPyWrapper*)type->tp_alloc(type, 0);
+    if (wrapper == NULL) {
+        PyErr_SetString(PyExc_RuntimeError, "Failed to allocate object");
+        return NULL;
+    }
+    wrapper->cfc_obj = cfc_obj;
+    return (PyObject*)wrapper;
+}
+
+static void
+S_CFCBase_dealloc(CFCPyWrapper *wrapper) {
+    CFCBase *temp = (CFCBase*)wrapper->cfc_obj;
+    wrapper->cfc_obj = NULL;
+    CFCBase_decref(temp);
+    Py_TYPE(wrapper)->tp_free(wrapper);
+}
+
+void*
+S_to_cfc_something(PyObject *wrapper, const char *class_name) {
+    if (wrapper == NULL || wrapper == Py_None) {
+        return NULL;
+    }
+    CFCBase *obj = (CFCBase*)((CFCPyWrapper*)wrapper)->cfc_obj;
+    if (strcmp(CFCBase_get_cfc_class(obj), class_name) != 0) {
+        CFCUtil_die("Object is not a %s, it's a %s", class_name,
+                    CFCBase_get_cfc_class(obj));
+    }
+    return obj;
+}
+
+static CFCHierarchy*
+S_to_Hierarchy(PyObject *wrapper) {
+    return (CFCHierarchy*)S_to_cfc_something(wrapper,
+        "Clownfish::CFC::Model::Hierarchy");
+}
+
+static CFCParcel*
+S_to_Parcel(PyObject *wrapper) {
+    return (CFCParcel*)S_to_cfc_something(wrapper,
+        "Clownfish::CFC::Model::Parcel");
+}
+
+static CFCBindCore*
+S_to_BindCore(PyObject *wrapper) {
+    return (CFCBindCore*)S_to_cfc_something(wrapper,
+        "Clownfish::CFC::Binding::Core");
+}
+
+static PyTypeObject *Hierarchy_pytype;
+static PyTypeObject *Parcel_pytype;
+static PyTypeObject *BindCore_pytype;
+
+/***************************** CFCHierarchy *****************************/
+
+static PyObject*
+S_CFCHierarchy_new(PyTypeObject *type, PyObject *args,
+                   PyObject *keyword_args) {
+    char *dest = NULL;
+    char *keywords[] = {"dest", NULL};
+    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "|s",
+                                             keywords, &dest);
+    if (!result) { return NULL; }
+    if (!dest) {
+        PyErr_SetString(PyExc_TypeError, "Missing required arg 'dest'");
+        return NULL;
+    }
+    PyObject *inc_func = PyObject_GetAttrString(cfc_module, "_get_inc_dirs");
+    PyObject *dirs = NULL;
+    if (PyCallable_Check(inc_func)) {
+        dirs = PyObject_CallObject(inc_func, NULL);
+    }
+    if (dirs == NULL || !PyList_Check(dirs)) {
+        Py_XDECREF(inc_func);
+        Py_XDECREF(dirs);
+        PyErr_SetString(PyExc_RuntimeError, "_get_inc_dirs failed");
+        return NULL;
+    }
+    CFCHierarchy *hierarchy = CFCHierarchy_new(dest);
+    for (Py_ssize_t i = 0, max = PyList_Size(dirs); i < max; i++) {
+        PyObject *dir = PyList_GetItem(dirs, i);
+        if (PyUnicode_Check(dir)) {
+            char *dir_utf8 = PyUnicode_AsUTF8(dir);
+            CFCHierarchy_add_include_dir(hierarchy, dir_utf8);
+        }
+        else {
+            PyErr_SetString(PyExc_RuntimeError, "not a string");
+            return NULL;
+        }
+    }
+
+    Py_XDECREF(inc_func);
+    Py_XDECREF(dirs);
+
+    return S_wrap_cfcbase(Hierarchy_pytype, hierarchy);
+}
+
+static PyObject*
+S_CFCHierarchy_build(PyObject *wrapper, PyObject *unused) {
+    CHY_UNUSED_VAR(unused);
+    CFCHierarchy_build(S_to_Hierarchy(wrapper));
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+S_CFCHierarchy_add_include_dir(PyObject *wrapper, PyObject *dir) {
+    CFCHierarchy_add_include_dir(S_to_Hierarchy(wrapper),
+                                 PyUnicode_AsUTF8(dir));
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+S_CFCHierarchy_add_source_dir(PyObject *wrapper, PyObject *dir) {
+    CFCHierarchy_add_source_dir(S_to_Hierarchy(wrapper),
+                                PyUnicode_AsUTF8(dir));
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+S_CFCHierarchy_write_log(PyObject *wrapper, PyObject *unused) {
+    CHY_UNUSED_VAR(unused);
+    CFCHierarchy_write_log(S_to_Hierarchy(wrapper));
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef hierarchy_methods[] = {
+    {"add_include_dir", (PyCFunction)S_CFCHierarchy_add_include_dir, METH_O,      NULL},
+    {"add_source_dir",  (PyCFunction)S_CFCHierarchy_add_source_dir,  METH_O,      NULL},
+    {"build",           (PyCFunction)S_CFCHierarchy_build,           METH_NOARGS, NULL},
+    {"write_log",       (PyCFunction)S_CFCHierarchy_write_log,       METH_NOARGS, NULL},
+    {NULL}
+};
+
+static PyTypeObject Hierarchy_pytype_struct = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "clownfish.cfc.model.Hierarchy",    // tp_name
+    sizeof(CFCPyWrapper),               // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)S_CFCBase_dealloc,      // tp_dealloc
+    0,                                  // tp_print
+    0,                                  // tp_getattr
+    0,                                  // tp_setattr
+    0,                                  // tp_reserved
+    0,                                  // tp_repr
+    0,                                  // tp_as_number
+    0,                                  // tp_as_sequence
+    0,                                  // tp_as_mapping
+    0,                                  // tp_hash
+    0,                                  // tp_call
+    0,                                  // tp_str
+    0,                                  // tp_getattro
+    0,                                  // tp_setattro
+    0,                                  // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "CFCHierarchy",                     // tp_doc
+    0,                                  // tp_traverse
+    0,                                  // tp_clear
+    0,                                  // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    0,                                  // tp_iter
+    0,                                  // tp_iternext
+    hierarchy_methods,                  // tp_methods
+    0,                                  // tp_members
+    0,                                  // tp_getset
+    0,                                  // tp_base
+    0,                                  // tp_dict
+    0,                                  // tp_descr_get
+    0,                                  // tp_descr_set
+    0,                                  // tp_dictoffset
+    0,                                  // tp_init
+    0,                                  // tp_allow
+    (newfunc)S_CFCHierarchy_new         // tp_new
+};
+
+/***************************** CFCParcel *****************************/
+
+PyObject*
+S_CFCParcel_fetch(PyObject *ignored, PyObject *name) {
+    CFCParcel *parcel = CFCParcel_fetch(PyUnicode_AsUTF8(name));
+    return S_wrap_cfcbase(Parcel_pytype, parcel);
+}
+
+static PyMethodDef parcel_methods[] = {
+    {"fetch", (PyCFunction)S_CFCParcel_fetch, METH_STATIC, NULL},
+    {NULL}
+};
+
+static PyTypeObject Parcel_pytype_struct = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "clownfish.cfc.model.Parcel",       // tp_name
+    sizeof(CFCPyWrapper),               // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)S_CFCBase_dealloc,      // tp_dealloc
+    0,                                  // tp_print
+    0,                                  // tp_getattr
+    0,                                  // tp_setattr
+    0,                                  // tp_reserved
+    0,                                  // tp_repr
+    0,                                  // tp_as_number
+    0,                                  // tp_as_sequence
+    0,                                  // tp_as_mapping
+    0,                                  // tp_hash
+    0,                                  // tp_call
+    0,                                  // tp_str
+    0,                                  // tp_getattro
+    0,                                  // tp_setattro
+    0,                                  // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "CFCParcel",                        // tp_doc
+    0,                                  // tp_traverse
+    0,                                  // tp_clear
+    0,                                  // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    0,                                  // tp_iter
+    0,                                  // tp_iternext
+    parcel_methods,                     // tp_methods
+    0,                                  // tp_members
+    0,                                  // tp_getset
+    0,                                  // tp_base
+    0,                                  // tp_dict
+    0,                                  // tp_descr_get
+    0,                                  // tp_descr_set
+    0,                                  // tp_dictoffset
+    0,                                  // tp_init
+    0,                                  // tp_allow
+    0                                   // tp_new
+};
+
+/***************************** CFCBindCore *****************************/
+
+static PyObject*
+S_CFCBindCore_new(PyTypeObject *type, PyObject *args,
+                   PyObject *keyword_args) {
+    PyObject *hierarchy_wrapped;
+    char *header = "";
+    char *footer = "";
+    char *keywords[] = {"hierarchy", "header", "footer", NULL};
+    int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "O!|ss",
+                                             keywords, Hierarchy_pytype,
+                                             &hierarchy_wrapped, &header,
+                                             &footer);
+    if (!result) { return NULL; }
+    CFCHierarchy *hierarchy = S_to_Hierarchy(hierarchy_wrapped);
+    CFCBindCore *obj = CFCBindCore_new(hierarchy, header, footer);
+    return S_wrap_cfcbase(BindCore_pytype, obj);
+}
+
+static PyObject*
+S_CFCBindCore_write_all_modified(PyObject *wrapper, PyObject *args) {
+    int modified = 0;
+    int result = PyArg_ParseTuple(args, "|p", &modified);
+    if (!result) { return NULL; }
+    CFCBindCore_write_all_modified(S_to_BindCore(wrapper), modified);
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef bindcore_methods[] = {
+    {"write_all_modified", (PyCFunction)S_CFCBindCore_write_all_modified, METH_VARARGS, NULL},
+    {NULL}
+};
+
+static PyTypeObject BindCore_pytype_struct = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "clownfish.cfc.binding.BindCore",   // tp_name
+    sizeof(CFCPyWrapper),               // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)S_CFCBase_dealloc,      // tp_dealloc
+    0,                                  // tp_print
+    0,                                  // tp_getattr
+    0,                                  // tp_setattr
+    0,                                  // tp_reserved
+    0,                                  // tp_repr
+    0,                                  // tp_as_number
+    0,                                  // tp_as_sequence
+    0,                                  // tp_as_mapping
+    0,                                  // tp_hash
+    0,                                  // tp_call
+    0,                                  // tp_str
+    0,                                  // tp_getattro
+    0,                                  // tp_setattro
+    0,                                  // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "CFCBindCore",                      // tp_doc
+    0,                                  // tp_traverse
+    0,                                  // tp_clear
+    0,                                  // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    0,                                  // tp_iter
+    0,                                  // tp_iternext
+    bindcore_methods,                   // tp_methods
+    0,                                  // tp_members
+    0,                                  // tp_getset
+    0,                                  // tp_base
+    0,                                  // tp_dict
+    0,                                  // tp_descr_get
+    0,                                  // tp_descr_set
+    0,                                  // tp_dictoffset
+    0,                                  // tp_init
+    0,                                  // tp_allow
+    (newfunc)S_CFCBindCore_new          // tp_new
+};
+
+/******************************* common ******************************/
+
+PyMODINIT_FUNC
+PyInit__cfc(void) {
+    // Initialize Python type objects.
+    Hierarchy_pytype = &Hierarchy_pytype_struct;
+    Parcel_pytype    = &Parcel_pytype_struct;
+    BindCore_pytype  = &BindCore_pytype_struct;
+    if (PyType_Ready(Hierarchy_pytype) < 0) {
+        return NULL;
+    }
+    if (PyType_Ready(Parcel_pytype) < 0) {
+        return NULL;
+    }
+    if (PyType_Ready(BindCore_pytype) < 0) {
+        return NULL;
+    }
+
+    // Initialize modules.
+    cfc_module = PyModule_Create(&cfc_module_def);
+    cfc_model_module = PyModule_Create(&cfc_model_module_def);
+    cfc_binding_module = PyModule_Create(&cfc_binding_module_def);
+    PyModule_AddObject(cfc_module, "model", (PyObject*)cfc_model_module);
+    PyModule_AddObject(cfc_module, "binding", (PyObject*)cfc_binding_module);
+
+    // Add type objects to "model" module.
+    Py_INCREF(Hierarchy_pytype);
+    PyModule_AddObject(cfc_model_module, "Hierarchy",
+                       (PyObject*)Hierarchy_pytype);
+    Py_INCREF(Parcel_pytype);
+    PyModule_AddObject(cfc_model_module, "Parcel",
+                       (PyObject*)Parcel_pytype);
+
+    // Add type objects to "binding" module.
+    Py_INCREF(BindCore_pytype);
+    PyModule_AddObject(cfc_binding_module, "BindCore",
+                       (PyObject*)BindCore_pytype);
+
+    return cfc_module;
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/47234c3d/compiler/python/src/clownfish/cfc/__init__.py
----------------------------------------------------------------------
diff --git a/compiler/python/src/clownfish/cfc/__init__.py b/compiler/python/src/clownfish/cfc/__init__.py
new file mode 100644
index 0000000..f7f3e0b
--- /dev/null
+++ b/compiler/python/src/clownfish/cfc/__init__.py
@@ -0,0 +1,29 @@
+# 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 clownfish._cfc
+from clownfish._cfc import *
+import site
+import os.path
+
+def _get_inc_dirs():
+    dirs = []
+    for path in site.getsitepackages():
+        path = os.path.join(path, "clownfish/_include")
+        dirs.append(path)
+    return dirs
+
+clownfish._cfc._get_inc_dirs = _get_inc_dirs
+


[10/12] lucy-clownfish git commit: Add test target for Python runtime bindings.

Posted by ma...@apache.org.
Add test target for Python runtime bindings.


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

Branch: refs/heads/master
Commit: 49361b775a6af4fd42c5fd3ceff8d946d93418f2
Parents: fb4cc37
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Jan 19 20:28:26 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Feb 6 10:23:21 2016 -0800

----------------------------------------------------------------------
 runtime/python/setup.py               | 30 ++++++++++++++++++++++++++++++
 runtime/python/test/test_clownfish.py | 27 +++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/49361b77/runtime/python/setup.py
----------------------------------------------------------------------
diff --git a/runtime/python/setup.py b/runtime/python/setup.py
index a522cb9..fdaa593 100644
--- a/runtime/python/setup.py
+++ b/runtime/python/setup.py
@@ -24,6 +24,8 @@ import glob
 import shutil
 import subprocess
 import sysconfig
+import sys
+import unittest
 
 # Get a compiler object and and strings representing the compiler type and
 # CFLAGS.  Add the Python headers include dir to CFLAGS.
@@ -113,6 +115,33 @@ class my_build(_build):
         self.run_command('charmony')
         _build.run(self)
 
+class test(_Command):
+    description = "Run unit tests."
+    user_options = []
+    def initialize_options(self):
+        pass
+    def finalize_options(self):
+        pass
+    def ext_build_dir(self):
+        """Returns the build directory for compiled extensions"""
+        pattern = "lib.{platform}-{version[0]}.{version[1]}"
+        dirname = pattern.format(platform=sysconfig.get_platform(),
+                                 version=sys.version_info)
+        return os.path.join('build', dirname)
+
+    def run(self):
+        self.run_command('build')
+        orig_sys_path = sys.path[:]
+        sys.path.append(self.ext_build_dir())
+
+        loader = unittest.TestLoader()
+        tests = loader.discover("test")
+        test_runner = unittest.runner.TextTestRunner()
+        test_runner.run(tests)
+
+        # restore sys.path
+        sys.path = orig_sys_path
+
 setup(name = 'clownfish',
       version = '0.4.0',
       description = 'Clownfish runtime',
@@ -125,6 +154,7 @@ setup(name = 'clownfish',
           'build': my_build,
           'clean': my_clean,
           'charmony': charmony,
+          'test': test,
       },
       package_dir={'': 'src'},)
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/49361b77/runtime/python/test/test_clownfish.py
----------------------------------------------------------------------
diff --git a/runtime/python/test/test_clownfish.py b/runtime/python/test/test_clownfish.py
new file mode 100644
index 0000000..fd124d3
--- /dev/null
+++ b/runtime/python/test/test_clownfish.py
@@ -0,0 +1,27 @@
+# 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
+
+class MyTest(unittest.TestCase):
+
+    def testTrue(self):
+        self.assertTrue(True, "True should be true")
+
+
+if __name__ == '__main__':
+    unittest.main()
+