You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2016/02/25 00:07:28 UTC
[01/20] lucy-clownfish git commit: Use Python refcounting.
Repository: lucy-clownfish
Updated Branches:
refs/heads/master 32e2701aa -> 7c80fb818
Use Python refcounting.
In our Python bindings, Clownfish objects are Python objects, so use
Python's refcounting.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/7910ca91
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/7910ca91
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/7910ca91
Branch: refs/heads/master
Commit: 7910ca91a9005798ae8d6537f5fb55e01d07a17a
Parents: 32e2701
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 20 16:25:02 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:01 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7910ca91/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index a386e4c..6b13120 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -40,23 +40,20 @@
uint32_t
cfish_get_refcount(void *vself) {
- CFISH_UNUSED_VAR(vself);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(uint32_t);
+ return Py_REFCNT(vself);
}
cfish_Obj*
cfish_inc_refcount(void *vself) {
- CFISH_UNUSED_VAR(vself);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(cfish_Obj*);
+ Py_INCREF(vself);
+ return (cfish_Obj*)vself;
}
uint32_t
cfish_dec_refcount(void *vself) {
- CFISH_UNUSED_VAR(vself);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(uint32_t);
+ uint32_t modified_refcount = Py_REFCNT(vself);
+ Py_DECREF(vself);
+ return modified_refcount;
}
/**** Obj ******************************************************************/
[14/20] lucy-clownfish git commit: Add dummy routine for fetching
PyTypeObject.
Posted by ma...@apache.org.
Add dummy routine for fetching PyTypeObject.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/9bbb13f4
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/9bbb13f4
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/9bbb13f4
Branch: refs/heads/master
Commit: 9bbb13f48240d2365b02371bf9f9ce23c7e30c34
Parents: 2b65f36
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 27 17:06:12 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:04 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 10 ++++++++++
1 file changed, 10 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9bbb13f4/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index e7d15ed..9ecd11e 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -42,6 +42,9 @@
static bool Err_initialized;
+static PyTypeObject*
+S_get_cached_py_type(cfish_Class *klass);
+
/**** Utility **************************************************************/
static bool
@@ -693,6 +696,13 @@ CFISH_Obj_To_Host_IMP(cfish_Obj *self) {
/**** Class ****************************************************************/
+static PyTypeObject*
+S_get_cached_py_type(cfish_Class *self) {
+ // FIXME: dummy implementation
+ CFISH_UNUSED_VAR(self);
+ return NULL;
+}
+
cfish_Obj*
CFISH_Class_Make_Obj_IMP(cfish_Class *self) {
CFISH_UNUSED_VAR(self);
[18/20] lucy-clownfish git commit: Gen OVERRIDE callbacks for Python.
Posted by ma...@apache.org.
Gen OVERRIDE callbacks for Python.
Generate the C functions which call back into Python from
Clownfish-flavored C when a method is overridden.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/335b61fc
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/335b61fc
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/335b61fc
Branch: refs/heads/master
Commit: 335b61fc0f35868d1cda0bb1bbd879c616df1ae3
Parents: 02617ac
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 27 19:24:32 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:05 2016 -0800
----------------------------------------------------------------------
compiler/src/CFCPyMethod.c | 109 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 107 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/335b61fc/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 3cc7b96..983df28 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -15,6 +15,7 @@
*/
#include <string.h>
+#include <ctype.h>
#include "CFCPyMethod.h"
#include "CFCPyTypeMap.h"
@@ -47,6 +48,93 @@ S_build_unused_vars(CFCVariable **vars);
static char*
S_maybe_unreachable(CFCType *return_type);
+static char*
+S_build_py_args(CFCParamList *param_list) {
+ int num_vars = CFCParamList_num_vars(param_list);
+ CFCVariable **vars = CFCParamList_get_variables(param_list);
+ char pattern[] = " PyObject *cfcb_ARGS = S_pack_tuple(%d";
+ char *py_args = CFCUtil_sprintf(pattern, num_vars - 1);
+
+ for (int i = 1; vars[i] != NULL; i++) {
+ const char *var_name = CFCVariable_get_name(vars[i]);
+ CFCType *type = CFCVariable_get_type(vars[i]);
+ char *conversion = CFCPyTypeMap_c_to_py(type, var_name);
+ py_args = CFCUtil_cat(py_args, ",\n ", conversion, NULL);
+ FREEMEM(conversion);
+ }
+ py_args = CFCUtil_cat(py_args, ");", NULL);
+
+ return py_args;
+}
+
+static char*
+S_build_pymeth_invocation(CFCMethod *method) {
+ CFCType *return_type = CFCMethod_get_return_type(method);
+ const char *micro_sym = CFCSymbol_get_name((CFCSymbol*)method);
+ char *invocation = NULL;
+ const char *ret_type_str = CFCType_to_c(return_type);
+
+ if (CFCType_is_void(return_type)) {
+ const char pattern[] =
+ " CALL_PYMETH_VOID((PyObject*)self, \"%s\", cfcb_ARGS);";
+ invocation = CFCUtil_sprintf(pattern, micro_sym);
+ }
+ else if (CFCType_is_object(return_type)) {
+ const char *nullable
+ = CFCType_nullable(return_type) ? "true" : "false";
+ const char *ret_class = CFCType_get_class_var(return_type);
+ const char pattern[] =
+ " %s cfcb_RESULT = (%s)CALL_PYMETH_OBJ((PyObject*)self, \"%s\", cfcb_ARGS, %s, %s);";
+ invocation = CFCUtil_sprintf(pattern, ret_type_str, ret_type_str, micro_sym,
+ ret_class, nullable);
+ }
+ else if (CFCType_is_primitive(return_type)) {
+ char type_upcase[64];
+ if (strlen(ret_type_str) > 63) {
+ CFCUtil_die("Unexpectedly long type name: %s", ret_type_str);
+ }
+ for (int i = 0, max = strlen(ret_type_str) + 1; i < max; i++) {
+ type_upcase[i] = toupper(ret_type_str[i]);
+ }
+ const char pattern[] =
+ " %s cfcb_RESULT = CALL_PYMETH_%s((PyObject*)self, \"%s\", cfcb_ARGS);";
+ invocation = CFCUtil_sprintf(pattern, ret_type_str, type_upcase,
+ micro_sym);
+ }
+ else {
+ CFCUtil_die("Unexpected return type: %s", CFCType_to_c(return_type));
+ }
+
+ return invocation;
+}
+
+static char*
+S_callback_refcount_mods(CFCParamList *param_list) {
+ char *refcount_mods = CFCUtil_strdup("");
+ CFCVariable **arg_vars = CFCParamList_get_variables(param_list);
+
+ // Adjust refcounts of arguments per method signature, so that Perl code
+ // does not have to.
+ for (int i = 0; arg_vars[i] != NULL; i++) {
+ CFCVariable *var = arg_vars[i];
+ CFCType *type = CFCVariable_get_type(var);
+ const char *name = CFCVariable_get_name(var);
+ if (!CFCType_is_object(type)) {
+ continue;
+ }
+ else if (CFCType_incremented(type)) {
+ refcount_mods = CFCUtil_cat(refcount_mods, " CFISH_INCREF(",
+ name, ");\n", NULL);
+ }
+ else if (CFCType_decremented(type)) {
+ refcount_mods = CFCUtil_cat(refcount_mods, " CFISH_DECREF(",
+ name, ");\n", NULL);
+ }
+ }
+
+ return refcount_mods;
+}
+
char*
CFCPyMethod_callback_def(CFCMethod *method, CFCClass *invoker) {
CFCParamList *param_list = CFCMethod_get_param_list(method);
@@ -57,8 +145,25 @@ CFCPyMethod_callback_def(CFCMethod *method, CFCClass *invoker) {
char *override_sym = CFCMethod_full_override_sym(method, invoker);
char *content;
- //if (CFCMethod_can_be_bound(method)) {
- if (false) {
+ if (CFCMethod_can_be_bound(method)) {
+ char *py_args = S_build_py_args(param_list);
+ char *invocation = S_build_pymeth_invocation(method);
+ char *refcount_mods = S_callback_refcount_mods(param_list);
+ const char *maybe_return = CFCType_is_void(return_type)
+ ? ""
+ : " return cfcb_RESULT;\n";
+
+ const char pattern[] =
+ "%s\n"
+ "%s(%s) {\n"
+ "%s\n"
+ "%s\n"
+ "%s"
+ "%s"
+ "}\n";
+ content = CFCUtil_sprintf(pattern, ret_type_str, override_sym, params,
+ py_args, invocation, refcount_mods,
+ maybe_return);
}
else {
char *unused = S_build_unused_vars(vars);
[05/20] lucy-clownfish git commit: Re-raise Python exceptions from
Clownfish.
Posted by ma...@apache.org.
Re-raise Python exceptions from Clownfish.
Add a function which takes the Python `sys.exc_info`, wraps it in a
Clownfish Err, and THROWs it.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/9162199c
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/9162199c
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/9162199c
Branch: refs/heads/master
Commit: 9162199c26ab869bff1133d517388899468b4170
Parents: eccf1b6
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Fri Jan 22 16:51:01 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:02 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 36 ++++++++++++++++++++++++++++++++++++
runtime/python/cfext/CFBind.h | 13 +++++++++++++
2 files changed, 49 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9162199c/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 3c4bb4b..95ae70d 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -40,6 +40,42 @@
static bool Err_initialized;
+/**** Utility **************************************************************/
+
+void
+CFBind_reraise_pyerr(cfish_Class *err_klass, cfish_String *mess) {
+ PyObject *type, *value, *traceback;
+ PyObject *type_pystr = NULL;
+ PyObject *value_pystr = NULL;
+ PyObject *traceback_pystr = NULL;
+ char *type_str = "";
+ char *value_str = "";
+ char *traceback_str = "";
+ PyErr_GetExcInfo(&type, &value, &traceback);
+ if (type != NULL) {
+ PyObject *type_pystr = PyObject_Str(type);
+ type_str = PyUnicode_AsUTF8(type_pystr);
+ }
+ if (value != NULL) {
+ PyObject *value_pystr = PyObject_Str(value);
+ value_str = PyUnicode_AsUTF8(value_pystr);
+ }
+ if (traceback != NULL) {
+ PyObject *traceback_pystr = PyObject_Str(traceback);
+ traceback_str = PyUnicode_AsUTF8(traceback_pystr);
+ }
+ cfish_String *new_mess = cfish_Str_newf("%o... %s: %s %s", mess, type_str,
+ value_str, traceback_str);
+ Py_XDECREF(type);
+ Py_XDECREF(value);
+ Py_XDECREF(traceback);
+ Py_XDECREF(type_pystr);
+ Py_XDECREF(value_pystr);
+ Py_XDECREF(traceback_pystr);
+ CFISH_DECREF(mess);
+ cfish_Err_throw_mess(err_klass, new_mess);
+}
+
/**** refcounting **********************************************************/
uint32_t
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9162199c/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index 810f201..d6a362e 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -24,6 +24,19 @@ extern "C" {
#include "cfish_platform.h"
#include "Python.h"
+struct cfish_Class;
+struct cfish_String;
+
+/** Wrap the current state of Python's sys.exc_info in a Clownfish Err and
+ * throw it.
+ *
+ * One refcount of `mess` will be consumed by this function.
+ *
+ * TODO: Leave the original exception intact.
+ */
+void
+CFBind_reraise_pyerr(struct cfish_Class *err_klass, struct cfish_String *mess);
+
#ifdef __cplusplus
}
#endif
[10/20] lucy-clownfish git commit: Implement scalar types To_Host for
Python.
Posted by ma...@apache.org.
Implement scalar types To_Host for Python.
- String -> string
- Blob -> bytes
- Boolean -> bool
- Integer -> int
- Float -> float
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/5d3809ba
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/5d3809ba
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/5d3809ba
Branch: refs/heads/master
Commit: 5d3809ba960455a6695fcfece1063e7d91f23fac
Parents: bebc758
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Jan 25 17:26:40 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:03 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 38 ++++++++++++++++++++------------------
1 file changed, 20 insertions(+), 18 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5d3809ba/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index f524b78..e991bf6 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -552,23 +552,23 @@ cfish_TestUtils_destroy_host_runtime(void *runtime) {
void*
CFISH_Str_To_Host_IMP(cfish_String *self) {
- CFISH_UNUSED_VAR(self);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(void*);
+ const char *ptr = CFISH_Str_Get_Ptr8(self);
+ size_t size = CFISH_Str_Get_Size(self);
+ return PyUnicode_FromStringAndSize(ptr, size);
}
void*
CFISH_Blob_To_Host_IMP(cfish_Blob *self) {
- CFISH_UNUSED_VAR(self);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(void*);
+ const char *buf = CFISH_Blob_Get_Buf(self);
+ size_t size = CFISH_Blob_Get_Size(self);
+ return PyBytes_FromStringAndSize(buf, size);
}
void*
CFISH_BB_To_Host_IMP(cfish_ByteBuf *self) {
- CFISH_UNUSED_VAR(self);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(void*);
+ CFISH_BB_To_Host_t super_to_host
+ = CFISH_SUPER_METHOD_PTR(CFISH_BYTEBUF, CFISH_BB_To_Host);
+ return super_to_host(self);
}
void*
@@ -613,22 +613,24 @@ CFISH_Hash_To_Host_IMP(cfish_Hash *self) {
void*
CFISH_Float_To_Host_IMP(cfish_Float *self) {
- CFISH_UNUSED_VAR(self);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(void*);
+ return PyFloat_FromDouble(CFISH_Float_Get_Value(self));
}
void*
CFISH_Int_To_Host_IMP(cfish_Integer *self) {
- CFISH_UNUSED_VAR(self);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(void*);
+ int64_t num = CFISH_Int_Get_Value(self);
+ return PyLong_FromLongLong(num);
}
void*
CFISH_Bool_To_Host_IMP(cfish_Boolean *self) {
- CFISH_UNUSED_VAR(self);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(void*);
+ if (self == CFISH_TRUE) {
+ Py_INCREF(Py_True);
+ return Py_True;
+ }
+ else {
+ Py_INCREF(Py_False);
+ return Py_False;
+ }
}
[12/20] lucy-clownfish git commit: ParseTuple routines for Obj,
String.
Posted by ma...@apache.org.
ParseTuple routines for Obj, String.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/514827b7
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/514827b7
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/514827b7
Branch: refs/heads/master
Commit: 514827b7293471645b0d6a5d450ef7ad1177e79d
Parents: 9bbb13f
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 27 17:13:51 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:04 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 100 +++++++++++++++++++++++++++++++++++++
runtime/python/cfext/CFBind.h | 13 +++++
2 files changed, 113 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/514827b7/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 9ecd11e..7e7f617 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -285,6 +285,106 @@ CFBind_py_to_cfish_noinc(PyObject *py_obj, cfish_Class *klass,
}
static int
+S_convert_obj(PyObject *py_obj, CFBindArg *arg, bool nullable) {
+ if (py_obj == Py_None) {
+ if (nullable) {
+ return 1;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "Required argument cannot be None");
+ return 0;
+ }
+ }
+ PyTypeObject *py_type = S_get_cached_py_type(arg->klass);
+ if (!PyObject_TypeCheck(py_obj, py_type)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid argument type");
+ return 0;
+ }
+ *((PyObject**)arg->ptr) = py_obj;
+ return 1;
+}
+
+int
+CFBind_convert_obj(PyObject *py_obj, CFBindArg *arg) {
+ return S_convert_obj(py_obj, arg, false);
+}
+
+int
+CFBind_maybe_convert_obj(PyObject *py_obj, CFBindArg *arg) {
+ return S_convert_obj(py_obj, arg, true);
+}
+
+static int
+S_convert_string(PyObject *py_obj, cfish_String **ptr, bool nullable) {
+ if (py_obj == NULL) { // Py_CLEANUP_SUPPORTED cleanup
+ if (*ptr != NULL) {
+ if (!CFISH_Str_Is_Copy_On_IncRef(*ptr)) {
+ CFISH_DECREF(*ptr);
+ }
+ *ptr = NULL;
+ }
+ return 1;
+ }
+
+ if (py_obj == Py_None) {
+ if (*ptr != NULL) {
+ // Default value passed as stack string.
+ *ptr = CFISH_Str_Clone(*ptr);
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else if (nullable) {
+ return 1;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "Required argument cannot be None");
+ return 0;
+ }
+ }
+ else if (PyUnicode_CheckExact(py_obj)) {
+ Py_ssize_t size;
+ char *utf8 = PyUnicode_AsUTF8AndSize(py_obj, &size);
+ if (!utf8) {
+ return 0;
+ }
+ *ptr = cfish_Str_new_from_trusted_utf8(utf8, size);
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else if (S_py_obj_is_a(py_obj, CFISH_STRING)) {
+ *ptr = (cfish_String*)CFISH_INCREF(py_obj);
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else if (S_py_obj_is_a(py_obj, CFISH_OBJ)) {
+ *ptr = CFISH_Obj_To_String((cfish_Obj*)py_obj);
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else {
+ PyObject *stringified = PyObject_Str(py_obj);
+ if (stringified == NULL) {
+ return 0;
+ }
+ Py_ssize_t size;
+ char *utf8 = PyUnicode_AsUTF8AndSize(stringified, &size);
+ if (!utf8) {
+ Py_DECREF(stringified);
+ return 0;
+ }
+ *ptr = cfish_Str_new_from_trusted_utf8(utf8, size);
+ Py_DECREF(stringified);
+ return Py_CLEANUP_SUPPORTED;
+ }
+}
+
+int
+CFBind_convert_string(PyObject *py_obj, cfish_String **ptr) {
+ return S_convert_string(py_obj, ptr, false);
+}
+
+int
+CFBind_maybe_convert_string(PyObject *py_obj, cfish_String **ptr) {
+ return S_convert_string(py_obj, ptr, true);
+}
+
+static int
S_convert_hash(PyObject *py_obj, cfish_Hash **hash_ptr, bool nullable) {
if (py_obj == NULL) { // Py_CLEANUP_SUPPORTED cleanup
CFISH_DECREF(*hash_ptr);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/514827b7/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index d7eb0ba..b6e57fd 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -100,16 +100,29 @@ cfish_Obj*
CFBind_py_to_cfish_noinc(PyObject *py_obj, cfish_Class *klass,
void *allocation);
+typedef struct CFBindArg {
+ cfish_Class *klass;
+ void *ptr;
+} CFBindArg;
+
/* ParseTuple conversion routines for reference types.
*
* If `input` is `None`, the "maybe_convert" variants will leave `ptr`
* untouched, while the "convert" routines will raise a TypeError.
*/
int
+CFBind_convert_obj(PyObject *input, CFBindArg *arg);
+int
+CFBind_convert_string(PyObject *input, cfish_String **ptr);
+int
CFBind_convert_hash(PyObject *input, cfish_Hash **ptr);
int
CFBind_convert_vec(PyObject *input, cfish_Vector **ptr);
int
+CFBind_maybe_convert_obj(PyObject *input, CFBindArg *arg);
+int
+CFBind_maybe_convert_string(PyObject *input, cfish_String **ptr);
+int
CFBind_maybe_convert_hash(PyObject *input, cfish_Hash **ptr);
int
CFBind_maybe_convert_vec(PyObject *input, cfish_Vector **ptr);
[02/20] lucy-clownfish git commit: `To_Host` for Python returns
incref'd self.
Posted by ma...@apache.org.
`To_Host` for Python returns incref'd self.
The default implementation for `To_Host` for Python just returns the
result of calling INCREF on the invocant.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/3e4952ca
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/3e4952ca
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/3e4952ca
Branch: refs/heads/master
Commit: 3e4952ca641308a8704fa41c51786dace4389ce7
Parents: 2aab6ef
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Jan 25 16:41:37 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:02 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e4952ca/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 7653325..ef0d094 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -405,9 +405,7 @@ cfish_dec_refcount(void *vself) {
void*
CFISH_Obj_To_Host_IMP(cfish_Obj *self) {
- CFISH_UNUSED_VAR(self);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(void*);
+ return CFISH_INCREF(self);
}
/**** Class ****************************************************************/
[09/20] lucy-clownfish git commit: To_Host for composite types to
Python.
Posted by ma...@apache.org.
To_Host for composite types to Python.
Implement To_Host conversion for Hash -> Python dict and Vector ->
Python list.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/bebc7589
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/bebc7589
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/bebc7589
Branch: refs/heads/master
Commit: bebc75899ec1dbbbd040fbf6ff21b1b6c4b9be97
Parents: 3e4952c
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Jan 25 17:02:25 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:03 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 39 ++++++++++++++++++++++++++++++++------
1 file changed, 33 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bebc7589/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index ef0d094..f524b78 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -31,6 +31,7 @@
#include "Clownfish/ByteBuf.h"
#include "Clownfish/Err.h"
#include "Clownfish/Hash.h"
+#include "Clownfish/HashIterator.h"
#include "Clownfish/Method.h"
#include "Clownfish/Num.h"
#include "Clownfish/String.h"
@@ -572,16 +573,42 @@ CFISH_BB_To_Host_IMP(cfish_ByteBuf *self) {
void*
CFISH_Vec_To_Host_IMP(cfish_Vector *self) {
- CFISH_UNUSED_VAR(self);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(void*);
+ uint32_t num_elems = CFISH_Vec_Get_Size(self);
+ PyObject *list = PyList_New(num_elems);
+
+ // Iterate over vector items.
+ for (uint32_t i = 0; i < num_elems; i++) {
+ cfish_Obj *val = CFISH_Vec_Fetch(self, i);
+ PyObject *item = CFBind_cfish_to_py(val);
+ PyList_SET_ITEM(list, i, item);
+ }
+
+ return list;
}
void*
CFISH_Hash_To_Host_IMP(cfish_Hash *self) {
- CFISH_UNUSED_VAR(self);
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(void*);
+ PyObject *dict = PyDict_New();
+
+ // Iterate over key-value pairs.
+ cfish_HashIterator *iter = cfish_HashIter_new(self);
+ while (CFISH_HashIter_Next(iter)) {
+ cfish_String *key = (cfish_String*)CFISH_HashIter_Get_Key(iter);
+ if (!cfish_Obj_is_a((cfish_Obj*)key, CFISH_STRING)) {
+ CFISH_THROW(CFISH_ERR, "Non-string key: %o",
+ cfish_Obj_get_class_name((cfish_Obj*)key));
+ }
+ size_t size = CFISH_Str_Get_Size(key);
+ const char *ptr = CFISH_Str_Get_Ptr8(key);
+ PyObject *py_key = PyUnicode_FromStringAndSize(ptr, size);
+ PyObject *py_val = CFBind_cfish_to_py(CFISH_HashIter_Get_Value(iter));
+ PyDict_SetItem(dict, py_key, py_val);
+ Py_DECREF(py_key);
+ Py_DECREF(py_val);
+ }
+ CFISH_DECREF(iter);
+
+ return dict;
}
void*
[13/20] lucy-clownfish git commit: Stub out callback-generating code
for Python.
Posted by ma...@apache.org.
Stub out callback-generating code for Python.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/8996f0f6
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/8996f0f6
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/8996f0f6
Branch: refs/heads/master
Commit: 8996f0f62d0e07ed3b0d14934041aeb9d71fa698
Parents: 514827b
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 27 16:05:37 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:04 2016 -0800
----------------------------------------------------------------------
compiler/src/CFCPyMethod.c | 38 ++++++++++++++++++++++++++++++++
compiler/src/CFCPyMethod.h | 39 ++++++++++++++++++++++++++++++++
compiler/src/CFCPython.c | 49 ++++++++++++++++++++++++++++++++++++++++-
3 files changed, 125 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8996f0f6/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
new file mode 100644
index 0000000..2892b86
--- /dev/null
+++ b/compiler/src/CFCPyMethod.c
@@ -0,0 +1,38 @@
+/* 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 "CFCPyMethod.h"
+#include "CFCPyTypeMap.h"
+#include "CFCUtil.h"
+#include "CFCClass.h"
+#include "CFCFunction.h"
+#include "CFCMethod.h"
+#include "CFCSymbol.h"
+#include "CFCType.h"
+#include "CFCParcel.h"
+#include "CFCParamList.h"
+#include "CFCVariable.h"
+
+#ifndef true
+#define true 1
+#define false 0
+#endif
+
+char*
+CFCPyMethod_callback_def(CFCMethod *method, CFCClass *invoker) {
+ return CFCUtil_strdup("");
+}
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8996f0f6/compiler/src/CFCPyMethod.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.h b/compiler/src/CFCPyMethod.h
new file mode 100644
index 0000000..15fa1e6
--- /dev/null
+++ b/compiler/src/CFCPyMethod.h
@@ -0,0 +1,39 @@
+/* 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_CFCPYMETHOD
+#define H_CFCPYMETHOD
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct CFCMethod;
+struct CFCClass;
+
+/** Return C code which knows how to call back into Python for this method. This
+ * code is run when a Python subclass has overridden a method in a Clownfish base
+ * class.
+ */
+char*
+CFCPyMethod_callback_def(struct CFCMethod *method, struct CFCClass *invoker);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_CFCPYMETHOD */
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8996f0f6/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 3efaa3a..10c9872 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -24,6 +24,7 @@
#define CFC_NEED_BASE_STRUCT_DEF
#include "CFCBase.h"
#include "CFCPython.h"
+#include "CFCPyMethod.h"
#include "CFCParcel.h"
#include "CFCClass.h"
#include "CFCMethod.h"
@@ -108,6 +109,48 @@ S_write_hostdefs(CFCPython *self) {
FREEMEM(content);
}
+static char*
+S_gen_callbacks(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
+ char *callbacks = CFCUtil_strdup("");
+
+ // Generate implementation files containing callback definitions.
+ for (size_t i = 0; ordered[i] != NULL; i++) {
+ CFCClass *klass = ordered[i];
+ if (CFCClass_included(klass)
+ || CFCClass_inert(klass)
+ //|| CFCClass_get_parcel(klass) != parcel
+ ) {
+ continue;
+ }
+
+ CFCMethod **fresh_methods = CFCClass_fresh_methods(klass);
+ for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
+ CFCMethod *method = fresh_methods[meth_num];
+
+ // Define callback.
+ if (CFCMethod_novel(method) && !CFCMethod_final(method)) {
+ char *cb_def = CFCPyMethod_callback_def(method, klass);
+ callbacks = CFCUtil_cat(callbacks, cb_def, "\n", NULL);
+ FREEMEM(cb_def);
+ }
+ }
+ }
+
+ static const char helpers[] =
+ ""
+ ;
+
+ static const char pattern[] =
+ "%s\n"
+ "\n"
+ "%s"
+ ;
+ char *content = CFCUtil_sprintf(pattern, helpers, callbacks);
+
+ FREEMEM(callbacks);
+ return content;
+}
+
static void
S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
const char *parcel_name = CFCParcel_get_name(parcel);
@@ -127,6 +170,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
CFCParcel **parcels = CFCParcel_all_parcels();
+ char *callbacks = S_gen_callbacks(self, parcel, ordered);
char *pound_includes = CFCUtil_strdup("");
for (size_t i = 0; ordered[i] != NULL; i++) {
@@ -146,6 +190,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
"#include \"CFBind.h\"\n"
"%s\n"
"\n"
+ "%s\n" // callbacks
+ "\n"
"static PyModuleDef module_def = {\n"
" PyModuleDef_HEAD_INIT,\n"
" \"%s\",\n" // module name
@@ -164,7 +210,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
"\n";
char *content
- = CFCUtil_sprintf(pattern, self->header, pound_includes,
+ = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
helper_mod_name, last_component, self->footer);
char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
@@ -176,6 +222,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
FREEMEM(helper_mod_name);
FREEMEM(pymod_name);
FREEMEM(pound_includes);
+ FREEMEM(callbacks);
FREEMEM(ordered);
}
[19/20] lucy-clownfish git commit: Prepare to trap errors in Python
glue code.
Posted by ma...@apache.org.
Prepare to trap errors in Python glue code.
Add private macro `CFBIND_TRY` and supporting routines, in an effort to
wrap Clownfish C routines and trap errors. This will be used inside
glue code for Python, setting `sys.exc_info` when something goes wrong.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/91622dbf
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/91622dbf
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/91622dbf
Branch: refs/heads/master
Commit: 91622dbf97f1afb2a195609fd1bea2b703119211
Parents: bb7e880
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Feb 18 19:31:30 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:05 2016 -0800
----------------------------------------------------------------------
compiler/src/CFCPython.c | 9 +++++++++
runtime/python/cfext/CFBind.c | 22 ++++++++++++++++++++++
runtime/python/cfext/CFBind.h | 12 ++++++++++++
3 files changed, 43 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/91622dbf/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index b39240d..a2b13a4 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -149,6 +149,15 @@ S_gen_callbacks(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
" va_end(args);\n"
" return tuple;\n"
"}\n"
+ "#define CFBIND_TRY(routine) \\\n"
+ " do { \\\n"
+ " jmp_buf env; \\\n"
+ " jmp_buf *prev_env = CFBind_swap_env(&env); \\\n"
+ " if (!setjmp(env)) { \\\n"
+ " routine; \\\n"
+ " } \\\n"
+ " CFBind_swap_env(prev_env); \\\n"
+ " } while (0)\n"
"\n"
"static PyObject*\n"
"S_call_pymeth(PyObject *self, const char *meth_name, PyObject *args,\n"
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/91622dbf/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 7e7f617..48743a7 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -855,6 +855,28 @@ static cfish_Err *current_error;
static cfish_Err *thrown_error;
static jmp_buf *current_env;
+jmp_buf*
+CFBind_swap_env(jmp_buf *env) {
+ jmp_buf *prev_env = current_env;
+ current_env = env;
+ return prev_env;
+}
+
+int
+CFBind_migrate_cferr() {
+ if (thrown_error != NULL) {
+ cfish_Err *err = thrown_error;
+ thrown_error = NULL;
+ cfish_String *mess = CFISH_Err_Get_Mess(err);
+ char *utf8 = CFISH_Str_To_Utf8(mess);
+ PyErr_SetString(PyExc_RuntimeError, utf8);
+ CFISH_FREEMEM(utf8);
+ CFISH_DECREF(err);
+ return true;
+ }
+ return false;
+}
+
void
cfish_Err_init_class(void) {
Err_initialized = true;
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/91622dbf/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index b6e57fd..9279510 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -21,6 +21,7 @@
extern "C" {
#endif
+#include <setjmp.h>
#include "cfish_platform.h"
#include "Python.h"
#include "Clownfish/Obj.h"
@@ -38,6 +39,17 @@ struct cfish_String;
void
CFBind_reraise_pyerr(struct cfish_Class *err_klass, struct cfish_String *mess);
+/** Set the current_env, return the old value (internal use only).
+ */
+jmp_buf*
+CFBind_swap_env(jmp_buf *env);
+
+/** If a Clownfish error was thrown, propagate it to Python and return true
+ * (internal use only).
+ */
+int
+CFBind_migrate_cferr(void);
+
/** Null-safe invocation of Obj_To_Host.
*/
static CFISH_INLINE PyObject*
[08/20] lucy-clownfish git commit: Add CF pound-includes in autogen
Py module file.
Posted by ma...@apache.org.
Add CF pound-includes in autogen Py module 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/82d79df8
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/82d79df8
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/82d79df8
Branch: refs/heads/master
Commit: 82d79df8bc4c57ff42922a60436425c078ae6731
Parents: 5d3809b
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Jan 26 17:24:22 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:03 2016 -0800
----------------------------------------------------------------------
compiler/src/CFCPython.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/82d79df8/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 2c57eb0..3efaa3a 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -125,12 +125,26 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
helper_mod_name[i] = tolower(helper_mod_name[i]);
}
+ CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
+ CFCParcel **parcels = CFCParcel_all_parcels();
+ char *pound_includes = CFCUtil_strdup("");
+
+ for (size_t i = 0; ordered[i] != NULL; i++) {
+ CFCClass *klass = ordered[i];
+ if (CFCClass_included(klass)) { continue; }
+
+ const char *include_h = CFCClass_include_h(klass);
+ pound_includes = CFCUtil_cat(pound_includes, "#include \"",
+ include_h, "\"\n", NULL);
+ }
+
const char pattern[] =
"%s\n"
"\n"
"#include \"Python.h\"\n"
"#include \"cfish_parcel.h\"\n"
"#include \"CFBind.h\"\n"
+ "%s\n"
"\n"
"static PyModuleDef module_def = {\n"
" PyModuleDef_HEAD_INIT,\n"
@@ -150,7 +164,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
"\n";
char *content
- = CFCUtil_sprintf(pattern, self->header,
+ = CFCUtil_sprintf(pattern, self->header, pound_includes,
helper_mod_name, last_component, self->footer);
char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
@@ -161,6 +175,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
FREEMEM(content);
FREEMEM(helper_mod_name);
FREEMEM(pymod_name);
+ FREEMEM(pound_includes);
+ FREEMEM(ordered);
}
void
[11/20] lucy-clownfish git commit: Add dummy py_obj_is_a
implementation.
Posted by ma...@apache.org.
Add dummy py_obj_is_a implementation.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/999b39f4
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/999b39f4
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/999b39f4
Branch: refs/heads/master
Commit: 999b39f44d69744f08f86e5688a84d7ff0153cd8
Parents: 82d79df
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Jan 26 17:42:39 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:03 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 8 ++++++++
1 file changed, 8 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/999b39f4/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index e991bf6..d3c39c2 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -43,6 +43,14 @@ static bool Err_initialized;
/**** Utility **************************************************************/
+static bool
+S_py_obj_is_a(PyObject *py_obj, cfish_Class *klass) {
+ CFISH_UNUSED_VAR(py_obj);
+ CFISH_UNUSED_VAR(klass);
+ CFISH_THROW(CFISH_ERR, "TODO");
+ CFISH_UNREACHABLE_RETURN(bool);
+}
+
void
CFBind_reraise_pyerr(cfish_Class *err_klass, cfish_String *mess) {
PyObject *type, *value, *traceback;
[15/20] lucy-clownfish git commit: Add helper routines for Python
callbacks.
Posted by ma...@apache.org.
Add helper routines for Python callbacks.
The generated C code for calling back into Python from Clownfish when a
method is overridden will require these helper functions for running the
Python callable, converting return values, etc.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/bb7e8807
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/bb7e8807
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/bb7e8807
Branch: refs/heads/master
Commit: bb7e880799d6bb0e4743d24fcacb630e04b2e32f
Parents: 8996f0f
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 27 18:23:36 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:04 2016 -0800
----------------------------------------------------------------------
compiler/src/CFCPython.c | 203 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 202 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bb7e8807/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 10c9872..b39240d 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -137,7 +137,208 @@ S_gen_callbacks(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
}
static const char helpers[] =
- ""
+ "static PyObject*\n"
+ "S_pack_tuple(int num_args, ...) {\n"
+ " PyObject *tuple = PyTuple_New(num_args);\n"
+ " va_list args;\n"
+ " va_start(args, num_args);\n"
+ " for (int i = 0; i < num_args; i++) {\n"
+ " PyObject *arg = va_arg(args, PyObject*);\n"
+ " PyTuple_SET_ITEM(tuple, i, arg);\n"
+ " }\n"
+ " va_end(args);\n"
+ " return tuple;\n"
+ "}\n"
+ "\n"
+ "static PyObject*\n"
+ "S_call_pymeth(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *callable = PyObject_GetAttrString(self, meth_name);\n"
+ " if (!PyCallable_Check(callable)) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func, \"Attr '%s' not callable\",\n"
+ " meth_name);\n"
+ " cfish_Err_throw_mess(CFISH_ERR, mess);\n"
+ " }\n"
+ " PyObject *result = PyObject_CallObject(callable, args);\n"
+ " Py_DECREF(args);\n"
+ " if (result == NULL) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func,\n"
+ " \"Callback to '%s' failed\", meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " return result;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_VOID(self, meth_name, args) \\\n"
+ " S_call_pymeth_void(self, meth_name, args, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "\n"
+ "static void\n"
+ "S_call_pymeth_void(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " if (py_result == NULL) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func, \"Call to %s failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_BOOL(self, meth_name, args) \\\n"
+ " S_call_pymeth_bool(self, meth_name, args, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "\n"
+ "static bool\n"
+ "S_call_pymeth_bool(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " int truthiness = py_result != NULL\n"
+ " ? PyObject_IsTrue(py_result)\n"
+ " : -1;\n"
+ " if (truthiness == -1) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func, \"Call to %s failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ " return !!truthiness;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_OBJ(self, meth_name, args, ret_class, nullable) \\\n"
+ " S_call_pymeth_obj(self, meth_name, args, ret_class, nullable, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "\n"
+ "static cfish_Obj*\n"
+ "S_call_pymeth_obj(PyObject *self, const char *meth_name,\n"
+ " PyObject *args, cfish_Class *ret_class, bool nullable,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " cfish_Obj *result = CFBind_py_to_cfish(py_result, ret_class);\n"
+ " Py_DECREF(py_result);\n"
+ " if (!nullable && result == NULL) {\n"
+ " CFISH_THROW(CFISH_ERR, \"%s cannot return NULL\", meth_name);\n"
+ " }\n"
+ " else if (!cfish_Obj_is_a(result, ret_class)) {\n"
+ " cfish_Class *result_class = cfish_Obj_get_class(result);\n"
+ " CFISH_DECREF(result);\n"
+ " CFISH_THROW(CFISH_ERR, \"%s returned %o instead of %o\", meth_name,\n"
+ " CFISH_Class_Get_Name(result_class),\n"
+ " CFISH_Class_Get_Name(ret_class));\n"
+ " }\n"
+ " return result;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_DOUBLE(self, meth_name, args) \\\n"
+ " S_call_pymeth_f64(self, meth_name, args, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "#define CALL_PYMETH_FLOAT(self, meth_name, args) \\\n"
+ " ((float)S_call_pymeth_f64(self, meth_name, args, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "\n"
+ "static double\n"
+ "S_call_pymeth_f64(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " PyErr_Clear();\n"
+ " double result = PyFloat_AsDouble(py_result);\n"
+ " if (PyErr_Occurred()) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func,\n"
+ " \"Converting result of '%s' to double failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ " return result;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_INT64_T(self, meth_name, args) \\\n"
+ " S_call_pymeth_i64(self, meth_name, args, INT64_MAX, INT64_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "#define CALL_PYMETH_INT32_T(self, meth_name, args) \\\n"
+ " ((int32_t)S_call_pymeth_i64(self, meth_name, args, INT32_MAX, INT32_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_INT16_T(self, meth_name, args) \\\n"
+ " ((int16_t)S_call_pymeth_i64(self, meth_name, args, INT16_MAX, INT16_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_INT8_T(self, meth_name, args) \\\n"
+ " ((int8_t)S_call_pymeth_i64(self, meth_name, args, INT8_MAX, INT8_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_CHAR(self, meth_name, args) \\\n"
+ " ((char)S_call_pymeth_i64(self, meth_name, args, CHAR_MAX, CHAR_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_SHORT(self, meth_name, args) \\\n"
+ " ((short)S_call_pymeth_i64(self, meth_name, args, SHRT_MAX, SHRT_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_INT(self, meth_name, args) \\\n"
+ " ((int16_t)S_call_pymeth_i64(self, meth_name, args, INT_MAX, INT_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_LONG(self, meth_name, args) \\\n"
+ " ((int16_t)S_call_pymeth_i64(self, meth_name, args, LONG_MAX, LONG_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "\n"
+ "static int64_t\n"
+ "S_call_pymeth_i64(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " int64_t max, int64_t min,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " PyErr_Clear();\n"
+ " int64_t result = PyLong_AsLongLong(py_result);\n"
+ " if (PyErr_Occurred() || result > max || result < min) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func,\n"
+ " \"Converting result of '%s' to int64_t failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ " return result;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_UINT64_T(self, meth_name, args) \\\n"
+ " S_call_pymeth_u64(self, meth_name, args, UINT64_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "#define CALL_PYMETH_UINT32_T(self, meth_name, args) \\\n"
+ " ((uint32_t)S_call_pymeth_u64(self, meth_name, args, UINT32_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_UINT16_T(self, meth_name, args) \\\n"
+ " ((uint32_t)S_call_pymeth_u64(self, meth_name, args, UINT16_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_UINT8_T(self, meth_name, args) \\\n"
+ " ((uint32_t)S_call_pymeth_u64(self, meth_name, args, UINT8_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_SIZE_T(self, meth_name, args) \\\n"
+ " S_call_pymeth_u64(self, meth_name, args, SIZE_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "\n"
+ "static uint64_t\n"
+ "S_call_pymeth_u64(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " uint64_t max,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " PyErr_Clear();\n"
+ " uint64_t result = PyLong_AsUnsignedLongLong(py_result);\n"
+ " if (PyErr_Occurred()) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func,\n"
+ " \"Converting result of '%s' to uint64_t failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ " return result;\n"
+ "}\n"
;
static const char pattern[] =
[06/20] lucy-clownfish git commit: Implement Clownfish exceptions
using `longjmp`.
Posted by ma...@apache.org.
Implement Clownfish exceptions using `longjmp`.
Though Python uses exceptions, executing exceptions from the Python C
API requires setting thread-local error information and indicating an
error condition to the Python interpreter by returning NULL from the
glue function. So Clownfish has to have its own independent exception
handling.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/eccf1b64
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/eccf1b64
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/eccf1b64
Branch: refs/heads/master
Commit: eccf1b645bb9042825d84bbe4db4041ad63e2fc1
Parents: 7910ca9
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Fri Jan 22 15:40:08 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:02 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 66 +++++++++++++++++++++++++++-----------
1 file changed, 48 insertions(+), 18 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/eccf1b64/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 6b13120..3c4bb4b 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -19,6 +19,8 @@
#define C_CFISH_METHOD
#define C_CFISH_ERR
+#include <setjmp.h>
+
#include "charmony.h"
#include "CFBind.h"
@@ -36,6 +38,8 @@
#include "Clownfish/Util/Memory.h"
#include "Clownfish/Vector.h"
+static bool Err_initialized;
+
/**** refcounting **********************************************************/
uint32_t
@@ -114,48 +118,74 @@ CFISH_Method_Host_Name_IMP(cfish_Method *self) {
/**** Err ******************************************************************/
+/* TODO: Thread safety? */
+static cfish_Err *current_error;
+static cfish_Err *thrown_error;
+static jmp_buf *current_env;
+
void
-cfish_Err_init_class() {
- CFISH_THROW(CFISH_ERR, "TODO");
+cfish_Err_init_class(void) {
+ Err_initialized = true;
}
cfish_Err*
cfish_Err_get_error() {
- CFISH_THROW(CFISH_ERR, "TODO");
- CFISH_UNREACHABLE_RETURN(cfish_Err*);
+ return current_error;
}
void
cfish_Err_set_error(cfish_Err *error) {
- CFISH_UNUSED_VAR(error);
- CFISH_THROW(CFISH_ERR, "TODO");
+ if (current_error) {
+ CFISH_DECREF(current_error);
+ }
+ current_error = error;
}
void
cfish_Err_do_throw(cfish_Err *error) {
- CFISH_UNUSED_VAR(error);
- CFISH_THROW(CFISH_ERR, "TODO");
+ if (current_env) {
+ thrown_error = error;
+ longjmp(*current_env, 1);
+ }
+ else {
+ cfish_String *message = CFISH_Err_Get_Mess(error);
+ char *utf8 = CFISH_Str_To_Utf8(message);
+ fprintf(stderr, "%s", utf8);
+ CFISH_FREEMEM(utf8);
+ exit(EXIT_FAILURE);
+ }
}
void
cfish_Err_throw_mess(cfish_Class *klass, cfish_String *message) {
- CFISH_UNUSED_VAR(klass);
- CFISH_UNUSED_VAR(message);
- CFISH_THROW(CFISH_ERR, "TODO");
+ CFISH_UNUSED_VAR(klass); // TODO use klass
+ cfish_Err *err = cfish_Err_new(message);
+ cfish_Err_do_throw(err);
}
void
cfish_Err_warn_mess(cfish_String *message) {
- CFISH_UNUSED_VAR(message);
- CFISH_THROW(CFISH_ERR, "TODO");
+ char *utf8 = CFISH_Str_To_Utf8(message);
+ fprintf(stderr, "%s", utf8);
+ CFISH_FREEMEM(utf8);
+ CFISH_DECREF(message);
}
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*);
+cfish_Err_trap(CFISH_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;
+
+ cfish_Err *error = thrown_error;
+ thrown_error = NULL;
+ return error;
}
/**** TestUtils ************************************************************/
[16/20] lucy-clownfish git commit: Add ParseTuple converters for
composite types.
Posted by ma...@apache.org.
Add ParseTuple converters for composite types.
Provide ParseTuple-compatible C functions which convert Python list to
Clownfish Vector and Python dict to Clownfish Hash.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/2b65f360
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/2b65f360
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/2b65f360
Branch: refs/heads/master
Commit: 2b65f36064ae0f733123a82202dc97f18a6dd325
Parents: 99d6bc0
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 27 16:43:55 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:04 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 78 ++++++++++++++++++++++++++++++++++++++
runtime/python/cfext/CFBind.h | 14 +++++++
2 files changed, 92 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b65f360/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 501c342..e7d15ed 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -282,6 +282,84 @@ CFBind_py_to_cfish_noinc(PyObject *py_obj, cfish_Class *klass,
}
static int
+S_convert_hash(PyObject *py_obj, cfish_Hash **hash_ptr, bool nullable) {
+ if (py_obj == NULL) { // Py_CLEANUP_SUPPORTED cleanup
+ CFISH_DECREF(*hash_ptr);
+ return 1;
+ }
+
+ if (py_obj == Py_None) {
+ if (nullable) {
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "Required argument cannot be None");
+ return 0;
+ }
+ }
+ else if (PyDict_CheckExact(py_obj)) {
+ *hash_ptr = S_py_dict_to_hash(py_obj);
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else if (S_py_obj_is_a(py_obj, CFISH_HASH)) {
+ *hash_ptr = (cfish_Hash*)CFISH_INCREF(py_obj);
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else {
+ return 0;
+ }
+}
+
+int
+CFBind_convert_hash(PyObject *py_obj, cfish_Hash **hash_ptr) {
+ return S_convert_hash(py_obj, hash_ptr, false);
+}
+
+int
+CFBind_maybe_convert_hash(PyObject *py_obj, cfish_Hash **hash_ptr) {
+ return S_convert_hash(py_obj, hash_ptr, true);
+}
+
+static int
+S_convert_vec(PyObject *py_obj, cfish_Vector **vec_ptr, bool nullable) {
+ if (py_obj == NULL) { // Py_CLEANUP_SUPPORTED cleanup
+ CFISH_DECREF(*vec_ptr);
+ return 1;
+ }
+
+ if (py_obj == Py_None) {
+ if (nullable) {
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "Required argument cannot be None");
+ return 0;
+ }
+ }
+ else if (PyList_CheckExact(py_obj)) {
+ *vec_ptr = S_py_list_to_vector(py_obj);
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else if (S_py_obj_is_a(py_obj, CFISH_VECTOR)) {
+ *vec_ptr = (cfish_Vector*)CFISH_INCREF(py_obj);
+ return Py_CLEANUP_SUPPORTED;
+ }
+ else {
+ return 0;
+ }
+}
+
+int
+CFBind_convert_vec(PyObject *py_obj, cfish_Vector **vec_ptr) {
+ return S_convert_vec(py_obj, vec_ptr, false);
+}
+
+int
+CFBind_maybe_convert_vec(PyObject *py_obj, cfish_Vector **vec_ptr) {
+ return S_convert_vec(py_obj, vec_ptr, true);
+}
+
+static int
S_convert_sint(PyObject *py_obj, void *ptr, bool nullable, unsigned width) {
if (py_obj == Py_None) {
if (nullable) {
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b65f360/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index e4e0f23..d7eb0ba 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -100,6 +100,20 @@ cfish_Obj*
CFBind_py_to_cfish_noinc(PyObject *py_obj, cfish_Class *klass,
void *allocation);
+/* ParseTuple conversion routines for reference types.
+ *
+ * If `input` is `None`, the "maybe_convert" variants will leave `ptr`
+ * untouched, while the "convert" routines will raise a TypeError.
+ */
+int
+CFBind_convert_hash(PyObject *input, cfish_Hash **ptr);
+int
+CFBind_convert_vec(PyObject *input, cfish_Vector **ptr);
+int
+CFBind_maybe_convert_hash(PyObject *input, cfish_Hash **ptr);
+int
+CFBind_maybe_convert_vec(PyObject *input, cfish_Vector **ptr);
+
/* ParseTuple conversion routines for primitive numeric types.
*
* If the value of `input` is out of range for the an integer C type, an
[03/20] lucy-clownfish git commit: Add wrappers for `To_Host` in
Python bindings.
Posted by ma...@apache.org.
Add wrappers for `To_Host` in Python bindings.
Add NULL-safe wrappers, one of which is refcount neutral.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/2aab6efe
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/2aab6efe
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/2aab6efe
Branch: refs/heads/master
Commit: 2aab6efe2533e6e5b526cd6b408e24443c6d0f61
Parents: 991e4a5
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Jan 25 16:39:02 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:02 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2aab6efe/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index 85be7af..6637fca 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -23,6 +23,7 @@ extern "C" {
#include "cfish_platform.h"
#include "Python.h"
+#include "Clownfish/Obj.h"
struct cfish_Class;
struct cfish_String;
@@ -37,6 +38,34 @@ struct cfish_String;
void
CFBind_reraise_pyerr(struct cfish_Class *err_klass, struct cfish_String *mess);
+/** Null-safe invocation of Obj_To_Host.
+ */
+static CFISH_INLINE PyObject*
+CFBind_cfish_to_py(struct cfish_Obj *obj) {
+ if (obj != NULL) {
+ return (PyObject*)CFISH_Obj_To_Host(obj);
+ }
+ else {
+ Py_RETURN_NONE;
+ }
+}
+
+/** Perform the same conversion as `CFBind_cfish_to_py`, but ensure that the
+ * result is refcount-neutral, decrementing a refcount from `obj` and passing
+ * it along.
+ */
+static CFISH_INLINE PyObject*
+CFBind_cfish_to_py_zeroref(struct cfish_Obj *obj) {
+ if (obj != NULL) {
+ PyObject *result = (PyObject*)CFISH_Obj_To_Host(obj);
+ CFISH_DECREF(obj);
+ return result;
+ }
+ else {
+ return Py_None;
+ }
+}
+
/* ParseTuple conversion routines for primitive numeric types.
*
* If the value of `input` is out of range for the an integer C type, an
[20/20] lucy-clownfish git commit: Merge branch
'CLOWNFISH-66-py-glue1-v2'
Posted by ma...@apache.org.
Merge branch 'CLOWNFISH-66-py-glue1-v2'
Glue code for the Python host.
* Refcounting
* Error handling
* Host conversion for basic types
* Argument conversion
* Callbacks for overridden methods
This closes #58.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/7c80fb81
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/7c80fb81
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/7c80fb81
Branch: refs/heads/master
Commit: 7c80fb8189328bc92c17b938701b60ede8e42be2
Parents: 32e2701 335b61f
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Feb 24 15:02:50 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:02:50 2016 -0800
----------------------------------------------------------------------
compiler/src/CFCPyMethod.c | 217 +++++++++
compiler/src/CFCPyMethod.h | 39 ++
compiler/src/CFCPython.c | 275 ++++++++++-
runtime/python/cfext/CFBind.c | 917 ++++++++++++++++++++++++++++++++++---
runtime/python/cfext/CFBind.h | 188 ++++++++
5 files changed, 1581 insertions(+), 55 deletions(-)
----------------------------------------------------------------------
[17/20] lucy-clownfish git commit: Generate OVERRIDEs for
non-overrideable meths.
Posted by ma...@apache.org.
Generate OVERRIDEs for non-overrideable meths.
Generate error-throwing OVERRIDE routines for methods which cannot be
overridden.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/02617ac0
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/02617ac0
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/02617ac0
Branch: refs/heads/master
Commit: 02617ac057b70a2358233d9f65fb205123b308e1
Parents: 91622db
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 27 19:14:25 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:05 2016 -0800
----------------------------------------------------------------------
compiler/src/CFCPyMethod.c | 76 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 75 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/02617ac0/compiler/src/CFCPyMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyMethod.c b/compiler/src/CFCPyMethod.c
index 2892b86..3cc7b96 100644
--- a/compiler/src/CFCPyMethod.c
+++ b/compiler/src/CFCPyMethod.c
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <string.h>
#include "CFCPyMethod.h"
#include "CFCPyTypeMap.h"
@@ -32,7 +33,80 @@
#define false 0
#endif
+/* Take a NULL-terminated list of CFCVariables and build up a string of
+ * directives like:
+ *
+ * UNUSED_VAR(var1);
+ * UNUSED_VAR(var2);
+ */
+static char*
+S_build_unused_vars(CFCVariable **vars);
+
+/* Create an unreachable return statement if necessary, in order to thwart
+ * compiler warnings. */
+static char*
+S_maybe_unreachable(CFCType *return_type);
+
char*
CFCPyMethod_callback_def(CFCMethod *method, CFCClass *invoker) {
- return CFCUtil_strdup("");
+ CFCParamList *param_list = CFCMethod_get_param_list(method);
+ CFCVariable **vars = CFCParamList_get_variables(param_list);
+ CFCType *return_type = CFCMethod_get_return_type(method);
+ const char *ret_type_str = CFCType_to_c(return_type);
+ const char *params = CFCParamList_to_c(param_list);
+ char *override_sym = CFCMethod_full_override_sym(method, invoker);
+ char *content;
+
+ //if (CFCMethod_can_be_bound(method)) {
+ if (false) {
+ }
+ else {
+ char *unused = S_build_unused_vars(vars);
+ char *unreachable = S_maybe_unreachable(return_type);
+ char *meth_sym = CFCMethod_full_method_sym(method, invoker);
+ const char pattern[] =
+ "%s\n"
+ "%s(%s) {%s\n"
+ " CFISH_THROW(CFISH_ERR, \"Can't override %s via binding\");%s\n"
+ "}\n";
+ content = CFCUtil_sprintf(pattern, ret_type_str, override_sym,
+ params, unused, meth_sym, unreachable);
+ FREEMEM(meth_sym);
+ FREEMEM(unused);
+ FREEMEM(unreachable);
+ }
+
+ FREEMEM(override_sym);
+ return content;
}
+
+static char*
+S_build_unused_vars(CFCVariable **vars) {
+ char *unused = CFCUtil_strdup("");
+
+ for (int i = 0; vars[i] != NULL; i++) {
+ const char *var_name = CFCVariable_get_name(vars[i]);
+ size_t size = strlen(unused) + strlen(var_name) + 80;
+ unused = (char*)REALLOCATE(unused, size);
+ strcat(unused, "\n CFISH_UNUSED_VAR(");
+ strcat(unused, var_name);
+ strcat(unused, ");");
+ }
+
+ return unused;
+}
+
+static char*
+S_maybe_unreachable(CFCType *return_type) {
+ char *return_statement;
+ if (CFCType_is_void(return_type)) {
+ return_statement = CFCUtil_strdup("");
+ }
+ else {
+ const char *ret_type_str = CFCType_to_c(return_type);
+ char pattern[] = "\n CFISH_UNREACHABLE_RETURN(%s);";
+ return_statement = CFCUtil_sprintf(pattern, ret_type_str);
+ }
+ return return_statement;
+}
+
[07/20] lucy-clownfish git commit: Conversion routines from Python to
Clownfish.
Posted by ma...@apache.org.
Conversion routines from Python to Clownfish.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/99d6bc0f
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/99d6bc0f
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/99d6bc0f
Branch: refs/heads/master
Commit: 99d6bc0fe89382c8492d97825fc03ca82eac051f
Parents: 999b39f
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 27 15:35:08 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:03 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 196 +++++++++++++++++++++++++++++++++++++
runtime/python/cfext/CFBind.h | 34 +++++++
2 files changed, 230 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/99d6bc0f/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index d3c39c2..501c342 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -37,6 +37,7 @@
#include "Clownfish/String.h"
#include "Clownfish/TestHarness/TestUtils.h"
#include "Clownfish/Util/Memory.h"
+#include "Clownfish/Util/StringHelper.h"
#include "Clownfish/Vector.h"
static bool Err_initialized;
@@ -85,6 +86,201 @@ CFBind_reraise_pyerr(cfish_Class *err_klass, cfish_String *mess) {
cfish_Err_throw_mess(err_klass, new_mess);
}
+static cfish_Vector*
+S_py_list_to_vector(PyObject *list) {
+ Py_ssize_t size = PyList_GET_SIZE(list);
+ cfish_Vector *vec = cfish_Vec_new(size);
+ for (Py_ssize_t i = 0; i < size; i++) {
+ CFISH_Vec_Store(vec, i, CFBind_py_to_cfish(PyList_GET_ITEM(list, i), NULL));
+ }
+ return vec;
+}
+
+static cfish_Hash*
+S_py_dict_to_hash(PyObject *dict) {
+ Py_ssize_t pos = 0;
+ PyObject *key, *value;
+ cfish_Hash *hash = cfish_Hash_new(PyDict_Size(dict));
+ while (PyDict_Next(dict, &pos, &key, &value)) {
+ char *ptr;
+ Py_ssize_t size;
+ PyObject *stringified = key;
+ if (!PyUnicode_CheckExact(key)) {
+ stringified = PyObject_Str(key);
+ }
+ ptr = PyUnicode_AsUTF8AndSize(stringified, &size);
+ if (!ptr) {
+ cfish_String *mess
+ = CFISH_MAKE_MESS("Failed to stringify as UTF-8");
+ CFBind_reraise_pyerr(CFISH_ERR, mess);
+ }
+ CFISH_Hash_Store_Utf8(hash, ptr, size, CFBind_py_to_cfish(value, NULL));
+ if (stringified != key) {
+ Py_DECREF(stringified);
+ }
+ }
+ return hash;
+}
+
+static cfish_Obj*
+S_maybe_increment(void *vobj, bool increment) {
+ if (increment) {
+ return CFISH_INCREF((cfish_Obj*)vobj);
+ }
+ return (cfish_Obj*)vobj;
+}
+
+static bool
+S_maybe_py_to_cfish(PyObject *py_obj, cfish_Class *klass, bool increment,
+ bool nullable, void *allocation, cfish_Obj **obj_ptr) {
+ CFISH_UNUSED_VAR(allocation); // FIXME implement stack strings
+
+ if (!py_obj || py_obj == Py_None) {
+ *obj_ptr = NULL;
+ return nullable;
+ }
+
+ // Default to accepting any type.
+ if (klass == NULL) {
+ klass = CFISH_OBJ;
+ }
+
+ if (S_py_obj_is_a(py_obj, klass)) {
+ *obj_ptr = S_maybe_increment(py_obj, increment);
+ return true;
+ }
+ else if (py_obj == Py_True) {
+ if (klass != CFISH_BOOLEAN && klass != CFISH_OBJ) {
+ return false;
+ }
+ *obj_ptr = S_maybe_increment(CFISH_TRUE, increment);
+ return true;
+ }
+ else if (py_obj == Py_False) {
+ if (klass != CFISH_BOOLEAN && klass != CFISH_OBJ) {
+ return false;
+ }
+ *obj_ptr = S_maybe_increment(CFISH_FALSE, increment);
+ return true;
+ }
+ else if (klass == CFISH_BOOLEAN) {
+ int truthiness = PyObject_IsTrue(py_obj);
+ if (truthiness == 1) {
+ *obj_ptr = S_maybe_increment(CFISH_TRUE, increment);
+ }
+ else if (truthiness == 0) {
+ *obj_ptr = S_maybe_increment(CFISH_FALSE, increment);
+ }
+ else {
+ return false;
+ }
+ return true;
+ }
+
+ // From here on out, we're going to return a new Clownfish object. The
+ // caller has to take ownership of a refcount; if they don't want to, then
+ // fail rather than attempt to return an object with a refcount of 0.
+ if (!increment) {
+ return false;
+ }
+
+ if (PyUnicode_CheckExact(py_obj)) {
+ if (klass != CFISH_STRING && klass != CFISH_OBJ) {
+ return false;
+ }
+ // TODO: Allow Clownfish String to wrap buffer of Python str?
+ Py_ssize_t size;
+ char *ptr = PyUnicode_AsUTF8AndSize(py_obj, &size);
+ // TODO: Can we guarantee that Python will always supply valid UTF-8?
+ if (!ptr || !cfish_StrHelp_utf8_valid(ptr, size)) {
+ return false;
+ }
+ *obj_ptr = (cfish_Obj*)cfish_Str_new_from_trusted_utf8(ptr, size);
+ return true;
+ }
+ else if (PyBytes_CheckExact(py_obj)) {
+ if (klass != CFISH_BLOB && klass != CFISH_OBJ) {
+ return false;
+ }
+ char *ptr = PyBytes_AS_STRING(py_obj);
+ Py_ssize_t size = PyBytes_GET_SIZE(py_obj);
+ *obj_ptr = (cfish_Obj*)cfish_BB_new_bytes(ptr, size);
+ return true;
+ }
+ else if (PyList_CheckExact(py_obj)) {
+ if (klass != CFISH_VECTOR && klass != CFISH_OBJ) {
+ return false;
+ }
+ *obj_ptr = (cfish_Obj*)S_py_list_to_vector(py_obj);
+ return true;
+ }
+ else if (PyDict_CheckExact(py_obj)) {
+ if (klass != CFISH_HASH && klass != CFISH_OBJ) {
+ return false;
+ }
+ *obj_ptr = (cfish_Obj*)S_py_dict_to_hash(py_obj);
+ return true;
+ }
+ else if (PyLong_CheckExact(py_obj)) {
+ if (klass != CFISH_INTEGER && klass != CFISH_OBJ) {
+ return false;
+ }
+ // Raises ValueError on overflow.
+ int64_t value = PyLong_AsLongLong(py_obj);
+ if (PyErr_Occurred()) {
+ return false;
+ }
+ *obj_ptr = (cfish_Obj*)cfish_Int_new(value);
+ return true;
+ }
+ else if (PyFloat_CheckExact(py_obj)) {
+ if (klass != CFISH_FLOAT && klass != CFISH_OBJ) {
+ return false;
+ }
+ double value = PyFloat_AsDouble(py_obj);
+ if (PyErr_Occurred()) {
+ return false;
+ }
+ *obj_ptr = (cfish_Obj*)cfish_Float_new(value);
+ return true;
+ }
+
+ // The value did not meet the required spec, so return false to indicate
+ // failure.
+ return false;
+}
+
+cfish_Obj*
+CFBind_py_to_cfish_nullable(PyObject *py_obj, cfish_Class *klass) {
+ cfish_Obj *retval;
+ bool success = S_maybe_py_to_cfish(py_obj, klass, true, true, NULL, &retval);
+ if (!success) {
+ CFISH_THROW(CFISH_ERR, "Can't convert to %o", klass);
+ }
+ return retval;
+}
+
+cfish_Obj*
+CFBind_py_to_cfish(PyObject *py_obj, cfish_Class *klass) {
+ cfish_Obj *retval;
+ bool success = S_maybe_py_to_cfish(py_obj, klass, true, false, NULL, &retval);
+ if (!success) {
+ CFISH_THROW(CFISH_ERR, "Can't convert to %o", klass);
+ }
+ return retval;
+}
+
+cfish_Obj*
+CFBind_py_to_cfish_noinc(PyObject *py_obj, cfish_Class *klass,
+ void *allocation) {
+ cfish_Obj *retval;
+ bool success = S_maybe_py_to_cfish(py_obj, klass, false, false, allocation, &retval);
+ if (!success) {
+ CFISH_THROW(CFISH_ERR, "Can't convert to %o", klass);
+ }
+ return retval;
+}
+
static int
S_convert_sint(PyObject *py_obj, void *ptr, bool nullable, unsigned width) {
if (py_obj == Py_None) {
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/99d6bc0f/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index 6637fca..e4e0f23 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -66,6 +66,40 @@ CFBind_cfish_to_py_zeroref(struct cfish_Obj *obj) {
}
}
+/** Perform recursive conversion of Python objects to Clownfish, return an
+ * incremented Clownfish Obj.
+ *
+ * string -> String
+ * bytes -> Blob
+ * None -> NULL
+ * bool -> Boolean
+ * int -> Integer
+ * float -> Float
+ * list -> Vector
+ * dict -> Hash
+ *
+ * Python dict keys will be stringified. Other Clownfish objects will be
+ * left intact. Anything else will be stringified.
+ */
+cfish_Obj*
+CFBind_py_to_cfish(PyObject *py_obj, cfish_Class *klass);
+
+/** As CFBind_py_to_cfish above, but returns NULL if the PyObject is None
+ * or NULL.
+ */
+cfish_Obj*
+CFBind_py_to_cfish_nullable(PyObject *py_obj, cfish_Class *klass);
+
+/** As CFBind_py_to_cfish above, but returns an object that can be used for a
+ * while with no need to decref.
+ *
+ * If `klass` is STRING or OBJ, `allocation` must point to stack-allocated
+ * memory that can hold a String. Otherwise, `allocation` should be NULL.
+ */
+cfish_Obj*
+CFBind_py_to_cfish_noinc(PyObject *py_obj, cfish_Class *klass,
+ void *allocation);
+
/* ParseTuple conversion routines for primitive numeric types.
*
* If the value of `input` is out of range for the an integer C type, an
[04/20] lucy-clownfish git commit: Add ParseTuple-compatible
converters for numerics.
Posted by ma...@apache.org.
Add ParseTuple-compatible converters for numerics.
Add some conversion functions which conform to the API specified by
Python's ParseTuple C functionality.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/991e4a57
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/991e4a57
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/991e4a57
Branch: refs/heads/master
Commit: 991e4a576ab7edfd96e285c8493c3bdbd1794d6d
Parents: 9162199
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Fri Jan 22 17:14:30 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:02 2016 -0800
----------------------------------------------------------------------
runtime/python/cfext/CFBind.c | 305 +++++++++++++++++++++++++++++++++++++
runtime/python/cfext/CFBind.h | 73 +++++++++
2 files changed, 378 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/991e4a57/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 95ae70d..7653325 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -76,6 +76,311 @@ CFBind_reraise_pyerr(cfish_Class *err_klass, cfish_String *mess) {
cfish_Err_throw_mess(err_klass, new_mess);
}
+static int
+S_convert_sint(PyObject *py_obj, void *ptr, bool nullable, unsigned width) {
+ if (py_obj == Py_None) {
+ if (nullable) {
+ return 1;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "Required argument cannot be None");
+ return 0;
+ }
+ }
+ int overflow = 0;
+ int64_t value = PyLong_AsLongLongAndOverflow(py_obj, &overflow);
+ if (value == -1 && PyErr_Occurred()) {
+ return 0;
+ }
+ switch (width & 0xF) {
+ case 1:
+ if (value < INT8_MIN || value > INT8_MAX) { overflow = 1; }
+ break;
+ case 2:
+ if (value < INT16_MIN || value > INT16_MAX) { overflow = 1; }
+ break;
+ case 4:
+ if (value < INT32_MIN || value > INT32_MAX) { overflow = 1; }
+ break;
+ case 8:
+ break;
+ }
+ if (overflow) {
+ PyErr_SetString(PyExc_OverflowError, "Python int out of range");
+ return 0;
+ }
+ switch (width & 0xF) {
+ case 1:
+ *((int8_t*)ptr) = (int8_t)value;
+ break;
+ case 2:
+ *((int16_t*)ptr) = (int16_t)value;
+ break;
+ case 4:
+ *((int32_t*)ptr) = (int32_t)value;
+ break;
+ case 8:
+ *((int64_t*)ptr) = value;
+ break;
+ }
+ return 1;
+}
+
+static int
+S_convert_uint(PyObject *py_obj, void *ptr, bool nullable, unsigned width) {
+ if (py_obj == Py_None) {
+ if (nullable) {
+ return 1;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "Required argument cannot be None");
+ return 0;
+ }
+ }
+ uint64_t value = PyLong_AsUnsignedLongLong(py_obj);
+ if (PyErr_Occurred()) {
+ return 0;
+ }
+ int overflow = 0;
+ switch (width & 0xF) {
+ case 1:
+ if (value > UINT8_MAX) { overflow = 1; }
+ break;
+ case 2:
+ if (value > UINT16_MAX) { overflow = 1; }
+ break;
+ case 4:
+ if (value > UINT32_MAX) { overflow = 1; }
+ break;
+ case 8:
+ break;
+ }
+ if (overflow) {
+ PyErr_SetString(PyExc_OverflowError, "Python int out of range");
+ return 0;
+ }
+ switch (width & 0xF) {
+ case 1:
+ *((uint8_t*)ptr) = (uint8_t)value;
+ break;
+ case 2:
+ *((uint16_t*)ptr) = (uint16_t)value;
+ break;
+ case 4:
+ *((uint32_t*)ptr) = (uint32_t)value;
+ break;
+ case 8:
+ *((uint64_t*)ptr) = value;
+ break;
+ }
+ return 1;
+}
+
+int
+CFBind_convert_char(PyObject *py_obj, char *ptr) {
+ return S_convert_sint(py_obj, ptr, false, sizeof(char));
+}
+
+int
+CFBind_convert_short(PyObject *py_obj, short *ptr) {
+ return S_convert_sint(py_obj, ptr, false, sizeof(short));
+}
+
+int
+CFBind_convert_int(PyObject *py_obj, int *ptr) {
+ return S_convert_sint(py_obj, ptr, false, sizeof(int));
+}
+
+int
+CFBind_convert_long(PyObject *py_obj, long *ptr) {
+ return S_convert_sint(py_obj, ptr, false, sizeof(long));
+}
+
+int
+CFBind_convert_int8_t(PyObject *py_obj, int8_t *ptr) {
+ return S_convert_sint(py_obj, ptr, false, sizeof(int8_t));
+}
+
+int
+CFBind_convert_int16_t(PyObject *py_obj, int16_t *ptr) {
+ return S_convert_sint(py_obj, ptr, false, sizeof(int16_t));
+}
+
+int
+CFBind_convert_int32_t(PyObject *py_obj, int32_t *ptr) {
+ return S_convert_sint(py_obj, ptr, false, sizeof(int32_t));
+}
+
+int
+CFBind_convert_int64_t(PyObject *py_obj, int64_t *ptr) {
+ return S_convert_sint(py_obj, ptr, false, sizeof(int64_t));
+}
+
+int
+CFBind_convert_uint8_t(PyObject *py_obj, uint8_t *ptr) {
+ return S_convert_uint(py_obj, ptr, false, sizeof(uint8_t));
+}
+
+int
+CFBind_convert_uint16_t(PyObject *py_obj, uint16_t *ptr) {
+ return S_convert_uint(py_obj, ptr, false, sizeof(uint16_t));
+}
+
+int
+CFBind_convert_uint32_t(PyObject *py_obj, uint32_t *ptr) {
+ return S_convert_uint(py_obj, ptr, false, sizeof(uint32_t));
+}
+
+int
+CFBind_convert_uint64_t(PyObject *py_obj, uint64_t *ptr) {
+ return S_convert_uint(py_obj, ptr, false, sizeof(uint64_t));
+}
+
+int
+CFBind_convert_size_t(PyObject *py_obj, size_t *ptr) {
+ return S_convert_uint(py_obj, ptr, false, sizeof(size_t));
+}
+
+int
+CFBind_maybe_convert_char(PyObject *py_obj, char *ptr) {
+ return S_convert_sint(py_obj, ptr, true, sizeof(char));
+}
+
+int
+CFBind_maybe_convert_short(PyObject *py_obj, short *ptr) {
+ return S_convert_sint(py_obj, ptr, true, sizeof(short));
+}
+
+int
+CFBind_maybe_convert_int(PyObject *py_obj, int *ptr) {
+ return S_convert_sint(py_obj, ptr, true, sizeof(int));
+}
+
+int
+CFBind_maybe_convert_long(PyObject *py_obj, long *ptr) {
+ return S_convert_sint(py_obj, ptr, true, sizeof(long));
+}
+
+int
+CFBind_maybe_convert_int8_t(PyObject *py_obj, int8_t *ptr) {
+ return S_convert_sint(py_obj, ptr, true, sizeof(int8_t));
+}
+
+int
+CFBind_maybe_convert_int16_t(PyObject *py_obj, int16_t *ptr) {
+ return S_convert_sint(py_obj, ptr, true, sizeof(int16_t));
+}
+
+int
+CFBind_maybe_convert_int32_t(PyObject *py_obj, int32_t *ptr) {
+ return S_convert_sint(py_obj, ptr, true, sizeof(int32_t));
+}
+
+int
+CFBind_maybe_convert_int64_t(PyObject *py_obj, int64_t *ptr) {
+ return S_convert_sint(py_obj, ptr, true, sizeof(int64_t));
+}
+
+int
+CFBind_maybe_convert_uint8_t(PyObject *py_obj, uint8_t *ptr) {
+ return S_convert_uint(py_obj, ptr, true, sizeof(uint8_t));
+}
+
+int
+CFBind_maybe_convert_uint16_t(PyObject *py_obj, uint16_t *ptr) {
+ return S_convert_uint(py_obj, ptr, true, sizeof(uint16_t));
+}
+
+int
+CFBind_maybe_convert_uint32_t(PyObject *py_obj, uint32_t *ptr) {
+ return S_convert_uint(py_obj, ptr, true, sizeof(uint32_t));
+}
+
+int
+CFBind_maybe_convert_uint64_t(PyObject *py_obj, uint64_t *ptr) {
+ return S_convert_uint(py_obj, ptr, true, sizeof(uint64_t));
+}
+
+int
+CFBind_maybe_convert_size_t(PyObject *py_obj, size_t *ptr) {
+ return S_convert_uint(py_obj, ptr, true, sizeof(size_t));
+}
+
+static int
+S_convert_floating(PyObject *py_obj, void *ptr, bool nullable, int width) {
+ if (py_obj == Py_None) {
+ if (nullable) {
+ return 1;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "Required argument cannot be None");
+ return 0;
+ }
+ }
+ double value = PyFloat_AsDouble(py_obj);
+ if (PyErr_Occurred()) {
+ return 0;
+ }
+ switch (width & 0xF) {
+ case sizeof(float):
+ *((float*)ptr) = (float)value;
+ break;
+ case sizeof(double):
+ *((double*)ptr) = value;
+ break;
+ }
+ return 1;
+}
+
+int
+CFBind_convert_float(PyObject *py_obj, float *ptr) {
+ return S_convert_floating(py_obj, ptr, false, sizeof(float));
+}
+
+int
+CFBind_convert_double(PyObject *py_obj, double *ptr) {
+ return S_convert_floating(py_obj, ptr, false, sizeof(double));
+}
+
+int
+CFBind_maybe_convert_float(PyObject *py_obj, float *ptr) {
+ return S_convert_floating(py_obj, ptr, true, sizeof(float));
+}
+
+int
+CFBind_maybe_convert_double(PyObject *py_obj, double *ptr) {
+ return S_convert_floating(py_obj, ptr, true, sizeof(double));
+}
+
+static int
+S_convert_bool(PyObject *py_obj, bool *ptr, bool nullable) {
+ if (py_obj == Py_None) {
+ if (nullable) {
+ return 1;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "Required argument cannot be None");
+ return 0;
+ }
+ }
+ int truth = PyObject_IsTrue(py_obj);
+ if (truth == -1) {
+ return 0;
+ }
+ *ptr = !!truth;
+ return 1;
+}
+
+int
+CFBind_convert_bool(PyObject *py_obj, bool *ptr) {
+ return S_convert_bool(py_obj, ptr, false);
+}
+
+int
+CFBind_maybe_convert_bool(PyObject *py_obj, bool *ptr) {
+ return S_convert_bool(py_obj, ptr, true);
+}
+
/**** refcounting **********************************************************/
uint32_t
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/991e4a57/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index d6a362e..85be7af 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -37,6 +37,79 @@ struct cfish_String;
void
CFBind_reraise_pyerr(struct cfish_Class *err_klass, struct cfish_String *mess);
+/* ParseTuple conversion routines for primitive numeric types.
+ *
+ * If the value of `input` is out of range for the an integer C type, an
+ * OverflowError will be raised.
+ *
+ * If `input` is `None`, the "maybe_convert" variants will leave `ptr`
+ * untouched, while the "convert" routines will raise a TypeError.
+ */
+int
+CFBind_convert_char(PyObject *input, char *ptr);
+int
+CFBind_convert_short(PyObject *input, short *ptr);
+int
+CFBind_convert_int(PyObject *input, int *ptr);
+int
+CFBind_convert_long(PyObject *input, long *ptr);
+int
+CFBind_convert_int8_t(PyObject *input, int8_t *ptr);
+int
+CFBind_convert_int16_t(PyObject *input, int16_t *ptr);
+int
+CFBind_convert_int32_t(PyObject *input, int32_t *ptr);
+int
+CFBind_convert_int64_t(PyObject *input, int64_t *ptr);
+int
+CFBind_convert_uint8_t(PyObject *input, uint8_t *ptr);
+int
+CFBind_convert_uint16_t(PyObject *input, uint16_t *ptr);
+int
+CFBind_convert_uint32_t(PyObject *input, uint32_t *ptr);
+int
+CFBind_convert_uint64_t(PyObject *input, uint64_t *ptr);
+int
+CFBind_convert_bool(PyObject *input, bool *ptr);
+int
+CFBind_convert_size_t(PyObject *input, size_t *ptr);
+int
+CFBind_convert_float(PyObject *input, float *ptr);
+int
+CFBind_convert_double(PyObject *input, double *ptr);
+int
+CFBind_maybe_convert_char(PyObject *input, char *ptr);
+int
+CFBind_maybe_convert_short(PyObject *input, short *ptr);
+int
+CFBind_maybe_convert_int(PyObject *input, int *ptr);
+int
+CFBind_maybe_convert_long(PyObject *input, long *ptr);
+int
+CFBind_maybe_convert_int8_t(PyObject *input, int8_t *ptr);
+int
+CFBind_maybe_convert_int16_t(PyObject *input, int16_t *ptr);
+int
+CFBind_maybe_convert_int32_t(PyObject *input, int32_t *ptr);
+int
+CFBind_maybe_convert_int64_t(PyObject *input, int64_t *ptr);
+int
+CFBind_maybe_convert_uint8_t(PyObject *input, uint8_t *ptr);
+int
+CFBind_maybe_convert_uint16_t(PyObject *input, uint16_t *ptr);
+int
+CFBind_maybe_convert_uint32_t(PyObject *input, uint32_t *ptr);
+int
+CFBind_maybe_convert_uint64_t(PyObject *input, uint64_t *ptr);
+int
+CFBind_maybe_convert_bool(PyObject *input, bool *ptr);
+int
+CFBind_maybe_convert_size_t(PyObject *input, size_t *ptr);
+int
+CFBind_maybe_convert_float(PyObject *input, float *ptr);
+int
+CFBind_maybe_convert_double(PyObject *input, double *ptr);
+
#ifdef __cplusplus
}
#endif