mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
Add support for future statements
This commit is contained in:
parent
42a0830713
commit
80e29bd139
4 changed files with 196 additions and 12 deletions
78
Tools/compiler/compiler/future.py
Normal file
78
Tools/compiler/compiler/future.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
"""Parser for future statements
|
||||
|
||||
"""
|
||||
|
||||
from compiler import ast, walk
|
||||
|
||||
def is_future(stmt):
|
||||
"""Return true if statement is a well-formed future statement"""
|
||||
if not isinstance(stmt, ast.From):
|
||||
return 0
|
||||
if stmt.modname == "__future__":
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
class FutureParser:
|
||||
|
||||
features = ("nested_scopes",)
|
||||
|
||||
def __init__(self):
|
||||
self.found = {} # set
|
||||
|
||||
def visitModule(self, node):
|
||||
if node.doc is None:
|
||||
off = 0
|
||||
else:
|
||||
off = 1
|
||||
|
||||
stmt = node.node
|
||||
for s in stmt.nodes[off:]:
|
||||
if not self.check_stmt(s):
|
||||
break
|
||||
|
||||
def check_stmt(self, stmt):
|
||||
if is_future(stmt):
|
||||
for name, asname in stmt.names:
|
||||
if name in self.features:
|
||||
self.found[name] = 1
|
||||
else:
|
||||
raise SyntaxError, \
|
||||
"future feature %s is not defined" % name
|
||||
stmt.valid_future = 1
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def get_features(self):
|
||||
"""Return list of features enabled by future statements"""
|
||||
return self.found.keys()
|
||||
|
||||
class BadFutureParser:
|
||||
"""Check for invalid future statements"""
|
||||
|
||||
def visitFrom(self, node):
|
||||
if hasattr(node, 'valid_future'):
|
||||
return
|
||||
if node.modname != "__future__":
|
||||
return
|
||||
raise SyntaxError, "invalid future statement"
|
||||
|
||||
def find_futures(node):
|
||||
p1 = FutureParser()
|
||||
p2 = BadFutureParser()
|
||||
walk(node, p1)
|
||||
walk(node, p2)
|
||||
return p1.get_features()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
from compiler import parseFile, walk
|
||||
|
||||
for file in sys.argv[1:]:
|
||||
print file
|
||||
tree = parseFile(file)
|
||||
v = FutureParser()
|
||||
walk(tree, v)
|
||||
print v.found
|
||||
print
|
||||
|
|
@ -9,7 +9,7 @@ import types
|
|||
from cStringIO import StringIO
|
||||
|
||||
from compiler import ast, parse, walk
|
||||
from compiler import pyassem, misc
|
||||
from compiler import pyassem, misc, future
|
||||
from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, TupleArg
|
||||
|
||||
# Do we have Python 1.x or Python 2.x?
|
||||
|
@ -43,13 +43,13 @@ class Module:
|
|||
self.code = None
|
||||
|
||||
def compile(self, display=0):
|
||||
ast = parse(self.source)
|
||||
tree = parse(self.source)
|
||||
root, filename = os.path.split(self.filename)
|
||||
gen = ModuleCodeGenerator(filename)
|
||||
walk(ast, gen, 1)
|
||||
walk(tree, gen, 1)
|
||||
if display:
|
||||
import pprint
|
||||
print pprint.pprint(ast)
|
||||
print pprint.pprint(tree)
|
||||
self.code = gen.getCode()
|
||||
|
||||
def dump(self, f):
|
||||
|
@ -862,12 +862,24 @@ class CodeGenerator:
|
|||
self.emit('STORE_SUBSCR')
|
||||
|
||||
class ModuleCodeGenerator(CodeGenerator):
|
||||
super_init = CodeGenerator.__init__
|
||||
__super_init = CodeGenerator.__init__
|
||||
__super_visitModule = CodeGenerator.visitModule
|
||||
|
||||
def __init__(self, filename):
|
||||
# XXX <module> is ? in compile.c
|
||||
self.graph = pyassem.PyFlowGraph("<module>", filename)
|
||||
self.super_init(filename)
|
||||
self.__super_init(filename)
|
||||
self.symbols = None
|
||||
self.future = None
|
||||
|
||||
def visitModule(self, node):
|
||||
self.future = future.find_futures(node)
|
||||
self.symbols = self.parseSymbols(node)
|
||||
self.__super_visitModule(node)
|
||||
|
||||
def parseSymbols(self, node):
|
||||
# XXX not implemented
|
||||
return None
|
||||
|
||||
class FunctionCodeGenerator(CodeGenerator):
|
||||
super_init = CodeGenerator.__init__
|
||||
|
@ -965,6 +977,8 @@ class LocalNameFinder:
|
|||
for name in names:
|
||||
self.names.add(name)
|
||||
|
||||
# XXX list comprehensions and for loops
|
||||
|
||||
def getLocals(self):
|
||||
for elt in self.globals.elements():
|
||||
if self.names.has_elt(elt):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue