Commit 7818d696 authored by Jeremy Hylton's avatar Jeremy Hylton

Add support for future statements

parent c9656e8b
"""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):
......
"""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):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment