From fc97fc880490faaf0d58daec4cc21d92e166fe0e Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Tue, 7 Oct 2008 14:20:09 -0700 Subject: [PATCH] c literal lists --- Cython/Compiler/ExprNodes.py | 67 +++++++++++++++++++------- Cython/Compiler/Nodes.py | 4 +- Cython/Compiler/ParseTreeTransforms.py | 6 +-- Cython/Compiler/PyrexTypes.py | 12 +++++ 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 8bb8cfae..7585e1ef 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -564,7 +564,7 @@ class ExprNode(Node): # reference, or temporary. return self.result_in_temp() - def as_cython_attribute(self): + def magic_cython_method(self): return None @@ -866,7 +866,7 @@ class NameNode(AtomicExprNode): node.analyse_types(env, entry=entry) return node - def as_cython_attribute(self): + def magic_cython_method(self): return self.cython_attribute create_analysed_rvalue = staticmethod(create_analysed_rvalue) @@ -1822,7 +1822,7 @@ class SimpleCallNode(CallNode): self.compile_time_value_error(e) def analyse_as_type(self, env): - attr = self.function.as_cython_attribute() + attr = self.function.magic_cython_method() if attr == 'pointer': if len(self.args) != 1: error(self.args.pos, "only one type allowed.") @@ -2173,7 +2173,7 @@ class AttributeNode(ExprNode): is_called = 0 needs_none_check = True - def as_cython_attribute(self): + def magic_cython_method(self): if isinstance(self.obj, NameNode) and self.obj.is_cython_module: return self.attribute @@ -2659,26 +2659,57 @@ class ListNode(SequenceNode): gil_message = "Constructing Python list" def analyse_types(self, env): - SequenceNode.analyse_types(self, env) - self.type = list_type + for arg in self.args: + arg.analyse_types(env) + self.is_temp = 1 + self.type = PyrexTypes.unspecified_type + + def coerce_to(self, dst_type, env): + if dst_type.is_pyobject: + self.gil_check(env) + self.type = list_type + for i in range(len(self.args)): + arg = self.args[i] + if not arg.type.is_pyobject: + self.args[i] = arg.coerce_to_pyobject(env) + if not self.type.subtype_of(dst_type): + error(self.pos, "Cannot coerce list to type '%s'" % dst_type) + elif dst_type.is_ptr: + base_type = dst_type.base_type + self.type = dst_type + for i in range(len(self.args)): + arg = self.args[i] + self.args[i] = arg.coerce_to(base_type, env) + else: + self.type = error_type + error(self.pos, "Cannot coerce list to type '%s'" % dst_type) + return self def compile_time_value(self, denv): return self.compile_time_value_list(denv) def generate_operation_code(self, code): - code.putln("%s = PyList_New(%s); %s" % - (self.result(), - len(self.args), - code.error_goto_if_null(self.result(), self.pos))) - for i in range(len(self.args)): - arg = self.args[i] - #if not arg.is_temp: - if not arg.result_in_temp(): - code.put_incref(arg.result(), arg.ctype()) - code.putln("PyList_SET_ITEM(%s, %s, %s);" % + if self.type.is_pyobject: + code.putln("%s = PyList_New(%s); %s" % (self.result(), - i, - arg.py_result())) + len(self.args), + code.error_goto_if_null(self.result(), self.pos))) + for i in range(len(self.args)): + arg = self.args[i] + #if not arg.is_temp: + if not arg.result_in_temp(): + code.put_incref(arg.result(), arg.ctype()) + code.putln("PyList_SET_ITEM(%s, %s, %s);" % + (self.result(), + i, + arg.py_result())) + else: + code.putln("%s = (%s[]) {" % (self.result(), self.type.base_type)) + for i, arg in enumerate(self.args): + code.put(arg.result()) + code.put(", ") + code.putln(); + code.putln("};") def generate_subexpr_disposal_code(self, code): # We call generate_post_assignment_code here instead diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 80ccfe6e..a57252bf 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -2552,7 +2552,7 @@ class ExprStatNode(StatNode): def analyse_declarations(self, env): import ExprNodes if isinstance(self.expr, ExprNodes.GeneralCallNode): - func = self.expr.function.as_cython_attribute() + func = self.expr.function.magic_cython_method() if func == u'declare': args, kwds = self.expr.explicit_args_kwds() if len(args): @@ -2620,7 +2620,7 @@ class SingleAssignmentNode(AssignmentNode): # handle declarations of the form x = cython.foo() if isinstance(self.rhs, ExprNodes.CallNode): - func_name = self.rhs.function.as_cython_attribute() + func_name = self.rhs.function.magic_cython_method() if func_name: args, kwds = self.rhs.explicit_args_kwds() diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 254a4218..94cf1681 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -355,7 +355,7 @@ class InterpretCompilerDirectives(CythonTransform): optname = None if isinstance(node, CallNode): self.visit(node.function) - optname = node.function.as_cython_attribute() + optname = node.function.magic_cython_method() # if (isinstance(node.function, AttributeNode) and # isinstance(node.function.obj, NameNode) and # node.function.obj.name in self.cython_module_names): @@ -714,7 +714,7 @@ class TransformBuiltinMethods(EnvTransform): return node def visit_AttributeNode(self, node): - attribute = node.as_cython_attribute() + attribute = node.magic_cython_method() if attribute: if attribute == u'compiled': node = BoolNode(node.pos, value=True) @@ -735,7 +735,7 @@ class TransformBuiltinMethods(EnvTransform): return ExprNodes.DictNode(pos, key_value_pairs=items) # cython.foo - function = node.function.as_cython_attribute() + function = node.function.magic_cython_method() if function: if function == u'cast': if len(node.args) != 2: diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index b23a626a..3caa102d 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -1047,6 +1047,17 @@ class CCharPtrType(CStringType, CPtrType): CPtrType.__init__(self, c_char_type) +class UnspecifiedType(PyrexType): + # Used as a placeholder until the type can be determined. + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + return "" + + def same_as_resolved_type(self, other_type): + return False + + class ErrorType(PyrexType): # Used to prevent propagation of error messages. @@ -1127,6 +1138,7 @@ c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer c_py_buffer_ptr_type = CPtrType(c_py_buffer_type) error_type = ErrorType() +unspecified_type = UnspecifiedType() lowest_float_rank = 6 -- 2.26.2