WIP start runtime Python 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/2245230b
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/2245230b
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/2245230b

Branch: refs/heads/py_exp1
Commit: 2245230bc12aae3980c211f68096465cb42b283d
Parents: f5f21ac
Author: Marvin Humphrey <[email protected]>
Authored: Tue Dec 16 16:30:56 2014 -0800
Committer: Marvin Humphrey <[email protected]>
Committed: Tue Dec 16 16:30:56 2014 -0800

----------------------------------------------------------------------
 runtime/python/cfext/clownfish.c      | 222 +++++++++++++++++++++++++++++
 runtime/python/clownfish/_clownfish.c |  35 +++++
 runtime/python/setup.py               | 176 +++++++++++++++++++++++
 3 files changed, 433 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2245230b/runtime/python/cfext/clownfish.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/clownfish.c b/runtime/python/cfext/clownfish.c
new file mode 100644
index 0000000..e631426
--- /dev/null
+++ b/runtime/python/cfext/clownfish.c
@@ -0,0 +1,222 @@
+/* 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 CFISH_USE_SHORT_NAMES
+#define C_CFISH_OBJ
+#define C_CFISH_CLASS
+#define C_CFISH_METHOD
+#define C_CFISH_ERR
+#define C_CFISH_LOCKFREEREGISTRY
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "charmony.h"
+
+#include "Clownfish/Obj.h"
+#include "Clownfish/Class.h"
+#include "Clownfish/Method.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Util/Memory.h"
+#include "Clownfish/String.h"
+#include "Clownfish/VArray.h"
+#include "Clownfish/LockFreeRegistry.h"
+
+/******************************** Obj **************************************/
+
+uint32_t
+Obj_Get_RefCount_IMP(Obj *self) {
+    return self->refcount;
+}
+
+Obj*
+Obj_Inc_RefCount_IMP(Obj *self) {
+    self->refcount++;
+    return self;
+}
+
+uint32_t
+Obj_Dec_RefCount_IMP(Obj *self) {
+    uint32_t modified_refcount = INT32_MAX;
+    switch (self->refcount) {
+        case 0:
+            THROW(ERR, "Illegal refcount of 0");
+            break; // useless
+        case 1:
+            modified_refcount = 0;
+            Obj_Destroy(self);
+            break;
+        default:
+            modified_refcount = --self->refcount;
+            break;
+    }
+    return modified_refcount;
+}
+
+void*
+Obj_To_Host_IMP(Obj *self) {
+    UNUSED_VAR(self);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(void*);
+}
+
+/******************************* Class *************************************/
+
+Obj*
+Class_Make_Obj_IMP(Class *self) {
+    Obj *obj = (Obj*)Memory_wrapped_calloc(self->obj_alloc_size, 1);
+    obj->klass = self;
+    obj->refcount = 1;
+    return obj;
+}
+
+Obj*
+Class_Init_Obj_IMP(Class *self, void *allocation) {
+    Obj *obj = (Obj*)allocation;
+    obj->klass = self;
+    obj->refcount = 1;
+    return obj;
+}
+
+Obj*
+Class_Foster_Obj_IMP(Class *self, void *host_obj) {
+    UNUSED_VAR(self);
+    UNUSED_VAR(host_obj);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(Obj*);
+}
+
+void
+Class_register_with_host(Class *singleton, Class *parent) {
+    UNUSED_VAR(singleton);
+    UNUSED_VAR(parent);
+}
+
+VArray*
+Class_fresh_host_methods(String *class_name) {
+    UNUSED_VAR(class_name);
+    return VA_new(0);
+}
+
+String*
+Class_find_parent_class(String *class_name) {
+    UNUSED_VAR(class_name);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(String*);
+}
+
+void*
+Class_To_Host_IMP(Class *self) {
+    UNUSED_VAR(self);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(void*);
+}
+
+/******************************* Method ************************************/
+
+String*
+Method_Host_Name_IMP(Method *self) {
+    return (String*)INCREF(self->name);
+}
+
+/******************************** Err **************************************/
+
+/* TODO: Thread safety */
+static Err *current_error;
+static Err *thrown_error;
+static jmp_buf  *current_env;
+
+void
+Err_init_class(void) {
+}
+
+Err*
+Err_get_error() {
+    return current_error;
+}
+
+void
+Err_set_error(Err *error) {
+    if (current_error) {
+        DECREF(current_error);
+    }
+    current_error = error;
+}
+
+void
+Err_do_throw(Err *error) {
+    if (current_env) {
+        thrown_error = error;
+        longjmp(*current_env, 1);
+    }
+    else {
+        String *message = Err_Get_Mess(error);
+        char *utf8 = Str_To_Utf8(message);
+        fprintf(stderr, "%s", utf8);
+        FREEMEM(utf8);
+        exit(EXIT_FAILURE);
+    }
+}
+
+void*
+Err_To_Host_IMP(Err *self) {
+    UNUSED_VAR(self);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(void*);
+}
+
+void
+Err_throw_mess(Class *klass, String *message) {
+    UNUSED_VAR(klass);
+    Err *err = Err_new(message);
+    Err_do_throw(err);
+}
+
+void
+Err_warn_mess(String *message) {
+    char *utf8 = Str_To_Utf8(message);
+    fprintf(stderr, "%s", utf8);
+    FREEMEM(utf8);
+    DECREF(message);
+}
+
+Err*
+Err_trap(Err_Attempt_t routine, void *context) {
+    jmp_buf  env;
+    jmp_buf *prev_env = current_env;
+    current_env = &env;
+
+    if (!setjmp(env)) {
+        routine(context);
+    }   
+
+    current_env = prev_env;
+
+    Err *error = thrown_error;
+    thrown_error = NULL;
+    return error;
+}
+
+/************************** LockFreeRegistry *******************************/
+
+void*
+LFReg_To_Host_IMP(LockFreeRegistry *self) {
+    UNUSED_VAR(self);
+    THROW(ERR, "TODO");
+    UNREACHABLE_RETURN(void*);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2245230b/runtime/python/clownfish/_clownfish.c
----------------------------------------------------------------------
diff --git a/runtime/python/clownfish/_clownfish.c 
b/runtime/python/clownfish/_clownfish.c
new file mode 100644
index 0000000..15d1873
--- /dev/null
+++ b/runtime/python/clownfish/_clownfish.c
@@ -0,0 +1,35 @@
+/* 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 "Clownfish/Obj.h"
+
+static PyModuleDef clownfish_module_def = {
+    PyModuleDef_HEAD_INIT,
+    "clownfish",
+    "Clownfish runtime",
+    -1,
+    NULL, NULL, NULL, NULL, NULL
+};
+
+PyMODINIT_FUNC
+PyInit__clownfish(void) {
+    cfish_bootstrap_parcel();
+    PyObject *cfc_module = PyModule_Create(&clownfish_module_def);
+    return cfc_module;
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2245230b/runtime/python/setup.py
----------------------------------------------------------------------
diff --git a/runtime/python/setup.py b/runtime/python/setup.py
new file mode 100644
index 0000000..b5e2a35
--- /dev/null
+++ b/runtime/python/setup.py
@@ -0,0 +1,176 @@
+# 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, Extension
+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 platform
+import re
+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.
+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"
+
+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, 'src')
+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'
+LIBCLOWNFISH_NAME    = 'libclownfish.a' # TODO portability
+LIBCLOWNFISH_PATH    = os.path.abspath(os.path.join(os.curdir, 
LIBCLOWNFISH_NAME))
+CFC_DIR              = os.path.join(BASE_DIR, 'compiler', 'python')
+CFC_BUILD_DIR        = ext_build_dir(os.path.join(CFC_DIR))
+
+c_filepaths = [os.path.join('clownfish', '_clownfish.c')]
+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',
+                '--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 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):
+        from pprint import pprint
+        sys.path.append(CFC_DIR)
+        sys.path.append(CFC_BUILD_DIR)
+        pprint(sys.path)
+        import clownfish.cfc as cfc
+        hierarchy = cfc.model.Hierarchy(dest="autogen")
+        hierarchy.add_source_dir(CORE_SOURCE_DIR)
+        hierarchy.build()
+
+class my_clean(_clean):
+    def run(self):
+        _clean.run(self)
+        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')
+        self.run_command('libclownfish')
+        _build.run(self)
+
+clownfish_extension = Extension('clownfish._clownfish',
+                                 include_dirs = [
+                                    CORE_SOURCE_DIR,
+                                    os.curdir,
+                                 ],
+                                 libraries = [LIBCLOWNFISH_PATH],
+                                 sources = c_filepaths)
+
+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,
+          'libclownfish': libclownfish,
+      },
+      ext_modules = [clownfish_extension])
+

Reply via email to