Commit 5f7ebe56 authored by Stefan Behnel's avatar Stefan Behnel

Optimise calls to the unicode() builtin.

parent b4b12c73
......@@ -482,21 +482,22 @@ class UtilityCode(UtilityCodeBase):
def inject_string_constants(self, impl, output):
"""Replace 'PYIDENT("xyz")' by a constant Python identifier cname.
"""
if 'PYIDENT(' not in impl:
if 'PYIDENT(' not in impl and 'PYUNICODE(' not in impl:
return False, impl
replacements = {}
def externalise(matchobj):
name = matchobj.group(1)
key = matchobj.groups()
try:
cname = replacements[name]
cname = replacements[key]
except KeyError:
cname = replacements[name] = output.get_interned_identifier(
StringEncoding.EncodedString(name)).cname
str_type, name = key
cname = replacements[key] = output.get_py_string_const(
StringEncoding.EncodedString(name), identifier=str_type == 'IDENT').cname
return cname
impl = re.sub(r'PYIDENT\("([^"]+)"\)', externalise, impl)
assert 'PYIDENT(' not in impl
impl = re.sub(r'PY(IDENT|UNICODE)\("([^"]+)"\)', externalise, impl)
assert 'PYIDENT(' not in impl and 'PYUNICODE(' not in impl
return bool(replacements), impl
def inject_unbound_methods(self, impl, output):
......
......@@ -2309,6 +2309,34 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
return ExprNodes.CachedBuiltinMethodCallNode(
node, function.obj, attr_name, arg_list)
PyObject_Unicode_func_type = PyrexTypes.CFuncType(
Builtin.unicode_type, [
PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None)
])
def _handle_simple_function_unicode(self, node, function, pos_args):
"""Optimise single argument calls to unicode().
"""
if len(pos_args) != 1:
if len(pos_args) == 0:
return ExprNodes.UnicodeNode(node.pos, value=EncodedString(), constant_result=u'')
return node
arg = pos_args[0]
if arg.type is Builtin.unicode_type:
if not arg.may_be_none():
return arg
cname = "__Pyx_PyUnicode_Unicode"
utility_code = UtilityCode.load_cached('PyUnicode_Unicode', 'StringTools.c')
else:
cname = "__Pyx_PyObject_Unicode"
utility_code = UtilityCode.load_cached('PyObject_Unicode', 'StringTools.c')
return ExprNodes.PythonCapiCallNode(
node.pos, cname, self.PyObject_Unicode_func_type,
args=pos_args,
is_temp=node.is_temp,
utility_code=utility_code,
py_name="unicode")
PyDict_Copy_func_type = PyrexTypes.CFuncType(
Builtin.dict_type, [
PyrexTypes.CFuncTypeArg("dict", Builtin.dict_type, None)
......
......@@ -1136,3 +1136,27 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatAndDecref(PyObject* s, PyObj
Py_DECREF(s);
return result;
}
//////////////////// PyUnicode_Unicode.proto ////////////////////
static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Unicode(PyObject *obj);/*proto*/
//////////////////// PyUnicode_Unicode ////////////////////
static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Unicode(PyObject *obj) {
if (unlikely(obj == Py_None))
obj = PYUNICODE("None");
return __Pyx_NewRef(obj);
}
//////////////////// PyObject_Unicode.proto ////////////////////
#if PY_MAJOR_VERSION >= 3
#define __Pyx_PyObject_Unicode(obj) \
(likely(PyUnicode_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Str(obj))
#else
#define __Pyx_PyObject_Unicode(obj) \
(likely(PyUnicode_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Unicode(obj))
#endif
# mode: run
# tag: unicode
__doc__ = u"""
>>> u('test')
u'test'
>>> e
u''
>>> z
u'test'
>>> c('testing')
......@@ -16,25 +21,63 @@ __doc__ = u"""
# u'testing a C subtype'
"""
cimport cython
import sys
if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u" u'", u" '")
u = unicode
e = unicode()
z = unicode(u'test')
def c(string):
return unicode(string)
class subu(unicode):
pass
def sub(string):
return subu(string)
#cdef class csubu(unicode):
# pass
#def csub(string):
# return csubu(string)
@cython.test_fail_if_path_exists("//SimpleCallNode")
@cython.test_assert_path_exists("//PythonCapiCallNode")
def typed(unicode s):
"""
>>> print(typed(None))
None
>>> type(typed(None)) is u or type(typed(None))
True
>>> print(typed(u'abc'))
abc
>>> type(typed(u'abc')) is u or type(typed(u'abc'))
True
"""
return unicode(s)
@cython.test_fail_if_path_exists(
"//SimpleCallNode",
"//PythonCapiCallNode",
)
def typed_not_none(unicode s not None):
"""
>>> print(typed(u'abc'))
abc
>>> type(typed(u'abc')) is u or type(typed(u'abc'))
True
"""
return unicode(s)
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