diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index c2d0c76866a00c695b0c687022787bfd0f2f3b75..55505e5269f3bd2dbcfcac6ca8b5483d829c54b9 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -2129,14 +2129,31 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): return test_node def _handle_simple_function_ord(self, node, pos_args): - """Unpack ord(Py_UNICODE). + """Unpack ord(Py_UNICODE) and ord('X'). """ if len(pos_args) != 1: return node arg = pos_args[0] if isinstance(arg, ExprNodes.CoerceToPyTypeNode): if arg.arg.type.is_unicode_char: - return arg.arg.coerce_to(node.type, self.current_env()) + return ExprNodes.TypecastNode( + arg.pos, operand=arg.arg, type=PyrexTypes.c_int_type + ).coerce_to(node.type, self.current_env()) + elif isinstance(arg, ExprNodes.UnicodeNode): + if len(arg.value) == 1: + return ExprNodes.IntNode( + ord(arg.value), type=PyrexTypes.c_int_type, + value=str(ord(arg.value)), + constant_result=ord(arg.value) + ).coerce_to(node.type, self.current_env()) + elif isinstance(arg, ExprNodes.StringNode): + if arg.unicode_value and len(arg.unicode_value) == 1 \ + and ord(arg.unicode_value) <= 255: # Py2/3 portability + return ExprNodes.IntNode( + ord(arg.unicode_value), type=PyrexTypes.c_int_type, + value=str(ord(arg.unicode_value)), + constant_result=ord(arg.unicode_value) + ).coerce_to(node.type, self.current_env()) return node ### special methods diff --git a/tests/run/builtin_ord.pyx b/tests/run/builtin_ord.pyx index 38c20a3c8646cc4157b79957cc8848bd1bf273a2..71e1b734d2bb8f12075a947c26f0cd752fee1553 100644 --- a/tests/run/builtin_ord.pyx +++ b/tests/run/builtin_ord.pyx @@ -4,6 +4,26 @@ cimport cython ustring_with_a = u'abcdefg' ustring_without_a = u'bcdefg' +@cython.test_fail_if_path_exists('//SimpleCallNode') +def ord_Py_UNICODE(unicode s): + """ + >>> ord_Py_UNICODE(u' ') + 32 + """ + cdef Py_UNICODE u + u = s[0] + return ord(u) + +@cython.test_assert_path_exists('//IntNode') +@cython.test_fail_if_path_exists('//SimpleCallNode') +def ord_const(): + """ + >>> ord_const() + 32 + """ + return ord(u' ') + +@cython.test_assert_path_exists('//PrimaryCmpNode//IntNode') @cython.test_fail_if_path_exists('//SimpleCallNode') def unicode_for_loop_ord(unicode s): """ @@ -13,6 +33,6 @@ def unicode_for_loop_ord(unicode s): False """ for c in s: - if ord(c) == u'a': + if ord(c) == ord(u'a'): return True return False