From b0339316bc3bce4c160ab0b4b0b1a98bc5add98a Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 10 Apr 2009 21:21:02 +0200 Subject: [PATCH] fix compile time constants in array size declarations (e.g. int a[enum_val+1]) --- Cython/Compiler/ExprNodes.py | 43 +++++++++++++++++++++++++++--------- Cython/Compiler/Nodes.py | 15 +++++++------ 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 0c4c081f..492eed64 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -230,15 +230,23 @@ class ExprNode(Node): # C type of the result_code expression). return self.result_ctype or self.type - def get_constant_result_code(self): + def get_constant_c_result_code(self): # Return the constant value of this node as a result code - # string, or None if the node is not constant. + # string, or None if the node is not constant. This method + # can be called when the constant result code is required + # before the code generation phase. + # + # The return value is a string that can represent a simple C + # value, a constant C name or a constant C expression. If the + # node type depends on Python code, this must return None. return None def calculate_constant_result(self): - # Calculate the constant result of this expression and store - # it in ``self.constant_result``. Does nothing by default, - # thus leaving ``self.constant_result`` unknown. + # Calculate the constant compile time result value of this + # expression and store it in ``self.constant_result``. Does + # nothing by default, thus leaving ``self.constant_result`` + # unknown. If valid, the result can be an arbitrary Python + # value. # # This must only be called when it is assured that all # sub-expressions have a valid constant_result value. The @@ -619,7 +627,7 @@ class ConstNode(AtomicExprNode): def check_const(self): pass - def get_constant_result_code(self): + def get_constant_c_result_code(self): return self.calculate_result_code() def calculate_result_code(self): @@ -648,7 +656,7 @@ class NullNode(ConstNode): value = "NULL" constant_result = 0 - def get_constant_result_code(self): + def get_constant_c_result_code(self): return self.value @@ -695,9 +703,9 @@ class IntNode(ConstNode): if self.type.is_pyobject: self.result_code = code.get_py_num(self.value, self.longness) else: - self.result_code = self.get_constant_result_code() + self.result_code = self.get_constant_c_result_code() - def get_constant_result_code(self): + def get_constant_c_result_code(self): return str(self.value) + self.unsigned + self.longness def calculate_result_code(self): @@ -784,7 +792,7 @@ class StringNode(ConstNode): else: self.result_code = code.get_string_const(self.value) - def get_constant_result_code(self): + def get_constant_c_result_code(self): return None # FIXME def calculate_result_code(self): @@ -825,7 +833,7 @@ class IdentifierStringNode(ConstNode): else: self.result_code = code.get_string_const(self.value) - def get_constant_result_code(self): + def get_constant_c_result_code(self): return None def calculate_result_code(self): @@ -915,6 +923,11 @@ class NameNode(AtomicExprNode): return denv.lookup(self.name) except KeyError: error(self.pos, "Compile-time name '%s' not defined" % self.name) + + def get_constant_c_result_code(self): + if not self.entry or self.entry.type.is_pyobject: + return None + return self.entry.cname def coerce_to(self, dst_type, env): # If coercing to a generic pyobject and this is a builtin @@ -4164,6 +4177,14 @@ class NumBinopNode(BinopNode): return PyrexTypes.widest_numeric_type(type1, type2) else: return None + + def get_constant_c_result_code(self): + value1 = self.operand1.get_constant_c_result_code() + value2 = self.operand2.get_constant_c_result_code() + if value1 and value2: + return "(%s %s %s)" % (value1, self.operator, value2) + else: + return None def c_types_okay(self, type1, type2): #print "NumBinopNode.c_types_okay:", type1, type2 ### diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 5ea5cfa4..89c0b3a3 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -455,12 +455,13 @@ class CArrayDeclaratorNode(CDeclaratorNode): self.dimension.analyse_const_expression(env) if not self.dimension.type.is_int: error(self.dimension.pos, "Array dimension not integer") - size = self.dimension.get_constant_result_code() - try: - size = int(size) - except (ValueError, TypeError): - # runtime constant? - pass + size = self.dimension.get_constant_c_result_code() + if size is not None: + try: + size = int(size) + except ValueError: + # runtime constant? + pass else: size = None if not base_type.is_complete(): @@ -541,7 +542,7 @@ class CFuncDeclaratorNode(CDeclaratorNode): else: if self.exception_value: self.exception_value.analyse_const_expression(env) - exc_val = self.exception_value.get_constant_result_code() + exc_val = self.exception_value.get_constant_c_result_code() if self.exception_check == '+': exc_val_type = self.exception_value.type if not exc_val_type.is_error and \ -- 2.26.2