From 7cec62b71f9f33a2757cbb667174ab32e82fa9dd Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Wed, 13 Feb 2013 18:54:51 +0100 Subject: [PATCH] support tuples as compile time constants --- Cython/Compiler/Parsing.pxd | 1 + Cython/Compiler/Parsing.py | 48 ++++++++++++++++++++++++++++++--------------- tests/run/ct_DEF.pyx | 27 ++++++++++++++----------- 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/Cython/Compiler/Parsing.pxd b/Cython/Compiler/Parsing.pxd index 2140e29..4b1757b 100644 --- a/Cython/Compiler/Parsing.pxd +++ b/Cython/Compiler/Parsing.pxd @@ -59,6 +59,7 @@ cdef p_atom(PyrexScanner s) @cython.locals(value=unicode) cdef p_int_literal(PyrexScanner s) cdef p_name(PyrexScanner s, name) +cdef wrap_compile_time_constant(pos, value) cdef p_cat_string_literal(PyrexScanner s) cdef p_opt_string_literal(PyrexScanner s, required_type=*) cdef bint check_for_non_ascii_characters(unicode string) diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index 7ce75e1..43b94d9 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -678,27 +678,43 @@ def p_int_literal(s): unsigned = unsigned, longness = longness) + def p_name(s, name): pos = s.position() if not s.compile_time_expr and name in s.compile_time_env: value = s.compile_time_env.lookup_here(name) - rep = repr(value) - if isinstance(value, bool): - return ExprNodes.BoolNode(pos, value = value) - elif isinstance(value, int): - return ExprNodes.IntNode(pos, value = rep) - elif isinstance(value, long): - return ExprNodes.IntNode(pos, value = rep, longness = "L") - elif isinstance(value, float): - return ExprNodes.FloatNode(pos, value = rep) - elif isinstance(value, _unicode): - return ExprNodes.UnicodeNode(pos, value = value) - elif isinstance(value, _bytes): - return ExprNodes.BytesNode(pos, value = value) + node = wrap_compile_time_constant(pos, value) + if node is not None: + return node + return ExprNodes.NameNode(pos, name=name) + + +def wrap_compile_time_constant(pos, value): + rep = repr(value) + if isinstance(value, bool): + return ExprNodes.BoolNode(pos, value=value) + elif isinstance(value, int): + return ExprNodes.IntNode(pos, value=rep) + elif isinstance(value, long): + return ExprNodes.IntNode(pos, value=rep, longness="L") + elif isinstance(value, float): + return ExprNodes.FloatNode(pos, value=rep) + elif isinstance(value, _unicode): + return ExprNodes.UnicodeNode(pos, value=value) + elif isinstance(value, _bytes): + return ExprNodes.BytesNode(pos, value=value) + elif isinstance(value, tuple): + args = [wrap_compile_time_constant(pos, arg) + for arg in value] + if None not in args: + return ExprNodes.TupleNode(pos, args=args) else: - error(pos, "Invalid type for compile-time constant: %s" - % value.__class__.__name__) - return ExprNodes.NameNode(pos, name = name) + # error already reported + return None + error(pos, "Invalid type for compile-time constant: %s" + % value.__class__.__name__) + return None + def p_cat_string_literal(s): # A sequence of one or more adjacent string literals. diff --git a/tests/run/ct_DEF.pyx b/tests/run/ct_DEF.pyx index a2f38e1..cef18ba 100644 --- a/tests/run/ct_DEF.pyx +++ b/tests/run/ct_DEF.pyx @@ -8,7 +8,7 @@ if sys.version_info[0] < 3: __doc__ = __doc__.replace(u" b'", u" '") -DEF TUPLE = (1, 2, u"buckle my shoe") +DEF TUPLE = (1, 2, "buckle my shoe") DEF TRUE_FALSE = (True, False) DEF CHAR = c'x' @@ -89,10 +89,21 @@ def s(): cdef char* s = STR return s -# this does not work! -#def t(): -# cdef object t = TUPLE -# return t +def constant_tuple(): + """ + >>> constant_tuple() + (1, 2, 'buckle my shoe') + """ + cdef object t = TUPLE + return t + +def tuple_indexing(): + """ + >>> tuple_indexing() + 2 + """ + cdef int two = INT_TUPLE1[-1] + return two def two(): """ @@ -102,12 +113,6 @@ def two(): cdef int two = TWO return two -# this doesn't currently work! -#def two2(): -# cdef int two -# two = INT_TUPLE1[-1] -# return two - def five(): """ >>> five() -- 2.7.4