Start using unspecified types.
authorRobert Bradshaw <robertwb@math.washington.edu>
Sun, 4 Oct 2009 05:37:01 +0000 (22:37 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Sun, 4 Oct 2009 05:37:01 +0000 (22:37 -0700)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Nodes.py
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/Symtab.py
Cython/Compiler/TypeInference.py

index 0e5ec88a92008fc100397771a1005e6019696f5a..31f76d48299d1f3e02b3c32eef05ee5cc450018b 100644 (file)
@@ -12,7 +12,7 @@ import Naming
 import Nodes
 from Nodes import Node
 import PyrexTypes
-from PyrexTypes import py_object_type, c_long_type, typecast, error_type
+from PyrexTypes import py_object_type, c_long_type, typecast, error_type, unspecified_type
 from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type, bytes_type
 import Builtin
 import Symtab
@@ -1023,7 +1023,11 @@ class NameNode(AtomicExprNode):
         if not self.entry:
             self.entry = env.lookup_here(self.name)
         if not self.entry:
-            self.entry = env.declare_var(self.name, py_object_type, self.pos)
+            if env.directives['infer_types']:
+                type = unspecified_type
+            else:
+                type = py_object_type
+            self.entry = env.declare_var(self.name, type, self.pos)
         env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
         env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
         if self.entry.is_declared_generic:
@@ -3382,6 +3386,9 @@ class ComprehensionNode(ExprNode):
         self.target.analyse_expressions(env)
         self.type = self.target.type
         self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
+        # We are analysing declarations to late.
+        self.loop.target.analyse_target_declaration(env)
+        env.infer_types()
         self.loop.analyse_declarations(env)
         self.loop.analyse_expressions(env)
 
index 882ca421851bdeed53e176cf8a8f1fe29b75a00c..82e211a42fca5fc7ab78ace9afd2df379a9ea932 100644 (file)
@@ -3200,7 +3200,7 @@ class InPlaceAssignmentNode(AssignmentNode):
     
     def create_binop_node(self):
         import ExprNodes
-        return ExprNodes.binop_node(self.pos, self.op, self.lhs, self.rhs)
+        return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
 
 
 class PrintStatNode(StatNode):
index a2b20d539d2245072094a9b20dcbfb2f856396fe..2836a36ead5e313d52864be7c8c34d4009fd31bb 100644 (file)
@@ -785,11 +785,13 @@ property NAME:
 class AnalyseExpressionsTransform(CythonTransform):
 
     def visit_ModuleNode(self, node):
+        node.scope.infer_types()
         node.body.analyse_expressions(node.scope)
         self.visitchildren(node)
         return node
         
     def visit_FuncDefNode(self, node):
+        node.local_scope.infer_types()
         node.body.analyse_expressions(node.local_scope)
         self.visitchildren(node)
         return node
index ba0299f8040a1d794ed33826ceb7689977cd604b..d19adf8577ffeb7c57ee0f547aa74be0c7524d81 100644 (file)
@@ -8,7 +8,7 @@ from Errors import warning, error, InternalError
 from StringEncoding import EncodedString
 import Options, Naming
 import PyrexTypes
-from PyrexTypes import py_object_type
+from PyrexTypes import py_object_type, unspecified_type
 import TypeSlots
 from TypeSlots import \
     pyfunction_signature, pymethod_signature, \
@@ -544,6 +544,12 @@ class Scope(object):
             if name in self.entries:    
                 return 1
         return 0
+    
+    def infer_types(self):
+        for name, entry in self.entries.items():
+            if entry.type is unspecified_type:
+                entry.type = py_object_type
+                entry.init_to_none = Options.init_local_none # TODO: is there a better place for this?
 
 class PreImportScope(Scope):
 
@@ -816,6 +822,8 @@ class ModuleScope(Scope):
         if not visibility in ('private', 'public', 'extern'):
             error(pos, "Module-level variable cannot be declared %s" % visibility)
         if not is_cdef:
+            if type is unspecified_type:
+                type = py_object_type
             if not (type.is_pyobject and not type.is_extension_type):
                 raise InternalError(
                     "Non-cdef global variable is not a generic Python object")
@@ -1191,6 +1199,8 @@ class PyClassScope(ClassScope):
     
     def declare_var(self, name, type, pos, 
             cname = None, visibility = 'private', is_cdef = 0):
+        if type is unspecified_type:
+            type = py_object_type
         # Add an entry for a class attribute.
         entry = Scope.declare_var(self, name, type, pos, 
             cname, visibility, is_cdef)
@@ -1277,6 +1287,8 @@ class CClassScope(ClassScope):
                     "Non-generic Python attribute cannot be exposed for writing from Python")
             return entry
         else:
+            if type is unspecified_type:
+                type = py_object_type
             # Add an entry for a class attribute.
             entry = Scope.declare_var(self, name, type, pos, 
                 cname, visibility, is_cdef)
index 9b0202596767e5fe15138b8be4009f7c49797742..a9d7af7d1550ad605795385ada36de7e831a6cbd 100644 (file)
@@ -12,10 +12,12 @@ object_expr = TypedExprNode(PyrexTypes.py_object_type)
 class MarkAssignments(CythonTransform):
     
     def mark_assignment(self, lhs, rhs):
-        print lhs.pos[1:]
         if isinstance(lhs, ExprNodes.NameNode):
+            if lhs.entry is None:
+                # TODO: This shouldn't happen...
+                # It looks like comprehension loop targets are not declared soon enough.
+                return
             lhs.entry.assignments.append(rhs)
-            print lhs.name, rhs
         elif isinstance(lhs, ExprNodes.SequenceNode):
             for arg in lhs.args:
                 self.mark_assignment(arg, object_expr)
@@ -48,7 +50,7 @@ class MarkAssignments(CythonTransform):
     def visit_ForFromStatNode(self, node):
         self.mark_assignment(node.target, node.bound1)
         if node.step is not None:
-            self.mark_assignment(node.target, ExprNodes.binop_node(self.pos, '+', node.bound1, node.step))
+            self.mark_assignment(node.target, ExprNodes.binop_node(node.pos, '+', node.bound1, node.step))
         self.visitchildren(node)
         return node
 
@@ -59,7 +61,7 @@ class MarkAssignments(CythonTransform):
         return node
     
     def visit_FromCImportStatNode(self, node):
-        raise NotImplementedError # Can't occur in local scopes anyways...
+        pass # Can't be assigned to...
 
     def visit_FromImportStatNode(self, node):
         for name, target in node.items: