244 lines
5.4 KiB
C
244 lines
5.4 KiB
C
/*
|
|
* Copyright (C) 2020 Weber Yann
|
|
*
|
|
* This file is part of pyrpn.
|
|
*
|
|
* pyrpn is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* any later version.
|
|
*
|
|
* pyrpn is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with pyrpn. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "python_pyrpn.h"
|
|
|
|
/**@file python_pyrpn.c
|
|
* @brief Python module & type definition
|
|
* @ingroup python_ext
|
|
* @ingroup python_pyrpn
|
|
*
|
|
* This file contains pyrpn Python module definition
|
|
*/
|
|
|
|
/**@brief pyrpn module's method definition */
|
|
static PyMethodDef rpnmodule_methods[] = {
|
|
PYRPN_method("get_ops", pyrpn_ops,
|
|
METH_NOARGS,
|
|
"/",
|
|
"Return a dict with valid operands"),
|
|
PYRPN_method("random_expr", pyrpn_random,
|
|
METH_VARARGS | METH_KEYWORDS,
|
|
"args_count, token_count",
|
|
"Return a random RPN expression string"),
|
|
{NULL} // Sentinel
|
|
};
|
|
|
|
PyModuleDef rpnmodule = {
|
|
PyModuleDef_HEAD_INIT,
|
|
"pyrpn",
|
|
"Python librarie for RPN evaluation",
|
|
-1, // module size
|
|
rpnmodule_methods,
|
|
NULL, // m_slots
|
|
NULL, // m_traverse
|
|
NULL, // m_clear
|
|
NULL // m_free
|
|
};
|
|
|
|
PyObject *mmap_module = NULL;
|
|
PyObject *mmap_cls = NULL;
|
|
|
|
PyMODINIT_FUNC
|
|
PyInit_pyrpn(void)
|
|
{
|
|
if(mmap_module == NULL)
|
|
{
|
|
mmap_module = PyImport_ImportModule("mmap");
|
|
if(PyErr_Occurred()) { return NULL; }
|
|
else if(!mmap_module)
|
|
{
|
|
PyErr_Format(PyExc_ImportError, "Unable to import mmap module");
|
|
return NULL;
|
|
}
|
|
}
|
|
if(mmap_cls == NULL)
|
|
{
|
|
mmap_cls = PyObject_GetAttrString(mmap_module, "mmap");
|
|
if(PyErr_Occurred()) { return NULL; }
|
|
else if (!mmap_cls)
|
|
{
|
|
PyErr_Format(PyExc_ImportError, "Unable to import mmap.mmap");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
PyObject *mod, *const_mod, *tokens_mod;
|
|
// init module & globals
|
|
mod = PyModule_Create(&rpnmodule);
|
|
if(mod == NULL) { return NULL; }
|
|
|
|
//init constants module
|
|
const_mod = rpnconst_init();
|
|
if(const_mod == NULL)
|
|
{
|
|
goto fail_init;
|
|
}
|
|
Py_INCREF(const_mod);
|
|
if(PyModule_AddObject(mod, "const", const_mod) < 0)
|
|
{
|
|
goto fail_add_const;
|
|
}
|
|
|
|
//init tokens module
|
|
tokens_mod = rpntokens_module_init();
|
|
if(tokens_mod == NULL)
|
|
{
|
|
goto fail_add_const;
|
|
}
|
|
Py_INCREF(tokens_mod);
|
|
if(PyModule_AddObject(mod, "tokens", tokens_mod) < 0)
|
|
{
|
|
goto fail_add_tokens;
|
|
}
|
|
|
|
// Init RPNExpr type
|
|
if(PyType_Ready(&RPNExprType) < 0)
|
|
{
|
|
goto fail_expr_type_ready;
|
|
}
|
|
|
|
// Add type to module
|
|
Py_INCREF(&RPNExprType);
|
|
if(PyModule_AddObject(mod, "RPNExpr", (PyObject*)&RPNExprType) < 0)
|
|
{
|
|
goto fail_add_rpnexpr;
|
|
}
|
|
|
|
// Init RPNIterExpr type
|
|
if(PyType_Ready(&RPNIterExprType) < 0)
|
|
{
|
|
goto fail_iter_type_ready;
|
|
}
|
|
|
|
Py_INCREF(&RPNIterExprType);
|
|
if(PyModule_AddObject(mod, "RPNIterExpr", (PyObject*)&RPNIterExprType) < 0)
|
|
{
|
|
goto fail_add_iter;
|
|
}
|
|
|
|
// Named tuple for RPNIterExpr's params
|
|
PyStructSequence_InitType(&rpnif_params_SeqDesc,&rpnif_params_desc);
|
|
Py_INCREF(&rpnif_params_SeqDesc);
|
|
/*
|
|
PyObject_SetAttrString((PyObject*)rpnif_params_SeqDesc, "__module__",
|
|
mod);
|
|
*/
|
|
if(PyModule_AddObject(mod, "RPNIterExprParams",
|
|
(PyObject*)&rpnif_params_SeqDesc) < 0)
|
|
{
|
|
goto fail_add_iter_expr_params;
|
|
}
|
|
|
|
// Named tuple for token types
|
|
PyStructSequence_InitType(&rpn_token_types_SeqDesc,
|
|
&rpn_token_types_desc);
|
|
Py_INCREF(&rpn_token_types_SeqDesc);
|
|
if(PyModule_AddObject(mod, "RPNTokenTypesTuple",
|
|
(PyObject*)&rpn_token_types_SeqDesc) < 0)
|
|
{
|
|
goto fail_add_token_types_tuple;
|
|
}
|
|
|
|
// Named tuple for mutation parameters
|
|
PyStructSequence_InitType(&rpn_mutation_params_SeqDesc,
|
|
&rpn_mutation_params_desc);
|
|
Py_INCREF(&rpn_mutation_params_SeqDesc);
|
|
if(PyModule_AddObject(mod, "RPNMutationParamsTuple",
|
|
(PyObject*)&rpn_mutation_params_SeqDesc) < 0)
|
|
{
|
|
goto fail_add_mutation_params_tuple;
|
|
}
|
|
|
|
return mod;
|
|
|
|
fail_add_mutation_params_tuple:
|
|
Py_DECREF(&rpn_token_types_SeqDesc);
|
|
fail_add_token_types_tuple:
|
|
Py_DECREF(&rpnif_params_SeqDesc);
|
|
fail_add_iter_expr_params:
|
|
fail_add_iter:
|
|
Py_DECREF(&RPNIterExprType);
|
|
fail_iter_type_ready:
|
|
fail_add_rpnexpr:
|
|
Py_DECREF(&RPNExprType);
|
|
fail_expr_type_ready:
|
|
fail_add_tokens:
|
|
Py_DECREF(tokens_mod);
|
|
fail_add_const:
|
|
Py_DECREF(const_mod);
|
|
fail_init:
|
|
Py_DECREF(mod);
|
|
return NULL;
|
|
}
|
|
|
|
PyObject* pyrpn_ops(PyObject* mod, PyObject* noargs)
|
|
{
|
|
PyObject *ret, *value;
|
|
const rpn_op_t *op;
|
|
size_t i;
|
|
|
|
ret = PyDict_New();
|
|
if(!ret)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
foreach_rpn_ops(i)
|
|
{
|
|
op = &rpn_ops[i];
|
|
value = Py_BuildValue("C", op->chr);
|
|
if(PyDict_SetItemString(ret, op->str, value))
|
|
{
|
|
Py_DECREF(value);
|
|
Py_DECREF(ret);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(value);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
PyObject* pyrpn_random(PyObject *mod, PyObject *args, PyObject *kwds)
|
|
{
|
|
long long int args_count, expr_sz;
|
|
char *expr, err_str[128];
|
|
PyObject *res;
|
|
char *names[] = {"args_count", "token_count", NULL};
|
|
|
|
expr_sz = 10;
|
|
if(!PyArg_ParseTupleAndKeywords(args, kwds, "L|L:pyrpn.random_expr", names,
|
|
&args_count, &expr_sz))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
expr = expr_sz?rpn_random(expr_sz, args_count):"";
|
|
if(!expr)
|
|
{
|
|
snprintf(err_str, 128,
|
|
"Error generating random expression : %s",
|
|
strerror(errno));
|
|
PyErr_SetString(PyExc_RuntimeError, err_str);
|
|
return NULL;
|
|
}
|
|
res = Py_BuildValue("s", expr);
|
|
return res;
|
|
}
|