Fix literal lists for C++
authorRobert Bradshaw <robertwb@math.washington.edu>
Wed, 8 Oct 2008 02:15:18 +0000 (19:15 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Wed, 8 Oct 2008 02:15:18 +0000 (19:15 -0700)
Stupid C++. Now it is more verbose, but should always work.

Cython/Compiler/ExprNodes.py
tests/run/literal_lists.pyx [new file with mode: 0644]

index 0b740a486023b0fc5b3b9f6dc82341e93e2f52fe..0b9f21cbcac34da2bc7aee6772508fc3119bae58 100644 (file)
@@ -2752,7 +2752,7 @@ class ListNode(SequenceNode):
                 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
+            self.type = PyrexTypes.CArrayType(base_type, len(self.args))
             for i in range(len(self.original_args)):
                 arg = self.args[i]
                 if isinstance(arg, CoerceToPyTypeNode):
@@ -2773,6 +2773,14 @@ class ListNode(SequenceNode):
             self.type = error_type
             error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
         return self
+        
+    def release_temp(self, env):
+        if self.type.is_array:
+            # To be valid C++, we must allocate the memory on the stack 
+            # manually and be sure not to reuse it for something else. 
+            pass
+        else:
+            SequenceNode.release_temp(self, env)
 
     def compile_time_value(self, denv):
         return self.compile_time_value_list(denv)
@@ -2794,13 +2802,12 @@ class ListNode(SequenceNode):
                     (self.result(),
                     i,
                     arg.py_result()))
-        elif self.type.is_ptr:
-            code.putln("%s = (%s[]) {" % (self.result(), self.type.base_type))
-            for arg in self.args:
-                code.put(arg.result())
-                code.put(", ")
-            code.putln();
-            code.putln("};")
+        elif self.type.is_array:
+            for i, arg in enumerate(self.args):
+                code.putln("%s[%s] = %s;" % (
+                                self.result(),
+                                i,
+                                arg.result()))
         elif self.type.is_struct or 1:
             for arg, member in zip(self.args, self.type.scope.var_entries):
                 code.putln("%s.%s = %s;" % (
diff --git a/tests/run/literal_lists.pyx b/tests/run/literal_lists.pyx
new file mode 100644 (file)
index 0000000..0c93535
--- /dev/null
@@ -0,0 +1,40 @@
+__doc__ = """
+    >>> test_ints(100)
+    (100, 100, 100)
+    >>> test_chars("yo")
+    ('a', 'bc', 'yo')
+    >>> test_chars(None)
+    Traceback (most recent call last):
+    ...
+    TypeError: expected string or Unicode object, NoneType found
+    >>> test_struct(-5, -10)
+    -5 -10 True
+    1 2 False
+"""
+
+def test_ints(int x):
+    cdef list L = [1,2,3,x]
+    cdef int* Li = [1,2,3,x]
+    cdef int** Lii = [Li, &x]
+    return L[3], Li[3], Lii[1][0]
+
+def test_chars(foo):
+    cdef char** ss = ["a", "bc", foo]
+    return ss[0], ss[1], ss[2]
+
+cdef struct MyStruct:
+    int x
+    int y
+    double** data
+
+cdef print_struct(MyStruct a):
+    print a.x, a.y, a.data == NULL
+
+def test_struct(int x, y):
+    cdef MyStruct* aa = [[x,y, NULL], [x+1,y+1,NULL]]
+    print_struct(aa[0])
+    print_struct([1, 2, <double**>1])
+
+# Make sure it's still naturally an object.
+
+[0,1,2,3].append(4)