[pypy-svn] r66507 - in pypy/branch/parser-compiler/pypy/interpreter: . astcompiler pyparser

benjamin at codespeak.net benjamin at codespeak.net
Wed Jul 22 20:25:44 CEST 2009


Author: benjamin
Date: Wed Jul 22 20:25:43 2009
New Revision: 66507

Modified:
   pypy/branch/parser-compiler/pypy/interpreter/astcompiler/codegen.py
   pypy/branch/parser-compiler/pypy/interpreter/pycompiler.py
   pypy/branch/parser-compiler/pypy/interpreter/pyparser/future.py
   pypy/branch/parser-compiler/pypy/interpreter/pyparser/pyparse.py
Log:
lots of checking for __future__ syntax errors

Modified: pypy/branch/parser-compiler/pypy/interpreter/astcompiler/codegen.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/astcompiler/codegen.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/astcompiler/codegen.py	Wed Jul 22 20:25:43 2009
@@ -6,6 +6,7 @@
                                           consts, misc)
 from pypy.interpreter.pyparser.error import SyntaxError
 from pypy.tool import stdlib_opcode as ops
+from pypy.interpreter.pyparser import future
 from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX
 
 
@@ -118,8 +119,8 @@
         self.symbols = symbols
         self.frame_blocks = []
         self.interactive = False
-        self.temporary_name_counter = 1
         self.done_with_future = False
+        self.temporary_name_counter = 1
         self._compile(tree)
 
     def _compile(self, tree):
@@ -551,6 +552,7 @@
 
     def visit_Import(self, imp):
         self.update_position(imp.lineno, True)
+        self.done_with_future = True
         for alias in imp.names:
             assert isinstance(alias, ast.alias)
             if self.compile_info.flags & consts.CO_FUTURE_ABSOLUTE_IMPORT:
@@ -573,10 +575,21 @@
     def visit_ImportFrom(self, imp):
         self.update_position(imp.lineno, True)
         space = self.space
+        first = imp.names[0]
+        assert isinstance(first, ast.alias)
+        star_import = len(imp.names) == 1 and first.name == "*"
         if imp.module == "__future__":
-            if self.done_with_future:
-                self.error("__future__ statements must appear before other " \
-                               "imports", imp)
+            if self.done_with_future or \
+                    imp.lineno > self.compile_info.last_future_import:
+                self.error("__future__ statements must appear at beginning " \
+                               "of file", imp)
+            if star_import:
+                self.error("* not valid in __future__ imports", imp)
+            for alias in imp.names:
+                assert isinstance(alias, ast.alias)
+                if alias.name not in future.futureFlags_2_5.compiler_features:
+                    self.error("future feature %s is not defined" %
+                               (alias.name,), imp)
         else:
             self.done_with_future = True
         if imp.level == 0 and \
@@ -596,9 +609,7 @@
         else:
             mod_name = ""
         self.emit_op_name(ops.IMPORT_NAME, self.names, mod_name)
-        first = imp.names[0]
-        assert isinstance(first, ast.alias)
-        if len(imp.names) == 1 and first.name == "*":
+        if star_import:
             self.emit_op(ops.IMPORT_STAR)
         else:
             for alias in imp.names:

Modified: pypy/branch/parser-compiler/pypy/interpreter/pycompiler.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/pycompiler.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/pycompiler.py	Wed Jul 22 20:25:43 2009
@@ -242,8 +242,9 @@
 
         space.timer.start("PythonAST compile")
         try:
-            flags |= getFutures(self.futureFlags, source)
-            info = CompileInfo(filename, mode, flags)
+            f_flags, future_lineno = getFutures(self.futureFlags, source)
+            flags |= f_flags
+            info = CompileInfo(filename, mode, flags, future_lineno)
             parse_tree = self.parser.parse_source(source, info)
             module = ast_from_node(space, parse_tree, info)
             code = compile_ast(space, module, info)

Modified: pypy/branch/parser-compiler/pypy/interpreter/pyparser/future.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/pyparser/future.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/pyparser/future.py	Wed Jul 22 20:25:43 2009
@@ -33,7 +33,7 @@
         futures.start()
     except DoneException, e:
         pass
-    return futures.flags
+    return futures.flags, futures.lineno
     
 class DoneException(Exception):
     pass
@@ -67,6 +67,7 @@
         self.futureFlags = futureFlags
         self.s = string
         self.pos = 0
+        self.lineno = 1
         self.docstringConsumed = False
         self.flags = 0
 
@@ -98,15 +99,23 @@
             while 1: # Deal with a triple quoted docstring
                 if self.getc() == '\\':
                     self.pos += 2
-                elif self.getc() != endchar:
-                    self.pos += 1
                 else:
-                    self.pos += 1
-                    if (self.getc() == endchar and
-                        self.getc(+1) == endchar):
-                        self.pos += 2
-                        self.consumeEmptyLine()
-                        break
+                    c = self.getc()
+                    if c != endchar:
+                        self.pos += 1
+                        if c == '\n':
+                            self.lineno += 1
+                        elif c == '\r':
+                            if self.getc() == '\n':
+                                self.pos += 1
+                                self.lineno += 1
+                    else:
+                        self.pos += 1
+                        if (self.getc() == endchar and
+                            self.getc(+1) == endchar):
+                            self.pos += 2
+                            self.consumeEmptyLine()
+                            break
 
         else: # Deal with a single quoted docstring
             self.pos += 1
@@ -142,11 +151,16 @@
             self.consumeWhitespace()
             self.start()
         elif self.getc() in '\r\n':
+            c = self.getc()
             self.pos += 1
-            if self.getc() == '\n':
-                self.pos += 1
+            if c == '\r':
+                if self.getc() == '\n':
+                    self.pos += 1
+                    self.lineno += 1
+            else:
+                self.lineno += 1
             self.start()
-            
+
     def consumeComment(self):
         self.pos += 1
         while self.getc() not in '\r\n':
@@ -196,11 +210,13 @@
                 c = self.getc()
                 if c == '\n':
                     self.pos += 1
+                    self.lineno += 1
                     continue
                 elif c == '\r':
                     self.pos += 1
                     if self.getc() == '\n':
                         self.pos += 1
+                        self.lineno += 1
                 else:
                     raise DoneException
             else:

Modified: pypy/branch/parser-compiler/pypy/interpreter/pyparser/pyparse.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/pyparser/pyparse.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/pyparser/pyparse.py	Wed Jul 22 20:25:43 2009
@@ -58,11 +58,12 @@
 
 class CompileInfo(object):
 
-    def __init__(self, filename, mode="exec", flags=0):
+    def __init__(self, filename, mode="exec", flags=0, future_lineno=0):
         self.filename = filename
         self.mode = mode
         self.encoding = None
         self.flags = flags
+        self.last_future_import = future_lineno
 
 
 _targets = {



More information about the Pypy-commit mailing list