Commit 9e0f30c1 authored by Stefan Behnel's avatar Stefan Behnel

- more versatile utility code setup: use a dedicated class to distinguish...

- more versatile utility code setup: use a dedicated class to distinguish proto/impl/init/cleanup code
- fix set initialisation by making it use the new setup
parent 497af27e
......@@ -4,6 +4,7 @@ from Cython.Compiler.Nodes import *
from Cython.Compiler.ExprNodes import *
from Cython.Compiler.StringEncoding import EncodedString
from Cython.Compiler.Errors import CompileError
from Cython.Utils import UtilityCode
import Interpreter
import PyrexTypes
......@@ -431,7 +432,7 @@ def use_empty_bufstruct_code(env, max_ndim):
Py_ssize_t __Pyx_zeros[] = {%s};
Py_ssize_t __Pyx_minusones[] = {%s};
""") % (", ".join(["0"] * max_ndim), ", ".join(["-1"] * max_ndim))
env.use_utility_code([code, ""], "empty_bufstruct_code")
env.use_utility_code(UtilityCode(proto=code), "empty_bufstruct_code")
def buf_lookup_full_code(proto, defin, name, nd):
......@@ -656,9 +657,9 @@ def get_getbuffer_code(dtype, code):
typestringchecker = get_typestringchecker(code, dtype)
dtype_name = str(dtype)
dtype_cname = dtype.declaration_code("")
utilcode = [dedent("""
utilcode = UtilityCode(proto = dedent("""
static int %s(PyObject* obj, Py_buffer* buf, int flags, int nd, int cast); /*proto*/
""") % name, dedent("""
""") % name, impl = dedent("""
static int %(name)s(PyObject* obj, Py_buffer* buf, int flags, int nd, int cast) {
const char* ts;
if (obj == Py_None) {
......@@ -697,7 +698,7 @@ def get_getbuffer_code(dtype, code):
fail:;
__Pyx_ZeroBuffer(buf);
return -1;
}""") % locals()]
}""") % locals())
code.globalstate.use_utility_code(utilcode, name)
return name
......@@ -776,7 +777,8 @@ def use_py2_buffer_functions(env):
#endif
""")
env.use_utility_code([dedent("""\
env.use_utility_code(UtilityCode(
proto = dedent("""\
#if PY_MAJOR_VERSION < 3
static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
static void __Pyx_ReleaseBuffer(Py_buffer *view);
......@@ -784,7 +786,7 @@ def use_py2_buffer_functions(env):
#define __Pyx_GetBuffer PyObject_GetBuffer
#define __Pyx_ReleaseBuffer PyBuffer_Release
#endif
"""), code], codename)
"""), impl = code), codename)
#
# Static utility code
......@@ -793,16 +795,17 @@ def use_py2_buffer_functions(env):
# Utility function to set the right exception
# The caller should immediately goto_error
raise_indexerror_code = [
"""\
raise_indexerror_code = UtilityCode(
proto = """\
static void __Pyx_RaiseBufferIndexError(int axis); /*proto*/
""","""\
""",
impl = """\
static void __Pyx_RaiseBufferIndexError(int axis) {
PyErr_Format(PyExc_IndexError,
"Out of bounds on buffer access (axis %d)", axis);
}
"""]
""")
#
# Buffer type checking. Utility code for checking that acquired
......@@ -810,13 +813,15 @@ static void __Pyx_RaiseBufferIndexError(int axis) {
# the format string; the access mode/flags is checked by the
# exporter.
#
acquire_utility_code = ["""\
acquire_utility_code = UtilityCode(
proto = """\
static INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
static INLINE void __Pyx_ZeroBuffer(Py_buffer* buf); /*proto*/
static INLINE const char* __Pyx_ConsumeWhitespace(const char* ts); /*proto*/
static void __Pyx_BufferNdimError(Py_buffer* buffer, int expected_ndim); /*proto*/
static const char* __Pyx_DescribeTokenInFormatString(const char* ts); /*proto*/
""", """
""",
impl = """
static INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
if (info->buf == NULL) return;
if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
......@@ -886,12 +891,14 @@ static const char* __Pyx_DescribeTokenInFormatString(const char* ts) {
}
}
"""]
""")
parse_typestring_repeat_code = ["""
parse_typestring_repeat_code = UtilityCode(
proto = """
static INLINE const char* __Pyx_ParseTypestringRepeat(const char* ts, int* out_count); /*proto*/
""","""
""",
impl = """
static INLINE const char* __Pyx_ParseTypestringRepeat(const char* ts, int* out_count) {
int count;
if (*ts < '0' || *ts > '9') {
......@@ -906,15 +913,16 @@ static INLINE const char* __Pyx_ParseTypestringRepeat(const char* ts, int* out_c
*out_count = count;
return ts;
}
"""]
""")
raise_buffer_fallback_code = ["""
raise_buffer_fallback_code = UtilityCode(
proto = """
static void __Pyx_RaiseBufferFallbackError(void); /*proto*/
""","""
""",
impl = """
static void __Pyx_RaiseBufferFallbackError(void) {
PyErr_Format(PyExc_ValueError,
"Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!");
}
"""]
""")
......@@ -3,6 +3,7 @@
#
from Symtab import BuiltinScope, StructOrUnionScope
from Cython.Utils import UtilityCode
from TypeSlots import Signature
import PyrexTypes
import __builtin__
......@@ -134,9 +135,11 @@ builtin_structs_table = [
])
]
getattr3_utility_code = ["""
getattr3_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
""","""
""",
impl = """
static PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) {
PyObject *r = PyObject_GetAttr(o, n);
if (!r) {
......@@ -150,18 +153,24 @@ static PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) {
bad:
return 0;
}
"""]
""")
intern_utility_code = ["""
intern_utility_code = UtilityCode(
proto = """
#if PY_MAJOR_VERSION >= 3
# define __Pyx_InternFromString(s) PyUnicode_InternFromString(s)
#else
# define __Pyx_InternFromString(s) PyString_InternFromString(s)
#endif
""","""
"""]
""")
py23_set_utility_code = ["""
def put_py23_set_init_utility_code(code, pos):
code.putln("#if PY_VERSION_HEX < 0x02040000")
code.putln(code.error_goto_if_neg("__Pyx_Py23SetsImport()", pos))
code.putln("#endif")
py23_set_utility_code = UtilityCode(
proto = """
#if PY_VERSION_HEX < 0x02050000
#ifndef PyAnySet_CheckExact
......@@ -250,8 +259,8 @@ static int py23sets_import(void) { return 0; }
#endif /* !Py_SETOBJECT_H */
#endif /* < Py2.4 */
#endif /* < Py2.5 */
""","""
"""]
""",
init = put_py23_set_init_utility_code)
builtin_utility_code = {
'getattr3' : getattr3_utility_code,
......
......@@ -334,7 +334,7 @@ class GlobalState(object):
# Utility code state
#
def use_utility_code(self, codetup, name=None):
def use_utility_code(self, utility_code, name=None):
"""
Adds the given utility code to the C file if needed.
......@@ -344,11 +344,13 @@ class GlobalState(object):
If name is provided, it is used as an identifier to avoid inserting
code twice. Otherwise, id(codetup) is used as such an identifier.
"""
if name is None: name = id(codetup)
if name is None: name = id(utility_code)
if self.check_utility_code_needed_and_register(name):
proto, _def = codetup
self.utilprotowriter.put(proto)
self.utildefwriter.put(_def)
if utility_code.proto:
self.utilprotowriter.put(utility_code.proto)
if utility_code.impl:
self.utildefwriter.put(utility_code.impl)
utility_code.write_init_code(self.initwriter, self.module_pos)
def has_code(self, name):
return name in self.used_utility_code
......
......@@ -7,6 +7,7 @@ from string import join
from Errors import error, warning, InternalError
from Errors import hold_errors, release_errors, held_errors, report_error
from Cython.Utils import UtilityCode
import StringEncoding
import Naming
from Nodes import Node
......@@ -4631,10 +4632,11 @@ class PersistentNode(ExprNode):
#
#------------------------------------------------------------------------------------
get_name_interned_utility_code = [
"""
get_name_interned_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
""","""
""",
impl = """
static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
PyObject *result;
result = PyObject_GetAttr(dict, name);
......@@ -4642,14 +4644,15 @@ static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
PyErr_SetObject(PyExc_NameError, name);
return result;
}
"""]
""")
#------------------------------------------------------------------------------------
import_utility_code = [
"""
import_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
""","""
""",
impl = """
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
PyObject *__import__ = 0;
PyObject *empty_list = 0;
......@@ -4685,14 +4688,15 @@ bad:
""" % {
"BUILTINS": Naming.builtins_cname,
"GLOBALS": Naming.module_cname,
}]
})
#------------------------------------------------------------------------------------
get_exception_utility_code = [
"""
get_exception_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_GetExcValue(void); /*proto*/
""","""
""",
impl = """
static PyObject *__Pyx_GetExcValue(void) {
PyObject *type = 0, *value = 0, *tb = 0;
PyObject *tmp_type, *tmp_value, *tmp_tb;
......@@ -4728,15 +4732,16 @@ bad:
Py_XDECREF(tb);
return result;
}
"""]
""")
#------------------------------------------------------------------------------------
unpacking_utility_code = [
"""
unpacking_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
static int __Pyx_EndUnpack(PyObject *); /*proto*/
""","""
""",
impl = """
static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
PyObject *item;
if (!(item = PyIter_Next(iter))) {
......@@ -4764,14 +4769,15 @@ static int __Pyx_EndUnpack(PyObject *iter) {
else
return -1;
}
"""]
""")
#------------------------------------------------------------------------------------
type_test_utility_code = [
"""
type_test_utility_code = UtilityCode(
proto = """
static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
""","""
""",
impl = """
static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
if (!type) {
PyErr_Format(PyExc_SystemError, "Missing type object");
......@@ -4783,14 +4789,15 @@ static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
Py_TYPE(obj)->tp_name, type->tp_name);
return 0;
}
"""]
""")
#------------------------------------------------------------------------------------
create_class_utility_code = [
"""
create_class_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
""","""
""",
impl = """
static PyObject *__Pyx_CreateClass(
PyObject *bases, PyObject *dict, PyObject *name, char *modname)
{
......@@ -4815,12 +4822,12 @@ bad:
Py_XDECREF(py_modname);
return result;
}
"""]
""")
#------------------------------------------------------------------------------------
cpp_exception_utility_code = [
"""
cpp_exception_utility_code = UtilityCode(
proto = """
#ifndef __Pyx_CppExn2PyErr
static void __Pyx_CppExn2PyErr() {
try {
......@@ -4840,12 +4847,14 @@ static void __Pyx_CppExn2PyErr() {
}
}
#endif
""",""]
""",
impl = ""
)
#------------------------------------------------------------------------------------
append_utility_code = [
"""
append_utility_code = UtilityCode(
proto = """
static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
if (likely(PyList_CheckExact(L))) {
if (PyList_Append(L, x) < 0) return NULL;
......@@ -4856,16 +4865,17 @@ static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
return PyObject_CallMethod(L, "append", "(O)", x);
}
}
""",""
]
""",
impl = ""
)
#------------------------------------------------------------------------------------
# If the is_unsigned flag is set, we need to do some extra work to make
# sure the index doesn't become negative.
getitem_int_utility_code = [
"""
getitem_int_utility_code = UtilityCode(
proto = """
static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
PyObject *r;
if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
......@@ -4888,13 +4898,13 @@ static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsig
return r;
}
""",
"""
"""]
impl = """
""")
#------------------------------------------------------------------------------------
setitem_int_utility_code = [
"""
setitem_int_utility_code = UtilityCode(
proto = """
static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
int r;
if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
......@@ -4915,24 +4925,27 @@ static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int i
return r;
}
""",
"""
"""]
impl = """
""")
#------------------------------------------------------------------------------------
raise_noneattr_error_utility_code = [
"""
raise_noneattr_error_utility_code = UtilityCode(
proto = """
static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname);
""", """
""",
impl = """
static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname) {
PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
}
"""]
""")
raise_noneindex_error_utility_code = [
"""
raise_noneindex_error_utility_code = UtilityCode(
proto = """
static INLINE void __Pyx_RaiseNoneIndexingError();
""", """
""",
impl = """
static INLINE void __Pyx_RaiseNoneIndexingError() {
PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
}
"""]
""")
......@@ -22,7 +22,7 @@ import Version
from Errors import error, warning
from PyrexTypes import py_object_type
from Cython.Utils import open_new_file, replace_suffix
from Cython.Utils import open_new_file, replace_suffix, UtilityCode
from StringEncoding import escape_byte_string, EncodedString
......@@ -182,15 +182,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
h_code.putln("static %s;" % type.declaration_code(entry.cname))
h_code.putln("")
h_code.put_h_guard(Naming.api_func_guard + "import_module")
h_code.put(import_module_utility_code[1])
h_code.put(import_module_utility_code.impl)
h_code.putln("")
h_code.putln("#endif")
if api_funcs:
h_code.putln("")
h_code.put(function_import_utility_code[1])
h_code.put(function_import_utility_code.impl)
if public_extension_types:
h_code.putln("")
h_code.put(type_import_utility_code[1])
h_code.put(type_import_utility_code.impl)
h_code.putln("")
h_code.putln("static int import_%s(void) {" % name)
h_code.putln("PyObject *module = 0;")
......@@ -457,7 +457,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("")
code.putln("#endif")
code.put(builtin_module_name_utility_code[0])
code.put(builtin_module_name_utility_code.proto)
code.putln("#if PY_MAJOR_VERSION >= 3")
code.putln(" #define Py_TPFLAGS_CHECKTYPES 0")
......@@ -1567,10 +1567,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("/*--- Initialize various global constants etc. ---*/")
code.putln(code.error_goto_if_neg("__Pyx_InitGlobals()", self.pos))
code.putln("#if PY_VERSION_HEX < 0x02040000")
code.putln(code.error_goto_if_neg("__Pyx_Py23SetsImport()", self.pos))
code.putln("#endif")
code.putln("/*--- Module creation code ---*/")
self.generate_module_creation_code(env, code)
......@@ -1955,20 +1951,20 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#
#------------------------------------------------------------------------------------
builtin_module_name_utility_code = [
"""\
builtin_module_name_utility_code = UtilityCode(
proto = """\
#if PY_MAJOR_VERSION < 3
#define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
#else
#define __Pyx_BUILTIN_MODULE_NAME "builtins"
#endif
"""]
""")
import_module_utility_code = [
"""
import_module_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_ImportModule(const char *name); /*proto*/
""","""
""",
impl = """
#ifndef __PYX_HAVE_RT_ImportModule
#define __PYX_HAVE_RT_ImportModule
static PyObject *__Pyx_ImportModule(const char *name) {
......@@ -1990,14 +1986,15 @@ bad:
return 0;
}
#endif
"""]
""")
#------------------------------------------------------------------------------------
type_import_utility_code = [
"""
type_import_utility_code = UtilityCode(
proto = """
static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, long size); /*proto*/
""","""
""",
impl = """
#ifndef __PYX_HAVE_RT_ImportType
#define __PYX_HAVE_RT_ImportType
static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name,
......@@ -2043,14 +2040,15 @@ bad:
return 0;
}
#endif
"""]
""")
#------------------------------------------------------------------------------------
function_export_utility_code = [
"""
function_export_utility_code = UtilityCode(
proto = """
static int __Pyx_ExportFunction(char *name, void *f, char *sig); /*proto*/
""",r"""
""",
impl = r"""
static int __Pyx_ExportFunction(char *name, void *f, char *sig) {
PyObject *d = 0;
PyObject *p = 0;
......@@ -2076,14 +2074,16 @@ bad:
Py_XDECREF(d);
return -1;
}
""" % {'MODULE': Naming.module_cname, 'API': Naming.api_name}]
""" % {'MODULE': Naming.module_cname, 'API': Naming.api_name}
)
#------------------------------------------------------------------------------------
function_import_utility_code = [
"""
function_import_utility_code = UtilityCode(
proto = """
static int __Pyx_ImportFunction(PyObject *module, char *funcname, void **f, char *sig); /*proto*/
""","""
""",
impl = """
#ifndef __PYX_HAVE_RT_ImportFunction
#define __PYX_HAVE_RT_ImportFunction
static int __Pyx_ImportFunction(PyObject *module, char *funcname, void **f, char *sig) {
......@@ -2118,14 +2118,16 @@ bad:
return -1;
}
#endif
""" % dict(API = Naming.api_name)]
""" % dict(API = Naming.api_name)
)
register_cleanup_utility_code = [
"""
register_cleanup_utility_code = UtilityCode(
proto = """
static int __Pyx_RegisterCleanup(void); /*proto*/
static PyObject* __pyx_module_cleanup(PyObject *self, PyObject *unused); /*proto*/
static PyMethodDef cleanup_def = {"__cleanup", (PyCFunction)&__pyx_module_cleanup, METH_NOARGS, 0};
""","""
""",
impl = """
static int __Pyx_RegisterCleanup(void) {
/* Don't use Py_AtExit because that has a 32-call limit
* and is called after python finalization.
......@@ -2163,7 +2165,7 @@ bad:
Py_XDECREF(res);
return ret;
}
"""]
""")
import_star_utility_code = """
......
This diff is collapsed.
......@@ -88,3 +88,20 @@ def long_literal(value):
else:
value = int(value)
return not -2**31 <= value < 2**31
# a simple class that simplifies the usage of utility code
class UtilityCode(object):
def __init__(self, proto=None, impl=None, init=None, cleanup=None):
self.proto = proto
self.impl = impl
self.init = init
self.cleanup = cleanup
def write_init_code(self, writer, pos):
if not self.init:
return
if callable(self.init):
self.init(writer, pos)
else:
writer.put(self.init)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment