Commit 2c8e7b22 authored by William Ayd's avatar William Ayd Committed by GitHub

Optimize builtin str() calls (GH-3478)

parent e9d7fd45
...@@ -2312,6 +2312,38 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin, ...@@ -2312,6 +2312,38 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
return ExprNodes.CachedBuiltinMethodCallNode( return ExprNodes.CachedBuiltinMethodCallNode(
node, function.obj, attr_name, arg_list) node, function.obj, attr_name, arg_list)
PyObject_String_func_type = PyrexTypes.CFuncType(
Builtin.str_type, [
PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None)
])
def _handle_simple_function_str(self, node, function, pos_args):
"""Optimize single argument calls to str().
"""
if len(pos_args) != 1:
if len(pos_args) == 0:
return ExprNodes.StringNode(node.pos, value=EncodedString(), constant_result='')
return node
arg = pos_args[0]
if arg.type is Builtin.str_type:
if not arg.may_be_none():
return arg
cname = "__Pyx_PyStr_Str"
utility_code = UtilityCode.load_cached('PyStr_Str', 'StringTools.c')
else:
cname = '__Pyx_PyObject_Str'
utility_code = UtilityCode.load_cached('PyObject_Str', 'StringTools.c')
return ExprNodes.PythonCapiCallNode(
node.pos, cname, self.PyObject_String_func_type,
args=pos_args,
is_temp=node.is_temp,
utility_code=utility_code,
py_name="str"
)
PyObject_Unicode_func_type = PyrexTypes.CFuncType( PyObject_Unicode_func_type = PyrexTypes.CFuncType(
Builtin.unicode_type, [ Builtin.unicode_type, [
PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None) PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None)
......
...@@ -1219,3 +1219,22 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Unicode(PyObject *obj) { ...@@ -1219,3 +1219,22 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Unicode(PyObject *obj) {
#define __Pyx_PyObject_Unicode(obj) \ #define __Pyx_PyObject_Unicode(obj) \
(likely(PyUnicode_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Unicode(obj)) (likely(PyUnicode_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Unicode(obj))
#endif #endif
//////////////////// PyStr_Str.proto ////////////////////
static CYTHON_INLINE PyObject* __Pyx_PyStr_Str(PyObject *obj);/*proto*/
//////////////////// PyStr_Str ////////////////////
static CYTHON_INLINE PyObject* __Pyx_PyStr_Str(PyObject *obj) {
if (unlikely(obj == Py_None))
obj = PYIDENT("None");
return __Pyx_NewRef(obj);
}
//////////////////// PyObject_Str.proto ////////////////////
#define __Pyx_PyObject_Str(obj) \
(likely(PyString_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Str(obj))
...@@ -5,6 +5,8 @@ __doc__ = u""" ...@@ -5,6 +5,8 @@ __doc__ = u"""
'test' 'test'
""" """
cimport cython
s = str s = str
z = str('test') z = str('test')
...@@ -39,3 +41,33 @@ def sub(string): ...@@ -39,3 +41,33 @@ def sub(string):
#def csub(string): #def csub(string):
# return csubs(string) # return csubs(string)
@cython.test_fail_if_path_exists("//SimpleCallNode")
@cython.test_assert_path_exists("//PythonCapiCallNode")
def typed(str s):
"""
>>> print(typed(None))
None
>>> type(typed(None)) is type(typed(None))
True
>>> print(typed('abc'))
abc
>>> type(typed('abc')) is type(typed('abc'))
True
"""
return str(s)
@cython.test_fail_if_path_exists(
"//SimpleCallNode",
"//PythonCapiCallNode",
)
def typed_not_none(str s not None):
"""
>>> print(typed('abc'))
abc
>>> type(typed('abc')) is type(typed('abc'))
True
"""
return str(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