Fast IFS using RPN notation
python
c
x86-64
nasm
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

python_pyrpn.c 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * Copyright (C) 2020 Weber Yann
  3. *
  4. * This file is part of pyrpn.
  5. *
  6. * pyrpn is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * any later version.
  10. *
  11. * pyrpn is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with pyrpn. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "python_pyrpn.h"
  20. /**@file python_pyrpn.c
  21. * @brief Python module & type definition
  22. * @ingroup python_ext
  23. * @ingroup python_pyrpn
  24. *
  25. * This file contains pyrpn Python module definition
  26. */
  27. /**@brief pyrpn module's method definition */
  28. static PyMethodDef rpnmodule_methods[] = {
  29. PYRPN_method("get_ops", pyrpn_ops,
  30. METH_NOARGS,
  31. "/",
  32. "Return a dict with valid operands"),
  33. PYRPN_method("random_expr", pyrpn_random,
  34. METH_VARARGS | METH_KEYWORDS,
  35. "args_count, token_count",
  36. "Return a random RPN expression string"),
  37. {NULL} // Sentinel
  38. };
  39. PyModuleDef rpnmodule = {
  40. PyModuleDef_HEAD_INIT,
  41. "pyrpn",
  42. "Python librarie for RPN evaluation",
  43. -1, // module size
  44. rpnmodule_methods,
  45. NULL, // m_slots
  46. NULL, // m_traverse
  47. NULL, // m_clear
  48. NULL // m_free
  49. };
  50. PyObject *mmap_module = NULL;
  51. PyObject *mmap_cls = NULL;
  52. PyMODINIT_FUNC
  53. PyInit_pyrpn(void)
  54. {
  55. if(mmap_module == NULL)
  56. {
  57. mmap_module = PyImport_ImportModule("mmap");
  58. if(PyErr_Occurred()) { return NULL; }
  59. else if(!mmap_module)
  60. {
  61. PyErr_Format(PyExc_ImportError, "Unable to import mmap module");
  62. return NULL;
  63. }
  64. }
  65. if(mmap_cls == NULL)
  66. {
  67. mmap_cls = PyObject_GetAttrString(mmap_module, "mmap");
  68. if(PyErr_Occurred()) { return NULL; }
  69. else if (!mmap_cls)
  70. {
  71. PyErr_Format(PyExc_ImportError, "Unable to import mmap.mmap");
  72. return NULL;
  73. }
  74. }
  75. PyObject *mod, *const_mod, *tokens_mod;
  76. // init module & globals
  77. mod = PyModule_Create(&rpnmodule);
  78. if(mod == NULL) { return NULL; }
  79. //init constants module
  80. const_mod = rpnconst_init();
  81. if(const_mod == NULL)
  82. {
  83. goto fail_init;
  84. }
  85. Py_INCREF(const_mod);
  86. if(PyModule_AddObject(mod, "const", const_mod) < 0)
  87. {
  88. goto fail_add_const;
  89. }
  90. //init tokens module
  91. tokens_mod = rpntokens_module_init();
  92. if(tokens_mod == NULL)
  93. {
  94. goto fail_add_const;
  95. }
  96. Py_INCREF(tokens_mod);
  97. if(PyModule_AddObject(mod, "tokens", tokens_mod) < 0)
  98. {
  99. goto fail_add_tokens;
  100. }
  101. // Init RPNExpr type
  102. if(PyType_Ready(&RPNExprType) < 0)
  103. {
  104. goto fail_expr_type_ready;
  105. }
  106. // Add type to module
  107. Py_INCREF(&RPNExprType);
  108. if(PyModule_AddObject(mod, "RPNExpr", (PyObject*)&RPNExprType) < 0)
  109. {
  110. goto fail_add_rpnexpr;
  111. }
  112. // Init RPNIterExpr type
  113. if(PyType_Ready(&RPNIterExprType) < 0)
  114. {
  115. goto fail_iter_type_ready;
  116. }
  117. Py_INCREF(&RPNIterExprType);
  118. if(PyModule_AddObject(mod, "RPNIterExpr", (PyObject*)&RPNIterExprType) < 0)
  119. {
  120. goto fail_add_iter;
  121. }
  122. if(PyType_Ready(&RPNIFSType) < 0)
  123. {
  124. goto fail_ifs_type_ready;
  125. }
  126. Py_INCREF(&RPNIFSType);
  127. if(PyModule_AddObject(mod, "RPNIFS", (PyObject*)&RPNIFSType) < 0)
  128. {
  129. goto fail_add_ifs;
  130. }
  131. // Named tuple for RPNIterExpr's params
  132. PyStructSequence_InitType(&rpnif_params_SeqDesc,&rpnif_params_desc);
  133. Py_INCREF(&rpnif_params_SeqDesc);
  134. /*
  135. PyObject_SetAttrString((PyObject*)rpnif_params_SeqDesc, "__module__",
  136. mod);
  137. */
  138. if(PyModule_AddObject(mod, "RPNIterExprParams",
  139. (PyObject*)&rpnif_params_SeqDesc) < 0)
  140. {
  141. goto fail_add_iter_expr_params;
  142. }
  143. // Named tuple for token types
  144. PyStructSequence_InitType(&rpn_token_types_SeqDesc,
  145. &rpn_token_types_desc);
  146. Py_INCREF(&rpn_token_types_SeqDesc);
  147. if(PyModule_AddObject(mod, "RPNTokenTypesTuple",
  148. (PyObject*)&rpn_token_types_SeqDesc) < 0)
  149. {
  150. goto fail_add_token_types_tuple;
  151. }
  152. if(pyrpn_python_mutation_init(mod) < 0)
  153. {
  154. goto fail_init_mutation;
  155. }
  156. return mod;
  157. fail_init_mutation:
  158. Py_DECREF(&rpn_token_types_SeqDesc);
  159. fail_add_token_types_tuple:
  160. Py_DECREF(&rpnif_params_SeqDesc);
  161. fail_add_iter_expr_params:
  162. fail_add_ifs:
  163. Py_DECREF(&RPNIFSType);
  164. fail_ifs_type_ready:
  165. fail_add_iter:
  166. Py_DECREF(&RPNIterExprType);
  167. fail_iter_type_ready:
  168. fail_add_rpnexpr:
  169. Py_DECREF(&RPNExprType);
  170. fail_expr_type_ready:
  171. fail_add_tokens:
  172. Py_DECREF(tokens_mod);
  173. fail_add_const:
  174. Py_DECREF(const_mod);
  175. fail_init:
  176. Py_DECREF(mod);
  177. return NULL;
  178. }
  179. PyObject* pyrpn_ops(PyObject* mod, PyObject* noargs)
  180. {
  181. PyObject *ret, *value;
  182. const rpn_op_t *op;
  183. size_t i;
  184. ret = PyDict_New();
  185. if(!ret)
  186. {
  187. return ret;
  188. }
  189. foreach_rpn_ops(i)
  190. {
  191. op = &rpn_ops[i];
  192. value = Py_BuildValue("C", op->chr);
  193. if(PyDict_SetItemString(ret, op->str, value))
  194. {
  195. Py_DECREF(value);
  196. Py_DECREF(ret);
  197. return NULL;
  198. }
  199. Py_DECREF(value);
  200. }
  201. return ret;
  202. }
  203. PyObject* pyrpn_random(PyObject *mod, PyObject *args, PyObject *kwds)
  204. {
  205. long long int args_count, expr_sz;
  206. char *expr, err_str[128];
  207. PyObject *res;
  208. char *names[] = {"args_count", "token_count", NULL};
  209. expr_sz = 10;
  210. if(!PyArg_ParseTupleAndKeywords(args, kwds, "L|L:pyrpn.random_expr", names,
  211. &args_count, &expr_sz))
  212. {
  213. return NULL;
  214. }
  215. expr = expr_sz?rpn_random(expr_sz, args_count):"";
  216. if(!expr)
  217. {
  218. snprintf(err_str, 128,
  219. "Error generating random expression : %s",
  220. strerror(errno));
  221. PyErr_SetString(PyExc_RuntimeError, err_str);
  222. return NULL;
  223. }
  224. res = Py_BuildValue("s", expr);
  225. return res;
  226. }