PageRenderTime 201ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/nuitka/codegen/templates/CodeTemplatesGeneratorFunction.py

https://bitbucket.org/pombredanne/nuitka
Python | 288 lines | 267 code | 1 blank | 20 comment | 1 complexity | c48b123ee1c5003fdfba2acc632cae32 MD5 | raw file
  1. # Copyright 2013, Kay Hayen, mailto:kay.hayen@gmail.com
  2. #
  3. # Part of "Nuitka", an optimizing Python compiler that is compatible and
  4. # integrates with CPython, but also works on its own.
  5. #
  6. # Licensed under the Apache License, Version 2.0 (the "License");
  7. # you may not use this file except in compliance with the License.
  8. # You may obtain a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. #
  18. """ Generator function (with yield) related templates.
  19. """
  20. genfunc_context_body_template = """
  21. // This structure is for attachment as self of the generator function %(function_identifier)s and
  22. // contains the common closure. It is allocated at the time the genexpr object is created.
  23. struct _context_common_%(function_identifier)s_t
  24. {
  25. // Ref count to keep track of common context usage and release only when it's the last one
  26. int ref_count;
  27. // The generator function can access a read-only closure of the creator.
  28. %(function_common_context_decl)s
  29. };
  30. struct _context_generator_%(function_identifier)s_t
  31. {
  32. _context_common_%(function_identifier)s_t *common_context;
  33. // The generator function instance can access its parameters from creation time.
  34. %(function_instance_context_decl)s
  35. };
  36. static void _context_common_%(function_identifier)s_destructor( void *context_voidptr )
  37. {
  38. _context_common_%(function_identifier)s_t *_python_context = (struct _context_common_%(function_identifier)s_t *)context_voidptr;
  39. assert( _python_context->ref_count > 0 );
  40. _python_context->ref_count -= 1;
  41. %(context_free)s
  42. if ( _python_context->ref_count == 0 )
  43. {
  44. delete _python_context;
  45. }
  46. }
  47. static void _context_generator_%(function_identifier)s_destructor( void *context_voidptr )
  48. {
  49. _context_generator_%(function_identifier)s_t *_python_context = (struct _context_generator_%(function_identifier)s_t *)context_voidptr;
  50. _context_common_%(function_identifier)s_destructor( _python_context->common_context );
  51. delete _python_context;
  52. }
  53. """
  54. genfunc_context_local_only_template = """
  55. struct _context_generator_%(function_identifier)s_t
  56. {
  57. // The generator function instance can access its parameters from creation time.
  58. %(function_instance_context_decl)s
  59. };
  60. static void _context_generator_%(function_identifier)s_destructor( void *context_voidptr )
  61. {
  62. _context_generator_%(function_identifier)s_t *_python_context = (struct _context_generator_%(function_identifier)s_t *)context_voidptr;
  63. delete _python_context;
  64. }
  65. """
  66. make_genfunc_with_context_template = """
  67. static PyObject *_MAKE_FUNCTION_%(function_identifier)s( %(function_creation_args)s )
  68. {
  69. struct _context_common_%(function_identifier)s_t *_python_context = new _context_common_%(function_identifier)s_t;
  70. _python_context->ref_count = 1;
  71. // Copy the parameter default values and closure values over.
  72. %(context_copy)s
  73. return Nuitka_Function_New(
  74. %(fparse_function_identifier)s,
  75. %(mparse_function_identifier)s,
  76. %(function_name_obj)s,
  77. #if PYTHON_VERSION >= 330
  78. %(function_qualname_obj)s,
  79. #endif
  80. %(code_identifier)s,
  81. %(defaults)s,
  82. #if PYTHON_VERSION >= 300
  83. %(kwdefaults)s,
  84. %(annotations)s,
  85. #endif
  86. %(module_identifier)s,
  87. %(function_doc)s,
  88. _python_context,
  89. _context_common_%(function_identifier)s_destructor
  90. );
  91. }
  92. """
  93. make_genfunc_without_context_template = """
  94. static PyObject *_MAKE_FUNCTION_%(function_identifier)s( %(function_creation_args)s )
  95. {
  96. return Nuitka_Function_New(
  97. %(fparse_function_identifier)s,
  98. %(mparse_function_identifier)s,
  99. %(function_name_obj)s,
  100. #if PYTHON_VERSION >= 330
  101. %(function_qualname_obj)s,
  102. #endif
  103. %(code_identifier)s,
  104. %(defaults)s,
  105. #if PYTHON_VERSION >= 300
  106. %(kwdefaults)s,
  107. %(annotations)s,
  108. #endif
  109. %(module_identifier)s,
  110. %(function_doc)s
  111. );
  112. }
  113. """
  114. genfunc_yielder_template = """
  115. static void %(function_identifier)s_context( Nuitka_GeneratorObject *generator )
  116. {
  117. {
  118. // Make context accessible if one is used.
  119. %(context_access)s
  120. // Local variable inits
  121. %(function_var_inits)s
  122. // Actual function code.
  123. %(function_body)s
  124. }
  125. // TODO: Won't return, we should tell the compiler about that.
  126. generator->m_yielded = NULL;
  127. swapFiber( &generator->m_yielder_context, &generator->m_caller_context );
  128. }
  129. """
  130. frame_guard_genfunc_template = """\
  131. static PyFrameObject *frame_%(frame_identifier)s = NULL;
  132. // Must be inside block, or else its d-tor will not be run.
  133. if ( isFrameUnusable( frame_%(frame_identifier)s ) )
  134. {
  135. if ( frame_%(frame_identifier)s )
  136. {
  137. #if _DEBUG_REFRAME
  138. puts( "reframe for %(frame_identifier)s" );
  139. #endif
  140. Py_DECREF( frame_%(frame_identifier)s );
  141. }
  142. frame_%(frame_identifier)s = MAKE_FRAME( %(code_identifier)s, %(module_identifier)s );
  143. }
  144. Py_INCREF( frame_%(frame_identifier)s );
  145. generator->m_frame = frame_%(frame_identifier)s;
  146. Py_CLEAR( generator->m_frame->f_back );
  147. generator->m_frame->f_back = PyThreadState_GET()->frame;
  148. Py_INCREF( generator->m_frame->f_back );
  149. PyThreadState_GET()->frame = generator->m_frame;
  150. FrameGuardLight frame_guard( &generator->m_frame );
  151. // TODO: The inject of the exception through C++ is very non-optimal, this flag
  152. // now indicates only if the exception occurs initially as supposed, or during
  153. // life, this could and should be shortcut.
  154. bool traceback;
  155. try
  156. {
  157. // TODO: In case we don't raise exceptions ourselves, we would still have to do this, so
  158. // beware to not optimize this away for generators without a replacement.
  159. traceback = true;
  160. CHECK_EXCEPTION( generator );
  161. traceback = false;
  162. %(codes)s
  163. PyErr_SetNone( PyExc_StopIteration );
  164. }
  165. catch ( PythonException &_exception )
  166. {
  167. if ( !_exception.hasTraceback() )
  168. {
  169. _exception.setTraceback( %(tb_making)s );
  170. }
  171. else if ( traceback == false )
  172. {
  173. _exception.addTraceback( generator->m_frame );
  174. }
  175. _exception.toPython();
  176. // TODO: Moving this code is not allowed yet.
  177. generator->m_yielded = NULL;
  178. }"""
  179. genfunc_common_context_use_template = """\
  180. struct _context_common_%(function_identifier)s_t *_python_common_context = (struct _context_common_%(function_identifier)s_t *)self->m_context;
  181. struct _context_generator_%(function_identifier)s_t *_python_context = new _context_generator_%(function_identifier)s_t;
  182. _python_context->common_context = _python_common_context;
  183. _python_common_context->ref_count += 1;"""
  184. genfunc_local_context_use_template = """\
  185. struct _context_generator_%(function_identifier)s_t *_python_context = \
  186. new _context_generator_%(function_identifier)s_t;"""
  187. genfunc_generator_without_context_making = """\
  188. PyObject *result = Nuitka_Generator_New(
  189. %(function_identifier)s_context,
  190. %(function_name_obj)s,
  191. %(code_identifier)s
  192. );"""
  193. genfunc_generator_with_context_making = """\
  194. PyObject *result = Nuitka_Generator_New(
  195. %(function_identifier)s_context,
  196. %(function_name_obj)s,
  197. %(code_identifier)s,
  198. _python_context,
  199. _context_generator_%(function_identifier)s_destructor
  200. );"""
  201. genfunc_function_maker_template = """
  202. static PyObject *impl_%(function_identifier)s( %(parameter_objects_decl)s )
  203. {
  204. // Create context if any
  205. %(context_making)s
  206. try
  207. {
  208. %(generator_making)s
  209. if (unlikely( result == NULL ))
  210. {
  211. PyErr_Format( PyExc_RuntimeError, "cannot create function %(function_name)s" );
  212. return NULL;
  213. }
  214. // Copy to context parameter values and closured variables if any.
  215. %(context_copy)s
  216. return result;
  217. }
  218. catch ( PythonException &_exception )
  219. {
  220. _exception.toPython();
  221. return NULL;
  222. }
  223. }
  224. """
  225. generator_context_access_template = """
  226. // The context of the generator.
  227. struct _context_common_%(function_identifier)s_t *_python_context = (struct _context_common_%(function_identifier)s_t *)self->m_context;
  228. """
  229. generator_context_unused_template = """\
  230. // No context is used.
  231. """
  232. # TODO: The NUITKA_MAY_BE_UNUSED is because Nuitka doesn't yet detect the case of unused
  233. # parameters (which are stored in the context for generators to share) reliably.
  234. generator_context_access_template2 = """
  235. NUITKA_MAY_BE_UNUSED struct _context_generator_%(function_identifier)s_t *_python_context = (_context_generator_%(function_identifier)s_t *)generator->m_context;
  236. """