c literal lists
authorRobert Bradshaw <robertwb@math.washington.edu>
Tue, 7 Oct 2008 21:20:09 +0000 (14:20 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Tue, 7 Oct 2008 21:20:09 +0000 (14:20 -0700)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Nodes.py
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/PyrexTypes.py

index 8bb8cfaef625f9e91231c1274a830a23cf123af5..7585e1efda8b658aff1990c94763fa98f74e497e 100644 (file)
@@ -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
index 80ccfe6e1aa1a3f972431a72ceb940883bee956c..a57252bf81145b4f350095d330b2cf5c2adb5bcb 100644 (file)
@@ -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()
                 
index 254a421873a657aa23fc41cc17c0151cc9a0e988..94cf1681042da90c023578aefd2599b87df5e92e 100644 (file)
@@ -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:
index b23a626a1ffd855706c90479a0c425d3532e521e..3caa102d1692c233afbeb43106eb3be7970e641f 100644 (file)
@@ -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 "<unspecified>"
+    
+    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