blob: 30968b3b23ffeabcdaef3fd50995966e4d3ee81c [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Python.h"
#include "CFC.h"
typedef struct {
PyObject_HEAD
void *cfc_obj;
} CFCPyWrapper;
static PyModuleDef cfc_module_def = {
PyModuleDef_HEAD_INIT,
"cfc._cfc",
"CFC: Clownfish compiler",
-1,
NULL, NULL, NULL, NULL, NULL
};
static PyModuleDef cfc_model_module_def = {
PyModuleDef_HEAD_INIT,
"cfc.model",
"CFC classes which model language constructs",
-1,
NULL, NULL, NULL, NULL, NULL
};
static PyModuleDef cfc_binding_module_def = {
PyModuleDef_HEAD_INIT,
"cfc.binding",
"CFC components which generate bindings",
-1,
NULL, NULL, NULL, NULL, NULL
};
static PyObject *cfc_module;
static PyObject *cfc_model_module;
static PyObject *cfc_binding_module;
static PyObject*
S_wrap_cfcbase(PyTypeObject *type, void *cfc_obj) {
if (cfc_obj == NULL) {
Py_RETURN_NONE;
}
CFCPyWrapper *wrapper = (CFCPyWrapper*)type->tp_alloc(type, 0);
if (wrapper == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Failed to allocate object");
return NULL;
}
wrapper->cfc_obj = cfc_obj;
return (PyObject*)wrapper;
}
static void
S_CFCBase_dealloc(CFCPyWrapper *wrapper) {
CFCBase *temp = (CFCBase*)wrapper->cfc_obj;
wrapper->cfc_obj = NULL;
CFCBase_decref(temp);
Py_TYPE(wrapper)->tp_free(wrapper);
}
void*
S_to_cfc_something(PyObject *wrapper, const char *class_name) {
if (wrapper == NULL || wrapper == Py_None) {
return NULL;
}
CFCBase *obj = (CFCBase*)((CFCPyWrapper*)wrapper)->cfc_obj;
if (strcmp(CFCBase_get_cfc_class(obj), class_name) != 0) {
CFCUtil_die("Object is not a %s, it's a %s", class_name,
CFCBase_get_cfc_class(obj));
}
return obj;
}
static CFCHierarchy*
S_to_Hierarchy(PyObject *wrapper) {
return (CFCHierarchy*)S_to_cfc_something(wrapper,
"Clownfish::CFC::Model::Hierarchy");
}
static CFCBindCore*
S_to_BindCore(PyObject *wrapper) {
return (CFCBindCore*)S_to_cfc_something(wrapper,
"Clownfish::CFC::Binding::Core");
}
static CFCPython*
S_to_BindPython(PyObject *wrapper) {
return (CFCPython*)S_to_cfc_something(wrapper,
"Clownfish::CFC::Binding::Python");
}
static PyTypeObject *Hierarchy_pytype;
static PyTypeObject *Parcel_pytype;
static PyTypeObject *BindCore_pytype;
static PyTypeObject *BindPython_pytype;
/***************************** CFCHierarchy *****************************/
static PyObject*
S_CFCHierarchy_new(PyTypeObject *type, PyObject *args,
PyObject *keyword_args) {
char *dest = NULL;
char *keywords[] = {"dest", NULL};
int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "|s",
keywords, &dest);
if (!result) { return NULL; }
if (!dest) {
PyErr_SetString(PyExc_TypeError, "Missing required arg 'dest'");
return NULL;
}
PyObject *inc_func = PyObject_GetAttrString(cfc_module, "_get_inc_dirs");
PyObject *dirs = NULL;
if (PyCallable_Check(inc_func)) {
dirs = PyObject_CallObject(inc_func, NULL);
}
if (dirs == NULL || !PyList_Check(dirs)) {
Py_XDECREF(inc_func);
Py_XDECREF(dirs);
PyErr_SetString(PyExc_RuntimeError, "_get_inc_dirs failed");
return NULL;
}
CFCHierarchy *hierarchy = CFCHierarchy_new(dest);
for (Py_ssize_t i = 0, max = PyList_Size(dirs); i < max; i++) {
PyObject *dir = PyList_GetItem(dirs, i);
if (PyUnicode_Check(dir)) {
char *dir_utf8 = PyUnicode_AsUTF8(dir);
CFCHierarchy_add_include_dir(hierarchy, dir_utf8);
}
else {
PyErr_SetString(PyExc_RuntimeError, "not a string");
return NULL;
}
}
Py_XDECREF(inc_func);
Py_XDECREF(dirs);
return S_wrap_cfcbase(Hierarchy_pytype, hierarchy);
}
static PyObject*
S_CFCHierarchy_build(PyObject *wrapper, PyObject *unused) {
CHY_UNUSED_VAR(unused);
CFCHierarchy_build(S_to_Hierarchy(wrapper));
Py_RETURN_NONE;
}
static PyObject*
S_CFCHierarchy_add_include_dir(PyObject *wrapper, PyObject *dir) {
CFCHierarchy_add_include_dir(S_to_Hierarchy(wrapper),
PyUnicode_AsUTF8(dir));
Py_RETURN_NONE;
}
static PyObject*
S_CFCHierarchy_add_source_dir(PyObject *wrapper, PyObject *dir) {
CFCHierarchy_add_source_dir(S_to_Hierarchy(wrapper),
PyUnicode_AsUTF8(dir));
Py_RETURN_NONE;
}
static PyObject*
S_CFCHierarchy_get_dest(PyObject *wrapper, PyObject *unused) {
CHY_UNUSED_VAR(unused);
const char *dest = CFCHierarchy_get_dest(S_to_Hierarchy(wrapper));
return PyUnicode_DecodeASCII(dest, (Py_ssize_t)strlen(dest), NULL);
}
static PyObject*
S_CFCHierarchy_write_log(PyObject *wrapper, PyObject *unused) {
CHY_UNUSED_VAR(unused);
CFCHierarchy_write_log(S_to_Hierarchy(wrapper));
Py_RETURN_NONE;
}
static PyMethodDef hierarchy_methods[] = {
{"add_include_dir", (PyCFunction)S_CFCHierarchy_add_include_dir, METH_O, NULL},
{"add_source_dir", (PyCFunction)S_CFCHierarchy_add_source_dir, METH_O, NULL},
{"build", (PyCFunction)S_CFCHierarchy_build, METH_NOARGS, NULL},
{"get_dest", (PyCFunction)S_CFCHierarchy_get_dest, METH_NOARGS, NULL},
{"write_log", (PyCFunction)S_CFCHierarchy_write_log, METH_NOARGS, NULL},
{NULL}
};
static PyTypeObject Hierarchy_pytype_struct = {
PyVarObject_HEAD_INIT(NULL, 0)
"cfc.model.Hierarchy", // tp_name
sizeof(CFCPyWrapper), // tp_basicsize
0, // tp_itemsize
(destructor)S_CFCBase_dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_reserved
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
"CFCHierarchy", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
hierarchy_methods, // tp_methods
0, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
0, // tp_allow
(newfunc)S_CFCHierarchy_new // tp_new
};
/***************************** CFCParcel *****************************/
PyObject*
S_CFCParcel_fetch(PyObject *ignored, PyObject *name) {
CFCParcel *parcel = CFCParcel_fetch(PyUnicode_AsUTF8(name));
return S_wrap_cfcbase(Parcel_pytype, parcel);
}
static PyMethodDef parcel_methods[] = {
{"fetch", (PyCFunction)S_CFCParcel_fetch, METH_STATIC, NULL},
{NULL}
};
static PyTypeObject Parcel_pytype_struct = {
PyVarObject_HEAD_INIT(NULL, 0)
"cfc.model.Parcel", // tp_name
sizeof(CFCPyWrapper), // tp_basicsize
0, // tp_itemsize
(destructor)S_CFCBase_dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_reserved
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
"CFCParcel", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
parcel_methods, // tp_methods
0, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
0, // tp_allow
0 // tp_new
};
/***************************** CFCBindCore *****************************/
static PyObject*
S_CFCBindCore_new(PyTypeObject *type, PyObject *args,
PyObject *keyword_args) {
PyObject *hierarchy_wrapped;
char *header = "";
char *footer = "";
char *keywords[] = {"hierarchy", "header", "footer", NULL};
int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "O!|ss",
keywords, Hierarchy_pytype,
&hierarchy_wrapped, &header,
&footer);
if (!result) { return NULL; }
CFCHierarchy *hierarchy = S_to_Hierarchy(hierarchy_wrapped);
CFCBindCore *obj = CFCBindCore_new(hierarchy, header, footer, 0);
return S_wrap_cfcbase(BindCore_pytype, obj);
}
static PyObject*
S_CFCBindCore_write_all_modified(PyObject *wrapper, PyObject *args) {
int modified = 0;
int result = PyArg_ParseTuple(args, "|p", &modified);
if (!result) { return NULL; }
modified = CFCBindCore_write_all_modified(S_to_BindCore(wrapper), modified);
if (modified) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyMethodDef bindcore_methods[] = {
{"write_all_modified", (PyCFunction)S_CFCBindCore_write_all_modified, METH_VARARGS, NULL},
{NULL}
};
static PyTypeObject BindCore_pytype_struct = {
PyVarObject_HEAD_INIT(NULL, 0)
"cfc.binding.BindCore", // tp_name
sizeof(CFCPyWrapper), // tp_basicsize
0, // tp_itemsize
(destructor)S_CFCBase_dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_reserved
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
"CFCBindCore", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
bindcore_methods, // tp_methods
0, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
0, // tp_allow
(newfunc)S_CFCBindCore_new // tp_new
};
/***************************** CFCPython *****************************/
static PyObject*
S_CFCPython_new(PyTypeObject *type, PyObject *args, PyObject *keyword_args) {
PyObject *hierarchy_wrapped;
char *keywords[] = {"hierarchy", NULL};
int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "O!",
keywords, Hierarchy_pytype,
&hierarchy_wrapped);
if (!result) { return NULL; }
CFCHierarchy *hierarchy = S_to_Hierarchy(hierarchy_wrapped);
CFCPython *obj = CFCPython_new(hierarchy);
return S_wrap_cfcbase(BindPython_pytype, obj);
}
static PyObject*
S_CFCPython_set_header(PyObject *wrapper, PyObject *header) {
CFCPython_set_header(S_to_BindPython(wrapper), PyUnicode_AsUTF8(header));
Py_RETURN_NONE;
}
static PyObject*
S_CFCPython_set_footer(PyObject *wrapper, PyObject *footer) {
CFCPython_set_footer(S_to_BindPython(wrapper), PyUnicode_AsUTF8(footer));
Py_RETURN_NONE;
}
static PyObject*
S_CFCPython_write_bindings(PyObject *wrapper, PyObject *args,
PyObject *keyword_args) {
char *parcel;
char *dest;
char *keywords[] = {"parcel", "dest", NULL};
int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "ss",
keywords, &parcel, &dest);
if (!result) { return NULL; }
CFCPython_write_bindings(S_to_BindPython(wrapper), parcel, dest);
Py_RETURN_NONE;
}
static PyMethodDef bindpython_methods[] = {
{"set_header", (PyCFunction)S_CFCPython_set_header, METH_O, NULL},
{"set_footer", (PyCFunction)S_CFCPython_set_footer, METH_O, NULL},
{"write_bindings", (PyCFunction)S_CFCPython_write_bindings, METH_KEYWORDS|METH_VARARGS, NULL},
{NULL}
};
static PyTypeObject BindPython_pytype_struct = {
PyVarObject_HEAD_INIT(NULL, 0)
"cfc.binding.Python", // tp_name
sizeof(CFCPyWrapper), // tp_basicsize
0, // tp_itemsize
(destructor)S_CFCBase_dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_reserved
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
"CFCBindPython", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
bindpython_methods, // tp_methods
0, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
0, // tp_allow
(newfunc)S_CFCPython_new // tp_new
};
/******************************* common ******************************/
PyMODINIT_FUNC
PyInit__cfc(void) {
// Initialize Python type objects.
Hierarchy_pytype = &Hierarchy_pytype_struct;
Parcel_pytype = &Parcel_pytype_struct;
BindCore_pytype = &BindCore_pytype_struct;
BindPython_pytype = &BindPython_pytype_struct;
if (PyType_Ready(Hierarchy_pytype) < 0) {
return NULL;
}
if (PyType_Ready(Parcel_pytype) < 0) {
return NULL;
}
if (PyType_Ready(BindCore_pytype) < 0) {
return NULL;
}
if (PyType_Ready(BindPython_pytype) < 0) {
return NULL;
}
// Initialize modules.
cfc_module = PyModule_Create(&cfc_module_def);
cfc_model_module = PyModule_Create(&cfc_model_module_def);
cfc_binding_module = PyModule_Create(&cfc_binding_module_def);
PyModule_AddObject(cfc_module, "model", (PyObject*)cfc_model_module);
PyModule_AddObject(cfc_module, "binding", (PyObject*)cfc_binding_module);
// Add type objects to "model" module.
Py_INCREF(Hierarchy_pytype);
PyModule_AddObject(cfc_model_module, "Hierarchy",
(PyObject*)Hierarchy_pytype);
Py_INCREF(Parcel_pytype);
PyModule_AddObject(cfc_model_module, "Parcel",
(PyObject*)Parcel_pytype);
// Add type objects to "binding" module.
Py_INCREF(BindCore_pytype);
PyModule_AddObject(cfc_binding_module, "BindCore",
(PyObject*)BindCore_pytype);
Py_INCREF(BindCore_pytype);
PyModule_AddObject(cfc_binding_module, "Python",
(PyObject*)BindPython_pytype);
return cfc_module;
}