diff options
Diffstat (limited to 'lib/python2.7/compiler')
-rw-r--r-- | lib/python2.7/compiler/__init__.py | 31 | ||||
-rw-r--r-- | lib/python2.7/compiler/ast.py | 1419 | ||||
-rw-r--r-- | lib/python2.7/compiler/consts.py | 23 | ||||
-rw-r--r-- | lib/python2.7/compiler/future.py | 74 | ||||
-rw-r--r-- | lib/python2.7/compiler/misc.py | 73 | ||||
-rw-r--r-- | lib/python2.7/compiler/pyassem.py | 763 | ||||
-rw-r--r-- | lib/python2.7/compiler/pycodegen.py | 1555 | ||||
-rw-r--r-- | lib/python2.7/compiler/symbols.py | 462 | ||||
-rw-r--r-- | lib/python2.7/compiler/syntax.py | 46 | ||||
-rw-r--r-- | lib/python2.7/compiler/transformer.py | 1535 | ||||
-rw-r--r-- | lib/python2.7/compiler/visitor.py | 113 |
11 files changed, 0 insertions, 6094 deletions
diff --git a/lib/python2.7/compiler/__init__.py b/lib/python2.7/compiler/__init__.py deleted file mode 100644 index 2a6f64f..0000000 --- a/lib/python2.7/compiler/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -"""Package for parsing and compiling Python source code - -There are several functions defined at the top level that are imported -from modules contained in the package. - -parse(buf, mode="exec") -> AST - Converts a string containing Python source code to an abstract - syntax tree (AST). The AST is defined in compiler.ast. - -parseFile(path) -> AST - The same as parse(open(path)) - -walk(ast, visitor, verbose=None) - Does a pre-order walk over the ast using the visitor instance. - See compiler.visitor for details. - -compile(source, filename, mode, flags=None, dont_inherit=None) - Returns a code object. A replacement for the builtin compile() function. - -compileFile(filename) - Generates a .pyc file by compiling filename. -""" - -import warnings - -warnings.warn("The compiler package is deprecated and removed in Python 3.x.", - DeprecationWarning, stacklevel=2) - -from compiler.transformer import parse, parseFile -from compiler.visitor import walk -from compiler.pycodegen import compile, compileFile diff --git a/lib/python2.7/compiler/ast.py b/lib/python2.7/compiler/ast.py deleted file mode 100644 index 4c3fc16..0000000 --- a/lib/python2.7/compiler/ast.py +++ /dev/null @@ -1,1419 +0,0 @@ -"""Python abstract syntax node definitions - -This file is automatically generated by Tools/compiler/astgen.py -""" -from compiler.consts import CO_VARARGS, CO_VARKEYWORDS - -def flatten(seq): - l = [] - for elt in seq: - t = type(elt) - if t is tuple or t is list: - for elt2 in flatten(elt): - l.append(elt2) - else: - l.append(elt) - return l - -def flatten_nodes(seq): - return [n for n in flatten(seq) if isinstance(n, Node)] - -nodes = {} - -class Node: - """Abstract base class for ast nodes.""" - def getChildren(self): - pass # implemented by subclasses - def __iter__(self): - for n in self.getChildren(): - yield n - def asList(self): # for backwards compatibility - return self.getChildren() - def getChildNodes(self): - pass # implemented by subclasses - -class EmptyNode(Node): - pass - -class Expression(Node): - # Expression is an artificial node class to support "eval" - nodes["expression"] = "Expression" - def __init__(self, node): - self.node = node - - def getChildren(self): - return self.node, - - def getChildNodes(self): - return self.node, - - def __repr__(self): - return "Expression(%s)" % (repr(self.node)) - -class Add(Node): - def __init__(self, leftright, lineno=None): - self.left = leftright[0] - self.right = leftright[1] - self.lineno = lineno - - def getChildren(self): - return self.left, self.right - - def getChildNodes(self): - return self.left, self.right - - def __repr__(self): - return "Add((%s, %s))" % (repr(self.left), repr(self.right)) - -class And(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "And(%s)" % (repr(self.nodes),) - -class AssAttr(Node): - def __init__(self, expr, attrname, flags, lineno=None): - self.expr = expr - self.attrname = attrname - self.flags = flags - self.lineno = lineno - - def getChildren(self): - return self.expr, self.attrname, self.flags - - def getChildNodes(self): - return self.expr, - - def __repr__(self): - return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags)) - -class AssList(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "AssList(%s)" % (repr(self.nodes),) - -class AssName(Node): - def __init__(self, name, flags, lineno=None): - self.name = name - self.flags = flags - self.lineno = lineno - - def getChildren(self): - return self.name, self.flags - - def getChildNodes(self): - return () - - def __repr__(self): - return "AssName(%s, %s)" % (repr(self.name), repr(self.flags)) - -class AssTuple(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "AssTuple(%s)" % (repr(self.nodes),) - -class Assert(Node): - def __init__(self, test, fail, lineno=None): - self.test = test - self.fail = fail - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.test) - children.append(self.fail) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.test) - if self.fail is not None: - nodelist.append(self.fail) - return tuple(nodelist) - - def __repr__(self): - return "Assert(%s, %s)" % (repr(self.test), repr(self.fail)) - -class Assign(Node): - def __init__(self, nodes, expr, lineno=None): - self.nodes = nodes - self.expr = expr - self.lineno = lineno - - def getChildren(self): - children = [] - children.extend(flatten(self.nodes)) - children.append(self.expr) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - nodelist.append(self.expr) - return tuple(nodelist) - - def __repr__(self): - return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr)) - -class AugAssign(Node): - def __init__(self, node, op, expr, lineno=None): - self.node = node - self.op = op - self.expr = expr - self.lineno = lineno - - def getChildren(self): - return self.node, self.op, self.expr - - def getChildNodes(self): - return self.node, self.expr - - def __repr__(self): - return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr)) - -class Backquote(Node): - def __init__(self, expr, lineno=None): - self.expr = expr - self.lineno = lineno - - def getChildren(self): - return self.expr, - - def getChildNodes(self): - return self.expr, - - def __repr__(self): - return "Backquote(%s)" % (repr(self.expr),) - -class Bitand(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "Bitand(%s)" % (repr(self.nodes),) - -class Bitor(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "Bitor(%s)" % (repr(self.nodes),) - -class Bitxor(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "Bitxor(%s)" % (repr(self.nodes),) - -class Break(Node): - def __init__(self, lineno=None): - self.lineno = lineno - - def getChildren(self): - return () - - def getChildNodes(self): - return () - - def __repr__(self): - return "Break()" - -class CallFunc(Node): - def __init__(self, node, args, star_args = None, dstar_args = None, lineno=None): - self.node = node - self.args = args - self.star_args = star_args - self.dstar_args = dstar_args - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.node) - children.extend(flatten(self.args)) - children.append(self.star_args) - children.append(self.dstar_args) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.node) - nodelist.extend(flatten_nodes(self.args)) - if self.star_args is not None: - nodelist.append(self.star_args) - if self.dstar_args is not None: - nodelist.append(self.dstar_args) - return tuple(nodelist) - - def __repr__(self): - return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args)) - -class Class(Node): - def __init__(self, name, bases, doc, code, decorators = None, lineno=None): - self.name = name - self.bases = bases - self.doc = doc - self.code = code - self.decorators = decorators - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.name) - children.extend(flatten(self.bases)) - children.append(self.doc) - children.append(self.code) - children.append(self.decorators) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.bases)) - nodelist.append(self.code) - if self.decorators is not None: - nodelist.append(self.decorators) - return tuple(nodelist) - - def __repr__(self): - return "Class(%s, %s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code), repr(self.decorators)) - -class Compare(Node): - def __init__(self, expr, ops, lineno=None): - self.expr = expr - self.ops = ops - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.expr) - children.extend(flatten(self.ops)) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.expr) - nodelist.extend(flatten_nodes(self.ops)) - return tuple(nodelist) - - def __repr__(self): - return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops)) - -class Const(Node): - def __init__(self, value, lineno=None): - self.value = value - self.lineno = lineno - - def getChildren(self): - return self.value, - - def getChildNodes(self): - return () - - def __repr__(self): - return "Const(%s)" % (repr(self.value),) - -class Continue(Node): - def __init__(self, lineno=None): - self.lineno = lineno - - def getChildren(self): - return () - - def getChildNodes(self): - return () - - def __repr__(self): - return "Continue()" - -class Decorators(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "Decorators(%s)" % (repr(self.nodes),) - -class Dict(Node): - def __init__(self, items, lineno=None): - self.items = items - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.items)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.items)) - return tuple(nodelist) - - def __repr__(self): - return "Dict(%s)" % (repr(self.items),) - -class Discard(Node): - def __init__(self, expr, lineno=None): - self.expr = expr - self.lineno = lineno - - def getChildren(self): - return self.expr, - - def getChildNodes(self): - return self.expr, - - def __repr__(self): - return "Discard(%s)" % (repr(self.expr),) - -class Div(Node): - def __init__(self, leftright, lineno=None): - self.left = leftright[0] - self.right = leftright[1] - self.lineno = lineno - - def getChildren(self): - return self.left, self.right - - def getChildNodes(self): - return self.left, self.right - - def __repr__(self): - return "Div((%s, %s))" % (repr(self.left), repr(self.right)) - -class Ellipsis(Node): - def __init__(self, lineno=None): - self.lineno = lineno - - def getChildren(self): - return () - - def getChildNodes(self): - return () - - def __repr__(self): - return "Ellipsis()" - -class Exec(Node): - def __init__(self, expr, locals, globals, lineno=None): - self.expr = expr - self.locals = locals - self.globals = globals - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.expr) - children.append(self.locals) - children.append(self.globals) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.expr) - if self.locals is not None: - nodelist.append(self.locals) - if self.globals is not None: - nodelist.append(self.globals) - return tuple(nodelist) - - def __repr__(self): - return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals)) - -class FloorDiv(Node): - def __init__(self, leftright, lineno=None): - self.left = leftright[0] - self.right = leftright[1] - self.lineno = lineno - - def getChildren(self): - return self.left, self.right - - def getChildNodes(self): - return self.left, self.right - - def __repr__(self): - return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right)) - -class For(Node): - def __init__(self, assign, list, body, else_, lineno=None): - self.assign = assign - self.list = list - self.body = body - self.else_ = else_ - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.assign) - children.append(self.list) - children.append(self.body) - children.append(self.else_) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.assign) - nodelist.append(self.list) - nodelist.append(self.body) - if self.else_ is not None: - nodelist.append(self.else_) - return tuple(nodelist) - - def __repr__(self): - return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_)) - -class From(Node): - def __init__(self, modname, names, level, lineno=None): - self.modname = modname - self.names = names - self.level = level - self.lineno = lineno - - def getChildren(self): - return self.modname, self.names, self.level - - def getChildNodes(self): - return () - - def __repr__(self): - return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level)) - -class Function(Node): - def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None): - self.decorators = decorators - self.name = name - self.argnames = argnames - self.defaults = defaults - self.flags = flags - self.doc = doc - self.code = code - self.lineno = lineno - self.varargs = self.kwargs = None - if flags & CO_VARARGS: - self.varargs = 1 - if flags & CO_VARKEYWORDS: - self.kwargs = 1 - - - def getChildren(self): - children = [] - children.append(self.decorators) - children.append(self.name) - children.append(self.argnames) - children.extend(flatten(self.defaults)) - children.append(self.flags) - children.append(self.doc) - children.append(self.code) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - if self.decorators is not None: - nodelist.append(self.decorators) - nodelist.extend(flatten_nodes(self.defaults)) - nodelist.append(self.code) - return tuple(nodelist) - - def __repr__(self): - return "Function(%s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code)) - -class GenExpr(Node): - def __init__(self, code, lineno=None): - self.code = code - self.lineno = lineno - self.argnames = ['.0'] - self.varargs = self.kwargs = None - - - def getChildren(self): - return self.code, - - def getChildNodes(self): - return self.code, - - def __repr__(self): - return "GenExpr(%s)" % (repr(self.code),) - -class GenExprFor(Node): - def __init__(self, assign, iter, ifs, lineno=None): - self.assign = assign - self.iter = iter - self.ifs = ifs - self.lineno = lineno - self.is_outmost = False - - def getChildren(self): - children = [] - children.append(self.assign) - children.append(self.iter) - children.extend(flatten(self.ifs)) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.assign) - nodelist.append(self.iter) - nodelist.extend(flatten_nodes(self.ifs)) - return tuple(nodelist) - - def __repr__(self): - return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs)) - -class GenExprIf(Node): - def __init__(self, test, lineno=None): - self.test = test - self.lineno = lineno - - def getChildren(self): - return self.test, - - def getChildNodes(self): - return self.test, - - def __repr__(self): - return "GenExprIf(%s)" % (repr(self.test),) - -class GenExprInner(Node): - def __init__(self, expr, quals, lineno=None): - self.expr = expr - self.quals = quals - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.expr) - children.extend(flatten(self.quals)) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.expr) - nodelist.extend(flatten_nodes(self.quals)) - return tuple(nodelist) - - def __repr__(self): - return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals)) - -class Getattr(Node): - def __init__(self, expr, attrname, lineno=None): - self.expr = expr - self.attrname = attrname - self.lineno = lineno - - def getChildren(self): - return self.expr, self.attrname - - def getChildNodes(self): - return self.expr, - - def __repr__(self): - return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname)) - -class Global(Node): - def __init__(self, names, lineno=None): - self.names = names - self.lineno = lineno - - def getChildren(self): - return self.names, - - def getChildNodes(self): - return () - - def __repr__(self): - return "Global(%s)" % (repr(self.names),) - -class If(Node): - def __init__(self, tests, else_, lineno=None): - self.tests = tests - self.else_ = else_ - self.lineno = lineno - - def getChildren(self): - children = [] - children.extend(flatten(self.tests)) - children.append(self.else_) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.tests)) - if self.else_ is not None: - nodelist.append(self.else_) - return tuple(nodelist) - - def __repr__(self): - return "If(%s, %s)" % (repr(self.tests), repr(self.else_)) - -class IfExp(Node): - def __init__(self, test, then, else_, lineno=None): - self.test = test - self.then = then - self.else_ = else_ - self.lineno = lineno - - def getChildren(self): - return self.test, self.then, self.else_ - - def getChildNodes(self): - return self.test, self.then, self.else_ - - def __repr__(self): - return "IfExp(%s, %s, %s)" % (repr(self.test), repr(self.then), repr(self.else_)) - -class Import(Node): - def __init__(self, names, lineno=None): - self.names = names - self.lineno = lineno - - def getChildren(self): - return self.names, - - def getChildNodes(self): - return () - - def __repr__(self): - return "Import(%s)" % (repr(self.names),) - -class Invert(Node): - def __init__(self, expr, lineno=None): - self.expr = expr - self.lineno = lineno - - def getChildren(self): - return self.expr, - - def getChildNodes(self): - return self.expr, - - def __repr__(self): - return "Invert(%s)" % (repr(self.expr),) - -class Keyword(Node): - def __init__(self, name, expr, lineno=None): - self.name = name - self.expr = expr - self.lineno = lineno - - def getChildren(self): - return self.name, self.expr - - def getChildNodes(self): - return self.expr, - - def __repr__(self): - return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr)) - -class Lambda(Node): - def __init__(self, argnames, defaults, flags, code, lineno=None): - self.argnames = argnames - self.defaults = defaults - self.flags = flags - self.code = code - self.lineno = lineno - self.varargs = self.kwargs = None - if flags & CO_VARARGS: - self.varargs = 1 - if flags & CO_VARKEYWORDS: - self.kwargs = 1 - - - def getChildren(self): - children = [] - children.append(self.argnames) - children.extend(flatten(self.defaults)) - children.append(self.flags) - children.append(self.code) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.defaults)) - nodelist.append(self.code) - return tuple(nodelist) - - def __repr__(self): - return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code)) - -class LeftShift(Node): - def __init__(self, leftright, lineno=None): - self.left = leftright[0] - self.right = leftright[1] - self.lineno = lineno - - def getChildren(self): - return self.left, self.right - - def getChildNodes(self): - return self.left, self.right - - def __repr__(self): - return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right)) - -class List(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "List(%s)" % (repr(self.nodes),) - -class ListComp(Node): - def __init__(self, expr, quals, lineno=None): - self.expr = expr - self.quals = quals - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.expr) - children.extend(flatten(self.quals)) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.expr) - nodelist.extend(flatten_nodes(self.quals)) - return tuple(nodelist) - - def __repr__(self): - return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals)) - -class ListCompFor(Node): - def __init__(self, assign, list, ifs, lineno=None): - self.assign = assign - self.list = list - self.ifs = ifs - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.assign) - children.append(self.list) - children.extend(flatten(self.ifs)) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.assign) - nodelist.append(self.list) - nodelist.extend(flatten_nodes(self.ifs)) - return tuple(nodelist) - - def __repr__(self): - return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs)) - -class ListCompIf(Node): - def __init__(self, test, lineno=None): - self.test = test - self.lineno = lineno - - def getChildren(self): - return self.test, - - def getChildNodes(self): - return self.test, - - def __repr__(self): - return "ListCompIf(%s)" % (repr(self.test),) - -class SetComp(Node): - def __init__(self, expr, quals, lineno=None): - self.expr = expr - self.quals = quals - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.expr) - children.extend(flatten(self.quals)) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.expr) - nodelist.extend(flatten_nodes(self.quals)) - return tuple(nodelist) - - def __repr__(self): - return "SetComp(%s, %s)" % (repr(self.expr), repr(self.quals)) - -class DictComp(Node): - def __init__(self, key, value, quals, lineno=None): - self.key = key - self.value = value - self.quals = quals - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.key) - children.append(self.value) - children.extend(flatten(self.quals)) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.key) - nodelist.append(self.value) - nodelist.extend(flatten_nodes(self.quals)) - return tuple(nodelist) - - def __repr__(self): - return "DictComp(%s, %s, %s)" % (repr(self.key), repr(self.value), repr(self.quals)) - -class Mod(Node): - def __init__(self, leftright, lineno=None): - self.left = leftright[0] - self.right = leftright[1] - self.lineno = lineno - - def getChildren(self): - return self.left, self.right - - def getChildNodes(self): - return self.left, self.right - - def __repr__(self): - return "Mod((%s, %s))" % (repr(self.left), repr(self.right)) - -class Module(Node): - def __init__(self, doc, node, lineno=None): - self.doc = doc - self.node = node - self.lineno = lineno - - def getChildren(self): - return self.doc, self.node - - def getChildNodes(self): - return self.node, - - def __repr__(self): - return "Module(%s, %s)" % (repr(self.doc), repr(self.node)) - -class Mul(Node): - def __init__(self, leftright, lineno=None): - self.left = leftright[0] - self.right = leftright[1] - self.lineno = lineno - - def getChildren(self): - return self.left, self.right - - def getChildNodes(self): - return self.left, self.right - - def __repr__(self): - return "Mul((%s, %s))" % (repr(self.left), repr(self.right)) - -class Name(Node): - def __init__(self, name, lineno=None): - self.name = name - self.lineno = lineno - - def getChildren(self): - return self.name, - - def getChildNodes(self): - return () - - def __repr__(self): - return "Name(%s)" % (repr(self.name),) - -class Not(Node): - def __init__(self, expr, lineno=None): - self.expr = expr - self.lineno = lineno - - def getChildren(self): - return self.expr, - - def getChildNodes(self): - return self.expr, - - def __repr__(self): - return "Not(%s)" % (repr(self.expr),) - -class Or(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "Or(%s)" % (repr(self.nodes),) - -class Pass(Node): - def __init__(self, lineno=None): - self.lineno = lineno - - def getChildren(self): - return () - - def getChildNodes(self): - return () - - def __repr__(self): - return "Pass()" - -class Power(Node): - def __init__(self, leftright, lineno=None): - self.left = leftright[0] - self.right = leftright[1] - self.lineno = lineno - - def getChildren(self): - return self.left, self.right - - def getChildNodes(self): - return self.left, self.right - - def __repr__(self): - return "Power((%s, %s))" % (repr(self.left), repr(self.right)) - -class Print(Node): - def __init__(self, nodes, dest, lineno=None): - self.nodes = nodes - self.dest = dest - self.lineno = lineno - - def getChildren(self): - children = [] - children.extend(flatten(self.nodes)) - children.append(self.dest) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - if self.dest is not None: - nodelist.append(self.dest) - return tuple(nodelist) - - def __repr__(self): - return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest)) - -class Printnl(Node): - def __init__(self, nodes, dest, lineno=None): - self.nodes = nodes - self.dest = dest - self.lineno = lineno - - def getChildren(self): - children = [] - children.extend(flatten(self.nodes)) - children.append(self.dest) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - if self.dest is not None: - nodelist.append(self.dest) - return tuple(nodelist) - - def __repr__(self): - return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest)) - -class Raise(Node): - def __init__(self, expr1, expr2, expr3, lineno=None): - self.expr1 = expr1 - self.expr2 = expr2 - self.expr3 = expr3 - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.expr1) - children.append(self.expr2) - children.append(self.expr3) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - if self.expr1 is not None: - nodelist.append(self.expr1) - if self.expr2 is not None: - nodelist.append(self.expr2) - if self.expr3 is not None: - nodelist.append(self.expr3) - return tuple(nodelist) - - def __repr__(self): - return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3)) - -class Return(Node): - def __init__(self, value, lineno=None): - self.value = value - self.lineno = lineno - - def getChildren(self): - return self.value, - - def getChildNodes(self): - return self.value, - - def __repr__(self): - return "Return(%s)" % (repr(self.value),) - -class RightShift(Node): - def __init__(self, leftright, lineno=None): - self.left = leftright[0] - self.right = leftright[1] - self.lineno = lineno - - def getChildren(self): - return self.left, self.right - - def getChildNodes(self): - return self.left, self.right - - def __repr__(self): - return "RightShift((%s, %s))" % (repr(self.left), repr(self.right)) - -class Set(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "Set(%s)" % (repr(self.nodes),) - -class Slice(Node): - def __init__(self, expr, flags, lower, upper, lineno=None): - self.expr = expr - self.flags = flags - self.lower = lower - self.upper = upper - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.expr) - children.append(self.flags) - children.append(self.lower) - children.append(self.upper) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.expr) - if self.lower is not None: - nodelist.append(self.lower) - if self.upper is not None: - nodelist.append(self.upper) - return tuple(nodelist) - - def __repr__(self): - return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper)) - -class Sliceobj(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "Sliceobj(%s)" % (repr(self.nodes),) - -class Stmt(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "Stmt(%s)" % (repr(self.nodes),) - -class Sub(Node): - def __init__(self, leftright, lineno=None): - self.left = leftright[0] - self.right = leftright[1] - self.lineno = lineno - - def getChildren(self): - return self.left, self.right - - def getChildNodes(self): - return self.left, self.right - - def __repr__(self): - return "Sub((%s, %s))" % (repr(self.left), repr(self.right)) - -class Subscript(Node): - def __init__(self, expr, flags, subs, lineno=None): - self.expr = expr - self.flags = flags - self.subs = subs - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.expr) - children.append(self.flags) - children.extend(flatten(self.subs)) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.expr) - nodelist.extend(flatten_nodes(self.subs)) - return tuple(nodelist) - - def __repr__(self): - return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs)) - -class TryExcept(Node): - def __init__(self, body, handlers, else_, lineno=None): - self.body = body - self.handlers = handlers - self.else_ = else_ - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.body) - children.extend(flatten(self.handlers)) - children.append(self.else_) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.body) - nodelist.extend(flatten_nodes(self.handlers)) - if self.else_ is not None: - nodelist.append(self.else_) - return tuple(nodelist) - - def __repr__(self): - return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_)) - -class TryFinally(Node): - def __init__(self, body, final, lineno=None): - self.body = body - self.final = final - self.lineno = lineno - - def getChildren(self): - return self.body, self.final - - def getChildNodes(self): - return self.body, self.final - - def __repr__(self): - return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final)) - -class Tuple(Node): - def __init__(self, nodes, lineno=None): - self.nodes = nodes - self.lineno = lineno - - def getChildren(self): - return tuple(flatten(self.nodes)) - - def getChildNodes(self): - nodelist = [] - nodelist.extend(flatten_nodes(self.nodes)) - return tuple(nodelist) - - def __repr__(self): - return "Tuple(%s)" % (repr(self.nodes),) - -class UnaryAdd(Node): - def __init__(self, expr, lineno=None): - self.expr = expr - self.lineno = lineno - - def getChildren(self): - return self.expr, - - def getChildNodes(self): - return self.expr, - - def __repr__(self): - return "UnaryAdd(%s)" % (repr(self.expr),) - -class UnarySub(Node): - def __init__(self, expr, lineno=None): - self.expr = expr - self.lineno = lineno - - def getChildren(self): - return self.expr, - - def getChildNodes(self): - return self.expr, - - def __repr__(self): - return "UnarySub(%s)" % (repr(self.expr),) - -class While(Node): - def __init__(self, test, body, else_, lineno=None): - self.test = test - self.body = body - self.else_ = else_ - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.test) - children.append(self.body) - children.append(self.else_) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.test) - nodelist.append(self.body) - if self.else_ is not None: - nodelist.append(self.else_) - return tuple(nodelist) - - def __repr__(self): - return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_)) - -class With(Node): - def __init__(self, expr, vars, body, lineno=None): - self.expr = expr - self.vars = vars - self.body = body - self.lineno = lineno - - def getChildren(self): - children = [] - children.append(self.expr) - children.append(self.vars) - children.append(self.body) - return tuple(children) - - def getChildNodes(self): - nodelist = [] - nodelist.append(self.expr) - if self.vars is not None: - nodelist.append(self.vars) - nodelist.append(self.body) - return tuple(nodelist) - - def __repr__(self): - return "With(%s, %s, %s)" % (repr(self.expr), repr(self.vars), repr(self.body)) - -class Yield(Node): - def __init__(self, value, lineno=None): - self.value = value - self.lineno = lineno - - def getChildren(self): - return self.value, - - def getChildNodes(self): - return self.value, - - def __repr__(self): - return "Yield(%s)" % (repr(self.value),) - -for name, obj in globals().items(): - if isinstance(obj, type) and issubclass(obj, Node): - nodes[name.lower()] = obj diff --git a/lib/python2.7/compiler/consts.py b/lib/python2.7/compiler/consts.py deleted file mode 100644 index c60b1d0..0000000 --- a/lib/python2.7/compiler/consts.py +++ /dev/null @@ -1,23 +0,0 @@ -# operation flags -OP_ASSIGN = 'OP_ASSIGN' -OP_DELETE = 'OP_DELETE' -OP_APPLY = 'OP_APPLY' - -SC_LOCAL = 1 -SC_GLOBAL_IMPLICIT = 2 -SC_GLOBAL_EXPLICIT = 3 -SC_FREE = 4 -SC_CELL = 5 -SC_UNKNOWN = 6 - -CO_OPTIMIZED = 0x0001 -CO_NEWLOCALS = 0x0002 -CO_VARARGS = 0x0004 -CO_VARKEYWORDS = 0x0008 -CO_NESTED = 0x0010 -CO_GENERATOR = 0x0020 -CO_GENERATOR_ALLOWED = 0 -CO_FUTURE_DIVISION = 0x2000 -CO_FUTURE_ABSIMPORT = 0x4000 -CO_FUTURE_WITH_STATEMENT = 0x8000 -CO_FUTURE_PRINT_FUNCTION = 0x10000 diff --git a/lib/python2.7/compiler/future.py b/lib/python2.7/compiler/future.py deleted file mode 100644 index fd5e5df..0000000 --- a/lib/python2.7/compiler/future.py +++ /dev/null @@ -1,74 +0,0 @@ -"""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", "generators", "division", - "absolute_import", "with_statement", "print_function", - "unicode_literals") - - def __init__(self): - self.found = {} # set - - def visitModule(self, node): - stmt = node.node - for s in stmt.nodes: - 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 " + repr(node) - -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 diff --git a/lib/python2.7/compiler/misc.py b/lib/python2.7/compiler/misc.py deleted file mode 100644 index 588c7fb..0000000 --- a/lib/python2.7/compiler/misc.py +++ /dev/null @@ -1,73 +0,0 @@ - -def flatten(tup): - elts = [] - for elt in tup: - if isinstance(elt, tuple): - elts = elts + flatten(elt) - else: - elts.append(elt) - return elts - -class Set: - def __init__(self): - self.elts = {} - def __len__(self): - return len(self.elts) - def __contains__(self, elt): - return elt in self.elts - def add(self, elt): - self.elts[elt] = elt - def elements(self): - return self.elts.keys() - def has_elt(self, elt): - return elt in self.elts - def remove(self, elt): - del self.elts[elt] - def copy(self): - c = Set() - c.elts.update(self.elts) - return c - -class Stack: - def __init__(self): - self.stack = [] - self.pop = self.stack.pop - def __len__(self): - return len(self.stack) - def push(self, elt): - self.stack.append(elt) - def top(self): - return self.stack[-1] - def __getitem__(self, index): # needed by visitContinue() - return self.stack[index] - -MANGLE_LEN = 256 # magic constant from compile.c - -def mangle(name, klass): - if not name.startswith('__'): - return name - if len(name) + 2 >= MANGLE_LEN: - return name - if name.endswith('__'): - return name - try: - i = 0 - while klass[i] == '_': - i = i + 1 - except IndexError: - return name - klass = klass[i:] - - tlen = len(klass) + len(name) - if tlen > MANGLE_LEN: - klass = klass[:MANGLE_LEN-tlen] - - return "_%s%s" % (klass, name) - -def set_filename(filename, tree): - """Set the filename attribute to filename on every node in tree""" - worklist = [tree] - while worklist: - node = worklist.pop(0) - node.filename = filename - worklist.extend(node.getChildNodes()) diff --git a/lib/python2.7/compiler/pyassem.py b/lib/python2.7/compiler/pyassem.py deleted file mode 100644 index 286be0c..0000000 --- a/lib/python2.7/compiler/pyassem.py +++ /dev/null @@ -1,763 +0,0 @@ -"""A flow graph representation for Python bytecode""" - -import dis -import types -import sys - -from compiler import misc -from compiler.consts \ - import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS - -class FlowGraph: - def __init__(self): - self.current = self.entry = Block() - self.exit = Block("exit") - self.blocks = misc.Set() - self.blocks.add(self.entry) - self.blocks.add(self.exit) - - def startBlock(self, block): - if self._debug: - if self.current: - print "end", repr(self.current) - print " next", self.current.next - print " prev", self.current.prev - print " ", self.current.get_children() - print repr(block) - self.current = block - - def nextBlock(self, block=None): - # XXX think we need to specify when there is implicit transfer - # from one block to the next. might be better to represent this - # with explicit JUMP_ABSOLUTE instructions that are optimized - # out when they are unnecessary. - # - # I think this strategy works: each block has a child - # designated as "next" which is returned as the last of the - # children. because the nodes in a graph are emitted in - # reverse post order, the "next" block will always be emitted - # immediately after its parent. - # Worry: maintaining this invariant could be tricky - if block is None: - block = self.newBlock() - - # Note: If the current block ends with an unconditional control - # transfer, then it is techically incorrect to add an implicit - # transfer to the block graph. Doing so results in code generation - # for unreachable blocks. That doesn't appear to be very common - # with Python code and since the built-in compiler doesn't optimize - # it out we don't either. - self.current.addNext(block) - self.startBlock(block) - - def newBlock(self): - b = Block() - self.blocks.add(b) - return b - - def startExitBlock(self): - self.startBlock(self.exit) - - _debug = 0 - - def _enable_debug(self): - self._debug = 1 - - def _disable_debug(self): - self._debug = 0 - - def emit(self, *inst): - if self._debug: - print "\t", inst - if len(inst) == 2 and isinstance(inst[1], Block): - self.current.addOutEdge(inst[1]) - self.current.emit(inst) - - def getBlocksInOrder(self): - """Return the blocks in reverse postorder - - i.e. each node appears before all of its successors - """ - order = order_blocks(self.entry, self.exit) - return order - - def getBlocks(self): - return self.blocks.elements() - - def getRoot(self): - """Return nodes appropriate for use with dominator""" - return self.entry - - def getContainedGraphs(self): - l = [] - for b in self.getBlocks(): - l.extend(b.getContainedGraphs()) - return l - - -def order_blocks(start_block, exit_block): - """Order blocks so that they are emitted in the right order""" - # Rules: - # - when a block has a next block, the next block must be emitted just after - # - when a block has followers (relative jumps), it must be emitted before - # them - # - all reachable blocks must be emitted - order = [] - - # Find all the blocks to be emitted. - remaining = set() - todo = [start_block] - while todo: - b = todo.pop() - if b in remaining: - continue - remaining.add(b) - for c in b.get_children(): - if c not in remaining: - todo.append(c) - - # A block is dominated by another block if that block must be emitted - # before it. - dominators = {} - for b in remaining: - if __debug__ and b.next: - assert b is b.next[0].prev[0], (b, b.next) - # Make sure every block appears in dominators, even if no - # other block must precede it. - dominators.setdefault(b, set()) - # preceeding blocks dominate following blocks - for c in b.get_followers(): - while 1: - dominators.setdefault(c, set()).add(b) - # Any block that has a next pointer leading to c is also - # dominated because the whole chain will be emitted at once. - # Walk backwards and add them all. - if c.prev and c.prev[0] is not b: - c = c.prev[0] - else: - break - - def find_next(): - # Find a block that can be emitted next. - for b in remaining: - for c in dominators[b]: - if c in remaining: - break # can't emit yet, dominated by a remaining block - else: - return b - assert 0, 'circular dependency, cannot find next block' - - b = start_block - while 1: - order.append(b) - remaining.discard(b) - if b.next: - b = b.next[0] - continue - elif b is not exit_block and not b.has_unconditional_transfer(): - order.append(exit_block) - if not remaining: - break - b = find_next() - return order - - -class Block: - _count = 0 - - def __init__(self, label=''): - self.insts = [] - self.outEdges = set() - self.label = label - self.bid = Block._count - self.next = [] - self.prev = [] - Block._count = Block._count + 1 - - def __repr__(self): - if self.label: - return "<block %s id=%d>" % (self.label, self.bid) - else: - return "<block id=%d>" % (self.bid) - - def __str__(self): - insts = map(str, self.insts) - return "<block %s %d:\n%s>" % (self.label, self.bid, - '\n'.join(insts)) - - def emit(self, inst): - op = inst[0] - self.insts.append(inst) - - def getInstructions(self): - return self.insts - - def addOutEdge(self, block): - self.outEdges.add(block) - - def addNext(self, block): - self.next.append(block) - assert len(self.next) == 1, map(str, self.next) - block.prev.append(self) - assert len(block.prev) == 1, map(str, block.prev) - - _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', - 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP', - ) - - def has_unconditional_transfer(self): - """Returns True if there is an unconditional transfer to an other block - at the end of this block. This means there is no risk for the bytecode - executer to go past this block's bytecode.""" - try: - op, arg = self.insts[-1] - except (IndexError, ValueError): - return - return op in self._uncond_transfer - - def get_children(self): - return list(self.outEdges) + self.next - - def get_followers(self): - """Get the whole list of followers, including the next block.""" - followers = set(self.next) - # Blocks that must be emitted *after* this one, because of - # bytecode offsets (e.g. relative jumps) pointing to them. - for inst in self.insts: - if inst[0] in PyFlowGraph.hasjrel: - followers.add(inst[1]) - return followers - - def getContainedGraphs(self): - """Return all graphs contained within this block. - - For example, a MAKE_FUNCTION block will contain a reference to - the graph for the function body. - """ - contained = [] - for inst in self.insts: - if len(inst) == 1: - continue - op = inst[1] - if hasattr(op, 'graph'): - contained.append(op.graph) - return contained - -# flags for code objects - -# the FlowGraph is transformed in place; it exists in one of these states -RAW = "RAW" -FLAT = "FLAT" -CONV = "CONV" -DONE = "DONE" - -class PyFlowGraph(FlowGraph): - super_init = FlowGraph.__init__ - - def __init__(self, name, filename, args=(), optimized=0, klass=None): - self.super_init() - self.name = name - self.filename = filename - self.docstring = None - self.args = args # XXX - self.argcount = getArgCount(args) - self.klass = klass - if optimized: - self.flags = CO_OPTIMIZED | CO_NEWLOCALS - else: - self.flags = 0 - self.consts = [] - self.names = [] - # Free variables found by the symbol table scan, including - # variables used only in nested scopes, are included here. - self.freevars = [] - self.cellvars = [] - # The closure list is used to track the order of cell - # variables and free variables in the resulting code object. - # The offsets used by LOAD_CLOSURE/LOAD_DEREF refer to both - # kinds of variables. - self.closure = [] - self.varnames = list(args) or [] - for i in range(len(self.varnames)): - var = self.varnames[i] - if isinstance(var, TupleArg): - self.varnames[i] = var.getName() - self.stage = RAW - - def setDocstring(self, doc): - self.docstring = doc - - def setFlag(self, flag): - self.flags = self.flags | flag - if flag == CO_VARARGS: - self.argcount = self.argcount - 1 - - def checkFlag(self, flag): - if self.flags & flag: - return 1 - - def setFreeVars(self, names): - self.freevars = list(names) - - def setCellVars(self, names): - self.cellvars = names - - def getCode(self): - """Get a Python code object""" - assert self.stage == RAW - self.computeStackDepth() - self.flattenGraph() - assert self.stage == FLAT - self.convertArgs() - assert self.stage == CONV - self.makeByteCode() - assert self.stage == DONE - return self.newCodeObject() - - def dump(self, io=None): - if io: - save = sys.stdout - sys.stdout = io - pc = 0 - for t in self.insts: - opname = t[0] - if opname == "SET_LINENO": - print - if len(t) == 1: - print "\t", "%3d" % pc, opname - pc = pc + 1 - else: - print "\t", "%3d" % pc, opname, t[1] - pc = pc + 3 - if io: - sys.stdout = save - - def computeStackDepth(self): - """Compute the max stack depth. - - Approach is to compute the stack effect of each basic block. - Then find the path through the code with the largest total - effect. - """ - depth = {} - exit = None - for b in self.getBlocks(): - depth[b] = findDepth(b.getInstructions()) - - seen = {} - - def max_depth(b, d): - if b in seen: - return d - seen[b] = 1 - d = d + depth[b] - children = b.get_children() - if children: - return max([max_depth(c, d) for c in children]) - else: - if not b.label == "exit": - return max_depth(self.exit, d) - else: - return d - - self.stacksize = max_depth(self.entry, 0) - - def flattenGraph(self): - """Arrange the blocks in order and resolve jumps""" - assert self.stage == RAW - self.insts = insts = [] - pc = 0 - begin = {} - end = {} - for b in self.getBlocksInOrder(): - begin[b] = pc - for inst in b.getInstructions(): - insts.append(inst) - if len(inst) == 1: - pc = pc + 1 - elif inst[0] != "SET_LINENO": - # arg takes 2 bytes - pc = pc + 3 - end[b] = pc - pc = 0 - for i in range(len(insts)): - inst = insts[i] - if len(inst) == 1: - pc = pc + 1 - elif inst[0] != "SET_LINENO": - pc = pc + 3 - opname = inst[0] - if opname in self.hasjrel: - oparg = inst[1] - offset = begin[oparg] - pc - insts[i] = opname, offset - elif opname in self.hasjabs: - insts[i] = opname, begin[inst[1]] - self.stage = FLAT - - hasjrel = set() - for i in dis.hasjrel: - hasjrel.add(dis.opname[i]) - hasjabs = set() - for i in dis.hasjabs: - hasjabs.add(dis.opname[i]) - - def convertArgs(self): - """Convert arguments from symbolic to concrete form""" - assert self.stage == FLAT - self.consts.insert(0, self.docstring) - self.sort_cellvars() - for i in range(len(self.insts)): - t = self.insts[i] - if len(t) == 2: - opname, oparg = t - conv = self._converters.get(opname, None) - if conv: - self.insts[i] = opname, conv(self, oparg) - self.stage = CONV - - def sort_cellvars(self): - """Sort cellvars in the order of varnames and prune from freevars. - """ - cells = {} - for name in self.cellvars: - cells[name] = 1 - self.cellvars = [name for name in self.varnames - if name in cells] - for name in self.cellvars: - del cells[name] - self.cellvars = self.cellvars + cells.keys() - self.closure = self.cellvars + self.freevars - - def _lookupName(self, name, list): - """Return index of name in list, appending if necessary - - This routine uses a list instead of a dictionary, because a - dictionary can't store two different keys if the keys have the - same value but different types, e.g. 2 and 2L. The compiler - must treat these two separately, so it does an explicit type - comparison before comparing the values. - """ - t = type(name) - for i in range(len(list)): - if t == type(list[i]) and list[i] == name: - return i - end = len(list) - list.append(name) - return end - - _converters = {} - def _convert_LOAD_CONST(self, arg): - if hasattr(arg, 'getCode'): - arg = arg.getCode() - return self._lookupName(arg, self.consts) - - def _convert_LOAD_FAST(self, arg): - self._lookupName(arg, self.names) - return self._lookupName(arg, self.varnames) - _convert_STORE_FAST = _convert_LOAD_FAST - _convert_DELETE_FAST = _convert_LOAD_FAST - - def _convert_LOAD_NAME(self, arg): - if self.klass is None: - self._lookupName(arg, self.varnames) - return self._lookupName(arg, self.names) - - def _convert_NAME(self, arg): - if self.klass is None: - self._lookupName(arg, self.varnames) - return self._lookupName(arg, self.names) - _convert_STORE_NAME = _convert_NAME - _convert_DELETE_NAME = _convert_NAME - _convert_IMPORT_NAME = _convert_NAME - _convert_IMPORT_FROM = _convert_NAME - _convert_STORE_ATTR = _convert_NAME - _convert_LOAD_ATTR = _convert_NAME - _convert_DELETE_ATTR = _convert_NAME - _convert_LOAD_GLOBAL = _convert_NAME - _convert_STORE_GLOBAL = _convert_NAME - _convert_DELETE_GLOBAL = _convert_NAME - - def _convert_DEREF(self, arg): - self._lookupName(arg, self.names) - self._lookupName(arg, self.varnames) - return self._lookupName(arg, self.closure) - _convert_LOAD_DEREF = _convert_DEREF - _convert_STORE_DEREF = _convert_DEREF - - def _convert_LOAD_CLOSURE(self, arg): - self._lookupName(arg, self.varnames) - return self._lookupName(arg, self.closure) - - _cmp = list(dis.cmp_op) - def _convert_COMPARE_OP(self, arg): - return self._cmp.index(arg) - - # similarly for other opcodes... - - for name, obj in locals().items(): - if name[:9] == "_convert_": - opname = name[9:] - _converters[opname] = obj - del name, obj, opname - - def makeByteCode(self): - assert self.stage == CONV - self.lnotab = lnotab = LineAddrTable() - for t in self.insts: - opname = t[0] - if len(t) == 1: - lnotab.addCode(self.opnum[opname]) - else: - oparg = t[1] - if opname == "SET_LINENO": - lnotab.nextLine(oparg) - continue - hi, lo = twobyte(oparg) - try: - lnotab.addCode(self.opnum[opname], lo, hi) - except ValueError: - print opname, oparg - print self.opnum[opname], lo, hi - raise - self.stage = DONE - - opnum = {} - for num in range(len(dis.opname)): - opnum[dis.opname[num]] = num - del num - - def newCodeObject(self): - assert self.stage == DONE - if (self.flags & CO_NEWLOCALS) == 0: - nlocals = 0 - else: - nlocals = len(self.varnames) - argcount = self.argcount - if self.flags & CO_VARKEYWORDS: - argcount = argcount - 1 - return types.CodeType(argcount, nlocals, self.stacksize, self.flags, - self.lnotab.getCode(), self.getConsts(), - tuple(self.names), tuple(self.varnames), - self.filename, self.name, self.lnotab.firstline, - self.lnotab.getTable(), tuple(self.freevars), - tuple(self.cellvars)) - - def getConsts(self): - """Return a tuple for the const slot of the code object - - Must convert references to code (MAKE_FUNCTION) to code - objects recursively. - """ - l = [] - for elt in self.consts: - if isinstance(elt, PyFlowGraph): - elt = elt.getCode() - l.append(elt) - return tuple(l) - -def isJump(opname): - if opname[:4] == 'JUMP': - return 1 - -class TupleArg: - """Helper for marking func defs with nested tuples in arglist""" - def __init__(self, count, names): - self.count = count - self.names = names - def __repr__(self): - return "TupleArg(%s, %s)" % (self.count, self.names) - def getName(self): - return ".%d" % self.count - -def getArgCount(args): - argcount = len(args) - if args: - for arg in args: - if isinstance(arg, TupleArg): - numNames = len(misc.flatten(arg.names)) - argcount = argcount - numNames - return argcount - -def twobyte(val): - """Convert an int argument into high and low bytes""" - assert isinstance(val, int) - return divmod(val, 256) - -class LineAddrTable: - """lnotab - - This class builds the lnotab, which is documented in compile.c. - Here's a brief recap: - - For each SET_LINENO instruction after the first one, two bytes are - added to lnotab. (In some cases, multiple two-byte entries are - added.) The first byte is the distance in bytes between the - instruction for the last SET_LINENO and the current SET_LINENO. - The second byte is offset in line numbers. If either offset is - greater than 255, multiple two-byte entries are added -- see - compile.c for the delicate details. - """ - - def __init__(self): - self.code = [] - self.codeOffset = 0 - self.firstline = 0 - self.lastline = 0 - self.lastoff = 0 - self.lnotab = [] - - def addCode(self, *args): - for arg in args: - self.code.append(chr(arg)) - self.codeOffset = self.codeOffset + len(args) - - def nextLine(self, lineno): - if self.firstline == 0: - self.firstline = lineno - self.lastline = lineno - else: - # compute deltas - addr = self.codeOffset - self.lastoff - line = lineno - self.lastline - # Python assumes that lineno always increases with - # increasing bytecode address (lnotab is unsigned char). - # Depending on when SET_LINENO instructions are emitted - # this is not always true. Consider the code: - # a = (1, - # b) - # In the bytecode stream, the assignment to "a" occurs - # after the loading of "b". This works with the C Python - # compiler because it only generates a SET_LINENO instruction - # for the assignment. - if line >= 0: - push = self.lnotab.append - while addr > 255: - push(255); push(0) - addr -= 255 - while line > 255: - push(addr); push(255) - line -= 255 - addr = 0 - if addr > 0 or line > 0: - push(addr); push(line) - self.lastline = lineno - self.lastoff = self.codeOffset - - def getCode(self): - return ''.join(self.code) - - def getTable(self): - return ''.join(map(chr, self.lnotab)) - -class StackDepthTracker: - # XXX 1. need to keep track of stack depth on jumps - # XXX 2. at least partly as a result, this code is broken - - def findDepth(self, insts, debug=0): - depth = 0 - maxDepth = 0 - for i in insts: - opname = i[0] - if debug: - print i, - delta = self.effect.get(opname, None) - if delta is not None: - depth = depth + delta - else: - # now check patterns - for pat, pat_delta in self.patterns: - if opname[:len(pat)] == pat: - delta = pat_delta - depth = depth + delta - break - # if we still haven't found a match - if delta is None: - meth = getattr(self, opname, None) - if meth is not None: - depth = depth + meth(i[1]) - if depth > maxDepth: - maxDepth = depth - if debug: - print depth, maxDepth - return maxDepth - - effect = { - 'POP_TOP': -1, - 'DUP_TOP': 1, - 'LIST_APPEND': -1, - 'SET_ADD': -1, - 'MAP_ADD': -2, - 'SLICE+1': -1, - 'SLICE+2': -1, - 'SLICE+3': -2, - 'STORE_SLICE+0': -1, - 'STORE_SLICE+1': -2, - 'STORE_SLICE+2': -2, - 'STORE_SLICE+3': -3, - 'DELETE_SLICE+0': -1, - 'DELETE_SLICE+1': -2, - 'DELETE_SLICE+2': -2, - 'DELETE_SLICE+3': -3, - 'STORE_SUBSCR': -3, - 'DELETE_SUBSCR': -2, - # PRINT_EXPR? - 'PRINT_ITEM': -1, - 'RETURN_VALUE': -1, - 'YIELD_VALUE': -1, - 'EXEC_STMT': -3, - 'BUILD_CLASS': -2, - 'STORE_NAME': -1, - 'STORE_ATTR': -2, - 'DELETE_ATTR': -1, - 'STORE_GLOBAL': -1, - 'BUILD_MAP': 1, - 'COMPARE_OP': -1, - 'STORE_FAST': -1, - 'IMPORT_STAR': -1, - 'IMPORT_NAME': -1, - 'IMPORT_FROM': 1, - 'LOAD_ATTR': 0, # unlike other loads - # close enough... - 'SETUP_EXCEPT': 3, - 'SETUP_FINALLY': 3, - 'FOR_ITER': 1, - 'WITH_CLEANUP': -1, - } - # use pattern match - patterns = [ - ('BINARY_', -1), - ('LOAD_', 1), - ] - - def UNPACK_SEQUENCE(self, count): - return count-1 - def BUILD_TUPLE(self, count): - return -count+1 - def BUILD_LIST(self, count): - return -count+1 - def BUILD_SET(self, count): - return -count+1 - def CALL_FUNCTION(self, argc): - hi, lo = divmod(argc, 256) - return -(lo + hi * 2) - def CALL_FUNCTION_VAR(self, argc): - return self.CALL_FUNCTION(argc)-1 - def CALL_FUNCTION_KW(self, argc): - return self.CALL_FUNCTION(argc)-1 - def CALL_FUNCTION_VAR_KW(self, argc): - return self.CALL_FUNCTION(argc)-2 - def MAKE_FUNCTION(self, argc): - return -argc - def MAKE_CLOSURE(self, argc): - # XXX need to account for free variables too! - return -argc - def BUILD_SLICE(self, argc): - if argc == 2: - return -1 - elif argc == 3: - return -2 - def DUP_TOPX(self, argc): - return argc - -findDepth = StackDepthTracker().findDepth diff --git a/lib/python2.7/compiler/pycodegen.py b/lib/python2.7/compiler/pycodegen.py deleted file mode 100644 index 6515945..0000000 --- a/lib/python2.7/compiler/pycodegen.py +++ /dev/null @@ -1,1555 +0,0 @@ -import imp -import os -import marshal -import struct -import sys -from cStringIO import StringIO - -from compiler import ast, parse, walk, syntax -from compiler import pyassem, misc, future, symbols -from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \ - SC_FREE, SC_CELL -from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, - CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION, - CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT, CO_FUTURE_PRINT_FUNCTION) -from compiler.pyassem import TupleArg - -# XXX The version-specific code can go, since this code only works with 2.x. -# Do we have Python 1.x or Python 2.x? -try: - VERSION = sys.version_info[0] -except AttributeError: - VERSION = 1 - -callfunc_opcode_info = { - # (Have *args, Have **args) : opcode - (0,0) : "CALL_FUNCTION", - (1,0) : "CALL_FUNCTION_VAR", - (0,1) : "CALL_FUNCTION_KW", - (1,1) : "CALL_FUNCTION_VAR_KW", -} - -LOOP = 1 -EXCEPT = 2 -TRY_FINALLY = 3 -END_FINALLY = 4 - -def compileFile(filename, display=0): - f = open(filename, 'U') - buf = f.read() - f.close() - mod = Module(buf, filename) - try: - mod.compile(display) - except SyntaxError: - raise - else: - f = open(filename + "c", "wb") - mod.dump(f) - f.close() - -def compile(source, filename, mode, flags=None, dont_inherit=None): - """Replacement for builtin compile() function""" - if flags is not None or dont_inherit is not None: - raise RuntimeError, "not implemented yet" - - if mode == "single": - gen = Interactive(source, filename) - elif mode == "exec": - gen = Module(source, filename) - elif mode == "eval": - gen = Expression(source, filename) - else: - raise ValueError("compile() 3rd arg must be 'exec' or " - "'eval' or 'single'") - gen.compile() - return gen.code - -class AbstractCompileMode: - - mode = None # defined by subclass - - def __init__(self, source, filename): - self.source = source - self.filename = filename - self.code = None - - def _get_tree(self): - tree = parse(self.source, self.mode) - misc.set_filename(self.filename, tree) - syntax.check(tree) - return tree - - def compile(self): - pass # implemented by subclass - - def getCode(self): - return self.code - -class Expression(AbstractCompileMode): - - mode = "eval" - - def compile(self): - tree = self._get_tree() - gen = ExpressionCodeGenerator(tree) - self.code = gen.getCode() - -class Interactive(AbstractCompileMode): - - mode = "single" - - def compile(self): - tree = self._get_tree() - gen = InteractiveCodeGenerator(tree) - self.code = gen.getCode() - -class Module(AbstractCompileMode): - - mode = "exec" - - def compile(self, display=0): - tree = self._get_tree() - gen = ModuleCodeGenerator(tree) - if display: - import pprint - print pprint.pprint(tree) - self.code = gen.getCode() - - def dump(self, f): - f.write(self.getPycHeader()) - marshal.dump(self.code, f) - - MAGIC = imp.get_magic() - - def getPycHeader(self): - # compile.c uses marshal to write a long directly, with - # calling the interface that would also generate a 1-byte code - # to indicate the type of the value. simplest way to get the - # same effect is to call marshal and then skip the code. - mtime = os.path.getmtime(self.filename) - mtime = struct.pack('<i', mtime) - return self.MAGIC + mtime - -class LocalNameFinder: - """Find local names in scope""" - def __init__(self, names=()): - self.names = misc.Set() - self.globals = misc.Set() - 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): - self.names.remove(elt) - return self.names - - def visitDict(self, node): - pass - - def visitGlobal(self, node): - for name in node.names: - self.globals.add(name) - - def visitFunction(self, node): - self.names.add(node.name) - - def visitLambda(self, node): - pass - - def visitImport(self, node): - for name, alias in node.names: - self.names.add(alias or name) - - def visitFrom(self, node): - for name, alias in node.names: - self.names.add(alias or name) - - def visitClass(self, node): - self.names.add(node.name) - - def visitAssName(self, node): - self.names.add(node.name) - -def is_constant_false(node): - if isinstance(node, ast.Const): - if not node.value: - return 1 - return 0 - -class CodeGenerator: - """Defines basic code generator for Python bytecode - - This class is an abstract base class. Concrete subclasses must - define an __init__() that defines self.graph and then calls the - __init__() defined in this class. - - The concrete class must also define the class attributes - NameFinder, FunctionGen, and ClassGen. These attributes can be - defined in the initClass() method, which is a hook for - initializing these methods after all the classes have been - defined. - """ - - optimized = 0 # is namespace access optimized? - __initialized = None - class_name = None # provide default for instance variable - - def __init__(self): - if self.__initialized is None: - self.initClass() - self.__class__.__initialized = 1 - self.checkClass() - self.locals = misc.Stack() - self.setups = misc.Stack() - self.last_lineno = None - self._setupGraphDelegation() - self._div_op = "BINARY_DIVIDE" - - # XXX set flags based on future features - futures = self.get_module().futures - for feature in futures: - if feature == "division": - self.graph.setFlag(CO_FUTURE_DIVISION) - self._div_op = "BINARY_TRUE_DIVIDE" - elif feature == "absolute_import": - self.graph.setFlag(CO_FUTURE_ABSIMPORT) - elif feature == "with_statement": - self.graph.setFlag(CO_FUTURE_WITH_STATEMENT) - elif feature == "print_function": - self.graph.setFlag(CO_FUTURE_PRINT_FUNCTION) - - def initClass(self): - """This method is called once for each class""" - - def checkClass(self): - """Verify that class is constructed correctly""" - try: - assert hasattr(self, 'graph') - assert getattr(self, 'NameFinder') - assert getattr(self, 'FunctionGen') - assert getattr(self, 'ClassGen') - except AssertionError, msg: - intro = "Bad class construction for %s" % self.__class__.__name__ - raise AssertionError, intro - - def _setupGraphDelegation(self): - self.emit = self.graph.emit - self.newBlock = self.graph.newBlock - self.startBlock = self.graph.startBlock - self.nextBlock = self.graph.nextBlock - self.setDocstring = self.graph.setDocstring - - def getCode(self): - """Return a code object""" - return self.graph.getCode() - - def mangle(self, name): - if self.class_name is not None: - return misc.mangle(name, self.class_name) - else: - return name - - def parseSymbols(self, tree): - s = symbols.SymbolVisitor() - walk(tree, s) - return s.scopes - - def get_module(self): - raise RuntimeError, "should be implemented by subclasses" - - # Next five methods handle name access - - def isLocalName(self, name): - return self.locals.top().has_elt(name) - - def storeName(self, name): - self._nameOp('STORE', name) - - def loadName(self, name): - self._nameOp('LOAD', name) - - def delName(self, name): - self._nameOp('DELETE', name) - - def _nameOp(self, prefix, name): - name = self.mangle(name) - scope = self.scope.check_name(name) - if scope == SC_LOCAL: - if not self.optimized: - self.emit(prefix + '_NAME', name) - else: - self.emit(prefix + '_FAST', name) - elif scope == SC_GLOBAL_EXPLICIT: - self.emit(prefix + '_GLOBAL', name) - elif scope == SC_GLOBAL_IMPLICIT: - if not self.optimized: - self.emit(prefix + '_NAME', name) - else: - self.emit(prefix + '_GLOBAL', name) - elif scope == SC_FREE or scope == SC_CELL: - self.emit(prefix + '_DEREF', name) - else: - raise RuntimeError, "unsupported scope for var %s: %d" % \ - (name, scope) - - def _implicitNameOp(self, prefix, name): - """Emit name ops for names generated implicitly by for loops - - The interpreter generates names that start with a period or - dollar sign. The symbol table ignores these names because - they aren't present in the program text. - """ - if self.optimized: - self.emit(prefix + '_FAST', name) - else: - self.emit(prefix + '_NAME', name) - - # The set_lineno() function and the explicit emit() calls for - # SET_LINENO below are only used to generate the line number table. - # As of Python 2.3, the interpreter does not have a SET_LINENO - # instruction. pyassem treats SET_LINENO opcodes as a special case. - - def set_lineno(self, node, force=False): - """Emit SET_LINENO if necessary. - - The instruction is considered necessary if the node has a - lineno attribute and it is different than the last lineno - emitted. - - Returns true if SET_LINENO was emitted. - - There are no rules for when an AST node should have a lineno - attribute. The transformer and AST code need to be reviewed - and a consistent policy implemented and documented. Until - then, this method works around missing line numbers. - """ - lineno = getattr(node, 'lineno', None) - if lineno is not None and (lineno != self.last_lineno - or force): - self.emit('SET_LINENO', lineno) - self.last_lineno = lineno - return True - return False - - # The first few visitor methods handle nodes that generator new - # code objects. They use class attributes to determine what - # specialized code generators to use. - - NameFinder = LocalNameFinder - FunctionGen = None - ClassGen = None - - def visitModule(self, node): - self.scopes = self.parseSymbols(node) - self.scope = self.scopes[node] - self.emit('SET_LINENO', 0) - if node.doc: - self.emit('LOAD_CONST', node.doc) - self.storeName('__doc__') - lnf = walk(node.node, self.NameFinder(), verbose=0) - self.locals.push(lnf.getLocals()) - self.visit(node.node) - self.emit('LOAD_CONST', None) - self.emit('RETURN_VALUE') - - def visitExpression(self, node): - self.set_lineno(node) - self.scopes = self.parseSymbols(node) - self.scope = self.scopes[node] - self.visit(node.node) - self.emit('RETURN_VALUE') - - def visitFunction(self, node): - self._visitFuncOrLambda(node, isLambda=0) - if node.doc: - self.setDocstring(node.doc) - self.storeName(node.name) - - def visitLambda(self, node): - self._visitFuncOrLambda(node, isLambda=1) - - def _visitFuncOrLambda(self, node, isLambda=0): - if not isLambda and node.decorators: - for decorator in node.decorators.nodes: - self.visit(decorator) - ndecorators = len(node.decorators.nodes) - else: - ndecorators = 0 - - gen = self.FunctionGen(node, self.scopes, isLambda, - self.class_name, self.get_module()) - walk(node.code, gen) - gen.finish() - self.set_lineno(node) - for default in node.defaults: - self.visit(default) - self._makeClosure(gen, len(node.defaults)) - for i in range(ndecorators): - self.emit('CALL_FUNCTION', 1) - - def visitClass(self, node): - gen = self.ClassGen(node, self.scopes, - self.get_module()) - walk(node.code, gen) - gen.finish() - self.set_lineno(node) - self.emit('LOAD_CONST', node.name) - for base in node.bases: - self.visit(base) - self.emit('BUILD_TUPLE', len(node.bases)) - self._makeClosure(gen, 0) - self.emit('CALL_FUNCTION', 0) - self.emit('BUILD_CLASS') - self.storeName(node.name) - - # The rest are standard visitor methods - - # The next few implement control-flow statements - - def visitIf(self, node): - end = self.newBlock() - numtests = len(node.tests) - for i in range(numtests): - test, suite = node.tests[i] - if is_constant_false(test): - # XXX will need to check generator stuff here - continue - self.set_lineno(test) - self.visit(test) - nextTest = self.newBlock() - self.emit('POP_JUMP_IF_FALSE', nextTest) - self.nextBlock() - self.visit(suite) - self.emit('JUMP_FORWARD', end) - self.startBlock(nextTest) - if node.else_: - self.visit(node.else_) - self.nextBlock(end) - - def visitWhile(self, node): - self.set_lineno(node) - - loop = self.newBlock() - else_ = self.newBlock() - - after = self.newBlock() - self.emit('SETUP_LOOP', after) - - self.nextBlock(loop) - self.setups.push((LOOP, loop)) - - self.set_lineno(node, force=True) - self.visit(node.test) - self.emit('POP_JUMP_IF_FALSE', else_ or after) - - self.nextBlock() - self.visit(node.body) - self.emit('JUMP_ABSOLUTE', loop) - - self.startBlock(else_) # or just the POPs if not else clause - self.emit('POP_BLOCK') - self.setups.pop() - if node.else_: - self.visit(node.else_) - self.nextBlock(after) - - def visitFor(self, node): - start = self.newBlock() - anchor = self.newBlock() - after = self.newBlock() - self.setups.push((LOOP, start)) - - self.set_lineno(node) - self.emit('SETUP_LOOP', after) - self.visit(node.list) - self.emit('GET_ITER') - - self.nextBlock(start) - self.set_lineno(node, force=1) - self.emit('FOR_ITER', anchor) - self.visit(node.assign) - self.visit(node.body) - self.emit('JUMP_ABSOLUTE', start) - self.nextBlock(anchor) - self.emit('POP_BLOCK') - self.setups.pop() - if node.else_: - self.visit(node.else_) - self.nextBlock(after) - - def visitBreak(self, node): - if not self.setups: - raise SyntaxError, "'break' outside loop (%s, %d)" % \ - (node.filename, node.lineno) - self.set_lineno(node) - self.emit('BREAK_LOOP') - - def visitContinue(self, node): - if not self.setups: - raise SyntaxError, "'continue' outside loop (%s, %d)" % \ - (node.filename, node.lineno) - kind, block = self.setups.top() - if kind == LOOP: - self.set_lineno(node) - self.emit('JUMP_ABSOLUTE', block) - self.nextBlock() - elif kind == EXCEPT or kind == TRY_FINALLY: - self.set_lineno(node) - # find the block that starts the loop - top = len(self.setups) - while top > 0: - top = top - 1 - kind, loop_block = self.setups[top] - if kind == LOOP: - break - if kind != LOOP: - raise SyntaxError, "'continue' outside loop (%s, %d)" % \ - (node.filename, node.lineno) - self.emit('CONTINUE_LOOP', loop_block) - self.nextBlock() - elif kind == END_FINALLY: - msg = "'continue' not allowed inside 'finally' clause (%s, %d)" - raise SyntaxError, msg % (node.filename, node.lineno) - - def visitTest(self, node, jump): - end = self.newBlock() - for child in node.nodes[:-1]: - self.visit(child) - self.emit(jump, end) - self.nextBlock() - self.visit(node.nodes[-1]) - self.nextBlock(end) - - def visitAnd(self, node): - self.visitTest(node, 'JUMP_IF_FALSE_OR_POP') - - def visitOr(self, node): - self.visitTest(node, 'JUMP_IF_TRUE_OR_POP') - - def visitIfExp(self, node): - endblock = self.newBlock() - elseblock = self.newBlock() - self.visit(node.test) - self.emit('POP_JUMP_IF_FALSE', elseblock) - self.visit(node.then) - self.emit('JUMP_FORWARD', endblock) - self.nextBlock(elseblock) - self.visit(node.else_) - self.nextBlock(endblock) - - def visitCompare(self, node): - self.visit(node.expr) - cleanup = self.newBlock() - for op, code in node.ops[:-1]: - self.visit(code) - self.emit('DUP_TOP') - self.emit('ROT_THREE') - self.emit('COMPARE_OP', op) - self.emit('JUMP_IF_FALSE_OR_POP', cleanup) - self.nextBlock() - # now do the last comparison - if node.ops: - op, code = node.ops[-1] - self.visit(code) - self.emit('COMPARE_OP', op) - if len(node.ops) > 1: - end = self.newBlock() - self.emit('JUMP_FORWARD', end) - self.startBlock(cleanup) - self.emit('ROT_TWO') - self.emit('POP_TOP') - self.nextBlock(end) - - # list comprehensions - def visitListComp(self, node): - self.set_lineno(node) - # setup list - self.emit('BUILD_LIST', 0) - - stack = [] - for i, for_ in zip(range(len(node.quals)), node.quals): - start, anchor = self.visit(for_) - cont = None - for if_ in for_.ifs: - if cont is None: - cont = self.newBlock() - self.visit(if_, cont) - stack.insert(0, (start, cont, anchor)) - - self.visit(node.expr) - self.emit('LIST_APPEND', len(node.quals) + 1) - - for start, cont, anchor in stack: - if cont: - self.nextBlock(cont) - self.emit('JUMP_ABSOLUTE', start) - self.startBlock(anchor) - - def visitSetComp(self, node): - self.set_lineno(node) - # setup list - self.emit('BUILD_SET', 0) - - stack = [] - for i, for_ in zip(range(len(node.quals)), node.quals): - start, anchor = self.visit(for_) - cont = None - for if_ in for_.ifs: - if cont is None: - cont = self.newBlock() - self.visit(if_, cont) - stack.insert(0, (start, cont, anchor)) - - self.visit(node.expr) - self.emit('SET_ADD', len(node.quals) + 1) - - for start, cont, anchor in stack: - if cont: - self.nextBlock(cont) - self.emit('JUMP_ABSOLUTE', start) - self.startBlock(anchor) - - def visitDictComp(self, node): - self.set_lineno(node) - # setup list - self.emit('BUILD_MAP', 0) - - stack = [] - for i, for_ in zip(range(len(node.quals)), node.quals): - start, anchor = self.visit(for_) - cont = None - for if_ in for_.ifs: - if cont is None: - cont = self.newBlock() - self.visit(if_, cont) - stack.insert(0, (start, cont, anchor)) - - self.visit(node.value) - self.visit(node.key) - self.emit('MAP_ADD', len(node.quals) + 1) - - for start, cont, anchor in stack: - if cont: - self.nextBlock(cont) - self.emit('JUMP_ABSOLUTE', start) - self.startBlock(anchor) - - def visitListCompFor(self, node): - start = self.newBlock() - anchor = self.newBlock() - - self.visit(node.list) - self.emit('GET_ITER') - self.nextBlock(start) - self.set_lineno(node, force=True) - self.emit('FOR_ITER', anchor) - self.nextBlock() - self.visit(node.assign) - return start, anchor - - def visitListCompIf(self, node, branch): - self.set_lineno(node, force=True) - self.visit(node.test) - self.emit('POP_JUMP_IF_FALSE', branch) - self.newBlock() - - def _makeClosure(self, gen, args): - frees = gen.scope.get_free_vars() - if frees: - for name in frees: - self.emit('LOAD_CLOSURE', name) - self.emit('BUILD_TUPLE', len(frees)) - self.emit('LOAD_CONST', gen) - self.emit('MAKE_CLOSURE', args) - else: - self.emit('LOAD_CONST', gen) - self.emit('MAKE_FUNCTION', args) - - def visitGenExpr(self, node): - gen = GenExprCodeGenerator(node, self.scopes, self.class_name, - self.get_module()) - walk(node.code, gen) - gen.finish() - self.set_lineno(node) - self._makeClosure(gen, 0) - # precomputation of outmost iterable - self.visit(node.code.quals[0].iter) - self.emit('GET_ITER') - self.emit('CALL_FUNCTION', 1) - - def visitGenExprInner(self, node): - self.set_lineno(node) - # setup list - - stack = [] - for i, for_ in zip(range(len(node.quals)), node.quals): - start, anchor, end = self.visit(for_) - cont = None - for if_ in for_.ifs: - if cont is None: - cont = self.newBlock() - self.visit(if_, cont) - stack.insert(0, (start, cont, anchor, end)) - - self.visit(node.expr) - self.emit('YIELD_VALUE') - self.emit('POP_TOP') - - for start, cont, anchor, end in stack: - if cont: - self.nextBlock(cont) - self.emit('JUMP_ABSOLUTE', start) - self.startBlock(anchor) - self.emit('POP_BLOCK') - self.setups.pop() - self.nextBlock(end) - - self.emit('LOAD_CONST', None) - - def visitGenExprFor(self, node): - start = self.newBlock() - anchor = self.newBlock() - end = self.newBlock() - - self.setups.push((LOOP, start)) - self.emit('SETUP_LOOP', end) - - if node.is_outmost: - self.loadName('.0') - else: - self.visit(node.iter) - self.emit('GET_ITER') - - self.nextBlock(start) - self.set_lineno(node, force=True) - self.emit('FOR_ITER', anchor) - self.nextBlock() - self.visit(node.assign) - return start, anchor, end - - def visitGenExprIf(self, node, branch): - self.set_lineno(node, force=True) - self.visit(node.test) - self.emit('POP_JUMP_IF_FALSE', branch) - self.newBlock() - - # exception related - - def visitAssert(self, node): - # XXX would be interesting to implement this via a - # transformation of the AST before this stage - if __debug__: - end = self.newBlock() - self.set_lineno(node) - # XXX AssertionError appears to be special case -- it is always - # loaded as a global even if there is a local name. I guess this - # is a sort of renaming op. - self.nextBlock() - self.visit(node.test) - self.emit('POP_JUMP_IF_TRUE', end) - self.nextBlock() - self.emit('LOAD_GLOBAL', 'AssertionError') - if node.fail: - self.visit(node.fail) - self.emit('RAISE_VARARGS', 2) - else: - self.emit('RAISE_VARARGS', 1) - self.nextBlock(end) - - def visitRaise(self, node): - self.set_lineno(node) - n = 0 - if node.expr1: - self.visit(node.expr1) - n = n + 1 - if node.expr2: - self.visit(node.expr2) - n = n + 1 - if node.expr3: - self.visit(node.expr3) - n = n + 1 - self.emit('RAISE_VARARGS', n) - - def visitTryExcept(self, node): - body = self.newBlock() - handlers = self.newBlock() - end = self.newBlock() - if node.else_: - lElse = self.newBlock() - else: - lElse = end - self.set_lineno(node) - self.emit('SETUP_EXCEPT', handlers) - self.nextBlock(body) - self.setups.push((EXCEPT, body)) - self.visit(node.body) - self.emit('POP_BLOCK') - self.setups.pop() - self.emit('JUMP_FORWARD', lElse) - self.startBlock(handlers) - - last = len(node.handlers) - 1 - for i in range(len(node.handlers)): - expr, target, body = node.handlers[i] - self.set_lineno(expr) - if expr: - self.emit('DUP_TOP') - self.visit(expr) - self.emit('COMPARE_OP', 'exception match') - next = self.newBlock() - self.emit('POP_JUMP_IF_FALSE', next) - self.nextBlock() - self.emit('POP_TOP') - if target: - self.visit(target) - else: - self.emit('POP_TOP') - self.emit('POP_TOP') - self.visit(body) - self.emit('JUMP_FORWARD', end) - if expr: - self.nextBlock(next) - else: - self.nextBlock() - self.emit('END_FINALLY') - if node.else_: - self.nextBlock(lElse) - self.visit(node.else_) - self.nextBlock(end) - - def visitTryFinally(self, node): - body = self.newBlock() - final = self.newBlock() - self.set_lineno(node) - self.emit('SETUP_FINALLY', final) - self.nextBlock(body) - self.setups.push((TRY_FINALLY, body)) - self.visit(node.body) - self.emit('POP_BLOCK') - self.setups.pop() - self.emit('LOAD_CONST', None) - self.nextBlock(final) - self.setups.push((END_FINALLY, final)) - self.visit(node.final) - self.emit('END_FINALLY') - self.setups.pop() - - __with_count = 0 - - def visitWith(self, node): - body = self.newBlock() - final = self.newBlock() - self.__with_count += 1 - valuevar = "_[%d]" % self.__with_count - self.set_lineno(node) - self.visit(node.expr) - self.emit('DUP_TOP') - self.emit('LOAD_ATTR', '__exit__') - self.emit('ROT_TWO') - self.emit('LOAD_ATTR', '__enter__') - self.emit('CALL_FUNCTION', 0) - if node.vars is None: - self.emit('POP_TOP') - else: - self._implicitNameOp('STORE', valuevar) - self.emit('SETUP_FINALLY', final) - self.nextBlock(body) - self.setups.push((TRY_FINALLY, body)) - if node.vars is not None: - self._implicitNameOp('LOAD', valuevar) - self._implicitNameOp('DELETE', valuevar) - self.visit(node.vars) - self.visit(node.body) - self.emit('POP_BLOCK') - self.setups.pop() - self.emit('LOAD_CONST', None) - self.nextBlock(final) - self.setups.push((END_FINALLY, final)) - self.emit('WITH_CLEANUP') - self.emit('END_FINALLY') - self.setups.pop() - self.__with_count -= 1 - - # misc - - def visitDiscard(self, node): - self.set_lineno(node) - self.visit(node.expr) - self.emit('POP_TOP') - - def visitConst(self, node): - self.emit('LOAD_CONST', node.value) - - def visitKeyword(self, node): - self.emit('LOAD_CONST', node.name) - self.visit(node.expr) - - def visitGlobal(self, node): - # no code to generate - pass - - def visitName(self, node): - self.set_lineno(node) - self.loadName(node.name) - - def visitPass(self, node): - self.set_lineno(node) - - def visitImport(self, node): - self.set_lineno(node) - level = 0 if self.graph.checkFlag(CO_FUTURE_ABSIMPORT) else -1 - for name, alias in node.names: - if VERSION > 1: - self.emit('LOAD_CONST', level) - self.emit('LOAD_CONST', None) - self.emit('IMPORT_NAME', name) - mod = name.split(".")[0] - if alias: - self._resolveDots(name) - self.storeName(alias) - else: - self.storeName(mod) - - def visitFrom(self, node): - self.set_lineno(node) - level = node.level - if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT): - level = -1 - fromlist = tuple(name for (name, alias) in node.names) - if VERSION > 1: - self.emit('LOAD_CONST', level) - self.emit('LOAD_CONST', fromlist) - self.emit('IMPORT_NAME', node.modname) - for name, alias in node.names: - if VERSION > 1: - if name == '*': - self.namespace = 0 - self.emit('IMPORT_STAR') - # There can only be one name w/ from ... import * - assert len(node.names) == 1 - return - else: - self.emit('IMPORT_FROM', name) - self._resolveDots(name) - self.storeName(alias or name) - else: - self.emit('IMPORT_FROM', name) - self.emit('POP_TOP') - - def _resolveDots(self, name): - elts = name.split(".") - if len(elts) == 1: - return - for elt in elts[1:]: - self.emit('LOAD_ATTR', elt) - - def visitGetattr(self, node): - self.visit(node.expr) - self.emit('LOAD_ATTR', self.mangle(node.attrname)) - - # next five implement assignments - - def visitAssign(self, node): - self.set_lineno(node) - self.visit(node.expr) - dups = len(node.nodes) - 1 - for i in range(len(node.nodes)): - elt = node.nodes[i] - if i < dups: - self.emit('DUP_TOP') - if isinstance(elt, ast.Node): - self.visit(elt) - - def visitAssName(self, node): - if node.flags == 'OP_ASSIGN': - self.storeName(node.name) - elif node.flags == 'OP_DELETE': - self.set_lineno(node) - self.delName(node.name) - else: - print "oops", node.flags - - def visitAssAttr(self, node): - self.visit(node.expr) - if node.flags == 'OP_ASSIGN': - self.emit('STORE_ATTR', self.mangle(node.attrname)) - elif node.flags == 'OP_DELETE': - self.emit('DELETE_ATTR', self.mangle(node.attrname)) - else: - print "warning: unexpected flags:", node.flags - print node - - def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'): - if findOp(node) != 'OP_DELETE': - self.emit(op, len(node.nodes)) - for child in node.nodes: - self.visit(child) - - if VERSION > 1: - visitAssTuple = _visitAssSequence - visitAssList = _visitAssSequence - else: - def visitAssTuple(self, node): - self._visitAssSequence(node, 'UNPACK_TUPLE') - - def visitAssList(self, node): - self._visitAssSequence(node, 'UNPACK_LIST') - - # augmented assignment - - def visitAugAssign(self, node): - self.set_lineno(node) - aug_node = wrap_aug(node.node) - self.visit(aug_node, "load") - self.visit(node.expr) - self.emit(self._augmented_opcode[node.op]) - self.visit(aug_node, "store") - - _augmented_opcode = { - '+=' : 'INPLACE_ADD', - '-=' : 'INPLACE_SUBTRACT', - '*=' : 'INPLACE_MULTIPLY', - '/=' : 'INPLACE_DIVIDE', - '//=': 'INPLACE_FLOOR_DIVIDE', - '%=' : 'INPLACE_MODULO', - '**=': 'INPLACE_POWER', - '>>=': 'INPLACE_RSHIFT', - '<<=': 'INPLACE_LSHIFT', - '&=' : 'INPLACE_AND', - '^=' : 'INPLACE_XOR', - '|=' : 'INPLACE_OR', - } - - def visitAugName(self, node, mode): - if mode == "load": - self.loadName(node.name) - elif mode == "store": - self.storeName(node.name) - - def visitAugGetattr(self, node, mode): - if mode == "load": - self.visit(node.expr) - self.emit('DUP_TOP') - self.emit('LOAD_ATTR', self.mangle(node.attrname)) - elif mode == "store": - self.emit('ROT_TWO') - self.emit('STORE_ATTR', self.mangle(node.attrname)) - - def visitAugSlice(self, node, mode): - if mode == "load": - self.visitSlice(node, 1) - elif mode == "store": - slice = 0 - if node.lower: - slice = slice | 1 - if node.upper: - slice = slice | 2 - if slice == 0: - self.emit('ROT_TWO') - elif slice == 3: - self.emit('ROT_FOUR') - else: - self.emit('ROT_THREE') - self.emit('STORE_SLICE+%d' % slice) - - def visitAugSubscript(self, node, mode): - if mode == "load": - self.visitSubscript(node, 1) - elif mode == "store": - self.emit('ROT_THREE') - self.emit('STORE_SUBSCR') - - def visitExec(self, node): - self.visit(node.expr) - if node.locals is None: - self.emit('LOAD_CONST', None) - else: - self.visit(node.locals) - if node.globals is None: - self.emit('DUP_TOP') - else: - self.visit(node.globals) - self.emit('EXEC_STMT') - - def visitCallFunc(self, node): - pos = 0 - kw = 0 - self.set_lineno(node) - self.visit(node.node) - for arg in node.args: - self.visit(arg) - if isinstance(arg, ast.Keyword): - kw = kw + 1 - else: - pos = pos + 1 - if node.star_args is not None: - self.visit(node.star_args) - if node.dstar_args is not None: - self.visit(node.dstar_args) - have_star = node.star_args is not None - have_dstar = node.dstar_args is not None - opcode = callfunc_opcode_info[have_star, have_dstar] - self.emit(opcode, kw << 8 | pos) - - def visitPrint(self, node, newline=0): - self.set_lineno(node) - if node.dest: - self.visit(node.dest) - for child in node.nodes: - if node.dest: - self.emit('DUP_TOP') - self.visit(child) - if node.dest: - self.emit('ROT_TWO') - self.emit('PRINT_ITEM_TO') - else: - self.emit('PRINT_ITEM') - if node.dest and not newline: - self.emit('POP_TOP') - - def visitPrintnl(self, node): - self.visitPrint(node, newline=1) - if node.dest: - self.emit('PRINT_NEWLINE_TO') - else: - self.emit('PRINT_NEWLINE') - - def visitReturn(self, node): - self.set_lineno(node) - self.visit(node.value) - self.emit('RETURN_VALUE') - - def visitYield(self, node): - self.set_lineno(node) - self.visit(node.value) - self.emit('YIELD_VALUE') - - # slice and subscript stuff - - def visitSlice(self, node, aug_flag=None): - # aug_flag is used by visitAugSlice - self.visit(node.expr) - slice = 0 - if node.lower: - self.visit(node.lower) - slice = slice | 1 - if node.upper: - self.visit(node.upper) - slice = slice | 2 - if aug_flag: - if slice == 0: - self.emit('DUP_TOP') - elif slice == 3: - self.emit('DUP_TOPX', 3) - else: - self.emit('DUP_TOPX', 2) - if node.flags == 'OP_APPLY': - self.emit('SLICE+%d' % slice) - elif node.flags == 'OP_ASSIGN': - self.emit('STORE_SLICE+%d' % slice) - elif node.flags == 'OP_DELETE': - self.emit('DELETE_SLICE+%d' % slice) - else: - print "weird slice", node.flags - raise - - def visitSubscript(self, node, aug_flag=None): - self.visit(node.expr) - for sub in node.subs: - self.visit(sub) - if len(node.subs) > 1: - self.emit('BUILD_TUPLE', len(node.subs)) - if aug_flag: - self.emit('DUP_TOPX', 2) - if node.flags == 'OP_APPLY': - self.emit('BINARY_SUBSCR') - elif node.flags == 'OP_ASSIGN': - self.emit('STORE_SUBSCR') - elif node.flags == 'OP_DELETE': - self.emit('DELETE_SUBSCR') - - # binary ops - - def binaryOp(self, node, op): - self.visit(node.left) - self.visit(node.right) - self.emit(op) - - def visitAdd(self, node): - return self.binaryOp(node, 'BINARY_ADD') - - def visitSub(self, node): - return self.binaryOp(node, 'BINARY_SUBTRACT') - - def visitMul(self, node): - return self.binaryOp(node, 'BINARY_MULTIPLY') - - def visitDiv(self, node): - return self.binaryOp(node, self._div_op) - - def visitFloorDiv(self, node): - return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE') - - def visitMod(self, node): - return self.binaryOp(node, 'BINARY_MODULO') - - def visitPower(self, node): - return self.binaryOp(node, 'BINARY_POWER') - - def visitLeftShift(self, node): - return self.binaryOp(node, 'BINARY_LSHIFT') - - def visitRightShift(self, node): - return self.binaryOp(node, 'BINARY_RSHIFT') - - # unary ops - - def unaryOp(self, node, op): - self.visit(node.expr) - self.emit(op) - - def visitInvert(self, node): - return self.unaryOp(node, 'UNARY_INVERT') - - def visitUnarySub(self, node): - return self.unaryOp(node, 'UNARY_NEGATIVE') - - def visitUnaryAdd(self, node): - return self.unaryOp(node, 'UNARY_POSITIVE') - - def visitUnaryInvert(self, node): - return self.unaryOp(node, 'UNARY_INVERT') - - def visitNot(self, node): - return self.unaryOp(node, 'UNARY_NOT') - - def visitBackquote(self, node): - return self.unaryOp(node, 'UNARY_CONVERT') - - # bit ops - - def bitOp(self, nodes, op): - self.visit(nodes[0]) - for node in nodes[1:]: - self.visit(node) - self.emit(op) - - def visitBitand(self, node): - return self.bitOp(node.nodes, 'BINARY_AND') - - def visitBitor(self, node): - return self.bitOp(node.nodes, 'BINARY_OR') - - def visitBitxor(self, node): - return self.bitOp(node.nodes, 'BINARY_XOR') - - # object constructors - - def visitEllipsis(self, node): - self.emit('LOAD_CONST', Ellipsis) - - def visitTuple(self, node): - self.set_lineno(node) - for elt in node.nodes: - self.visit(elt) - self.emit('BUILD_TUPLE', len(node.nodes)) - - def visitList(self, node): - self.set_lineno(node) - for elt in node.nodes: - self.visit(elt) - self.emit('BUILD_LIST', len(node.nodes)) - - def visitSet(self, node): - self.set_lineno(node) - for elt in node.nodes: - self.visit(elt) - self.emit('BUILD_SET', len(node.nodes)) - - def visitSliceobj(self, node): - for child in node.nodes: - self.visit(child) - self.emit('BUILD_SLICE', len(node.nodes)) - - def visitDict(self, node): - self.set_lineno(node) - self.emit('BUILD_MAP', 0) - for k, v in node.items: - self.emit('DUP_TOP') - self.visit(k) - self.visit(v) - self.emit('ROT_THREE') - self.emit('STORE_SUBSCR') - -class NestedScopeMixin: - """Defines initClass() for nested scoping (Python 2.2-compatible)""" - def initClass(self): - self.__class__.NameFinder = LocalNameFinder - self.__class__.FunctionGen = FunctionCodeGenerator - self.__class__.ClassGen = ClassCodeGenerator - -class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator): - __super_init = CodeGenerator.__init__ - - scopes = None - - def __init__(self, tree): - self.graph = pyassem.PyFlowGraph("<module>", tree.filename) - self.futures = future.find_futures(tree) - self.__super_init() - walk(tree, self) - - def get_module(self): - return self - -class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator): - __super_init = CodeGenerator.__init__ - - scopes = None - futures = () - - def __init__(self, tree): - self.graph = pyassem.PyFlowGraph("<expression>", tree.filename) - self.__super_init() - walk(tree, self) - - def get_module(self): - return self - -class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator): - - __super_init = CodeGenerator.__init__ - - scopes = None - futures = () - - def __init__(self, tree): - self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename) - self.__super_init() - self.set_lineno(tree) - walk(tree, self) - self.emit('RETURN_VALUE') - - def get_module(self): - return self - - def visitDiscard(self, node): - # XXX Discard means it's an expression. Perhaps this is a bad - # name. - self.visit(node.expr) - self.emit('PRINT_EXPR') - -class AbstractFunctionCode: - optimized = 1 - lambdaCount = 0 - - def __init__(self, func, scopes, isLambda, class_name, mod): - self.class_name = class_name - self.module = mod - if isLambda: - klass = FunctionCodeGenerator - name = "<lambda.%d>" % klass.lambdaCount - klass.lambdaCount = klass.lambdaCount + 1 - else: - name = func.name - - args, hasTupleArg = generateArgList(func.argnames) - self.graph = pyassem.PyFlowGraph(name, func.filename, args, - optimized=1) - self.isLambda = isLambda - self.super_init() - - if not isLambda and func.doc: - self.setDocstring(func.doc) - - lnf = walk(func.code, self.NameFinder(args), verbose=0) - self.locals.push(lnf.getLocals()) - if func.varargs: - self.graph.setFlag(CO_VARARGS) - if func.kwargs: - self.graph.setFlag(CO_VARKEYWORDS) - self.set_lineno(func) - if hasTupleArg: - self.generateArgUnpack(func.argnames) - - def get_module(self): - return self.module - - def finish(self): - self.graph.startExitBlock() - if not self.isLambda: - self.emit('LOAD_CONST', None) - self.emit('RETURN_VALUE') - - def generateArgUnpack(self, args): - for i in range(len(args)): - arg = args[i] - if isinstance(arg, tuple): - self.emit('LOAD_FAST', '.%d' % (i * 2)) - self.unpackSequence(arg) - - def unpackSequence(self, tup): - if VERSION > 1: - self.emit('UNPACK_SEQUENCE', len(tup)) - else: - self.emit('UNPACK_TUPLE', len(tup)) - for elt in tup: - if isinstance(elt, tuple): - self.unpackSequence(elt) - else: - self._nameOp('STORE', elt) - - unpackTuple = unpackSequence - -class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode, - CodeGenerator): - super_init = CodeGenerator.__init__ # call be other init - scopes = None - - __super_init = AbstractFunctionCode.__init__ - - def __init__(self, func, scopes, isLambda, class_name, mod): - self.scopes = scopes - self.scope = scopes[func] - self.__super_init(func, scopes, isLambda, class_name, mod) - self.graph.setFreeVars(self.scope.get_free_vars()) - self.graph.setCellVars(self.scope.get_cell_vars()) - if self.scope.generator is not None: - self.graph.setFlag(CO_GENERATOR) - -class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode, - CodeGenerator): - super_init = CodeGenerator.__init__ # call be other init - scopes = None - - __super_init = AbstractFunctionCode.__init__ - - def __init__(self, gexp, scopes, class_name, mod): - self.scopes = scopes - self.scope = scopes[gexp] - self.__super_init(gexp, scopes, 1, class_name, mod) - self.graph.setFreeVars(self.scope.get_free_vars()) - self.graph.setCellVars(self.scope.get_cell_vars()) - self.graph.setFlag(CO_GENERATOR) - -class AbstractClassCode: - - def __init__(self, klass, scopes, module): - self.class_name = klass.name - self.module = module - self.graph = pyassem.PyFlowGraph(klass.name, klass.filename, - optimized=0, klass=1) - self.super_init() - lnf = walk(klass.code, self.NameFinder(), verbose=0) - self.locals.push(lnf.getLocals()) - self.graph.setFlag(CO_NEWLOCALS) - if klass.doc: - self.setDocstring(klass.doc) - - def get_module(self): - return self.module - - def finish(self): - self.graph.startExitBlock() - self.emit('LOAD_LOCALS') - self.emit('RETURN_VALUE') - -class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator): - super_init = CodeGenerator.__init__ - scopes = None - - __super_init = AbstractClassCode.__init__ - - def __init__(self, klass, scopes, module): - self.scopes = scopes - self.scope = scopes[klass] - self.__super_init(klass, scopes, module) - self.graph.setFreeVars(self.scope.get_free_vars()) - self.graph.setCellVars(self.scope.get_cell_vars()) - self.set_lineno(klass) - self.emit("LOAD_GLOBAL", "__name__") - self.storeName("__module__") - if klass.doc: - self.emit("LOAD_CONST", klass.doc) - self.storeName('__doc__') - -def generateArgList(arglist): - """Generate an arg list marking TupleArgs""" - args = [] - extra = [] - count = 0 - for i in range(len(arglist)): - elt = arglist[i] - if isinstance(elt, str): - args.append(elt) - elif isinstance(elt, tuple): - args.append(TupleArg(i * 2, elt)) - extra.extend(misc.flatten(elt)) - count = count + 1 - else: - raise ValueError, "unexpect argument type:", elt - return args + extra, count - -def findOp(node): - """Find the op (DELETE, LOAD, STORE) in an AssTuple tree""" - v = OpFinder() - walk(node, v, verbose=0) - return v.op - -class OpFinder: - def __init__(self): - self.op = None - def visitAssName(self, node): - if self.op is None: - self.op = node.flags - elif self.op != node.flags: - raise ValueError, "mixed ops in stmt" - visitAssAttr = visitAssName - visitSubscript = visitAssName - -class Delegator: - """Base class to support delegation for augmented assignment nodes - - To generator code for augmented assignments, we use the following - wrapper classes. In visitAugAssign, the left-hand expression node - is visited twice. The first time the visit uses the normal method - for that node . The second time the visit uses a different method - that generates the appropriate code to perform the assignment. - These delegator classes wrap the original AST nodes in order to - support the variant visit methods. - """ - def __init__(self, obj): - self.obj = obj - - def __getattr__(self, attr): - return getattr(self.obj, attr) - -class AugGetattr(Delegator): - pass - -class AugName(Delegator): - pass - -class AugSlice(Delegator): - pass - -class AugSubscript(Delegator): - pass - -wrapper = { - ast.Getattr: AugGetattr, - ast.Name: AugName, - ast.Slice: AugSlice, - ast.Subscript: AugSubscript, - } - -def wrap_aug(node): - return wrapper[node.__class__](node) - -if __name__ == "__main__": - for file in sys.argv[1:]: - compileFile(file) diff --git a/lib/python2.7/compiler/symbols.py b/lib/python2.7/compiler/symbols.py deleted file mode 100644 index afeec50..0000000 --- a/lib/python2.7/compiler/symbols.py +++ /dev/null @@ -1,462 +0,0 @@ -"""Module symbol-table generator""" - -from compiler import ast -from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \ - SC_FREE, SC_CELL, SC_UNKNOWN -from compiler.misc import mangle -import types - - -import sys - -MANGLE_LEN = 256 - -class Scope: - # XXX how much information do I need about each name? - def __init__(self, name, module, klass=None): - self.name = name - self.module = module - self.defs = {} - self.uses = {} - self.globals = {} - self.params = {} - self.frees = {} - self.cells = {} - self.children = [] - # nested is true if the class could contain free variables, - # i.e. if it is nested within another function. - self.nested = None - self.generator = None - self.klass = None - if klass is not None: - for i in range(len(klass)): - if klass[i] != '_': - self.klass = klass[i:] - break - - def __repr__(self): - return "<%s: %s>" % (self.__class__.__name__, self.name) - - def mangle(self, name): - if self.klass is None: - return name - return mangle(name, self.klass) - - def add_def(self, name): - self.defs[self.mangle(name)] = 1 - - def add_use(self, name): - self.uses[self.mangle(name)] = 1 - - def add_global(self, name): - name = self.mangle(name) - if name in self.uses or name in self.defs: - pass # XXX warn about global following def/use - if name in self.params: - raise SyntaxError, "%s in %s is global and parameter" % \ - (name, self.name) - self.globals[name] = 1 - self.module.add_def(name) - - def add_param(self, name): - name = self.mangle(name) - self.defs[name] = 1 - self.params[name] = 1 - - def get_names(self): - d = {} - d.update(self.defs) - d.update(self.uses) - d.update(self.globals) - return d.keys() - - def add_child(self, child): - self.children.append(child) - - def get_children(self): - return self.children - - def DEBUG(self): - print >> sys.stderr, self.name, self.nested and "nested" or "" - print >> sys.stderr, "\tglobals: ", self.globals - print >> sys.stderr, "\tcells: ", self.cells - print >> sys.stderr, "\tdefs: ", self.defs - print >> sys.stderr, "\tuses: ", self.uses - print >> sys.stderr, "\tfrees:", self.frees - - def check_name(self, name): - """Return scope of name. - - The scope of a name could be LOCAL, GLOBAL, FREE, or CELL. - """ - if name in self.globals: - return SC_GLOBAL_EXPLICIT - if name in self.cells: - return SC_CELL - if name in self.defs: - return SC_LOCAL - if self.nested and (name in self.frees or name in self.uses): - return SC_FREE - if self.nested: - return SC_UNKNOWN - else: - return SC_GLOBAL_IMPLICIT - - def get_free_vars(self): - if not self.nested: - return () - free = {} - free.update(self.frees) - for name in self.uses.keys(): - if name not in self.defs and name not in self.globals: - free[name] = 1 - return free.keys() - - def handle_children(self): - for child in self.children: - frees = child.get_free_vars() - globals = self.add_frees(frees) - for name in globals: - child.force_global(name) - - def force_global(self, name): - """Force name to be global in scope. - - Some child of the current node had a free reference to name. - When the child was processed, it was labelled a free - variable. Now that all its enclosing scope have been - processed, the name is known to be a global or builtin. So - walk back down the child chain and set the name to be global - rather than free. - - Be careful to stop if a child does not think the name is - free. - """ - self.globals[name] = 1 - if name in self.frees: - del self.frees[name] - for child in self.children: - if child.check_name(name) == SC_FREE: - child.force_global(name) - - def add_frees(self, names): - """Process list of free vars from nested scope. - - Returns a list of names that are either 1) declared global in the - parent or 2) undefined in a top-level parent. In either case, - the nested scope should treat them as globals. - """ - child_globals = [] - for name in names: - sc = self.check_name(name) - if self.nested: - if sc == SC_UNKNOWN or sc == SC_FREE \ - or isinstance(self, ClassScope): - self.frees[name] = 1 - elif sc == SC_GLOBAL_IMPLICIT: - child_globals.append(name) - elif isinstance(self, FunctionScope) and sc == SC_LOCAL: - self.cells[name] = 1 - elif sc != SC_CELL: - child_globals.append(name) - else: - if sc == SC_LOCAL: - self.cells[name] = 1 - elif sc != SC_CELL: - child_globals.append(name) - return child_globals - - def get_cell_vars(self): - return self.cells.keys() - -class ModuleScope(Scope): - __super_init = Scope.__init__ - - def __init__(self): - self.__super_init("global", self) - -class FunctionScope(Scope): - pass - -class GenExprScope(Scope): - __super_init = Scope.__init__ - - __counter = 1 - - def __init__(self, module, klass=None): - i = self.__counter - self.__counter += 1 - self.__super_init("generator expression<%d>"%i, module, klass) - self.add_param('.0') - - def get_names(self): - keys = Scope.get_names(self) - return keys - -class LambdaScope(FunctionScope): - __super_init = Scope.__init__ - - __counter = 1 - - def __init__(self, module, klass=None): - i = self.__counter - self.__counter += 1 - self.__super_init("lambda.%d" % i, module, klass) - -class ClassScope(Scope): - __super_init = Scope.__init__ - - def __init__(self, name, module): - self.__super_init(name, module, name) - -class SymbolVisitor: - def __init__(self): - self.scopes = {} - self.klass = None - - # node that define new scopes - - def visitModule(self, node): - scope = self.module = self.scopes[node] = ModuleScope() - self.visit(node.node, scope) - - visitExpression = visitModule - - def visitFunction(self, node, parent): - if node.decorators: - self.visit(node.decorators, parent) - parent.add_def(node.name) - for n in node.defaults: - self.visit(n, parent) - scope = FunctionScope(node.name, self.module, self.klass) - if parent.nested or isinstance(parent, FunctionScope): - scope.nested = 1 - self.scopes[node] = scope - self._do_args(scope, node.argnames) - self.visit(node.code, scope) - self.handle_free_vars(scope, parent) - - def visitGenExpr(self, node, parent): - scope = GenExprScope(self.module, self.klass); - if parent.nested or isinstance(parent, FunctionScope) \ - or isinstance(parent, GenExprScope): - scope.nested = 1 - - self.scopes[node] = scope - self.visit(node.code, scope) - - self.handle_free_vars(scope, parent) - - def visitGenExprInner(self, node, scope): - for genfor in node.quals: - self.visit(genfor, scope) - - self.visit(node.expr, scope) - - def visitGenExprFor(self, node, scope): - self.visit(node.assign, scope, 1) - self.visit(node.iter, scope) - for if_ in node.ifs: - self.visit(if_, scope) - - def visitGenExprIf(self, node, scope): - self.visit(node.test, scope) - - def visitLambda(self, node, parent, assign=0): - # Lambda is an expression, so it could appear in an expression - # context where assign is passed. The transformer should catch - # any code that has a lambda on the left-hand side. - assert not assign - - for n in node.defaults: - self.visit(n, parent) - scope = LambdaScope(self.module, self.klass) - if parent.nested or isinstance(parent, FunctionScope): - scope.nested = 1 - self.scopes[node] = scope - self._do_args(scope, node.argnames) - self.visit(node.code, scope) - self.handle_free_vars(scope, parent) - - def _do_args(self, scope, args): - for name in args: - if type(name) == types.TupleType: - self._do_args(scope, name) - else: - scope.add_param(name) - - def handle_free_vars(self, scope, parent): - parent.add_child(scope) - scope.handle_children() - - def visitClass(self, node, parent): - parent.add_def(node.name) - for n in node.bases: - self.visit(n, parent) - scope = ClassScope(node.name, self.module) - if parent.nested or isinstance(parent, FunctionScope): - scope.nested = 1 - if node.doc is not None: - scope.add_def('__doc__') - scope.add_def('__module__') - self.scopes[node] = scope - prev = self.klass - self.klass = node.name - self.visit(node.code, scope) - self.klass = prev - self.handle_free_vars(scope, parent) - - # name can be a def or a use - - # XXX a few calls and nodes expect a third "assign" arg that is - # true if the name is being used as an assignment. only - # expressions contained within statements may have the assign arg. - - def visitName(self, node, scope, assign=0): - if assign: - scope.add_def(node.name) - else: - scope.add_use(node.name) - - # operations that bind new names - - def visitFor(self, node, scope): - self.visit(node.assign, scope, 1) - self.visit(node.list, scope) - self.visit(node.body, scope) - if node.else_: - self.visit(node.else_, scope) - - def visitFrom(self, node, scope): - for name, asname in node.names: - if name == "*": - continue - scope.add_def(asname or name) - - def visitImport(self, node, scope): - for name, asname in node.names: - i = name.find(".") - if i > -1: - name = name[:i] - scope.add_def(asname or name) - - def visitGlobal(self, node, scope): - for name in node.names: - scope.add_global(name) - - def visitAssign(self, node, scope): - """Propagate assignment flag down to child nodes. - - The Assign node doesn't itself contains the variables being - assigned to. Instead, the children in node.nodes are visited - with the assign flag set to true. When the names occur in - those nodes, they are marked as defs. - - Some names that occur in an assignment target are not bound by - the assignment, e.g. a name occurring inside a slice. The - visitor handles these nodes specially; they do not propagate - the assign flag to their children. - """ - for n in node.nodes: - self.visit(n, scope, 1) - self.visit(node.expr, scope) - - def visitAssName(self, node, scope, assign=1): - scope.add_def(node.name) - - def visitAssAttr(self, node, scope, assign=0): - self.visit(node.expr, scope, 0) - - def visitSubscript(self, node, scope, assign=0): - self.visit(node.expr, scope, 0) - for n in node.subs: - self.visit(n, scope, 0) - - def visitSlice(self, node, scope, assign=0): - self.visit(node.expr, scope, 0) - if node.lower: - self.visit(node.lower, scope, 0) - if node.upper: - self.visit(node.upper, scope, 0) - - def visitAugAssign(self, node, scope): - # If the LHS is a name, then this counts as assignment. - # Otherwise, it's just use. - self.visit(node.node, scope) - if isinstance(node.node, ast.Name): - self.visit(node.node, scope, 1) # XXX worry about this - self.visit(node.expr, scope) - - # prune if statements if tests are false - - _const_types = types.StringType, types.IntType, types.FloatType - - def visitIf(self, node, scope): - for test, body in node.tests: - if isinstance(test, ast.Const): - if type(test.value) in self._const_types: - if not test.value: - continue - self.visit(test, scope) - self.visit(body, scope) - if node.else_: - self.visit(node.else_, scope) - - # a yield statement signals a generator - - def visitYield(self, node, scope): - scope.generator = 1 - self.visit(node.value, scope) - -def list_eq(l1, l2): - return sorted(l1) == sorted(l2) - -if __name__ == "__main__": - import sys - from compiler import parseFile, walk - import symtable - - def get_names(syms): - return [s for s in [s.get_name() for s in syms.get_symbols()] - if not (s.startswith('_[') or s.startswith('.'))] - - for file in sys.argv[1:]: - print file - f = open(file) - buf = f.read() - f.close() - syms = symtable.symtable(buf, file, "exec") - mod_names = get_names(syms) - tree = parseFile(file) - s = SymbolVisitor() - walk(tree, s) - - # compare module-level symbols - names2 = s.scopes[tree].get_names() - - if not list_eq(mod_names, names2): - print - print "oops", file - print sorted(mod_names) - print sorted(names2) - sys.exit(-1) - - d = {} - d.update(s.scopes) - del d[tree] - scopes = d.values() - del d - - for s in syms.get_symbols(): - if s.is_namespace(): - l = [sc for sc in scopes - if sc.name == s.get_name()] - if len(l) > 1: - print "skipping", s.get_name() - else: - if not list_eq(get_names(s.get_namespace()), - l[0].get_names()): - print s.get_name() - print sorted(get_names(s.get_namespace())) - print sorted(l[0].get_names()) - sys.exit(-1) diff --git a/lib/python2.7/compiler/syntax.py b/lib/python2.7/compiler/syntax.py deleted file mode 100644 index a45d9c2..0000000 --- a/lib/python2.7/compiler/syntax.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Check for errs in the AST. - -The Python parser does not catch all syntax errors. Others, like -assignments with invalid targets, are caught in the code generation -phase. - -The compiler package catches some errors in the transformer module. -But it seems clearer to write checkers that use the AST to detect -errors. -""" - -from compiler import ast, walk - -def check(tree, multi=None): - v = SyntaxErrorChecker(multi) - walk(tree, v) - return v.errors - -class SyntaxErrorChecker: - """A visitor to find syntax errors in the AST.""" - - def __init__(self, multi=None): - """Create new visitor object. - - If optional argument multi is not None, then print messages - for each error rather than raising a SyntaxError for the - first. - """ - self.multi = multi - self.errors = 0 - - def error(self, node, msg): - self.errors = self.errors + 1 - if self.multi is not None: - print "%s:%s: %s" % (node.filename, node.lineno, msg) - else: - raise SyntaxError, "%s (%s:%s)" % (msg, node.filename, node.lineno) - - def visitAssign(self, node): - # the transformer module handles many of these - pass -## for target in node.nodes: -## if isinstance(target, ast.AssList): -## if target.lineno is None: -## target.lineno = node.lineno -## self.error(target, "can't assign to list comprehension") diff --git a/lib/python2.7/compiler/transformer.py b/lib/python2.7/compiler/transformer.py deleted file mode 100644 index d4f4613..0000000 --- a/lib/python2.7/compiler/transformer.py +++ /dev/null @@ -1,1535 +0,0 @@ -"""Parse tree transformation module. - -Transforms Python source code into an abstract syntax tree (AST) -defined in the ast module. - -The simplest ways to invoke this module are via parse and parseFile. -parse(buf) -> AST -parseFile(path) -> AST -""" - -# Original version written by Greg Stein (gstein@lyra.org) -# and Bill Tutt (rassilon@lima.mudlib.org) -# February 1997. -# -# Modifications and improvements for Python 2.0 by Jeremy Hylton and -# Mark Hammond -# -# Some fixes to try to have correct line number on almost all nodes -# (except Module, Discard and Stmt) added by Sylvain Thenault -# -# Portions of this file are: -# Copyright (C) 1997-1998 Greg Stein. All Rights Reserved. -# -# This module is provided under a BSD-ish license. See -# http://www.opensource.org/licenses/bsd-license.html -# and replace OWNER, ORGANIZATION, and YEAR as appropriate. - -from compiler.ast import * -import parser -import symbol -import token - -class WalkerError(StandardError): - pass - -from compiler.consts import CO_VARARGS, CO_VARKEYWORDS -from compiler.consts import OP_ASSIGN, OP_DELETE, OP_APPLY - -def parseFile(path): - f = open(path, "U") - # XXX The parser API tolerates files without a trailing newline, - # but not strings without a trailing newline. Always add an extra - # newline to the file contents, since we're going through the string - # version of the API. - src = f.read() + "\n" - f.close() - return parse(src) - -def parse(buf, mode="exec"): - if mode == "exec" or mode == "single": - return Transformer().parsesuite(buf) - elif mode == "eval": - return Transformer().parseexpr(buf) - else: - raise ValueError("compile() arg 3 must be" - " 'exec' or 'eval' or 'single'") - -def asList(nodes): - l = [] - for item in nodes: - if hasattr(item, "asList"): - l.append(item.asList()) - else: - if type(item) is type( (None, None) ): - l.append(tuple(asList(item))) - elif type(item) is type( [] ): - l.append(asList(item)) - else: - l.append(item) - return l - -def extractLineNo(ast): - if not isinstance(ast[1], tuple): - # get a terminal node - return ast[2] - for child in ast[1:]: - if isinstance(child, tuple): - lineno = extractLineNo(child) - if lineno is not None: - return lineno - -def Node(*args): - kind = args[0] - if kind in nodes: - try: - return nodes[kind](*args[1:]) - except TypeError: - print nodes[kind], len(args), args - raise - else: - raise WalkerError, "Can't find appropriate Node type: %s" % str(args) - #return apply(ast.Node, args) - -class Transformer: - """Utility object for transforming Python parse trees. - - Exposes the following methods: - tree = transform(ast_tree) - tree = parsesuite(text) - tree = parseexpr(text) - tree = parsefile(fileob | filename) - """ - - def __init__(self): - self._dispatch = {} - for value, name in symbol.sym_name.items(): - if hasattr(self, name): - self._dispatch[value] = getattr(self, name) - self._dispatch[token.NEWLINE] = self.com_NEWLINE - self._atom_dispatch = {token.LPAR: self.atom_lpar, - token.LSQB: self.atom_lsqb, - token.LBRACE: self.atom_lbrace, - token.BACKQUOTE: self.atom_backquote, - token.NUMBER: self.atom_number, - token.STRING: self.atom_string, - token.NAME: self.atom_name, - } - self.encoding = None - - def transform(self, tree): - """Transform an AST into a modified parse tree.""" - if not (isinstance(tree, tuple) or isinstance(tree, list)): - tree = parser.st2tuple(tree, line_info=1) - return self.compile_node(tree) - - def parsesuite(self, text): - """Return a modified parse tree for the given suite text.""" - return self.transform(parser.suite(text)) - - def parseexpr(self, text): - """Return a modified parse tree for the given expression text.""" - return self.transform(parser.expr(text)) - - def parsefile(self, file): - """Return a modified parse tree for the contents of the given file.""" - if type(file) == type(''): - file = open(file) - return self.parsesuite(file.read()) - - # -------------------------------------------------------------- - # - # PRIVATE METHODS - # - - def compile_node(self, node): - ### emit a line-number node? - n = node[0] - - if n == symbol.encoding_decl: - self.encoding = node[2] - node = node[1] - n = node[0] - - if n == symbol.single_input: - return self.single_input(node[1:]) - if n == symbol.file_input: - return self.file_input(node[1:]) - if n == symbol.eval_input: - return self.eval_input(node[1:]) - if n == symbol.lambdef: - return self.lambdef(node[1:]) - if n == symbol.funcdef: - return self.funcdef(node[1:]) - if n == symbol.classdef: - return self.classdef(node[1:]) - - raise WalkerError, ('unexpected node type', n) - - def single_input(self, node): - ### do we want to do anything about being "interactive" ? - - # NEWLINE | simple_stmt | compound_stmt NEWLINE - n = node[0][0] - if n != token.NEWLINE: - return self.com_stmt(node[0]) - - return Pass() - - def file_input(self, nodelist): - doc = self.get_docstring(nodelist, symbol.file_input) - if doc is not None: - i = 1 - else: - i = 0 - stmts = [] - for node in nodelist[i:]: - if node[0] != token.ENDMARKER and node[0] != token.NEWLINE: - self.com_append_stmt(stmts, node) - return Module(doc, Stmt(stmts)) - - def eval_input(self, nodelist): - # from the built-in function input() - ### is this sufficient? - return Expression(self.com_node(nodelist[0])) - - def decorator_name(self, nodelist): - listlen = len(nodelist) - assert listlen >= 1 and listlen % 2 == 1 - - item = self.atom_name(nodelist) - i = 1 - while i < listlen: - assert nodelist[i][0] == token.DOT - assert nodelist[i + 1][0] == token.NAME - item = Getattr(item, nodelist[i + 1][1]) - i += 2 - - return item - - def decorator(self, nodelist): - # '@' dotted_name [ '(' [arglist] ')' ] - assert len(nodelist) in (3, 5, 6) - assert nodelist[0][0] == token.AT - assert nodelist[-1][0] == token.NEWLINE - - assert nodelist[1][0] == symbol.dotted_name - funcname = self.decorator_name(nodelist[1][1:]) - - if len(nodelist) > 3: - assert nodelist[2][0] == token.LPAR - expr = self.com_call_function(funcname, nodelist[3]) - else: - expr = funcname - - return expr - - def decorators(self, nodelist): - # decorators: decorator ([NEWLINE] decorator)* NEWLINE - items = [] - for dec_nodelist in nodelist: - assert dec_nodelist[0] == symbol.decorator - items.append(self.decorator(dec_nodelist[1:])) - return Decorators(items) - - def decorated(self, nodelist): - assert nodelist[0][0] == symbol.decorators - if nodelist[1][0] == symbol.funcdef: - n = [nodelist[0]] + list(nodelist[1][1:]) - return self.funcdef(n) - elif nodelist[1][0] == symbol.classdef: - decorators = self.decorators(nodelist[0][1:]) - cls = self.classdef(nodelist[1][1:]) - cls.decorators = decorators - return cls - raise WalkerError() - - def funcdef(self, nodelist): - # -6 -5 -4 -3 -2 -1 - # funcdef: [decorators] 'def' NAME parameters ':' suite - # parameters: '(' [varargslist] ')' - - if len(nodelist) == 6: - assert nodelist[0][0] == symbol.decorators - decorators = self.decorators(nodelist[0][1:]) - else: - assert len(nodelist) == 5 - decorators = None - - lineno = nodelist[-4][2] - name = nodelist[-4][1] - args = nodelist[-3][2] - - if args[0] == symbol.varargslist: - names, defaults, flags = self.com_arglist(args[1:]) - else: - names = defaults = () - flags = 0 - doc = self.get_docstring(nodelist[-1]) - - # code for function - code = self.com_node(nodelist[-1]) - - if doc is not None: - assert isinstance(code, Stmt) - assert isinstance(code.nodes[0], Discard) - del code.nodes[0] - return Function(decorators, name, names, defaults, flags, doc, code, - lineno=lineno) - - def lambdef(self, nodelist): - # lambdef: 'lambda' [varargslist] ':' test - if nodelist[2][0] == symbol.varargslist: - names, defaults, flags = self.com_arglist(nodelist[2][1:]) - else: - names = defaults = () - flags = 0 - - # code for lambda - code = self.com_node(nodelist[-1]) - - return Lambda(names, defaults, flags, code, lineno=nodelist[1][2]) - old_lambdef = lambdef - - def classdef(self, nodelist): - # classdef: 'class' NAME ['(' [testlist] ')'] ':' suite - - name = nodelist[1][1] - doc = self.get_docstring(nodelist[-1]) - if nodelist[2][0] == token.COLON: - bases = [] - elif nodelist[3][0] == token.RPAR: - bases = [] - else: - bases = self.com_bases(nodelist[3]) - - # code for class - code = self.com_node(nodelist[-1]) - - if doc is not None: - assert isinstance(code, Stmt) - assert isinstance(code.nodes[0], Discard) - del code.nodes[0] - - return Class(name, bases, doc, code, lineno=nodelist[1][2]) - - def stmt(self, nodelist): - return self.com_stmt(nodelist[0]) - - small_stmt = stmt - flow_stmt = stmt - compound_stmt = stmt - - def simple_stmt(self, nodelist): - # small_stmt (';' small_stmt)* [';'] NEWLINE - stmts = [] - for i in range(0, len(nodelist), 2): - self.com_append_stmt(stmts, nodelist[i]) - return Stmt(stmts) - - def parameters(self, nodelist): - raise WalkerError - - def varargslist(self, nodelist): - raise WalkerError - - def fpdef(self, nodelist): - raise WalkerError - - def fplist(self, nodelist): - raise WalkerError - - def dotted_name(self, nodelist): - raise WalkerError - - def comp_op(self, nodelist): - raise WalkerError - - def trailer(self, nodelist): - raise WalkerError - - def sliceop(self, nodelist): - raise WalkerError - - def argument(self, nodelist): - raise WalkerError - - # -------------------------------------------------------------- - # - # STATEMENT NODES (invoked by com_node()) - # - - def expr_stmt(self, nodelist): - # augassign testlist | testlist ('=' testlist)* - en = nodelist[-1] - exprNode = self.lookup_node(en)(en[1:]) - if len(nodelist) == 1: - return Discard(exprNode, lineno=exprNode.lineno) - if nodelist[1][0] == token.EQUAL: - nodesl = [] - for i in range(0, len(nodelist) - 2, 2): - nodesl.append(self.com_assign(nodelist[i], OP_ASSIGN)) - return Assign(nodesl, exprNode, lineno=nodelist[1][2]) - else: - lval = self.com_augassign(nodelist[0]) - op = self.com_augassign_op(nodelist[1]) - return AugAssign(lval, op[1], exprNode, lineno=op[2]) - raise WalkerError, "can't get here" - - def print_stmt(self, nodelist): - # print ([ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ]) - items = [] - if len(nodelist) == 1: - start = 1 - dest = None - elif nodelist[1][0] == token.RIGHTSHIFT: - assert len(nodelist) == 3 \ - or nodelist[3][0] == token.COMMA - dest = self.com_node(nodelist[2]) - start = 4 - else: - dest = None - start = 1 - for i in range(start, len(nodelist), 2): - items.append(self.com_node(nodelist[i])) - if nodelist[-1][0] == token.COMMA: - return Print(items, dest, lineno=nodelist[0][2]) - return Printnl(items, dest, lineno=nodelist[0][2]) - - def del_stmt(self, nodelist): - return self.com_assign(nodelist[1], OP_DELETE) - - def pass_stmt(self, nodelist): - return Pass(lineno=nodelist[0][2]) - - def break_stmt(self, nodelist): - return Break(lineno=nodelist[0][2]) - - def continue_stmt(self, nodelist): - return Continue(lineno=nodelist[0][2]) - - def return_stmt(self, nodelist): - # return: [testlist] - if len(nodelist) < 2: - return Return(Const(None), lineno=nodelist[0][2]) - return Return(self.com_node(nodelist[1]), lineno=nodelist[0][2]) - - def yield_stmt(self, nodelist): - expr = self.com_node(nodelist[0]) - return Discard(expr, lineno=expr.lineno) - - def yield_expr(self, nodelist): - if len(nodelist) > 1: - value = self.com_node(nodelist[1]) - else: - value = Const(None) - return Yield(value, lineno=nodelist[0][2]) - - def raise_stmt(self, nodelist): - # raise: [test [',' test [',' test]]] - if len(nodelist) > 5: - expr3 = self.com_node(nodelist[5]) - else: - expr3 = None - if len(nodelist) > 3: - expr2 = self.com_node(nodelist[3]) - else: - expr2 = None - if len(nodelist) > 1: - expr1 = self.com_node(nodelist[1]) - else: - expr1 = None - return Raise(expr1, expr2, expr3, lineno=nodelist[0][2]) - - def import_stmt(self, nodelist): - # import_stmt: import_name | import_from - assert len(nodelist) == 1 - return self.com_node(nodelist[0]) - - def import_name(self, nodelist): - # import_name: 'import' dotted_as_names - return Import(self.com_dotted_as_names(nodelist[1]), - lineno=nodelist[0][2]) - - def import_from(self, nodelist): - # import_from: 'from' ('.'* dotted_name | '.') 'import' ('*' | - # '(' import_as_names ')' | import_as_names) - assert nodelist[0][1] == 'from' - idx = 1 - while nodelist[idx][1] == '.': - idx += 1 - level = idx - 1 - if nodelist[idx][0] == symbol.dotted_name: - fromname = self.com_dotted_name(nodelist[idx]) - idx += 1 - else: - fromname = "" - assert nodelist[idx][1] == 'import' - if nodelist[idx + 1][0] == token.STAR: - return From(fromname, [('*', None)], level, - lineno=nodelist[0][2]) - else: - node = nodelist[idx + 1 + (nodelist[idx + 1][0] == token.LPAR)] - return From(fromname, self.com_import_as_names(node), level, - lineno=nodelist[0][2]) - - def global_stmt(self, nodelist): - # global: NAME (',' NAME)* - names = [] - for i in range(1, len(nodelist), 2): - names.append(nodelist[i][1]) - return Global(names, lineno=nodelist[0][2]) - - def exec_stmt(self, nodelist): - # exec_stmt: 'exec' expr ['in' expr [',' expr]] - expr1 = self.com_node(nodelist[1]) - if len(nodelist) >= 4: - expr2 = self.com_node(nodelist[3]) - if len(nodelist) >= 6: - expr3 = self.com_node(nodelist[5]) - else: - expr3 = None - else: - expr2 = expr3 = None - - return Exec(expr1, expr2, expr3, lineno=nodelist[0][2]) - - def assert_stmt(self, nodelist): - # 'assert': test, [',' test] - expr1 = self.com_node(nodelist[1]) - if (len(nodelist) == 4): - expr2 = self.com_node(nodelist[3]) - else: - expr2 = None - return Assert(expr1, expr2, lineno=nodelist[0][2]) - - def if_stmt(self, nodelist): - # if: test ':' suite ('elif' test ':' suite)* ['else' ':' suite] - tests = [] - for i in range(0, len(nodelist) - 3, 4): - testNode = self.com_node(nodelist[i + 1]) - suiteNode = self.com_node(nodelist[i + 3]) - tests.append((testNode, suiteNode)) - - if len(nodelist) % 4 == 3: - elseNode = self.com_node(nodelist[-1]) -## elseNode.lineno = nodelist[-1][1][2] - else: - elseNode = None - return If(tests, elseNode, lineno=nodelist[0][2]) - - def while_stmt(self, nodelist): - # 'while' test ':' suite ['else' ':' suite] - - testNode = self.com_node(nodelist[1]) - bodyNode = self.com_node(nodelist[3]) - - if len(nodelist) > 4: - elseNode = self.com_node(nodelist[6]) - else: - elseNode = None - - return While(testNode, bodyNode, elseNode, lineno=nodelist[0][2]) - - def for_stmt(self, nodelist): - # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] - - assignNode = self.com_assign(nodelist[1], OP_ASSIGN) - listNode = self.com_node(nodelist[3]) - bodyNode = self.com_node(nodelist[5]) - - if len(nodelist) > 8: - elseNode = self.com_node(nodelist[8]) - else: - elseNode = None - - return For(assignNode, listNode, bodyNode, elseNode, - lineno=nodelist[0][2]) - - def try_stmt(self, nodelist): - return self.com_try_except_finally(nodelist) - - def with_stmt(self, nodelist): - return self.com_with(nodelist) - - def with_var(self, nodelist): - return self.com_with_var(nodelist) - - def suite(self, nodelist): - # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT - if len(nodelist) == 1: - return self.com_stmt(nodelist[0]) - - stmts = [] - for node in nodelist: - if node[0] == symbol.stmt: - self.com_append_stmt(stmts, node) - return Stmt(stmts) - - # -------------------------------------------------------------- - # - # EXPRESSION NODES (invoked by com_node()) - # - - def testlist(self, nodelist): - # testlist: expr (',' expr)* [','] - # testlist_safe: test [(',' test)+ [',']] - # exprlist: expr (',' expr)* [','] - return self.com_binary(Tuple, nodelist) - - testlist_safe = testlist # XXX - testlist1 = testlist - exprlist = testlist - - def testlist_comp(self, nodelist): - # test ( comp_for | (',' test)* [','] ) - assert nodelist[0][0] == symbol.test - if len(nodelist) == 2 and nodelist[1][0] == symbol.comp_for: - test = self.com_node(nodelist[0]) - return self.com_generator_expression(test, nodelist[1]) - return self.testlist(nodelist) - - def test(self, nodelist): - # or_test ['if' or_test 'else' test] | lambdef - if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef: - return self.lambdef(nodelist[0]) - then = self.com_node(nodelist[0]) - if len(nodelist) > 1: - assert len(nodelist) == 5 - assert nodelist[1][1] == 'if' - assert nodelist[3][1] == 'else' - test = self.com_node(nodelist[2]) - else_ = self.com_node(nodelist[4]) - return IfExp(test, then, else_, lineno=nodelist[1][2]) - return then - - def or_test(self, nodelist): - # and_test ('or' and_test)* | lambdef - if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef: - return self.lambdef(nodelist[0]) - return self.com_binary(Or, nodelist) - old_test = or_test - - def and_test(self, nodelist): - # not_test ('and' not_test)* - return self.com_binary(And, nodelist) - - def not_test(self, nodelist): - # 'not' not_test | comparison - result = self.com_node(nodelist[-1]) - if len(nodelist) == 2: - return Not(result, lineno=nodelist[0][2]) - return result - - def comparison(self, nodelist): - # comparison: expr (comp_op expr)* - node = self.com_node(nodelist[0]) - if len(nodelist) == 1: - return node - - results = [] - for i in range(2, len(nodelist), 2): - nl = nodelist[i-1] - - # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '==' - # | 'in' | 'not' 'in' | 'is' | 'is' 'not' - n = nl[1] - if n[0] == token.NAME: - type = n[1] - if len(nl) == 3: - if type == 'not': - type = 'not in' - else: - type = 'is not' - else: - type = _cmp_types[n[0]] - - lineno = nl[1][2] - results.append((type, self.com_node(nodelist[i]))) - - # we need a special "compare" node so that we can distinguish - # 3 < x < 5 from (3 < x) < 5 - # the two have very different semantics and results (note that the - # latter form is always true) - - return Compare(node, results, lineno=lineno) - - def expr(self, nodelist): - # xor_expr ('|' xor_expr)* - return self.com_binary(Bitor, nodelist) - - def xor_expr(self, nodelist): - # xor_expr ('^' xor_expr)* - return self.com_binary(Bitxor, nodelist) - - def and_expr(self, nodelist): - # xor_expr ('&' xor_expr)* - return self.com_binary(Bitand, nodelist) - - def shift_expr(self, nodelist): - # shift_expr ('<<'|'>>' shift_expr)* - node = self.com_node(nodelist[0]) - for i in range(2, len(nodelist), 2): - right = self.com_node(nodelist[i]) - if nodelist[i-1][0] == token.LEFTSHIFT: - node = LeftShift([node, right], lineno=nodelist[1][2]) - elif nodelist[i-1][0] == token.RIGHTSHIFT: - node = RightShift([node, right], lineno=nodelist[1][2]) - else: - raise ValueError, "unexpected token: %s" % nodelist[i-1][0] - return node - - def arith_expr(self, nodelist): - node = self.com_node(nodelist[0]) - for i in range(2, len(nodelist), 2): - right = self.com_node(nodelist[i]) - if nodelist[i-1][0] == token.PLUS: - node = Add([node, right], lineno=nodelist[1][2]) - elif nodelist[i-1][0] == token.MINUS: - node = Sub([node, right], lineno=nodelist[1][2]) - else: - raise ValueError, "unexpected token: %s" % nodelist[i-1][0] - return node - - def term(self, nodelist): - node = self.com_node(nodelist[0]) - for i in range(2, len(nodelist), 2): - right = self.com_node(nodelist[i]) - t = nodelist[i-1][0] - if t == token.STAR: - node = Mul([node, right]) - elif t == token.SLASH: - node = Div([node, right]) - elif t == token.PERCENT: - node = Mod([node, right]) - elif t == token.DOUBLESLASH: - node = FloorDiv([node, right]) - else: - raise ValueError, "unexpected token: %s" % t - node.lineno = nodelist[1][2] - return node - - def factor(self, nodelist): - elt = nodelist[0] - t = elt[0] - node = self.lookup_node(nodelist[-1])(nodelist[-1][1:]) - # need to handle (unary op)constant here... - if t == token.PLUS: - return UnaryAdd(node, lineno=elt[2]) - elif t == token.MINUS: - return UnarySub(node, lineno=elt[2]) - elif t == token.TILDE: - node = Invert(node, lineno=elt[2]) - return node - - def power(self, nodelist): - # power: atom trailer* ('**' factor)* - node = self.com_node(nodelist[0]) - for i in range(1, len(nodelist)): - elt = nodelist[i] - if elt[0] == token.DOUBLESTAR: - return Power([node, self.com_node(nodelist[i+1])], - lineno=elt[2]) - - node = self.com_apply_trailer(node, elt) - - return node - - def atom(self, nodelist): - return self._atom_dispatch[nodelist[0][0]](nodelist) - - def atom_lpar(self, nodelist): - if nodelist[1][0] == token.RPAR: - return Tuple((), lineno=nodelist[0][2]) - return self.com_node(nodelist[1]) - - def atom_lsqb(self, nodelist): - if nodelist[1][0] == token.RSQB: - return List((), lineno=nodelist[0][2]) - return self.com_list_constructor(nodelist[1]) - - def atom_lbrace(self, nodelist): - if nodelist[1][0] == token.RBRACE: - return Dict((), lineno=nodelist[0][2]) - return self.com_dictorsetmaker(nodelist[1]) - - def atom_backquote(self, nodelist): - return Backquote(self.com_node(nodelist[1])) - - def atom_number(self, nodelist): - ### need to verify this matches compile.c - k = eval(nodelist[0][1]) - return Const(k, lineno=nodelist[0][2]) - - def decode_literal(self, lit): - if self.encoding: - # this is particularly fragile & a bit of a - # hack... changes in compile.c:parsestr and - # tokenizer.c must be reflected here. - if self.encoding not in ['utf-8', 'iso-8859-1']: - lit = unicode(lit, 'utf-8').encode(self.encoding) - return eval("# coding: %s\n%s" % (self.encoding, lit)) - else: - return eval(lit) - - def atom_string(self, nodelist): - k = '' - for node in nodelist: - k += self.decode_literal(node[1]) - return Const(k, lineno=nodelist[0][2]) - - def atom_name(self, nodelist): - return Name(nodelist[0][1], lineno=nodelist[0][2]) - - # -------------------------------------------------------------- - # - # INTERNAL PARSING UTILITIES - # - - # The use of com_node() introduces a lot of extra stack frames, - # enough to cause a stack overflow compiling test.test_parser with - # the standard interpreter recursionlimit. The com_node() is a - # convenience function that hides the dispatch details, but comes - # at a very high cost. It is more efficient to dispatch directly - # in the callers. In these cases, use lookup_node() and call the - # dispatched node directly. - - def lookup_node(self, node): - return self._dispatch[node[0]] - - def com_node(self, node): - # Note: compile.c has handling in com_node for del_stmt, pass_stmt, - # break_stmt, stmt, small_stmt, flow_stmt, simple_stmt, - # and compound_stmt. - # We'll just dispatch them. - return self._dispatch[node[0]](node[1:]) - - def com_NEWLINE(self, *args): - # A ';' at the end of a line can make a NEWLINE token appear - # here, Render it harmless. (genc discards ('discard', - # ('const', xxxx)) Nodes) - return Discard(Const(None)) - - def com_arglist(self, nodelist): - # varargslist: - # (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) - # | fpdef ['=' test] (',' fpdef ['=' test])* [','] - # fpdef: NAME | '(' fplist ')' - # fplist: fpdef (',' fpdef)* [','] - names = [] - defaults = [] - flags = 0 - - i = 0 - while i < len(nodelist): - node = nodelist[i] - if node[0] == token.STAR or node[0] == token.DOUBLESTAR: - if node[0] == token.STAR: - node = nodelist[i+1] - if node[0] == token.NAME: - names.append(node[1]) - flags = flags | CO_VARARGS - i = i + 3 - - if i < len(nodelist): - # should be DOUBLESTAR - t = nodelist[i][0] - if t == token.DOUBLESTAR: - node = nodelist[i+1] - else: - raise ValueError, "unexpected token: %s" % t - names.append(node[1]) - flags = flags | CO_VARKEYWORDS - - break - - # fpdef: NAME | '(' fplist ')' - names.append(self.com_fpdef(node)) - - i = i + 1 - if i < len(nodelist) and nodelist[i][0] == token.EQUAL: - defaults.append(self.com_node(nodelist[i + 1])) - i = i + 2 - elif len(defaults): - # we have already seen an argument with default, but here - # came one without - raise SyntaxError, "non-default argument follows default argument" - - # skip the comma - i = i + 1 - - return names, defaults, flags - - def com_fpdef(self, node): - # fpdef: NAME | '(' fplist ')' - if node[1][0] == token.LPAR: - return self.com_fplist(node[2]) - return node[1][1] - - def com_fplist(self, node): - # fplist: fpdef (',' fpdef)* [','] - if len(node) == 2: - return self.com_fpdef(node[1]) - list = [] - for i in range(1, len(node), 2): - list.append(self.com_fpdef(node[i])) - return tuple(list) - - def com_dotted_name(self, node): - # String together the dotted names and return the string - name = "" - for n in node: - if type(n) == type(()) and n[0] == 1: - name = name + n[1] + '.' - return name[:-1] - - def com_dotted_as_name(self, node): - assert node[0] == symbol.dotted_as_name - node = node[1:] - dot = self.com_dotted_name(node[0][1:]) - if len(node) == 1: - return dot, None - assert node[1][1] == 'as' - assert node[2][0] == token.NAME - return dot, node[2][1] - - def com_dotted_as_names(self, node): - assert node[0] == symbol.dotted_as_names - node = node[1:] - names = [self.com_dotted_as_name(node[0])] - for i in range(2, len(node), 2): - names.append(self.com_dotted_as_name(node[i])) - return names - - def com_import_as_name(self, node): - assert node[0] == symbol.import_as_name - node = node[1:] - assert node[0][0] == token.NAME - if len(node) == 1: - return node[0][1], None - assert node[1][1] == 'as', node - assert node[2][0] == token.NAME - return node[0][1], node[2][1] - - def com_import_as_names(self, node): - assert node[0] == symbol.import_as_names - node = node[1:] - names = [self.com_import_as_name(node[0])] - for i in range(2, len(node), 2): - names.append(self.com_import_as_name(node[i])) - return names - - def com_bases(self, node): - bases = [] - for i in range(1, len(node), 2): - bases.append(self.com_node(node[i])) - return bases - - def com_try_except_finally(self, nodelist): - # ('try' ':' suite - # ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] - # | 'finally' ':' suite)) - - if nodelist[3][0] == token.NAME: - # first clause is a finally clause: only try-finally - return TryFinally(self.com_node(nodelist[2]), - self.com_node(nodelist[5]), - lineno=nodelist[0][2]) - - #tryexcept: [TryNode, [except_clauses], elseNode)] - clauses = [] - elseNode = None - finallyNode = None - for i in range(3, len(nodelist), 3): - node = nodelist[i] - if node[0] == symbol.except_clause: - # except_clause: 'except' [expr [(',' | 'as') expr]] */ - if len(node) > 2: - expr1 = self.com_node(node[2]) - if len(node) > 4: - expr2 = self.com_assign(node[4], OP_ASSIGN) - else: - expr2 = None - else: - expr1 = expr2 = None - clauses.append((expr1, expr2, self.com_node(nodelist[i+2]))) - - if node[0] == token.NAME: - if node[1] == 'else': - elseNode = self.com_node(nodelist[i+2]) - elif node[1] == 'finally': - finallyNode = self.com_node(nodelist[i+2]) - try_except = TryExcept(self.com_node(nodelist[2]), clauses, elseNode, - lineno=nodelist[0][2]) - if finallyNode: - return TryFinally(try_except, finallyNode, lineno=nodelist[0][2]) - else: - return try_except - - def com_with(self, nodelist): - # with_stmt: 'with' with_item (',' with_item)* ':' suite - body = self.com_node(nodelist[-1]) - for i in range(len(nodelist) - 3, 0, -2): - ret = self.com_with_item(nodelist[i], body, nodelist[0][2]) - if i == 1: - return ret - body = ret - - def com_with_item(self, nodelist, body, lineno): - # with_item: test ['as' expr] - if len(nodelist) == 4: - var = self.com_assign(nodelist[3], OP_ASSIGN) - else: - var = None - expr = self.com_node(nodelist[1]) - return With(expr, var, body, lineno=lineno) - - def com_augassign_op(self, node): - assert node[0] == symbol.augassign - return node[1] - - def com_augassign(self, node): - """Return node suitable for lvalue of augmented assignment - - Names, slices, and attributes are the only allowable nodes. - """ - l = self.com_node(node) - if l.__class__ in (Name, Slice, Subscript, Getattr): - return l - raise SyntaxError, "can't assign to %s" % l.__class__.__name__ - - def com_assign(self, node, assigning): - # return a node suitable for use as an "lvalue" - # loop to avoid trivial recursion - while 1: - t = node[0] - if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_comp): - if len(node) > 2: - return self.com_assign_tuple(node, assigning) - node = node[1] - elif t in _assign_types: - if len(node) > 2: - raise SyntaxError, "can't assign to operator" - node = node[1] - elif t == symbol.power: - if node[1][0] != symbol.atom: - raise SyntaxError, "can't assign to operator" - if len(node) > 2: - primary = self.com_node(node[1]) - for i in range(2, len(node)-1): - ch = node[i] - if ch[0] == token.DOUBLESTAR: - raise SyntaxError, "can't assign to operator" - primary = self.com_apply_trailer(primary, ch) - return self.com_assign_trailer(primary, node[-1], - assigning) - node = node[1] - elif t == symbol.atom: - t = node[1][0] - if t == token.LPAR: - node = node[2] - if node[0] == token.RPAR: - raise SyntaxError, "can't assign to ()" - elif t == token.LSQB: - node = node[2] - if node[0] == token.RSQB: - raise SyntaxError, "can't assign to []" - return self.com_assign_list(node, assigning) - elif t == token.NAME: - return self.com_assign_name(node[1], assigning) - else: - raise SyntaxError, "can't assign to literal" - else: - raise SyntaxError, "bad assignment (%s)" % t - - def com_assign_tuple(self, node, assigning): - assigns = [] - for i in range(1, len(node), 2): - assigns.append(self.com_assign(node[i], assigning)) - return AssTuple(assigns, lineno=extractLineNo(node)) - - def com_assign_list(self, node, assigning): - assigns = [] - for i in range(1, len(node), 2): - if i + 1 < len(node): - if node[i + 1][0] == symbol.list_for: - raise SyntaxError, "can't assign to list comprehension" - assert node[i + 1][0] == token.COMMA, node[i + 1] - assigns.append(self.com_assign(node[i], assigning)) - return AssList(assigns, lineno=extractLineNo(node)) - - def com_assign_name(self, node, assigning): - return AssName(node[1], assigning, lineno=node[2]) - - def com_assign_trailer(self, primary, node, assigning): - t = node[1][0] - if t == token.DOT: - return self.com_assign_attr(primary, node[2], assigning) - if t == token.LSQB: - return self.com_subscriptlist(primary, node[2], assigning) - if t == token.LPAR: - raise SyntaxError, "can't assign to function call" - raise SyntaxError, "unknown trailer type: %s" % t - - def com_assign_attr(self, primary, node, assigning): - return AssAttr(primary, node[1], assigning, lineno=node[-1]) - - def com_binary(self, constructor, nodelist): - "Compile 'NODE (OP NODE)*' into (type, [ node1, ..., nodeN ])." - l = len(nodelist) - if l == 1: - n = nodelist[0] - return self.lookup_node(n)(n[1:]) - items = [] - for i in range(0, l, 2): - n = nodelist[i] - items.append(self.lookup_node(n)(n[1:])) - return constructor(items, lineno=extractLineNo(nodelist)) - - def com_stmt(self, node): - result = self.lookup_node(node)(node[1:]) - assert result is not None - if isinstance(result, Stmt): - return result - return Stmt([result]) - - def com_append_stmt(self, stmts, node): - result = self.lookup_node(node)(node[1:]) - assert result is not None - if isinstance(result, Stmt): - stmts.extend(result.nodes) - else: - stmts.append(result) - - def com_list_constructor(self, nodelist): - # listmaker: test ( list_for | (',' test)* [','] ) - values = [] - for i in range(1, len(nodelist)): - if nodelist[i][0] == symbol.list_for: - assert len(nodelist[i:]) == 1 - return self.com_list_comprehension(values[0], - nodelist[i]) - elif nodelist[i][0] == token.COMMA: - continue - values.append(self.com_node(nodelist[i])) - return List(values, lineno=values[0].lineno) - - def com_list_comprehension(self, expr, node): - return self.com_comprehension(expr, None, node, 'list') - - def com_comprehension(self, expr1, expr2, node, type): - # list_iter: list_for | list_if - # list_for: 'for' exprlist 'in' testlist [list_iter] - # list_if: 'if' test [list_iter] - - # XXX should raise SyntaxError for assignment - # XXX(avassalotti) Set and dict comprehensions should have generator - # semantics. In other words, they shouldn't leak - # variables outside of the comprehension's scope. - - lineno = node[1][2] - fors = [] - while node: - t = node[1][1] - if t == 'for': - assignNode = self.com_assign(node[2], OP_ASSIGN) - compNode = self.com_node(node[4]) - newfor = ListCompFor(assignNode, compNode, []) - newfor.lineno = node[1][2] - fors.append(newfor) - if len(node) == 5: - node = None - elif type == 'list': - node = self.com_list_iter(node[5]) - else: - node = self.com_comp_iter(node[5]) - elif t == 'if': - test = self.com_node(node[2]) - newif = ListCompIf(test, lineno=node[1][2]) - newfor.ifs.append(newif) - if len(node) == 3: - node = None - elif type == 'list': - node = self.com_list_iter(node[3]) - else: - node = self.com_comp_iter(node[3]) - else: - raise SyntaxError, \ - ("unexpected comprehension element: %s %d" - % (node, lineno)) - if type == 'list': - return ListComp(expr1, fors, lineno=lineno) - elif type == 'set': - return SetComp(expr1, fors, lineno=lineno) - elif type == 'dict': - return DictComp(expr1, expr2, fors, lineno=lineno) - else: - raise ValueError("unexpected comprehension type: " + repr(type)) - - def com_list_iter(self, node): - assert node[0] == symbol.list_iter - return node[1] - - def com_comp_iter(self, node): - assert node[0] == symbol.comp_iter - return node[1] - - def com_generator_expression(self, expr, node): - # comp_iter: comp_for | comp_if - # comp_for: 'for' exprlist 'in' test [comp_iter] - # comp_if: 'if' test [comp_iter] - - lineno = node[1][2] - fors = [] - while node: - t = node[1][1] - if t == 'for': - assignNode = self.com_assign(node[2], OP_ASSIGN) - genNode = self.com_node(node[4]) - newfor = GenExprFor(assignNode, genNode, [], - lineno=node[1][2]) - fors.append(newfor) - if (len(node)) == 5: - node = None - else: - node = self.com_comp_iter(node[5]) - elif t == 'if': - test = self.com_node(node[2]) - newif = GenExprIf(test, lineno=node[1][2]) - newfor.ifs.append(newif) - if len(node) == 3: - node = None - else: - node = self.com_comp_iter(node[3]) - else: - raise SyntaxError, \ - ("unexpected generator expression element: %s %d" - % (node, lineno)) - fors[0].is_outmost = True - return GenExpr(GenExprInner(expr, fors), lineno=lineno) - - def com_dictorsetmaker(self, nodelist): - # dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | - # (test (comp_for | (',' test)* [','])) ) - assert nodelist[0] == symbol.dictorsetmaker - nodelist = nodelist[1:] - if len(nodelist) == 1 or nodelist[1][0] == token.COMMA: - # set literal - items = [] - for i in range(0, len(nodelist), 2): - items.append(self.com_node(nodelist[i])) - return Set(items, lineno=items[0].lineno) - elif nodelist[1][0] == symbol.comp_for: - # set comprehension - expr = self.com_node(nodelist[0]) - return self.com_comprehension(expr, None, nodelist[1], 'set') - elif len(nodelist) > 3 and nodelist[3][0] == symbol.comp_for: - # dict comprehension - assert nodelist[1][0] == token.COLON - key = self.com_node(nodelist[0]) - value = self.com_node(nodelist[2]) - return self.com_comprehension(key, value, nodelist[3], 'dict') - else: - # dict literal - items = [] - for i in range(0, len(nodelist), 4): - items.append((self.com_node(nodelist[i]), - self.com_node(nodelist[i+2]))) - return Dict(items, lineno=items[0][0].lineno) - - def com_apply_trailer(self, primaryNode, nodelist): - t = nodelist[1][0] - if t == token.LPAR: - return self.com_call_function(primaryNode, nodelist[2]) - if t == token.DOT: - return self.com_select_member(primaryNode, nodelist[2]) - if t == token.LSQB: - return self.com_subscriptlist(primaryNode, nodelist[2], OP_APPLY) - - raise SyntaxError, 'unknown node type: %s' % t - - def com_select_member(self, primaryNode, nodelist): - if nodelist[0] != token.NAME: - raise SyntaxError, "member must be a name" - return Getattr(primaryNode, nodelist[1], lineno=nodelist[2]) - - def com_call_function(self, primaryNode, nodelist): - if nodelist[0] == token.RPAR: - return CallFunc(primaryNode, [], lineno=extractLineNo(nodelist)) - args = [] - kw = 0 - star_node = dstar_node = None - len_nodelist = len(nodelist) - i = 1 - while i < len_nodelist: - node = nodelist[i] - - if node[0]==token.STAR: - if star_node is not None: - raise SyntaxError, 'already have the varargs indentifier' - star_node = self.com_node(nodelist[i+1]) - i = i + 3 - continue - elif node[0]==token.DOUBLESTAR: - if dstar_node is not None: - raise SyntaxError, 'already have the kwargs indentifier' - dstar_node = self.com_node(nodelist[i+1]) - i = i + 3 - continue - - # positional or named parameters - kw, result = self.com_argument(node, kw, star_node) - - if len_nodelist != 2 and isinstance(result, GenExpr) \ - and len(node) == 3 and node[2][0] == symbol.comp_for: - # allow f(x for x in y), but reject f(x for x in y, 1) - # should use f((x for x in y), 1) instead of f(x for x in y, 1) - raise SyntaxError, 'generator expression needs parenthesis' - - args.append(result) - i = i + 2 - - return CallFunc(primaryNode, args, star_node, dstar_node, - lineno=extractLineNo(nodelist)) - - def com_argument(self, nodelist, kw, star_node): - if len(nodelist) == 3 and nodelist[2][0] == symbol.comp_for: - test = self.com_node(nodelist[1]) - return 0, self.com_generator_expression(test, nodelist[2]) - if len(nodelist) == 2: - if kw: - raise SyntaxError, "non-keyword arg after keyword arg" - if star_node: - raise SyntaxError, "only named arguments may follow *expression" - return 0, self.com_node(nodelist[1]) - result = self.com_node(nodelist[3]) - n = nodelist[1] - while len(n) == 2 and n[0] != token.NAME: - n = n[1] - if n[0] != token.NAME: - raise SyntaxError, "keyword can't be an expression (%s)"%n[0] - node = Keyword(n[1], result, lineno=n[2]) - return 1, node - - def com_subscriptlist(self, primary, nodelist, assigning): - # slicing: simple_slicing | extended_slicing - # simple_slicing: primary "[" short_slice "]" - # extended_slicing: primary "[" slice_list "]" - # slice_list: slice_item ("," slice_item)* [","] - - # backwards compat slice for '[i:j]' - if len(nodelist) == 2: - sub = nodelist[1] - if (sub[1][0] == token.COLON or \ - (len(sub) > 2 and sub[2][0] == token.COLON)) and \ - sub[-1][0] != symbol.sliceop: - return self.com_slice(primary, sub, assigning) - - subscripts = [] - for i in range(1, len(nodelist), 2): - subscripts.append(self.com_subscript(nodelist[i])) - return Subscript(primary, assigning, subscripts, - lineno=extractLineNo(nodelist)) - - def com_subscript(self, node): - # slice_item: expression | proper_slice | ellipsis - ch = node[1] - t = ch[0] - if t == token.DOT and node[2][0] == token.DOT: - return Ellipsis() - if t == token.COLON or len(node) > 2: - return self.com_sliceobj(node) - return self.com_node(ch) - - def com_sliceobj(self, node): - # proper_slice: short_slice | long_slice - # short_slice: [lower_bound] ":" [upper_bound] - # long_slice: short_slice ":" [stride] - # lower_bound: expression - # upper_bound: expression - # stride: expression - # - # Note: a stride may be further slicing... - - items = [] - - if node[1][0] == token.COLON: - items.append(Const(None)) - i = 2 - else: - items.append(self.com_node(node[1])) - # i == 2 is a COLON - i = 3 - - if i < len(node) and node[i][0] == symbol.test: - items.append(self.com_node(node[i])) - i = i + 1 - else: - items.append(Const(None)) - - # a short_slice has been built. look for long_slice now by looking - # for strides... - for j in range(i, len(node)): - ch = node[j] - if len(ch) == 2: - items.append(Const(None)) - else: - items.append(self.com_node(ch[2])) - return Sliceobj(items, lineno=extractLineNo(node)) - - def com_slice(self, primary, node, assigning): - # short_slice: [lower_bound] ":" [upper_bound] - lower = upper = None - if len(node) == 3: - if node[1][0] == token.COLON: - upper = self.com_node(node[2]) - else: - lower = self.com_node(node[1]) - elif len(node) == 4: - lower = self.com_node(node[1]) - upper = self.com_node(node[3]) - return Slice(primary, assigning, lower, upper, - lineno=extractLineNo(node)) - - def get_docstring(self, node, n=None): - if n is None: - n = node[0] - node = node[1:] - if n == symbol.suite: - if len(node) == 1: - return self.get_docstring(node[0]) - for sub in node: - if sub[0] == symbol.stmt: - return self.get_docstring(sub) - return None - if n == symbol.file_input: - for sub in node: - if sub[0] == symbol.stmt: - return self.get_docstring(sub) - return None - if n == symbol.atom: - if node[0][0] == token.STRING: - s = '' - for t in node: - s = s + eval(t[1]) - return s - return None - if n == symbol.stmt or n == symbol.simple_stmt \ - or n == symbol.small_stmt: - return self.get_docstring(node[0]) - if n in _doc_nodes and len(node) == 1: - return self.get_docstring(node[0]) - return None - - -_doc_nodes = [ - symbol.expr_stmt, - symbol.testlist, - symbol.testlist_safe, - symbol.test, - symbol.or_test, - symbol.and_test, - symbol.not_test, - symbol.comparison, - symbol.expr, - symbol.xor_expr, - symbol.and_expr, - symbol.shift_expr, - symbol.arith_expr, - symbol.term, - symbol.factor, - symbol.power, - ] - -# comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '==' -# | 'in' | 'not' 'in' | 'is' | 'is' 'not' -_cmp_types = { - token.LESS : '<', - token.GREATER : '>', - token.EQEQUAL : '==', - token.EQUAL : '==', - token.LESSEQUAL : '<=', - token.GREATEREQUAL : '>=', - token.NOTEQUAL : '!=', - } - -_legal_node_types = [ - symbol.funcdef, - symbol.classdef, - symbol.stmt, - symbol.small_stmt, - symbol.flow_stmt, - symbol.simple_stmt, - symbol.compound_stmt, - symbol.expr_stmt, - symbol.print_stmt, - symbol.del_stmt, - symbol.pass_stmt, - symbol.break_stmt, - symbol.continue_stmt, - symbol.return_stmt, - symbol.raise_stmt, - symbol.import_stmt, - symbol.global_stmt, - symbol.exec_stmt, - symbol.assert_stmt, - symbol.if_stmt, - symbol.while_stmt, - symbol.for_stmt, - symbol.try_stmt, - symbol.with_stmt, - symbol.suite, - symbol.testlist, - symbol.testlist_safe, - symbol.test, - symbol.and_test, - symbol.not_test, - symbol.comparison, - symbol.exprlist, - symbol.expr, - symbol.xor_expr, - symbol.and_expr, - symbol.shift_expr, - symbol.arith_expr, - symbol.term, - symbol.factor, - symbol.power, - symbol.atom, - ] - -if hasattr(symbol, 'yield_stmt'): - _legal_node_types.append(symbol.yield_stmt) -if hasattr(symbol, 'yield_expr'): - _legal_node_types.append(symbol.yield_expr) - -_assign_types = [ - symbol.test, - symbol.or_test, - symbol.and_test, - symbol.not_test, - symbol.comparison, - symbol.expr, - symbol.xor_expr, - symbol.and_expr, - symbol.shift_expr, - symbol.arith_expr, - symbol.term, - symbol.factor, - ] - -_names = {} -for k, v in symbol.sym_name.items(): - _names[k] = v -for k, v in token.tok_name.items(): - _names[k] = v - -def debug_tree(tree): - l = [] - for elt in tree: - if isinstance(elt, int): - l.append(_names.get(elt, elt)) - elif isinstance(elt, str): - l.append(elt) - else: - l.append(debug_tree(elt)) - return l diff --git a/lib/python2.7/compiler/visitor.py b/lib/python2.7/compiler/visitor.py deleted file mode 100644 index f10f560..0000000 --- a/lib/python2.7/compiler/visitor.py +++ /dev/null @@ -1,113 +0,0 @@ -from compiler import ast - -# XXX should probably rename ASTVisitor to ASTWalker -# XXX can it be made even more generic? - -class ASTVisitor: - """Performs a depth-first walk of the AST - - The ASTVisitor will walk the AST, performing either a preorder or - postorder traversal depending on which method is called. - - methods: - preorder(tree, visitor) - postorder(tree, visitor) - tree: an instance of ast.Node - visitor: an instance with visitXXX methods - - The ASTVisitor is responsible for walking over the tree in the - correct order. For each node, it checks the visitor argument for - a method named 'visitNodeType' where NodeType is the name of the - node's class, e.g. Class. If the method exists, it is called - with the node as its sole argument. - - The visitor method for a particular node type can control how - child nodes are visited during a preorder walk. (It can't control - the order during a postorder walk, because it is called _after_ - the walk has occurred.) The ASTVisitor modifies the visitor - argument by adding a visit method to the visitor; this method can - be used to visit a child node of arbitrary type. - """ - - VERBOSE = 0 - - def __init__(self): - self.node = None - self._cache = {} - - def default(self, node, *args): - for child in node.getChildNodes(): - self.dispatch(child, *args) - - def dispatch(self, node, *args): - self.node = node - klass = node.__class__ - meth = self._cache.get(klass, None) - if meth is None: - className = klass.__name__ - meth = getattr(self.visitor, 'visit' + className, self.default) - self._cache[klass] = meth -## if self.VERBOSE > 0: -## className = klass.__name__ -## if self.VERBOSE == 1: -## if meth == 0: -## print "dispatch", className -## else: -## print "dispatch", className, (meth and meth.__name__ or '') - return meth(node, *args) - - def preorder(self, tree, visitor, *args): - """Do preorder walk of tree using visitor""" - self.visitor = visitor - visitor.visit = self.dispatch - self.dispatch(tree, *args) # XXX *args make sense? - -class ExampleASTVisitor(ASTVisitor): - """Prints examples of the nodes that aren't visited - - This visitor-driver is only useful for development, when it's - helpful to develop a visitor incrementally, and get feedback on what - you still have to do. - """ - examples = {} - - def dispatch(self, node, *args): - self.node = node - meth = self._cache.get(node.__class__, None) - className = node.__class__.__name__ - if meth is None: - meth = getattr(self.visitor, 'visit' + className, 0) - self._cache[node.__class__] = meth - if self.VERBOSE > 1: - print "dispatch", className, (meth and meth.__name__ or '') - if meth: - meth(node, *args) - elif self.VERBOSE > 0: - klass = node.__class__ - if klass not in self.examples: - self.examples[klass] = klass - print - print self.visitor - print klass - for attr in dir(node): - if attr[0] != '_': - print "\t", "%-12.12s" % attr, getattr(node, attr) - print - return self.default(node, *args) - -# XXX this is an API change - -_walker = ASTVisitor -def walk(tree, visitor, walker=None, verbose=None): - if walker is None: - walker = _walker() - if verbose is not None: - walker.VERBOSE = verbose - walker.preorder(tree, visitor) - return walker.visitor - -def dumpNode(node): - print node.__class__ - for attr in dir(node): - if attr[0] != '_': - print "\t", "%-10.10s" % attr, getattr(node, attr) |