Support for [] operator.
authorRobert Bradshaw <robertwb@math.washington.edu>
Sat, 16 Jan 2010 01:35:47 +0000 (17:35 -0800)
committerRobert Bradshaw <robertwb@math.washington.edu>
Sat, 16 Jan 2010 01:35:47 +0000 (17:35 -0800)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Parsing.py
tests/run/cpp_stl_vector.pyx

index afbf2f8e4747799fb4338267a6af8ab6136ecdc8..6e9388b69f787f0b8b31b0d679a2722ad408af5b 100755 (executable)
@@ -1914,18 +1914,37 @@ class IndexNode(ExprNode):
             else:
                 if self.base.type.is_ptr or self.base.type.is_array:
                     self.type = self.base.type.base_type
+                    if self.index.type.is_pyobject:
+                        self.index = self.index.coerce_to(
+                            PyrexTypes.c_py_ssize_t_type, env)
+                    if not self.index.type.is_int:
+                        error(self.pos,
+                            "Invalid index type '%s'" %
+                                self.index.type)
+                elif self.base.type.is_cpp_class:
+                    function = self.base.type.scope.lookup("operator[]")
+                    if function is None:
+                        error(self.pos, "Indexing '%s' not supported" % self.base.type)
+                    else:
+                        function = PyrexTypes.best_match([self.index], function.all_alternatives(), self.pos)
+                        if function is None:
+                            error(self.pos, "Invalid index type '%s'" % self.index.type)
+                    if function is None:
+                        self.type = PyrexTypes.error_type
+                        self.result_code = "<error>"
+                        return
+                    func_type = function.type
+                    if func_type.is_ptr:
+                        func_type = func_type.base_type
+                    self.index = self.index.coerce_to(func_type.args[0].type, env)
+                    self.type = func_type.return_type
+                    if setting and not func_type.return_type.is_reference:
+                        error(self.pos, "Can't set non-reference '%s'" % self.type)
                 else:
                     error(self.pos,
                         "Attempting to index non-array type '%s'" %
                             self.base.type)
                     self.type = PyrexTypes.error_type
-                if self.index.type.is_pyobject:
-                    self.index = self.index.coerce_to(
-                        PyrexTypes.c_py_ssize_t_type, env)
-                if not self.index.type.is_int:
-                    error(self.pos,
-                        "Invalid index type '%s'" %
-                            self.index.type)
     gil_message = "Indexing Python object"
 
     def nogil_check(self, env):
@@ -4738,6 +4757,7 @@ class NumBinopNode(BinopNode):
         if type2.is_ptr:
             type2 = type2.base_type
         entry = env.lookup(type1.name)
+        # Shouldn't this be type1.scope?
         function = entry.type.scope.lookup("operator%s" % self.operator)
         if function is not None:
             operands = [self.operand2]
index bf638e95bd554e7561a5dd92a5a17b16a3d6bc2b..b1dd18473e05f75b2cefd339f97a72c16be9962a 100644 (file)
@@ -2061,6 +2061,7 @@ supported_overloaded_operators = set([
     '+', '-', '*', '/', '%', 
     '++', '--', '~', '|', '&', '^', '<<', '>>',
     '==', '!=', '>=', '>', '<=', '<',
+    '[]',
 ])
 
 def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag,
@@ -2108,6 +2109,7 @@ def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag,
             cname = ctx.namespace + "::" + name
         if name == 'operator' and ctx.visibility == 'extern':
             op = s.sy
+            s.next()
             # Handle diphthong operators.
             if op == '(':
                 s.expect(')')
@@ -2115,7 +2117,6 @@ def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag,
             elif op == '[':
                 s.expect(']')
                 op = '[]'
-            s.next()
             if op in ['-', '+', '|', '&'] and s.sy == op:
                 op = op*2
                 s.next()
index cdcb71bae6f922be3719bdbf5833f5309b810745..f6a81b57b0144b217bed75b1a924005fd68176eb 100644 (file)
@@ -3,6 +3,7 @@ cdef extern from "<vector>" namespace std:
     cdef cppclass vector[T]:
         void push_back(T)
         size_t size()
+        T operator[](size_t)
 
 def simple_test(double x):
     """
@@ -37,3 +38,19 @@ def list_test(L):
         return len(L), v.size()
     finally:
         del v
+
+def index_test(L):
+    """
+    >>> index_test([1,2,4,8])
+    (1.0, 8.0)
+    >>> index_test([1.25])
+    (1.25, 1.25)
+    """
+    cdef vector[double] *v 
+    try:
+        v = new vector[double]()
+        for a in L:
+            v.push_back(a)
+        return v[0][0], v[0][len(L)-1]
+    finally:
+        del v