1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/compiler/__init__.py Fri May 18 20:51:41 2012 +0200
1.3 @@ -0,0 +1,29 @@
1.4 +"""Package for parsing and compiling Python source code
1.5 +
1.6 +There are several functions defined at the top level that are imported
1.7 +from modules contained in the package.
1.8 +
1.9 +parse(buf, mode="exec") -> AST
1.10 + Converts a string containing Python source code to an abstract
1.11 + syntax tree (AST). The AST is defined in compiler.ast.
1.12 +
1.13 +parseFile(path) -> AST
1.14 + The same as parse(open(path))
1.15 +
1.16 +walk(ast, visitor, verbose=None)
1.17 + Does a pre-order walk over the ast using the visitor instance.
1.18 + See compiler.visitor for details.
1.19 +
1.20 +compile(source, filename, mode, flags=None, dont_inherit=None)
1.21 + Returns a code object. A replacement for the builtin compile() function.
1.22 +
1.23 +compileFile(filename)
1.24 + Generates a .pyc file by compiling filename.
1.25 +"""
1.26 +from warnings import warnpy3k
1.27 +warnpy3k("the compiler package has been removed in Python 3.0", stacklevel=2)
1.28 +del warnpy3k
1.29 +
1.30 +from compiler.transformer import parse, parseFile
1.31 +from compiler.visitor import walk
1.32 +from compiler.pycodegen import compile, compileFile
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/compiler/ast.py Fri May 18 20:51:41 2012 +0200
2.3 @@ -0,0 +1,1358 @@
2.4 +"""Python abstract syntax node definitions
2.5 +
2.6 +This file is automatically generated by Tools/compiler/astgen.py
2.7 +"""
2.8 +from compiler.consts import CO_VARARGS, CO_VARKEYWORDS
2.9 +
2.10 +def flatten(seq):
2.11 + l = []
2.12 + for elt in seq:
2.13 + t = type(elt)
2.14 + if t is tuple or t is list:
2.15 + for elt2 in flatten(elt):
2.16 + l.append(elt2)
2.17 + else:
2.18 + l.append(elt)
2.19 + return l
2.20 +
2.21 +def flatten_nodes(seq):
2.22 + return [n for n in flatten(seq) if isinstance(n, Node)]
2.23 +
2.24 +nodes = {}
2.25 +
2.26 +class Node:
2.27 + """Abstract base class for ast nodes."""
2.28 + def getChildren(self):
2.29 + pass # implemented by subclasses
2.30 + def __iter__(self):
2.31 + for n in self.getChildren():
2.32 + yield n
2.33 + def asList(self): # for backwards compatibility
2.34 + return self.getChildren()
2.35 + def getChildNodes(self):
2.36 + pass # implemented by subclasses
2.37 +
2.38 +class EmptyNode(Node):
2.39 + pass
2.40 +
2.41 +class Expression(Node):
2.42 + # Expression is an artificial node class to support "eval"
2.43 + nodes["expression"] = "Expression"
2.44 + def __init__(self, node):
2.45 + self.node = node
2.46 +
2.47 + def getChildren(self):
2.48 + return self.node,
2.49 +
2.50 + def getChildNodes(self):
2.51 + return self.node,
2.52 +
2.53 + def __repr__(self):
2.54 + return "Expression(%s)" % (repr(self.node))
2.55 +
2.56 +class Add(Node):
2.57 + def __init__(self, leftright, lineno=None):
2.58 + self.left = leftright[0]
2.59 + self.right = leftright[1]
2.60 + self.lineno = lineno
2.61 +
2.62 + def getChildren(self):
2.63 + return self.left, self.right
2.64 +
2.65 + def getChildNodes(self):
2.66 + return self.left, self.right
2.67 +
2.68 + def __repr__(self):
2.69 + return "Add((%s, %s))" % (repr(self.left), repr(self.right))
2.70 +
2.71 +class And(Node):
2.72 + def __init__(self, nodes, lineno=None):
2.73 + self.nodes = nodes
2.74 + self.lineno = lineno
2.75 +
2.76 + def getChildren(self):
2.77 + return tuple(flatten(self.nodes))
2.78 +
2.79 + def getChildNodes(self):
2.80 + nodelist = []
2.81 + nodelist.extend(flatten_nodes(self.nodes))
2.82 + return tuple(nodelist)
2.83 +
2.84 + def __repr__(self):
2.85 + return "And(%s)" % (repr(self.nodes),)
2.86 +
2.87 +class AssAttr(Node):
2.88 + def __init__(self, expr, attrname, flags, lineno=None):
2.89 + self.expr = expr
2.90 + self.attrname = attrname
2.91 + self.flags = flags
2.92 + self.lineno = lineno
2.93 +
2.94 + def getChildren(self):
2.95 + return self.expr, self.attrname, self.flags
2.96 +
2.97 + def getChildNodes(self):
2.98 + return self.expr,
2.99 +
2.100 + def __repr__(self):
2.101 + return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags))
2.102 +
2.103 +class AssList(Node):
2.104 + def __init__(self, nodes, lineno=None):
2.105 + self.nodes = nodes
2.106 + self.lineno = lineno
2.107 +
2.108 + def getChildren(self):
2.109 + return tuple(flatten(self.nodes))
2.110 +
2.111 + def getChildNodes(self):
2.112 + nodelist = []
2.113 + nodelist.extend(flatten_nodes(self.nodes))
2.114 + return tuple(nodelist)
2.115 +
2.116 + def __repr__(self):
2.117 + return "AssList(%s)" % (repr(self.nodes),)
2.118 +
2.119 +class AssName(Node):
2.120 + def __init__(self, name, flags, lineno=None):
2.121 + self.name = name
2.122 + self.flags = flags
2.123 + self.lineno = lineno
2.124 +
2.125 + def getChildren(self):
2.126 + return self.name, self.flags
2.127 +
2.128 + def getChildNodes(self):
2.129 + return ()
2.130 +
2.131 + def __repr__(self):
2.132 + return "AssName(%s, %s)" % (repr(self.name), repr(self.flags))
2.133 +
2.134 +class AssTuple(Node):
2.135 + def __init__(self, nodes, lineno=None):
2.136 + self.nodes = nodes
2.137 + self.lineno = lineno
2.138 +
2.139 + def getChildren(self):
2.140 + return tuple(flatten(self.nodes))
2.141 +
2.142 + def getChildNodes(self):
2.143 + nodelist = []
2.144 + nodelist.extend(flatten_nodes(self.nodes))
2.145 + return tuple(nodelist)
2.146 +
2.147 + def __repr__(self):
2.148 + return "AssTuple(%s)" % (repr(self.nodes),)
2.149 +
2.150 +class Assert(Node):
2.151 + def __init__(self, test, fail, lineno=None):
2.152 + self.test = test
2.153 + self.fail = fail
2.154 + self.lineno = lineno
2.155 +
2.156 + def getChildren(self):
2.157 + children = []
2.158 + children.append(self.test)
2.159 + children.append(self.fail)
2.160 + return tuple(children)
2.161 +
2.162 + def getChildNodes(self):
2.163 + nodelist = []
2.164 + nodelist.append(self.test)
2.165 + if self.fail is not None:
2.166 + nodelist.append(self.fail)
2.167 + return tuple(nodelist)
2.168 +
2.169 + def __repr__(self):
2.170 + return "Assert(%s, %s)" % (repr(self.test), repr(self.fail))
2.171 +
2.172 +class Assign(Node):
2.173 + def __init__(self, nodes, expr, lineno=None):
2.174 + self.nodes = nodes
2.175 + self.expr = expr
2.176 + self.lineno = lineno
2.177 +
2.178 + def getChildren(self):
2.179 + children = []
2.180 + children.extend(flatten(self.nodes))
2.181 + children.append(self.expr)
2.182 + return tuple(children)
2.183 +
2.184 + def getChildNodes(self):
2.185 + nodelist = []
2.186 + nodelist.extend(flatten_nodes(self.nodes))
2.187 + nodelist.append(self.expr)
2.188 + return tuple(nodelist)
2.189 +
2.190 + def __repr__(self):
2.191 + return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr))
2.192 +
2.193 +class AugAssign(Node):
2.194 + def __init__(self, node, op, expr, lineno=None):
2.195 + self.node = node
2.196 + self.op = op
2.197 + self.expr = expr
2.198 + self.lineno = lineno
2.199 +
2.200 + def getChildren(self):
2.201 + return self.node, self.op, self.expr
2.202 +
2.203 + def getChildNodes(self):
2.204 + return self.node, self.expr
2.205 +
2.206 + def __repr__(self):
2.207 + return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr))
2.208 +
2.209 +class Backquote(Node):
2.210 + def __init__(self, expr, lineno=None):
2.211 + self.expr = expr
2.212 + self.lineno = lineno
2.213 +
2.214 + def getChildren(self):
2.215 + return self.expr,
2.216 +
2.217 + def getChildNodes(self):
2.218 + return self.expr,
2.219 +
2.220 + def __repr__(self):
2.221 + return "Backquote(%s)" % (repr(self.expr),)
2.222 +
2.223 +class Bitand(Node):
2.224 + def __init__(self, nodes, lineno=None):
2.225 + self.nodes = nodes
2.226 + self.lineno = lineno
2.227 +
2.228 + def getChildren(self):
2.229 + return tuple(flatten(self.nodes))
2.230 +
2.231 + def getChildNodes(self):
2.232 + nodelist = []
2.233 + nodelist.extend(flatten_nodes(self.nodes))
2.234 + return tuple(nodelist)
2.235 +
2.236 + def __repr__(self):
2.237 + return "Bitand(%s)" % (repr(self.nodes),)
2.238 +
2.239 +class Bitor(Node):
2.240 + def __init__(self, nodes, lineno=None):
2.241 + self.nodes = nodes
2.242 + self.lineno = lineno
2.243 +
2.244 + def getChildren(self):
2.245 + return tuple(flatten(self.nodes))
2.246 +
2.247 + def getChildNodes(self):
2.248 + nodelist = []
2.249 + nodelist.extend(flatten_nodes(self.nodes))
2.250 + return tuple(nodelist)
2.251 +
2.252 + def __repr__(self):
2.253 + return "Bitor(%s)" % (repr(self.nodes),)
2.254 +
2.255 +class Bitxor(Node):
2.256 + def __init__(self, nodes, lineno=None):
2.257 + self.nodes = nodes
2.258 + self.lineno = lineno
2.259 +
2.260 + def getChildren(self):
2.261 + return tuple(flatten(self.nodes))
2.262 +
2.263 + def getChildNodes(self):
2.264 + nodelist = []
2.265 + nodelist.extend(flatten_nodes(self.nodes))
2.266 + return tuple(nodelist)
2.267 +
2.268 + def __repr__(self):
2.269 + return "Bitxor(%s)" % (repr(self.nodes),)
2.270 +
2.271 +class Break(Node):
2.272 + def __init__(self, lineno=None):
2.273 + self.lineno = lineno
2.274 +
2.275 + def getChildren(self):
2.276 + return ()
2.277 +
2.278 + def getChildNodes(self):
2.279 + return ()
2.280 +
2.281 + def __repr__(self):
2.282 + return "Break()"
2.283 +
2.284 +class CallFunc(Node):
2.285 + def __init__(self, node, args, star_args = None, dstar_args = None, lineno=None):
2.286 + self.node = node
2.287 + self.args = args
2.288 + self.star_args = star_args
2.289 + self.dstar_args = dstar_args
2.290 + self.lineno = lineno
2.291 +
2.292 + def getChildren(self):
2.293 + children = []
2.294 + children.append(self.node)
2.295 + children.extend(flatten(self.args))
2.296 + children.append(self.star_args)
2.297 + children.append(self.dstar_args)
2.298 + return tuple(children)
2.299 +
2.300 + def getChildNodes(self):
2.301 + nodelist = []
2.302 + nodelist.append(self.node)
2.303 + nodelist.extend(flatten_nodes(self.args))
2.304 + if self.star_args is not None:
2.305 + nodelist.append(self.star_args)
2.306 + if self.dstar_args is not None:
2.307 + nodelist.append(self.dstar_args)
2.308 + return tuple(nodelist)
2.309 +
2.310 + def __repr__(self):
2.311 + return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args))
2.312 +
2.313 +class Class(Node):
2.314 + def __init__(self, name, bases, doc, code, decorators = None, lineno=None):
2.315 + self.name = name
2.316 + self.bases = bases
2.317 + self.doc = doc
2.318 + self.code = code
2.319 + self.decorators = decorators
2.320 + self.lineno = lineno
2.321 +
2.322 + def getChildren(self):
2.323 + children = []
2.324 + children.append(self.name)
2.325 + children.extend(flatten(self.bases))
2.326 + children.append(self.doc)
2.327 + children.append(self.code)
2.328 + children.append(self.decorators)
2.329 + return tuple(children)
2.330 +
2.331 + def getChildNodes(self):
2.332 + nodelist = []
2.333 + nodelist.extend(flatten_nodes(self.bases))
2.334 + nodelist.append(self.code)
2.335 + if self.decorators is not None:
2.336 + nodelist.append(self.decorators)
2.337 + return tuple(nodelist)
2.338 +
2.339 + def __repr__(self):
2.340 + return "Class(%s, %s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code), repr(self.decorators))
2.341 +
2.342 +class Compare(Node):
2.343 + def __init__(self, expr, ops, lineno=None):
2.344 + self.expr = expr
2.345 + self.ops = ops
2.346 + self.lineno = lineno
2.347 +
2.348 + def getChildren(self):
2.349 + children = []
2.350 + children.append(self.expr)
2.351 + children.extend(flatten(self.ops))
2.352 + return tuple(children)
2.353 +
2.354 + def getChildNodes(self):
2.355 + nodelist = []
2.356 + nodelist.append(self.expr)
2.357 + nodelist.extend(flatten_nodes(self.ops))
2.358 + return tuple(nodelist)
2.359 +
2.360 + def __repr__(self):
2.361 + return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops))
2.362 +
2.363 +class Const(Node):
2.364 + def __init__(self, value, lineno=None):
2.365 + self.value = value
2.366 + self.lineno = lineno
2.367 +
2.368 + def getChildren(self):
2.369 + return self.value,
2.370 +
2.371 + def getChildNodes(self):
2.372 + return ()
2.373 +
2.374 + def __repr__(self):
2.375 + return "Const(%s)" % (repr(self.value),)
2.376 +
2.377 +class Continue(Node):
2.378 + def __init__(self, lineno=None):
2.379 + self.lineno = lineno
2.380 +
2.381 + def getChildren(self):
2.382 + return ()
2.383 +
2.384 + def getChildNodes(self):
2.385 + return ()
2.386 +
2.387 + def __repr__(self):
2.388 + return "Continue()"
2.389 +
2.390 +class Decorators(Node):
2.391 + def __init__(self, nodes, lineno=None):
2.392 + self.nodes = nodes
2.393 + self.lineno = lineno
2.394 +
2.395 + def getChildren(self):
2.396 + return tuple(flatten(self.nodes))
2.397 +
2.398 + def getChildNodes(self):
2.399 + nodelist = []
2.400 + nodelist.extend(flatten_nodes(self.nodes))
2.401 + return tuple(nodelist)
2.402 +
2.403 + def __repr__(self):
2.404 + return "Decorators(%s)" % (repr(self.nodes),)
2.405 +
2.406 +class Dict(Node):
2.407 + def __init__(self, items, lineno=None):
2.408 + self.items = items
2.409 + self.lineno = lineno
2.410 +
2.411 + def getChildren(self):
2.412 + return tuple(flatten(self.items))
2.413 +
2.414 + def getChildNodes(self):
2.415 + nodelist = []
2.416 + nodelist.extend(flatten_nodes(self.items))
2.417 + return tuple(nodelist)
2.418 +
2.419 + def __repr__(self):
2.420 + return "Dict(%s)" % (repr(self.items),)
2.421 +
2.422 +class Discard(Node):
2.423 + def __init__(self, expr, lineno=None):
2.424 + self.expr = expr
2.425 + self.lineno = lineno
2.426 +
2.427 + def getChildren(self):
2.428 + return self.expr,
2.429 +
2.430 + def getChildNodes(self):
2.431 + return self.expr,
2.432 +
2.433 + def __repr__(self):
2.434 + return "Discard(%s)" % (repr(self.expr),)
2.435 +
2.436 +class Div(Node):
2.437 + def __init__(self, leftright, lineno=None):
2.438 + self.left = leftright[0]
2.439 + self.right = leftright[1]
2.440 + self.lineno = lineno
2.441 +
2.442 + def getChildren(self):
2.443 + return self.left, self.right
2.444 +
2.445 + def getChildNodes(self):
2.446 + return self.left, self.right
2.447 +
2.448 + def __repr__(self):
2.449 + return "Div((%s, %s))" % (repr(self.left), repr(self.right))
2.450 +
2.451 +class Ellipsis(Node):
2.452 + def __init__(self, lineno=None):
2.453 + self.lineno = lineno
2.454 +
2.455 + def getChildren(self):
2.456 + return ()
2.457 +
2.458 + def getChildNodes(self):
2.459 + return ()
2.460 +
2.461 + def __repr__(self):
2.462 + return "Ellipsis()"
2.463 +
2.464 +class Exec(Node):
2.465 + def __init__(self, expr, locals, globals, lineno=None):
2.466 + self.expr = expr
2.467 + self.locals = locals
2.468 + self.globals = globals
2.469 + self.lineno = lineno
2.470 +
2.471 + def getChildren(self):
2.472 + children = []
2.473 + children.append(self.expr)
2.474 + children.append(self.locals)
2.475 + children.append(self.globals)
2.476 + return tuple(children)
2.477 +
2.478 + def getChildNodes(self):
2.479 + nodelist = []
2.480 + nodelist.append(self.expr)
2.481 + if self.locals is not None:
2.482 + nodelist.append(self.locals)
2.483 + if self.globals is not None:
2.484 + nodelist.append(self.globals)
2.485 + return tuple(nodelist)
2.486 +
2.487 + def __repr__(self):
2.488 + return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals))
2.489 +
2.490 +class FloorDiv(Node):
2.491 + def __init__(self, leftright, lineno=None):
2.492 + self.left = leftright[0]
2.493 + self.right = leftright[1]
2.494 + self.lineno = lineno
2.495 +
2.496 + def getChildren(self):
2.497 + return self.left, self.right
2.498 +
2.499 + def getChildNodes(self):
2.500 + return self.left, self.right
2.501 +
2.502 + def __repr__(self):
2.503 + return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right))
2.504 +
2.505 +class For(Node):
2.506 + def __init__(self, assign, list, body, else_, lineno=None):
2.507 + self.assign = assign
2.508 + self.list = list
2.509 + self.body = body
2.510 + self.else_ = else_
2.511 + self.lineno = lineno
2.512 +
2.513 + def getChildren(self):
2.514 + children = []
2.515 + children.append(self.assign)
2.516 + children.append(self.list)
2.517 + children.append(self.body)
2.518 + children.append(self.else_)
2.519 + return tuple(children)
2.520 +
2.521 + def getChildNodes(self):
2.522 + nodelist = []
2.523 + nodelist.append(self.assign)
2.524 + nodelist.append(self.list)
2.525 + nodelist.append(self.body)
2.526 + if self.else_ is not None:
2.527 + nodelist.append(self.else_)
2.528 + return tuple(nodelist)
2.529 +
2.530 + def __repr__(self):
2.531 + return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_))
2.532 +
2.533 +class From(Node):
2.534 + def __init__(self, modname, names, level, lineno=None):
2.535 + self.modname = modname
2.536 + self.names = names
2.537 + self.level = level
2.538 + self.lineno = lineno
2.539 +
2.540 + def getChildren(self):
2.541 + return self.modname, self.names, self.level
2.542 +
2.543 + def getChildNodes(self):
2.544 + return ()
2.545 +
2.546 + def __repr__(self):
2.547 + return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level))
2.548 +
2.549 +class Function(Node):
2.550 + def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None):
2.551 + self.decorators = decorators
2.552 + self.name = name
2.553 + self.argnames = argnames
2.554 + self.defaults = defaults
2.555 + self.flags = flags
2.556 + self.doc = doc
2.557 + self.code = code
2.558 + self.lineno = lineno
2.559 + self.varargs = self.kwargs = None
2.560 + if flags & CO_VARARGS:
2.561 + self.varargs = 1
2.562 + if flags & CO_VARKEYWORDS:
2.563 + self.kwargs = 1
2.564 +
2.565 +
2.566 + def getChildren(self):
2.567 + children = []
2.568 + children.append(self.decorators)
2.569 + children.append(self.name)
2.570 + children.append(self.argnames)
2.571 + children.extend(flatten(self.defaults))
2.572 + children.append(self.flags)
2.573 + children.append(self.doc)
2.574 + children.append(self.code)
2.575 + return tuple(children)
2.576 +
2.577 + def getChildNodes(self):
2.578 + nodelist = []
2.579 + if self.decorators is not None:
2.580 + nodelist.append(self.decorators)
2.581 + nodelist.extend(flatten_nodes(self.defaults))
2.582 + nodelist.append(self.code)
2.583 + return tuple(nodelist)
2.584 +
2.585 + def __repr__(self):
2.586 + 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))
2.587 +
2.588 +class GenExpr(Node):
2.589 + def __init__(self, code, lineno=None):
2.590 + self.code = code
2.591 + self.lineno = lineno
2.592 + self.argnames = ['.0']
2.593 + self.varargs = self.kwargs = None
2.594 +
2.595 +
2.596 + def getChildren(self):
2.597 + return self.code,
2.598 +
2.599 + def getChildNodes(self):
2.600 + return self.code,
2.601 +
2.602 + def __repr__(self):
2.603 + return "GenExpr(%s)" % (repr(self.code),)
2.604 +
2.605 +class GenExprFor(Node):
2.606 + def __init__(self, assign, iter, ifs, lineno=None):
2.607 + self.assign = assign
2.608 + self.iter = iter
2.609 + self.ifs = ifs
2.610 + self.lineno = lineno
2.611 + self.is_outmost = False
2.612 +
2.613 + def getChildren(self):
2.614 + children = []
2.615 + children.append(self.assign)
2.616 + children.append(self.iter)
2.617 + children.extend(flatten(self.ifs))
2.618 + return tuple(children)
2.619 +
2.620 + def getChildNodes(self):
2.621 + nodelist = []
2.622 + nodelist.append(self.assign)
2.623 + nodelist.append(self.iter)
2.624 + nodelist.extend(flatten_nodes(self.ifs))
2.625 + return tuple(nodelist)
2.626 +
2.627 + def __repr__(self):
2.628 + return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs))
2.629 +
2.630 +class GenExprIf(Node):
2.631 + def __init__(self, test, lineno=None):
2.632 + self.test = test
2.633 + self.lineno = lineno
2.634 +
2.635 + def getChildren(self):
2.636 + return self.test,
2.637 +
2.638 + def getChildNodes(self):
2.639 + return self.test,
2.640 +
2.641 + def __repr__(self):
2.642 + return "GenExprIf(%s)" % (repr(self.test),)
2.643 +
2.644 +class GenExprInner(Node):
2.645 + def __init__(self, expr, quals, lineno=None):
2.646 + self.expr = expr
2.647 + self.quals = quals
2.648 + self.lineno = lineno
2.649 +
2.650 + def getChildren(self):
2.651 + children = []
2.652 + children.append(self.expr)
2.653 + children.extend(flatten(self.quals))
2.654 + return tuple(children)
2.655 +
2.656 + def getChildNodes(self):
2.657 + nodelist = []
2.658 + nodelist.append(self.expr)
2.659 + nodelist.extend(flatten_nodes(self.quals))
2.660 + return tuple(nodelist)
2.661 +
2.662 + def __repr__(self):
2.663 + return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals))
2.664 +
2.665 +class Getattr(Node):
2.666 + def __init__(self, expr, attrname, lineno=None):
2.667 + self.expr = expr
2.668 + self.attrname = attrname
2.669 + self.lineno = lineno
2.670 +
2.671 + def getChildren(self):
2.672 + return self.expr, self.attrname
2.673 +
2.674 + def getChildNodes(self):
2.675 + return self.expr,
2.676 +
2.677 + def __repr__(self):
2.678 + return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname))
2.679 +
2.680 +class Global(Node):
2.681 + def __init__(self, names, lineno=None):
2.682 + self.names = names
2.683 + self.lineno = lineno
2.684 +
2.685 + def getChildren(self):
2.686 + return self.names,
2.687 +
2.688 + def getChildNodes(self):
2.689 + return ()
2.690 +
2.691 + def __repr__(self):
2.692 + return "Global(%s)" % (repr(self.names),)
2.693 +
2.694 +class If(Node):
2.695 + def __init__(self, tests, else_, lineno=None):
2.696 + self.tests = tests
2.697 + self.else_ = else_
2.698 + self.lineno = lineno
2.699 +
2.700 + def getChildren(self):
2.701 + children = []
2.702 + children.extend(flatten(self.tests))
2.703 + children.append(self.else_)
2.704 + return tuple(children)
2.705 +
2.706 + def getChildNodes(self):
2.707 + nodelist = []
2.708 + nodelist.extend(flatten_nodes(self.tests))
2.709 + if self.else_ is not None:
2.710 + nodelist.append(self.else_)
2.711 + return tuple(nodelist)
2.712 +
2.713 + def __repr__(self):
2.714 + return "If(%s, %s)" % (repr(self.tests), repr(self.else_))
2.715 +
2.716 +class IfExp(Node):
2.717 + def __init__(self, test, then, else_, lineno=None):
2.718 + self.test = test
2.719 + self.then = then
2.720 + self.else_ = else_
2.721 + self.lineno = lineno
2.722 +
2.723 + def getChildren(self):
2.724 + return self.test, self.then, self.else_
2.725 +
2.726 + def getChildNodes(self):
2.727 + return self.test, self.then, self.else_
2.728 +
2.729 + def __repr__(self):
2.730 + return "IfExp(%s, %s, %s)" % (repr(self.test), repr(self.then), repr(self.else_))
2.731 +
2.732 +class Import(Node):
2.733 + def __init__(self, names, lineno=None):
2.734 + self.names = names
2.735 + self.lineno = lineno
2.736 +
2.737 + def getChildren(self):
2.738 + return self.names,
2.739 +
2.740 + def getChildNodes(self):
2.741 + return ()
2.742 +
2.743 + def __repr__(self):
2.744 + return "Import(%s)" % (repr(self.names),)
2.745 +
2.746 +class Invert(Node):
2.747 + def __init__(self, expr, lineno=None):
2.748 + self.expr = expr
2.749 + self.lineno = lineno
2.750 +
2.751 + def getChildren(self):
2.752 + return self.expr,
2.753 +
2.754 + def getChildNodes(self):
2.755 + return self.expr,
2.756 +
2.757 + def __repr__(self):
2.758 + return "Invert(%s)" % (repr(self.expr),)
2.759 +
2.760 +class Keyword(Node):
2.761 + def __init__(self, name, expr, lineno=None):
2.762 + self.name = name
2.763 + self.expr = expr
2.764 + self.lineno = lineno
2.765 +
2.766 + def getChildren(self):
2.767 + return self.name, self.expr
2.768 +
2.769 + def getChildNodes(self):
2.770 + return self.expr,
2.771 +
2.772 + def __repr__(self):
2.773 + return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
2.774 +
2.775 +class Lambda(Node):
2.776 + def __init__(self, argnames, defaults, flags, code, lineno=None):
2.777 + self.argnames = argnames
2.778 + self.defaults = defaults
2.779 + self.flags = flags
2.780 + self.code = code
2.781 + self.lineno = lineno
2.782 + self.varargs = self.kwargs = None
2.783 + if flags & CO_VARARGS:
2.784 + self.varargs = 1
2.785 + if flags & CO_VARKEYWORDS:
2.786 + self.kwargs = 1
2.787 +
2.788 +
2.789 + def getChildren(self):
2.790 + children = []
2.791 + children.append(self.argnames)
2.792 + children.extend(flatten(self.defaults))
2.793 + children.append(self.flags)
2.794 + children.append(self.code)
2.795 + return tuple(children)
2.796 +
2.797 + def getChildNodes(self):
2.798 + nodelist = []
2.799 + nodelist.extend(flatten_nodes(self.defaults))
2.800 + nodelist.append(self.code)
2.801 + return tuple(nodelist)
2.802 +
2.803 + def __repr__(self):
2.804 + return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code))
2.805 +
2.806 +class LeftShift(Node):
2.807 + def __init__(self, leftright, lineno=None):
2.808 + self.left = leftright[0]
2.809 + self.right = leftright[1]
2.810 + self.lineno = lineno
2.811 +
2.812 + def getChildren(self):
2.813 + return self.left, self.right
2.814 +
2.815 + def getChildNodes(self):
2.816 + return self.left, self.right
2.817 +
2.818 + def __repr__(self):
2.819 + return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right))
2.820 +
2.821 +class List(Node):
2.822 + def __init__(self, nodes, lineno=None):
2.823 + self.nodes = nodes
2.824 + self.lineno = lineno
2.825 +
2.826 + def getChildren(self):
2.827 + return tuple(flatten(self.nodes))
2.828 +
2.829 + def getChildNodes(self):
2.830 + nodelist = []
2.831 + nodelist.extend(flatten_nodes(self.nodes))
2.832 + return tuple(nodelist)
2.833 +
2.834 + def __repr__(self):
2.835 + return "List(%s)" % (repr(self.nodes),)
2.836 +
2.837 +class ListComp(Node):
2.838 + def __init__(self, expr, quals, lineno=None):
2.839 + self.expr = expr
2.840 + self.quals = quals
2.841 + self.lineno = lineno
2.842 +
2.843 + def getChildren(self):
2.844 + children = []
2.845 + children.append(self.expr)
2.846 + children.extend(flatten(self.quals))
2.847 + return tuple(children)
2.848 +
2.849 + def getChildNodes(self):
2.850 + nodelist = []
2.851 + nodelist.append(self.expr)
2.852 + nodelist.extend(flatten_nodes(self.quals))
2.853 + return tuple(nodelist)
2.854 +
2.855 + def __repr__(self):
2.856 + return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals))
2.857 +
2.858 +class ListCompFor(Node):
2.859 + def __init__(self, assign, list, ifs, lineno=None):
2.860 + self.assign = assign
2.861 + self.list = list
2.862 + self.ifs = ifs
2.863 + self.lineno = lineno
2.864 +
2.865 + def getChildren(self):
2.866 + children = []
2.867 + children.append(self.assign)
2.868 + children.append(self.list)
2.869 + children.extend(flatten(self.ifs))
2.870 + return tuple(children)
2.871 +
2.872 + def getChildNodes(self):
2.873 + nodelist = []
2.874 + nodelist.append(self.assign)
2.875 + nodelist.append(self.list)
2.876 + nodelist.extend(flatten_nodes(self.ifs))
2.877 + return tuple(nodelist)
2.878 +
2.879 + def __repr__(self):
2.880 + return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs))
2.881 +
2.882 +class ListCompIf(Node):
2.883 + def __init__(self, test, lineno=None):
2.884 + self.test = test
2.885 + self.lineno = lineno
2.886 +
2.887 + def getChildren(self):
2.888 + return self.test,
2.889 +
2.890 + def getChildNodes(self):
2.891 + return self.test,
2.892 +
2.893 + def __repr__(self):
2.894 + return "ListCompIf(%s)" % (repr(self.test),)
2.895 +
2.896 +class Mod(Node):
2.897 + def __init__(self, leftright, lineno=None):
2.898 + self.left = leftright[0]
2.899 + self.right = leftright[1]
2.900 + self.lineno = lineno
2.901 +
2.902 + def getChildren(self):
2.903 + return self.left, self.right
2.904 +
2.905 + def getChildNodes(self):
2.906 + return self.left, self.right
2.907 +
2.908 + def __repr__(self):
2.909 + return "Mod((%s, %s))" % (repr(self.left), repr(self.right))
2.910 +
2.911 +class Module(Node):
2.912 + def __init__(self, doc, node, lineno=None):
2.913 + self.doc = doc
2.914 + self.node = node
2.915 + self.lineno = lineno
2.916 +
2.917 + def getChildren(self):
2.918 + return self.doc, self.node
2.919 +
2.920 + def getChildNodes(self):
2.921 + return self.node,
2.922 +
2.923 + def __repr__(self):
2.924 + return "Module(%s, %s)" % (repr(self.doc), repr(self.node))
2.925 +
2.926 +class Mul(Node):
2.927 + def __init__(self, leftright, lineno=None):
2.928 + self.left = leftright[0]
2.929 + self.right = leftright[1]
2.930 + self.lineno = lineno
2.931 +
2.932 + def getChildren(self):
2.933 + return self.left, self.right
2.934 +
2.935 + def getChildNodes(self):
2.936 + return self.left, self.right
2.937 +
2.938 + def __repr__(self):
2.939 + return "Mul((%s, %s))" % (repr(self.left), repr(self.right))
2.940 +
2.941 +class Name(Node):
2.942 + def __init__(self, name, lineno=None):
2.943 + self.name = name
2.944 + self.lineno = lineno
2.945 +
2.946 + def getChildren(self):
2.947 + return self.name,
2.948 +
2.949 + def getChildNodes(self):
2.950 + return ()
2.951 +
2.952 + def __repr__(self):
2.953 + return "Name(%s)" % (repr(self.name),)
2.954 +
2.955 +class Not(Node):
2.956 + def __init__(self, expr, lineno=None):
2.957 + self.expr = expr
2.958 + self.lineno = lineno
2.959 +
2.960 + def getChildren(self):
2.961 + return self.expr,
2.962 +
2.963 + def getChildNodes(self):
2.964 + return self.expr,
2.965 +
2.966 + def __repr__(self):
2.967 + return "Not(%s)" % (repr(self.expr),)
2.968 +
2.969 +class Or(Node):
2.970 + def __init__(self, nodes, lineno=None):
2.971 + self.nodes = nodes
2.972 + self.lineno = lineno
2.973 +
2.974 + def getChildren(self):
2.975 + return tuple(flatten(self.nodes))
2.976 +
2.977 + def getChildNodes(self):
2.978 + nodelist = []
2.979 + nodelist.extend(flatten_nodes(self.nodes))
2.980 + return tuple(nodelist)
2.981 +
2.982 + def __repr__(self):
2.983 + return "Or(%s)" % (repr(self.nodes),)
2.984 +
2.985 +class Pass(Node):
2.986 + def __init__(self, lineno=None):
2.987 + self.lineno = lineno
2.988 +
2.989 + def getChildren(self):
2.990 + return ()
2.991 +
2.992 + def getChildNodes(self):
2.993 + return ()
2.994 +
2.995 + def __repr__(self):
2.996 + return "Pass()"
2.997 +
2.998 +class Power(Node):
2.999 + def __init__(self, leftright, lineno=None):
2.1000 + self.left = leftright[0]
2.1001 + self.right = leftright[1]
2.1002 + self.lineno = lineno
2.1003 +
2.1004 + def getChildren(self):
2.1005 + return self.left, self.right
2.1006 +
2.1007 + def getChildNodes(self):
2.1008 + return self.left, self.right
2.1009 +
2.1010 + def __repr__(self):
2.1011 + return "Power((%s, %s))" % (repr(self.left), repr(self.right))
2.1012 +
2.1013 +class Print(Node):
2.1014 + def __init__(self, nodes, dest, lineno=None):
2.1015 + self.nodes = nodes
2.1016 + self.dest = dest
2.1017 + self.lineno = lineno
2.1018 +
2.1019 + def getChildren(self):
2.1020 + children = []
2.1021 + children.extend(flatten(self.nodes))
2.1022 + children.append(self.dest)
2.1023 + return tuple(children)
2.1024 +
2.1025 + def getChildNodes(self):
2.1026 + nodelist = []
2.1027 + nodelist.extend(flatten_nodes(self.nodes))
2.1028 + if self.dest is not None:
2.1029 + nodelist.append(self.dest)
2.1030 + return tuple(nodelist)
2.1031 +
2.1032 + def __repr__(self):
2.1033 + return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest))
2.1034 +
2.1035 +class Printnl(Node):
2.1036 + def __init__(self, nodes, dest, lineno=None):
2.1037 + self.nodes = nodes
2.1038 + self.dest = dest
2.1039 + self.lineno = lineno
2.1040 +
2.1041 + def getChildren(self):
2.1042 + children = []
2.1043 + children.extend(flatten(self.nodes))
2.1044 + children.append(self.dest)
2.1045 + return tuple(children)
2.1046 +
2.1047 + def getChildNodes(self):
2.1048 + nodelist = []
2.1049 + nodelist.extend(flatten_nodes(self.nodes))
2.1050 + if self.dest is not None:
2.1051 + nodelist.append(self.dest)
2.1052 + return tuple(nodelist)
2.1053 +
2.1054 + def __repr__(self):
2.1055 + return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest))
2.1056 +
2.1057 +class Raise(Node):
2.1058 + def __init__(self, expr1, expr2, expr3, lineno=None):
2.1059 + self.expr1 = expr1
2.1060 + self.expr2 = expr2
2.1061 + self.expr3 = expr3
2.1062 + self.lineno = lineno
2.1063 +
2.1064 + def getChildren(self):
2.1065 + children = []
2.1066 + children.append(self.expr1)
2.1067 + children.append(self.expr2)
2.1068 + children.append(self.expr3)
2.1069 + return tuple(children)
2.1070 +
2.1071 + def getChildNodes(self):
2.1072 + nodelist = []
2.1073 + if self.expr1 is not None:
2.1074 + nodelist.append(self.expr1)
2.1075 + if self.expr2 is not None:
2.1076 + nodelist.append(self.expr2)
2.1077 + if self.expr3 is not None:
2.1078 + nodelist.append(self.expr3)
2.1079 + return tuple(nodelist)
2.1080 +
2.1081 + def __repr__(self):
2.1082 + return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3))
2.1083 +
2.1084 +class Return(Node):
2.1085 + def __init__(self, value, lineno=None):
2.1086 + self.value = value
2.1087 + self.lineno = lineno
2.1088 +
2.1089 + def getChildren(self):
2.1090 + return self.value,
2.1091 +
2.1092 + def getChildNodes(self):
2.1093 + return self.value,
2.1094 +
2.1095 + def __repr__(self):
2.1096 + return "Return(%s)" % (repr(self.value),)
2.1097 +
2.1098 +class RightShift(Node):
2.1099 + def __init__(self, leftright, lineno=None):
2.1100 + self.left = leftright[0]
2.1101 + self.right = leftright[1]
2.1102 + self.lineno = lineno
2.1103 +
2.1104 + def getChildren(self):
2.1105 + return self.left, self.right
2.1106 +
2.1107 + def getChildNodes(self):
2.1108 + return self.left, self.right
2.1109 +
2.1110 + def __repr__(self):
2.1111 + return "RightShift((%s, %s))" % (repr(self.left), repr(self.right))
2.1112 +
2.1113 +class Slice(Node):
2.1114 + def __init__(self, expr, flags, lower, upper, lineno=None):
2.1115 + self.expr = expr
2.1116 + self.flags = flags
2.1117 + self.lower = lower
2.1118 + self.upper = upper
2.1119 + self.lineno = lineno
2.1120 +
2.1121 + def getChildren(self):
2.1122 + children = []
2.1123 + children.append(self.expr)
2.1124 + children.append(self.flags)
2.1125 + children.append(self.lower)
2.1126 + children.append(self.upper)
2.1127 + return tuple(children)
2.1128 +
2.1129 + def getChildNodes(self):
2.1130 + nodelist = []
2.1131 + nodelist.append(self.expr)
2.1132 + if self.lower is not None:
2.1133 + nodelist.append(self.lower)
2.1134 + if self.upper is not None:
2.1135 + nodelist.append(self.upper)
2.1136 + return tuple(nodelist)
2.1137 +
2.1138 + def __repr__(self):
2.1139 + return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper))
2.1140 +
2.1141 +class Sliceobj(Node):
2.1142 + def __init__(self, nodes, lineno=None):
2.1143 + self.nodes = nodes
2.1144 + self.lineno = lineno
2.1145 +
2.1146 + def getChildren(self):
2.1147 + return tuple(flatten(self.nodes))
2.1148 +
2.1149 + def getChildNodes(self):
2.1150 + nodelist = []
2.1151 + nodelist.extend(flatten_nodes(self.nodes))
2.1152 + return tuple(nodelist)
2.1153 +
2.1154 + def __repr__(self):
2.1155 + return "Sliceobj(%s)" % (repr(self.nodes),)
2.1156 +
2.1157 +class Stmt(Node):
2.1158 + def __init__(self, nodes, lineno=None):
2.1159 + self.nodes = nodes
2.1160 + self.lineno = lineno
2.1161 +
2.1162 + def getChildren(self):
2.1163 + return tuple(flatten(self.nodes))
2.1164 +
2.1165 + def getChildNodes(self):
2.1166 + nodelist = []
2.1167 + nodelist.extend(flatten_nodes(self.nodes))
2.1168 + return tuple(nodelist)
2.1169 +
2.1170 + def __repr__(self):
2.1171 + return "Stmt(%s)" % (repr(self.nodes),)
2.1172 +
2.1173 +class Sub(Node):
2.1174 + def __init__(self, leftright, lineno=None):
2.1175 + self.left = leftright[0]
2.1176 + self.right = leftright[1]
2.1177 + self.lineno = lineno
2.1178 +
2.1179 + def getChildren(self):
2.1180 + return self.left, self.right
2.1181 +
2.1182 + def getChildNodes(self):
2.1183 + return self.left, self.right
2.1184 +
2.1185 + def __repr__(self):
2.1186 + return "Sub((%s, %s))" % (repr(self.left), repr(self.right))
2.1187 +
2.1188 +class Subscript(Node):
2.1189 + def __init__(self, expr, flags, subs, lineno=None):
2.1190 + self.expr = expr
2.1191 + self.flags = flags
2.1192 + self.subs = subs
2.1193 + self.lineno = lineno
2.1194 +
2.1195 + def getChildren(self):
2.1196 + children = []
2.1197 + children.append(self.expr)
2.1198 + children.append(self.flags)
2.1199 + children.extend(flatten(self.subs))
2.1200 + return tuple(children)
2.1201 +
2.1202 + def getChildNodes(self):
2.1203 + nodelist = []
2.1204 + nodelist.append(self.expr)
2.1205 + nodelist.extend(flatten_nodes(self.subs))
2.1206 + return tuple(nodelist)
2.1207 +
2.1208 + def __repr__(self):
2.1209 + return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs))
2.1210 +
2.1211 +class TryExcept(Node):
2.1212 + def __init__(self, body, handlers, else_, lineno=None):
2.1213 + self.body = body
2.1214 + self.handlers = handlers
2.1215 + self.else_ = else_
2.1216 + self.lineno = lineno
2.1217 +
2.1218 + def getChildren(self):
2.1219 + children = []
2.1220 + children.append(self.body)
2.1221 + children.extend(flatten(self.handlers))
2.1222 + children.append(self.else_)
2.1223 + return tuple(children)
2.1224 +
2.1225 + def getChildNodes(self):
2.1226 + nodelist = []
2.1227 + nodelist.append(self.body)
2.1228 + nodelist.extend(flatten_nodes(self.handlers))
2.1229 + if self.else_ is not None:
2.1230 + nodelist.append(self.else_)
2.1231 + return tuple(nodelist)
2.1232 +
2.1233 + def __repr__(self):
2.1234 + return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_))
2.1235 +
2.1236 +class TryFinally(Node):
2.1237 + def __init__(self, body, final, lineno=None):
2.1238 + self.body = body
2.1239 + self.final = final
2.1240 + self.lineno = lineno
2.1241 +
2.1242 + def getChildren(self):
2.1243 + return self.body, self.final
2.1244 +
2.1245 + def getChildNodes(self):
2.1246 + return self.body, self.final
2.1247 +
2.1248 + def __repr__(self):
2.1249 + return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final))
2.1250 +
2.1251 +class Tuple(Node):
2.1252 + def __init__(self, nodes, lineno=None):
2.1253 + self.nodes = nodes
2.1254 + self.lineno = lineno
2.1255 +
2.1256 + def getChildren(self):
2.1257 + return tuple(flatten(self.nodes))
2.1258 +
2.1259 + def getChildNodes(self):
2.1260 + nodelist = []
2.1261 + nodelist.extend(flatten_nodes(self.nodes))
2.1262 + return tuple(nodelist)
2.1263 +
2.1264 + def __repr__(self):
2.1265 + return "Tuple(%s)" % (repr(self.nodes),)
2.1266 +
2.1267 +class UnaryAdd(Node):
2.1268 + def __init__(self, expr, lineno=None):
2.1269 + self.expr = expr
2.1270 + self.lineno = lineno
2.1271 +
2.1272 + def getChildren(self):
2.1273 + return self.expr,
2.1274 +
2.1275 + def getChildNodes(self):
2.1276 + return self.expr,
2.1277 +
2.1278 + def __repr__(self):
2.1279 + return "UnaryAdd(%s)" % (repr(self.expr),)
2.1280 +
2.1281 +class UnarySub(Node):
2.1282 + def __init__(self, expr, lineno=None):
2.1283 + self.expr = expr
2.1284 + self.lineno = lineno
2.1285 +
2.1286 + def getChildren(self):
2.1287 + return self.expr,
2.1288 +
2.1289 + def getChildNodes(self):
2.1290 + return self.expr,
2.1291 +
2.1292 + def __repr__(self):
2.1293 + return "UnarySub(%s)" % (repr(self.expr),)
2.1294 +
2.1295 +class While(Node):
2.1296 + def __init__(self, test, body, else_, lineno=None):
2.1297 + self.test = test
2.1298 + self.body = body
2.1299 + self.else_ = else_
2.1300 + self.lineno = lineno
2.1301 +
2.1302 + def getChildren(self):
2.1303 + children = []
2.1304 + children.append(self.test)
2.1305 + children.append(self.body)
2.1306 + children.append(self.else_)
2.1307 + return tuple(children)
2.1308 +
2.1309 + def getChildNodes(self):
2.1310 + nodelist = []
2.1311 + nodelist.append(self.test)
2.1312 + nodelist.append(self.body)
2.1313 + if self.else_ is not None:
2.1314 + nodelist.append(self.else_)
2.1315 + return tuple(nodelist)
2.1316 +
2.1317 + def __repr__(self):
2.1318 + return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_))
2.1319 +
2.1320 +class With(Node):
2.1321 + def __init__(self, expr, vars, body, lineno=None):
2.1322 + self.expr = expr
2.1323 + self.vars = vars
2.1324 + self.body = body
2.1325 + self.lineno = lineno
2.1326 +
2.1327 + def getChildren(self):
2.1328 + children = []
2.1329 + children.append(self.expr)
2.1330 + children.append(self.vars)
2.1331 + children.append(self.body)
2.1332 + return tuple(children)
2.1333 +
2.1334 + def getChildNodes(self):
2.1335 + nodelist = []
2.1336 + nodelist.append(self.expr)
2.1337 + if self.vars is not None:
2.1338 + nodelist.append(self.vars)
2.1339 + nodelist.append(self.body)
2.1340 + return tuple(nodelist)
2.1341 +
2.1342 + def __repr__(self):
2.1343 + return "With(%s, %s, %s)" % (repr(self.expr), repr(self.vars), repr(self.body))
2.1344 +
2.1345 +class Yield(Node):
2.1346 + def __init__(self, value, lineno=None):
2.1347 + self.value = value
2.1348 + self.lineno = lineno
2.1349 +
2.1350 + def getChildren(self):
2.1351 + return self.value,
2.1352 +
2.1353 + def getChildNodes(self):
2.1354 + return self.value,
2.1355 +
2.1356 + def __repr__(self):
2.1357 + return "Yield(%s)" % (repr(self.value),)
2.1358 +
2.1359 +for name, obj in globals().items():
2.1360 + if isinstance(obj, type) and issubclass(obj, Node):
2.1361 + nodes[name.lower()] = obj
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/compiler/consts.py Fri May 18 20:51:41 2012 +0200
3.3 @@ -0,0 +1,22 @@
3.4 +# operation flags
3.5 +OP_ASSIGN = 'OP_ASSIGN'
3.6 +OP_DELETE = 'OP_DELETE'
3.7 +OP_APPLY = 'OP_APPLY'
3.8 +
3.9 +SC_LOCAL = 1
3.10 +SC_GLOBAL = 2
3.11 +SC_FREE = 3
3.12 +SC_CELL = 4
3.13 +SC_UNKNOWN = 5
3.14 +
3.15 +CO_OPTIMIZED = 0x0001
3.16 +CO_NEWLOCALS = 0x0002
3.17 +CO_VARARGS = 0x0004
3.18 +CO_VARKEYWORDS = 0x0008
3.19 +CO_NESTED = 0x0010
3.20 +CO_GENERATOR = 0x0020
3.21 +CO_GENERATOR_ALLOWED = 0
3.22 +CO_FUTURE_DIVISION = 0x2000
3.23 +CO_FUTURE_ABSIMPORT = 0x4000
3.24 +CO_FUTURE_WITH_STATEMENT = 0x8000
3.25 +CO_FUTURE_PRINT_FUNCTION = 0x10000
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/compiler/future.py Fri May 18 20:51:41 2012 +0200
4.3 @@ -0,0 +1,74 @@
4.4 +"""Parser for future statements
4.5 +
4.6 +"""
4.7 +
4.8 +from compiler import ast, walk
4.9 +
4.10 +def is_future(stmt):
4.11 + """Return true if statement is a well-formed future statement"""
4.12 + if not isinstance(stmt, ast.From):
4.13 + return 0
4.14 + if stmt.modname == "__future__":
4.15 + return 1
4.16 + else:
4.17 + return 0
4.18 +
4.19 +class FutureParser:
4.20 +
4.21 + features = ("nested_scopes", "generators", "division",
4.22 + "absolute_import", "with_statement", "print_function",
4.23 + "unicode_literals")
4.24 +
4.25 + def __init__(self):
4.26 + self.found = {} # set
4.27 +
4.28 + def visitModule(self, node):
4.29 + stmt = node.node
4.30 + for s in stmt.nodes:
4.31 + if not self.check_stmt(s):
4.32 + break
4.33 +
4.34 + def check_stmt(self, stmt):
4.35 + if is_future(stmt):
4.36 + for name, asname in stmt.names:
4.37 + if name in self.features:
4.38 + self.found[name] = 1
4.39 + else:
4.40 + raise SyntaxError, \
4.41 + "future feature %s is not defined" % name
4.42 + stmt.valid_future = 1
4.43 + return 1
4.44 + return 0
4.45 +
4.46 + def get_features(self):
4.47 + """Return list of features enabled by future statements"""
4.48 + return self.found.keys()
4.49 +
4.50 +class BadFutureParser:
4.51 + """Check for invalid future statements"""
4.52 +
4.53 + def visitFrom(self, node):
4.54 + if hasattr(node, 'valid_future'):
4.55 + return
4.56 + if node.modname != "__future__":
4.57 + return
4.58 + raise SyntaxError, "invalid future statement " + repr(node)
4.59 +
4.60 +def find_futures(node):
4.61 + p1 = FutureParser()
4.62 + p2 = BadFutureParser()
4.63 + walk(node, p1)
4.64 + walk(node, p2)
4.65 + return p1.get_features()
4.66 +
4.67 +if __name__ == "__main__":
4.68 + import sys
4.69 + from compiler import parseFile, walk
4.70 +
4.71 + for file in sys.argv[1:]:
4.72 + print file
4.73 + tree = parseFile(file)
4.74 + v = FutureParser()
4.75 + walk(tree, v)
4.76 + print v.found
4.77 + print
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/compiler/misc.py Fri May 18 20:51:41 2012 +0200
5.3 @@ -0,0 +1,73 @@
5.4 +
5.5 +def flatten(tup):
5.6 + elts = []
5.7 + for elt in tup:
5.8 + if isinstance(elt, tuple):
5.9 + elts = elts + flatten(elt)
5.10 + else:
5.11 + elts.append(elt)
5.12 + return elts
5.13 +
5.14 +class Set:
5.15 + def __init__(self):
5.16 + self.elts = {}
5.17 + def __len__(self):
5.18 + return len(self.elts)
5.19 + def __contains__(self, elt):
5.20 + return elt in self.elts
5.21 + def add(self, elt):
5.22 + self.elts[elt] = elt
5.23 + def elements(self):
5.24 + return self.elts.keys()
5.25 + def has_elt(self, elt):
5.26 + return elt in self.elts
5.27 + def remove(self, elt):
5.28 + del self.elts[elt]
5.29 + def copy(self):
5.30 + c = Set()
5.31 + c.elts.update(self.elts)
5.32 + return c
5.33 +
5.34 +class Stack:
5.35 + def __init__(self):
5.36 + self.stack = []
5.37 + self.pop = self.stack.pop
5.38 + def __len__(self):
5.39 + return len(self.stack)
5.40 + def push(self, elt):
5.41 + self.stack.append(elt)
5.42 + def top(self):
5.43 + return self.stack[-1]
5.44 + def __getitem__(self, index): # needed by visitContinue()
5.45 + return self.stack[index]
5.46 +
5.47 +MANGLE_LEN = 256 # magic constant from compile.c
5.48 +
5.49 +def mangle(name, klass):
5.50 + if not name.startswith('__'):
5.51 + return name
5.52 + if len(name) + 2 >= MANGLE_LEN:
5.53 + return name
5.54 + if name.endswith('__'):
5.55 + return name
5.56 + try:
5.57 + i = 0
5.58 + while klass[i] == '_':
5.59 + i = i + 1
5.60 + except IndexError:
5.61 + return name
5.62 + klass = klass[i:]
5.63 +
5.64 + tlen = len(klass) + len(name)
5.65 + if tlen > MANGLE_LEN:
5.66 + klass = klass[:MANGLE_LEN-tlen]
5.67 +
5.68 + return "_%s%s" % (klass, name)
5.69 +
5.70 +def set_filename(filename, tree):
5.71 + """Set the filename attribute to filename on every node in tree"""
5.72 + worklist = [tree]
5.73 + while worklist:
5.74 + node = worklist.pop(0)
5.75 + node.filename = filename
5.76 + worklist.extend(node.getChildNodes())
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/compiler/pyassem.py Fri May 18 20:51:41 2012 +0200
6.3 @@ -0,0 +1,818 @@
6.4 +"""A flow graph representation for Python bytecode"""
6.5 +
6.6 +import dis
6.7 +import types
6.8 +import sys
6.9 +
6.10 +from compiler import misc
6.11 +from compiler.consts \
6.12 + import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS
6.13 +
6.14 +class FlowGraph:
6.15 + def __init__(self):
6.16 + self.current = self.entry = Block()
6.17 + self.exit = Block("exit")
6.18 + self.blocks = misc.Set()
6.19 + self.blocks.add(self.entry)
6.20 + self.blocks.add(self.exit)
6.21 +
6.22 + def startBlock(self, block):
6.23 + if self._debug:
6.24 + if self.current:
6.25 + print "end", repr(self.current)
6.26 + print " next", self.current.next
6.27 + print " ", self.current.get_children()
6.28 + print repr(block)
6.29 + self.current = block
6.30 +
6.31 + def nextBlock(self, block=None):
6.32 + # XXX think we need to specify when there is implicit transfer
6.33 + # from one block to the next. might be better to represent this
6.34 + # with explicit JUMP_ABSOLUTE instructions that are optimized
6.35 + # out when they are unnecessary.
6.36 + #
6.37 + # I think this strategy works: each block has a child
6.38 + # designated as "next" which is returned as the last of the
6.39 + # children. because the nodes in a graph are emitted in
6.40 + # reverse post order, the "next" block will always be emitted
6.41 + # immediately after its parent.
6.42 + # Worry: maintaining this invariant could be tricky
6.43 + if block is None:
6.44 + block = self.newBlock()
6.45 +
6.46 + # Note: If the current block ends with an unconditional
6.47 + # control transfer, then it is incorrect to add an implicit
6.48 + # transfer to the block graph. The current code requires
6.49 + # these edges to get the blocks emitted in the right order,
6.50 + # however. :-( If a client needs to remove these edges, call
6.51 + # pruneEdges().
6.52 +
6.53 + self.current.addNext(block)
6.54 + self.startBlock(block)
6.55 +
6.56 + def newBlock(self):
6.57 + b = Block()
6.58 + self.blocks.add(b)
6.59 + return b
6.60 +
6.61 + def startExitBlock(self):
6.62 + self.startBlock(self.exit)
6.63 +
6.64 + _debug = 0
6.65 +
6.66 + def _enable_debug(self):
6.67 + self._debug = 1
6.68 +
6.69 + def _disable_debug(self):
6.70 + self._debug = 0
6.71 +
6.72 + def emit(self, *inst):
6.73 + if self._debug:
6.74 + print "\t", inst
6.75 + if inst[0] in ['RETURN_VALUE', 'YIELD_VALUE']:
6.76 + self.current.addOutEdge(self.exit)
6.77 + if len(inst) == 2 and isinstance(inst[1], Block):
6.78 + self.current.addOutEdge(inst[1])
6.79 + self.current.emit(inst)
6.80 +
6.81 + def getBlocksInOrder(self):
6.82 + """Return the blocks in reverse postorder
6.83 +
6.84 + i.e. each node appears before all of its successors
6.85 + """
6.86 + # XXX make sure every node that doesn't have an explicit next
6.87 + # is set so that next points to exit
6.88 + for b in self.blocks.elements():
6.89 + if b is self.exit:
6.90 + continue
6.91 + if not b.next:
6.92 + b.addNext(self.exit)
6.93 + order = dfs_postorder(self.entry, {})
6.94 + order.reverse()
6.95 + self.fixupOrder(order, self.exit)
6.96 + # hack alert
6.97 + if not self.exit in order:
6.98 + order.append(self.exit)
6.99 +
6.100 + return order
6.101 +
6.102 + def fixupOrder(self, blocks, default_next):
6.103 + """Fixup bad order introduced by DFS."""
6.104 +
6.105 + # XXX This is a total mess. There must be a better way to get
6.106 + # the code blocks in the right order.
6.107 +
6.108 + self.fixupOrderHonorNext(blocks, default_next)
6.109 + self.fixupOrderForward(blocks, default_next)
6.110 +
6.111 + def fixupOrderHonorNext(self, blocks, default_next):
6.112 + """Fix one problem with DFS.
6.113 +
6.114 + The DFS uses child block, but doesn't know about the special
6.115 + "next" block. As a result, the DFS can order blocks so that a
6.116 + block isn't next to the right block for implicit control
6.117 + transfers.
6.118 + """
6.119 + index = {}
6.120 + for i in range(len(blocks)):
6.121 + index[blocks[i]] = i
6.122 +
6.123 + for i in range(0, len(blocks) - 1):
6.124 + b = blocks[i]
6.125 + n = blocks[i + 1]
6.126 + if not b.next or b.next[0] == default_next or b.next[0] == n:
6.127 + continue
6.128 + # The blocks are in the wrong order. Find the chain of
6.129 + # blocks to insert where they belong.
6.130 + cur = b
6.131 + chain = []
6.132 + elt = cur
6.133 + while elt.next and elt.next[0] != default_next:
6.134 + chain.append(elt.next[0])
6.135 + elt = elt.next[0]
6.136 + # Now remove the blocks in the chain from the current
6.137 + # block list, so that they can be re-inserted.
6.138 + l = []
6.139 + for b in chain:
6.140 + assert index[b] > i
6.141 + l.append((index[b], b))
6.142 + l.sort()
6.143 + l.reverse()
6.144 + for j, b in l:
6.145 + del blocks[index[b]]
6.146 + # Insert the chain in the proper location
6.147 + blocks[i:i + 1] = [cur] + chain
6.148 + # Finally, re-compute the block indexes
6.149 + for i in range(len(blocks)):
6.150 + index[blocks[i]] = i
6.151 +
6.152 + def fixupOrderForward(self, blocks, default_next):
6.153 + """Make sure all JUMP_FORWARDs jump forward"""
6.154 + index = {}
6.155 + chains = []
6.156 + cur = []
6.157 + for b in blocks:
6.158 + index[b] = len(chains)
6.159 + cur.append(b)
6.160 + if b.next and b.next[0] == default_next:
6.161 + chains.append(cur)
6.162 + cur = []
6.163 + chains.append(cur)
6.164 +
6.165 + while 1:
6.166 + constraints = []
6.167 +
6.168 + for i in range(len(chains)):
6.169 + l = chains[i]
6.170 + for b in l:
6.171 + for c in b.get_children():
6.172 + if index[c] < i:
6.173 + forward_p = 0
6.174 + for inst in b.insts:
6.175 + if inst[0] == 'JUMP_FORWARD':
6.176 + if inst[1] == c:
6.177 + forward_p = 1
6.178 + if not forward_p:
6.179 + continue
6.180 + constraints.append((index[c], i))
6.181 +
6.182 + if not constraints:
6.183 + break
6.184 +
6.185 + # XXX just do one for now
6.186 + # do swaps to get things in the right order
6.187 + goes_before, a_chain = constraints[0]
6.188 + assert a_chain > goes_before
6.189 + c = chains[a_chain]
6.190 + chains.remove(c)
6.191 + chains.insert(goes_before, c)
6.192 +
6.193 + del blocks[:]
6.194 + for c in chains:
6.195 + for b in c:
6.196 + blocks.append(b)
6.197 +
6.198 + def getBlocks(self):
6.199 + return self.blocks.elements()
6.200 +
6.201 + def getRoot(self):
6.202 + """Return nodes appropriate for use with dominator"""
6.203 + return self.entry
6.204 +
6.205 + def getContainedGraphs(self):
6.206 + l = []
6.207 + for b in self.getBlocks():
6.208 + l.extend(b.getContainedGraphs())
6.209 + return l
6.210 +
6.211 +def dfs_postorder(b, seen):
6.212 + """Depth-first search of tree rooted at b, return in postorder"""
6.213 + order = []
6.214 + seen[b] = b
6.215 + for c in b.get_children():
6.216 + if c in seen:
6.217 + continue
6.218 + order = order + dfs_postorder(c, seen)
6.219 + order.append(b)
6.220 + return order
6.221 +
6.222 +class Block:
6.223 + _count = 0
6.224 +
6.225 + def __init__(self, label=''):
6.226 + self.insts = []
6.227 + self.inEdges = misc.Set()
6.228 + self.outEdges = misc.Set()
6.229 + self.label = label
6.230 + self.bid = Block._count
6.231 + self.next = []
6.232 + Block._count = Block._count + 1
6.233 +
6.234 + def __repr__(self):
6.235 + if self.label:
6.236 + return "<block %s id=%d>" % (self.label, self.bid)
6.237 + else:
6.238 + return "<block id=%d>" % (self.bid)
6.239 +
6.240 + def __str__(self):
6.241 + insts = map(str, self.insts)
6.242 + return "<block %s %d:\n%s>" % (self.label, self.bid,
6.243 + '\n'.join(insts))
6.244 +
6.245 + def emit(self, inst):
6.246 + op = inst[0]
6.247 + if op[:4] == 'JUMP':
6.248 + self.outEdges.add(inst[1])
6.249 + self.insts.append(inst)
6.250 +
6.251 + def getInstructions(self):
6.252 + return self.insts
6.253 +
6.254 + def addInEdge(self, block):
6.255 + self.inEdges.add(block)
6.256 +
6.257 + def addOutEdge(self, block):
6.258 + self.outEdges.add(block)
6.259 +
6.260 + def addNext(self, block):
6.261 + self.next.append(block)
6.262 + assert len(self.next) == 1, map(str, self.next)
6.263 +
6.264 + _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'YIELD_VALUE',
6.265 + 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
6.266 +
6.267 + def pruneNext(self):
6.268 + """Remove bogus edge for unconditional transfers
6.269 +
6.270 + Each block has a next edge that accounts for implicit control
6.271 + transfers, e.g. from a JUMP_IF_FALSE to the block that will be
6.272 + executed if the test is true.
6.273 +
6.274 + These edges must remain for the current assembler code to
6.275 + work. If they are removed, the dfs_postorder gets things in
6.276 + weird orders. However, they shouldn't be there for other
6.277 + purposes, e.g. conversion to SSA form. This method will
6.278 + remove the next edge when it follows an unconditional control
6.279 + transfer.
6.280 + """
6.281 + try:
6.282 + op, arg = self.insts[-1]
6.283 + except (IndexError, ValueError):
6.284 + return
6.285 + if op in self._uncond_transfer:
6.286 + self.next = []
6.287 +
6.288 + def get_children(self):
6.289 + if self.next and self.next[0] in self.outEdges:
6.290 + self.outEdges.remove(self.next[0])
6.291 + return self.outEdges.elements() + self.next
6.292 +
6.293 + def getContainedGraphs(self):
6.294 + """Return all graphs contained within this block.
6.295 +
6.296 + For example, a MAKE_FUNCTION block will contain a reference to
6.297 + the graph for the function body.
6.298 + """
6.299 + contained = []
6.300 + for inst in self.insts:
6.301 + if len(inst) == 1:
6.302 + continue
6.303 + op = inst[1]
6.304 + if hasattr(op, 'graph'):
6.305 + contained.append(op.graph)
6.306 + return contained
6.307 +
6.308 +# flags for code objects
6.309 +
6.310 +# the FlowGraph is transformed in place; it exists in one of these states
6.311 +RAW = "RAW"
6.312 +FLAT = "FLAT"
6.313 +CONV = "CONV"
6.314 +DONE = "DONE"
6.315 +
6.316 +class PyFlowGraph(FlowGraph):
6.317 + super_init = FlowGraph.__init__
6.318 +
6.319 + def __init__(self, name, filename, args=(), optimized=0, klass=None):
6.320 + self.super_init()
6.321 + self.name = name
6.322 + self.filename = filename
6.323 + self.docstring = None
6.324 + self.args = args # XXX
6.325 + self.argcount = getArgCount(args)
6.326 + self.klass = klass
6.327 + if optimized:
6.328 + self.flags = CO_OPTIMIZED | CO_NEWLOCALS
6.329 + else:
6.330 + self.flags = 0
6.331 + self.consts = []
6.332 + self.names = []
6.333 + # Free variables found by the symbol table scan, including
6.334 + # variables used only in nested scopes, are included here.
6.335 + self.freevars = []
6.336 + self.cellvars = []
6.337 + # The closure list is used to track the order of cell
6.338 + # variables and free variables in the resulting code object.
6.339 + # The offsets used by LOAD_CLOSURE/LOAD_DEREF refer to both
6.340 + # kinds of variables.
6.341 + self.closure = []
6.342 + self.varnames = list(args) or []
6.343 + for i in range(len(self.varnames)):
6.344 + var = self.varnames[i]
6.345 + if isinstance(var, TupleArg):
6.346 + self.varnames[i] = var.getName()
6.347 + self.stage = RAW
6.348 +
6.349 + def setDocstring(self, doc):
6.350 + self.docstring = doc
6.351 +
6.352 + def setFlag(self, flag):
6.353 + self.flags = self.flags | flag
6.354 + if flag == CO_VARARGS:
6.355 + self.argcount = self.argcount - 1
6.356 +
6.357 + def checkFlag(self, flag):
6.358 + if self.flags & flag:
6.359 + return 1
6.360 +
6.361 + def setFreeVars(self, names):
6.362 + self.freevars = list(names)
6.363 +
6.364 + def setCellVars(self, names):
6.365 + self.cellvars = names
6.366 +
6.367 + def getCode(self):
6.368 + """Get a Python code object"""
6.369 + assert self.stage == RAW
6.370 + self.computeStackDepth()
6.371 + self.flattenGraph()
6.372 + assert self.stage == FLAT
6.373 + self.convertArgs()
6.374 + assert self.stage == CONV
6.375 + self.makeByteCode()
6.376 + assert self.stage == DONE
6.377 + return self.newCodeObject()
6.378 +
6.379 + def dump(self, io=None):
6.380 + if io:
6.381 + save = sys.stdout
6.382 + sys.stdout = io
6.383 + pc = 0
6.384 + for t in self.insts:
6.385 + opname = t[0]
6.386 + if opname == "SET_LINENO":
6.387 + print
6.388 + if len(t) == 1:
6.389 + print "\t", "%3d" % pc, opname
6.390 + pc = pc + 1
6.391 + else:
6.392 + print "\t", "%3d" % pc, opname, t[1]
6.393 + pc = pc + 3
6.394 + if io:
6.395 + sys.stdout = save
6.396 +
6.397 + def computeStackDepth(self):
6.398 + """Compute the max stack depth.
6.399 +
6.400 + Approach is to compute the stack effect of each basic block.
6.401 + Then find the path through the code with the largest total
6.402 + effect.
6.403 + """
6.404 + depth = {}
6.405 + exit = None
6.406 + for b in self.getBlocks():
6.407 + depth[b] = findDepth(b.getInstructions())
6.408 +
6.409 + seen = {}
6.410 +
6.411 + def max_depth(b, d):
6.412 + if b in seen:
6.413 + return d
6.414 + seen[b] = 1
6.415 + d = d + depth[b]
6.416 + children = b.get_children()
6.417 + if children:
6.418 + return max([max_depth(c, d) for c in children])
6.419 + else:
6.420 + if not b.label == "exit":
6.421 + return max_depth(self.exit, d)
6.422 + else:
6.423 + return d
6.424 +
6.425 + self.stacksize = max_depth(self.entry, 0)
6.426 +
6.427 + def flattenGraph(self):
6.428 + """Arrange the blocks in order and resolve jumps"""
6.429 + assert self.stage == RAW
6.430 + self.insts = insts = []
6.431 + pc = 0
6.432 + begin = {}
6.433 + end = {}
6.434 + for b in self.getBlocksInOrder():
6.435 + begin[b] = pc
6.436 + for inst in b.getInstructions():
6.437 + insts.append(inst)
6.438 + if len(inst) == 1:
6.439 + pc = pc + 1
6.440 + elif inst[0] != "SET_LINENO":
6.441 + # arg takes 2 bytes
6.442 + pc = pc + 3
6.443 + end[b] = pc
6.444 + pc = 0
6.445 + for i in range(len(insts)):
6.446 + inst = insts[i]
6.447 + if len(inst) == 1:
6.448 + pc = pc + 1
6.449 + elif inst[0] != "SET_LINENO":
6.450 + pc = pc + 3
6.451 + opname = inst[0]
6.452 + if self.hasjrel.has_elt(opname):
6.453 + oparg = inst[1]
6.454 + offset = begin[oparg] - pc
6.455 + insts[i] = opname, offset
6.456 + elif self.hasjabs.has_elt(opname):
6.457 + insts[i] = opname, begin[inst[1]]
6.458 + self.stage = FLAT
6.459 +
6.460 + hasjrel = misc.Set()
6.461 + for i in dis.hasjrel:
6.462 + hasjrel.add(dis.opname[i])
6.463 + hasjabs = misc.Set()
6.464 + for i in dis.hasjabs:
6.465 + hasjabs.add(dis.opname[i])
6.466 +
6.467 + def convertArgs(self):
6.468 + """Convert arguments from symbolic to concrete form"""
6.469 + assert self.stage == FLAT
6.470 + self.consts.insert(0, self.docstring)
6.471 + self.sort_cellvars()
6.472 + for i in range(len(self.insts)):
6.473 + t = self.insts[i]
6.474 + if len(t) == 2:
6.475 + opname, oparg = t
6.476 + conv = self._converters.get(opname, None)
6.477 + if conv:
6.478 + self.insts[i] = opname, conv(self, oparg)
6.479 + self.stage = CONV
6.480 +
6.481 + def sort_cellvars(self):
6.482 + """Sort cellvars in the order of varnames and prune from freevars.
6.483 + """
6.484 + cells = {}
6.485 + for name in self.cellvars:
6.486 + cells[name] = 1
6.487 + self.cellvars = [name for name in self.varnames
6.488 + if name in cells]
6.489 + for name in self.cellvars:
6.490 + del cells[name]
6.491 + self.cellvars = self.cellvars + cells.keys()
6.492 + self.closure = self.cellvars + self.freevars
6.493 +
6.494 + def _lookupName(self, name, list):
6.495 + """Return index of name in list, appending if necessary
6.496 +
6.497 + This routine uses a list instead of a dictionary, because a
6.498 + dictionary can't store two different keys if the keys have the
6.499 + same value but different types, e.g. 2 and 2L. The compiler
6.500 + must treat these two separately, so it does an explicit type
6.501 + comparison before comparing the values.
6.502 + """
6.503 + t = type(name)
6.504 + for i in range(len(list)):
6.505 + if t == type(list[i]) and list[i] == name:
6.506 + return i
6.507 + end = len(list)
6.508 + list.append(name)
6.509 + return end
6.510 +
6.511 + _converters = {}
6.512 + def _convert_LOAD_CONST(self, arg):
6.513 + if hasattr(arg, 'getCode'):
6.514 + arg = arg.getCode()
6.515 + return self._lookupName(arg, self.consts)
6.516 +
6.517 + def _convert_LOAD_FAST(self, arg):
6.518 + self._lookupName(arg, self.names)
6.519 + return self._lookupName(arg, self.varnames)
6.520 + _convert_STORE_FAST = _convert_LOAD_FAST
6.521 + _convert_DELETE_FAST = _convert_LOAD_FAST
6.522 +
6.523 + def _convert_LOAD_NAME(self, arg):
6.524 + if self.klass is None:
6.525 + self._lookupName(arg, self.varnames)
6.526 + return self._lookupName(arg, self.names)
6.527 +
6.528 + def _convert_NAME(self, arg):
6.529 + if self.klass is None:
6.530 + self._lookupName(arg, self.varnames)
6.531 + return self._lookupName(arg, self.names)
6.532 + _convert_STORE_NAME = _convert_NAME
6.533 + _convert_DELETE_NAME = _convert_NAME
6.534 + _convert_IMPORT_NAME = _convert_NAME
6.535 + _convert_IMPORT_FROM = _convert_NAME
6.536 + _convert_STORE_ATTR = _convert_NAME
6.537 + _convert_LOAD_ATTR = _convert_NAME
6.538 + _convert_DELETE_ATTR = _convert_NAME
6.539 + _convert_LOAD_GLOBAL = _convert_NAME
6.540 + _convert_STORE_GLOBAL = _convert_NAME
6.541 + _convert_DELETE_GLOBAL = _convert_NAME
6.542 +
6.543 + def _convert_DEREF(self, arg):
6.544 + self._lookupName(arg, self.names)
6.545 + self._lookupName(arg, self.varnames)
6.546 + return self._lookupName(arg, self.closure)
6.547 + _convert_LOAD_DEREF = _convert_DEREF
6.548 + _convert_STORE_DEREF = _convert_DEREF
6.549 +
6.550 + def _convert_LOAD_CLOSURE(self, arg):
6.551 + self._lookupName(arg, self.varnames)
6.552 + return self._lookupName(arg, self.closure)
6.553 +
6.554 + _cmp = list(dis.cmp_op)
6.555 + def _convert_COMPARE_OP(self, arg):
6.556 + return self._cmp.index(arg)
6.557 +
6.558 + # similarly for other opcodes...
6.559 +
6.560 + for name, obj in locals().items():
6.561 + if name[:9] == "_convert_":
6.562 + opname = name[9:]
6.563 + _converters[opname] = obj
6.564 + del name, obj, opname
6.565 +
6.566 + def makeByteCode(self):
6.567 + assert self.stage == CONV
6.568 + self.lnotab = lnotab = LineAddrTable()
6.569 + for t in self.insts:
6.570 + opname = t[0]
6.571 + if len(t) == 1:
6.572 + lnotab.addCode(self.opnum[opname])
6.573 + else:
6.574 + oparg = t[1]
6.575 + if opname == "SET_LINENO":
6.576 + lnotab.nextLine(oparg)
6.577 + continue
6.578 + hi, lo = twobyte(oparg)
6.579 + try:
6.580 + lnotab.addCode(self.opnum[opname], lo, hi)
6.581 + except ValueError:
6.582 + print opname, oparg
6.583 + print self.opnum[opname], lo, hi
6.584 + raise
6.585 + self.stage = DONE
6.586 +
6.587 + opnum = {}
6.588 + for num in range(len(dis.opname)):
6.589 + opnum[dis.opname[num]] = num
6.590 + del num
6.591 +
6.592 + def newCodeObject(self):
6.593 + assert self.stage == DONE
6.594 + if (self.flags & CO_NEWLOCALS) == 0:
6.595 + nlocals = 0
6.596 + else:
6.597 + nlocals = len(self.varnames)
6.598 + argcount = self.argcount
6.599 + if self.flags & CO_VARKEYWORDS:
6.600 + argcount = argcount - 1
6.601 + return types.CodeType(argcount, nlocals, self.stacksize, self.flags,
6.602 + self.lnotab.getCode(), self.getConsts(),
6.603 + tuple(self.names), tuple(self.varnames),
6.604 + self.filename, self.name, self.lnotab.firstline,
6.605 + self.lnotab.getTable(), tuple(self.freevars),
6.606 + tuple(self.cellvars))
6.607 +
6.608 + def getConsts(self):
6.609 + """Return a tuple for the const slot of the code object
6.610 +
6.611 + Must convert references to code (MAKE_FUNCTION) to code
6.612 + objects recursively.
6.613 + """
6.614 + l = []
6.615 + for elt in self.consts:
6.616 + if isinstance(elt, PyFlowGraph):
6.617 + elt = elt.getCode()
6.618 + l.append(elt)
6.619 + return tuple(l)
6.620 +
6.621 +def isJump(opname):
6.622 + if opname[:4] == 'JUMP':
6.623 + return 1
6.624 +
6.625 +class TupleArg:
6.626 + """Helper for marking func defs with nested tuples in arglist"""
6.627 + def __init__(self, count, names):
6.628 + self.count = count
6.629 + self.names = names
6.630 + def __repr__(self):
6.631 + return "TupleArg(%s, %s)" % (self.count, self.names)
6.632 + def getName(self):
6.633 + return ".%d" % self.count
6.634 +
6.635 +def getArgCount(args):
6.636 + argcount = len(args)
6.637 + if args:
6.638 + for arg in args:
6.639 + if isinstance(arg, TupleArg):
6.640 + numNames = len(misc.flatten(arg.names))
6.641 + argcount = argcount - numNames
6.642 + return argcount
6.643 +
6.644 +def twobyte(val):
6.645 + """Convert an int argument into high and low bytes"""
6.646 + assert isinstance(val, int)
6.647 + return divmod(val, 256)
6.648 +
6.649 +class LineAddrTable:
6.650 + """lnotab
6.651 +
6.652 + This class builds the lnotab, which is documented in compile.c.
6.653 + Here's a brief recap:
6.654 +
6.655 + For each SET_LINENO instruction after the first one, two bytes are
6.656 + added to lnotab. (In some cases, multiple two-byte entries are
6.657 + added.) The first byte is the distance in bytes between the
6.658 + instruction for the last SET_LINENO and the current SET_LINENO.
6.659 + The second byte is offset in line numbers. If either offset is
6.660 + greater than 255, multiple two-byte entries are added -- see
6.661 + compile.c for the delicate details.
6.662 + """
6.663 +
6.664 + def __init__(self):
6.665 + self.code = []
6.666 + self.codeOffset = 0
6.667 + self.firstline = 0
6.668 + self.lastline = 0
6.669 + self.lastoff = 0
6.670 + self.lnotab = []
6.671 +
6.672 + def addCode(self, *args):
6.673 + for arg in args:
6.674 + self.code.append(chr(arg))
6.675 + self.codeOffset = self.codeOffset + len(args)
6.676 +
6.677 + def nextLine(self, lineno):
6.678 + if self.firstline == 0:
6.679 + self.firstline = lineno
6.680 + self.lastline = lineno
6.681 + else:
6.682 + # compute deltas
6.683 + addr = self.codeOffset - self.lastoff
6.684 + line = lineno - self.lastline
6.685 + # Python assumes that lineno always increases with
6.686 + # increasing bytecode address (lnotab is unsigned char).
6.687 + # Depending on when SET_LINENO instructions are emitted
6.688 + # this is not always true. Consider the code:
6.689 + # a = (1,
6.690 + # b)
6.691 + # In the bytecode stream, the assignment to "a" occurs
6.692 + # after the loading of "b". This works with the C Python
6.693 + # compiler because it only generates a SET_LINENO instruction
6.694 + # for the assignment.
6.695 + if line >= 0:
6.696 + push = self.lnotab.append
6.697 + while addr > 255:
6.698 + push(255); push(0)
6.699 + addr -= 255
6.700 + while line > 255:
6.701 + push(addr); push(255)
6.702 + line -= 255
6.703 + addr = 0
6.704 + if addr > 0 or line > 0:
6.705 + push(addr); push(line)
6.706 + self.lastline = lineno
6.707 + self.lastoff = self.codeOffset
6.708 +
6.709 + def getCode(self):
6.710 + return ''.join(self.code)
6.711 +
6.712 + def getTable(self):
6.713 + return ''.join(map(chr, self.lnotab))
6.714 +
6.715 +class StackDepthTracker:
6.716 + # XXX 1. need to keep track of stack depth on jumps
6.717 + # XXX 2. at least partly as a result, this code is broken
6.718 +
6.719 + def findDepth(self, insts, debug=0):
6.720 + depth = 0
6.721 + maxDepth = 0
6.722 + for i in insts:
6.723 + opname = i[0]
6.724 + if debug:
6.725 + print i,
6.726 + delta = self.effect.get(opname, None)
6.727 + if delta is not None:
6.728 + depth = depth + delta
6.729 + else:
6.730 + # now check patterns
6.731 + for pat, pat_delta in self.patterns:
6.732 + if opname[:len(pat)] == pat:
6.733 + delta = pat_delta
6.734 + depth = depth + delta
6.735 + break
6.736 + # if we still haven't found a match
6.737 + if delta is None:
6.738 + meth = getattr(self, opname, None)
6.739 + if meth is not None:
6.740 + depth = depth + meth(i[1])
6.741 + if depth > maxDepth:
6.742 + maxDepth = depth
6.743 + if debug:
6.744 + print depth, maxDepth
6.745 + return maxDepth
6.746 +
6.747 + effect = {
6.748 + 'POP_TOP': -1,
6.749 + 'DUP_TOP': 1,
6.750 + 'LIST_APPEND': -2,
6.751 + 'SLICE+1': -1,
6.752 + 'SLICE+2': -1,
6.753 + 'SLICE+3': -2,
6.754 + 'STORE_SLICE+0': -1,
6.755 + 'STORE_SLICE+1': -2,
6.756 + 'STORE_SLICE+2': -2,
6.757 + 'STORE_SLICE+3': -3,
6.758 + 'DELETE_SLICE+0': -1,
6.759 + 'DELETE_SLICE+1': -2,
6.760 + 'DELETE_SLICE+2': -2,
6.761 + 'DELETE_SLICE+3': -3,
6.762 + 'STORE_SUBSCR': -3,
6.763 + 'DELETE_SUBSCR': -2,
6.764 + # PRINT_EXPR?
6.765 + 'PRINT_ITEM': -1,
6.766 + 'RETURN_VALUE': -1,
6.767 + 'YIELD_VALUE': -1,
6.768 + 'EXEC_STMT': -3,
6.769 + 'BUILD_CLASS': -2,
6.770 + 'STORE_NAME': -1,
6.771 + 'STORE_ATTR': -2,
6.772 + 'DELETE_ATTR': -1,
6.773 + 'STORE_GLOBAL': -1,
6.774 + 'BUILD_MAP': 1,
6.775 + 'COMPARE_OP': -1,
6.776 + 'STORE_FAST': -1,
6.777 + 'IMPORT_STAR': -1,
6.778 + 'IMPORT_NAME': -1,
6.779 + 'IMPORT_FROM': 1,
6.780 + 'LOAD_ATTR': 0, # unlike other loads
6.781 + # close enough...
6.782 + 'SETUP_EXCEPT': 3,
6.783 + 'SETUP_FINALLY': 3,
6.784 + 'FOR_ITER': 1,
6.785 + 'WITH_CLEANUP': -1,
6.786 + }
6.787 + # use pattern match
6.788 + patterns = [
6.789 + ('BINARY_', -1),
6.790 + ('LOAD_', 1),
6.791 + ]
6.792 +
6.793 + def UNPACK_SEQUENCE(self, count):
6.794 + return count-1
6.795 + def BUILD_TUPLE(self, count):
6.796 + return -count+1
6.797 + def BUILD_LIST(self, count):
6.798 + return -count+1
6.799 + def CALL_FUNCTION(self, argc):
6.800 + hi, lo = divmod(argc, 256)
6.801 + return -(lo + hi * 2)
6.802 + def CALL_FUNCTION_VAR(self, argc):
6.803 + return self.CALL_FUNCTION(argc)-1
6.804 + def CALL_FUNCTION_KW(self, argc):
6.805 + return self.CALL_FUNCTION(argc)-1
6.806 + def CALL_FUNCTION_VAR_KW(self, argc):
6.807 + return self.CALL_FUNCTION(argc)-2
6.808 + def MAKE_FUNCTION(self, argc):
6.809 + return -argc
6.810 + def MAKE_CLOSURE(self, argc):
6.811 + # XXX need to account for free variables too!
6.812 + return -argc
6.813 + def BUILD_SLICE(self, argc):
6.814 + if argc == 2:
6.815 + return -1
6.816 + elif argc == 3:
6.817 + return -2
6.818 + def DUP_TOPX(self, argc):
6.819 + return argc
6.820 +
6.821 +findDepth = StackDepthTracker().findDepth
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/compiler/pycodegen.py Fri May 18 20:51:41 2012 +0200
7.3 @@ -0,0 +1,1530 @@
7.4 +import imp
7.5 +import os
7.6 +import marshal
7.7 +import struct
7.8 +import sys
7.9 +from cStringIO import StringIO
7.10 +
7.11 +from compiler import ast, parse, walk, syntax
7.12 +from compiler import pyassem, misc, future, symbols
7.13 +from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
7.14 +from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,
7.15 + CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION,
7.16 + CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT, CO_FUTURE_PRINT_FUNCTION)
7.17 +from compiler.pyassem import TupleArg
7.18 +
7.19 +# XXX The version-specific code can go, since this code only works with 2.x.
7.20 +# Do we have Python 1.x or Python 2.x?
7.21 +try:
7.22 + VERSION = sys.version_info[0]
7.23 +except AttributeError:
7.24 + VERSION = 1
7.25 +
7.26 +callfunc_opcode_info = {
7.27 + # (Have *args, Have **args) : opcode
7.28 + (0,0) : "CALL_FUNCTION",
7.29 + (1,0) : "CALL_FUNCTION_VAR",
7.30 + (0,1) : "CALL_FUNCTION_KW",
7.31 + (1,1) : "CALL_FUNCTION_VAR_KW",
7.32 +}
7.33 +
7.34 +LOOP = 1
7.35 +EXCEPT = 2
7.36 +TRY_FINALLY = 3
7.37 +END_FINALLY = 4
7.38 +
7.39 +def compileFile(filename, display=0):
7.40 + f = open(filename, 'U')
7.41 + buf = f.read()
7.42 + f.close()
7.43 + mod = Module(buf, filename)
7.44 + try:
7.45 + mod.compile(display)
7.46 + except SyntaxError:
7.47 + raise
7.48 + else:
7.49 + f = open(filename + "c", "wb")
7.50 + mod.dump(f)
7.51 + f.close()
7.52 +
7.53 +def compile(source, filename, mode, flags=None, dont_inherit=None):
7.54 + """Replacement for builtin compile() function"""
7.55 + if flags is not None or dont_inherit is not None:
7.56 + raise RuntimeError, "not implemented yet"
7.57 +
7.58 + if mode == "single":
7.59 + gen = Interactive(source, filename)
7.60 + elif mode == "exec":
7.61 + gen = Module(source, filename)
7.62 + elif mode == "eval":
7.63 + gen = Expression(source, filename)
7.64 + else:
7.65 + raise ValueError("compile() 3rd arg must be 'exec' or "
7.66 + "'eval' or 'single'")
7.67 + gen.compile()
7.68 + return gen.code
7.69 +
7.70 +class AbstractCompileMode:
7.71 +
7.72 + mode = None # defined by subclass
7.73 +
7.74 + def __init__(self, source, filename):
7.75 + self.source = source
7.76 + self.filename = filename
7.77 + self.code = None
7.78 +
7.79 + def _get_tree(self):
7.80 + tree = parse(self.source, self.mode)
7.81 + misc.set_filename(self.filename, tree)
7.82 + syntax.check(tree)
7.83 + return tree
7.84 +
7.85 + def compile(self):
7.86 + pass # implemented by subclass
7.87 +
7.88 + def getCode(self):
7.89 + return self.code
7.90 +
7.91 +class Expression(AbstractCompileMode):
7.92 +
7.93 + mode = "eval"
7.94 +
7.95 + def compile(self):
7.96 + tree = self._get_tree()
7.97 + gen = ExpressionCodeGenerator(tree)
7.98 + self.code = gen.getCode()
7.99 +
7.100 +class Interactive(AbstractCompileMode):
7.101 +
7.102 + mode = "single"
7.103 +
7.104 + def compile(self):
7.105 + tree = self._get_tree()
7.106 + gen = InteractiveCodeGenerator(tree)
7.107 + self.code = gen.getCode()
7.108 +
7.109 +class Module(AbstractCompileMode):
7.110 +
7.111 + mode = "exec"
7.112 +
7.113 + def compile(self, display=0):
7.114 + tree = self._get_tree()
7.115 + gen = ModuleCodeGenerator(tree)
7.116 + if display:
7.117 + import pprint
7.118 + print pprint.pprint(tree)
7.119 + self.code = gen.getCode()
7.120 +
7.121 + def dump(self, f):
7.122 + f.write(self.getPycHeader())
7.123 + marshal.dump(self.code, f)
7.124 +
7.125 + MAGIC = imp.get_magic()
7.126 +
7.127 + def getPycHeader(self):
7.128 + # compile.c uses marshal to write a long directly, with
7.129 + # calling the interface that would also generate a 1-byte code
7.130 + # to indicate the type of the value. simplest way to get the
7.131 + # same effect is to call marshal and then skip the code.
7.132 + mtime = os.path.getmtime(self.filename)
7.133 + mtime = struct.pack('<i', mtime)
7.134 + return self.MAGIC + mtime
7.135 +
7.136 +class LocalNameFinder:
7.137 + """Find local names in scope"""
7.138 + def __init__(self, names=()):
7.139 + self.names = misc.Set()
7.140 + self.globals = misc.Set()
7.141 + for name in names:
7.142 + self.names.add(name)
7.143 +
7.144 + # XXX list comprehensions and for loops
7.145 +
7.146 + def getLocals(self):
7.147 + for elt in self.globals.elements():
7.148 + if self.names.has_elt(elt):
7.149 + self.names.remove(elt)
7.150 + return self.names
7.151 +
7.152 + def visitDict(self, node):
7.153 + pass
7.154 +
7.155 + def visitGlobal(self, node):
7.156 + for name in node.names:
7.157 + self.globals.add(name)
7.158 +
7.159 + def visitFunction(self, node):
7.160 + self.names.add(node.name)
7.161 +
7.162 + def visitLambda(self, node):
7.163 + pass
7.164 +
7.165 + def visitImport(self, node):
7.166 + for name, alias in node.names:
7.167 + self.names.add(alias or name)
7.168 +
7.169 + def visitFrom(self, node):
7.170 + for name, alias in node.names:
7.171 + self.names.add(alias or name)
7.172 +
7.173 + def visitClass(self, node):
7.174 + self.names.add(node.name)
7.175 +
7.176 + def visitAssName(self, node):
7.177 + self.names.add(node.name)
7.178 +
7.179 +def is_constant_false(node):
7.180 + if isinstance(node, ast.Const):
7.181 + if not node.value:
7.182 + return 1
7.183 + return 0
7.184 +
7.185 +class CodeGenerator:
7.186 + """Defines basic code generator for Python bytecode
7.187 +
7.188 + This class is an abstract base class. Concrete subclasses must
7.189 + define an __init__() that defines self.graph and then calls the
7.190 + __init__() defined in this class.
7.191 +
7.192 + The concrete class must also define the class attributes
7.193 + NameFinder, FunctionGen, and ClassGen. These attributes can be
7.194 + defined in the initClass() method, which is a hook for
7.195 + initializing these methods after all the classes have been
7.196 + defined.
7.197 + """
7.198 +
7.199 + optimized = 0 # is namespace access optimized?
7.200 + __initialized = None
7.201 + class_name = None # provide default for instance variable
7.202 +
7.203 + def __init__(self):
7.204 + if self.__initialized is None:
7.205 + self.initClass()
7.206 + self.__class__.__initialized = 1
7.207 + self.checkClass()
7.208 + self.locals = misc.Stack()
7.209 + self.setups = misc.Stack()
7.210 + self.last_lineno = None
7.211 + self._setupGraphDelegation()
7.212 + self._div_op = "BINARY_DIVIDE"
7.213 +
7.214 + # XXX set flags based on future features
7.215 + futures = self.get_module().futures
7.216 + for feature in futures:
7.217 + if feature == "division":
7.218 + self.graph.setFlag(CO_FUTURE_DIVISION)
7.219 + self._div_op = "BINARY_TRUE_DIVIDE"
7.220 + elif feature == "absolute_import":
7.221 + self.graph.setFlag(CO_FUTURE_ABSIMPORT)
7.222 + elif feature == "with_statement":
7.223 + self.graph.setFlag(CO_FUTURE_WITH_STATEMENT)
7.224 + elif feature == "print_function":
7.225 + self.graph.setFlag(CO_FUTURE_PRINT_FUNCTION)
7.226 +
7.227 + def initClass(self):
7.228 + """This method is called once for each class"""
7.229 +
7.230 + def checkClass(self):
7.231 + """Verify that class is constructed correctly"""
7.232 + try:
7.233 + assert hasattr(self, 'graph')
7.234 + assert getattr(self, 'NameFinder')
7.235 + assert getattr(self, 'FunctionGen')
7.236 + assert getattr(self, 'ClassGen')
7.237 + except AssertionError, msg:
7.238 + intro = "Bad class construction for %s" % self.__class__.__name__
7.239 + raise AssertionError, intro
7.240 +
7.241 + def _setupGraphDelegation(self):
7.242 + self.emit = self.graph.emit
7.243 + self.newBlock = self.graph.newBlock
7.244 + self.startBlock = self.graph.startBlock
7.245 + self.nextBlock = self.graph.nextBlock
7.246 + self.setDocstring = self.graph.setDocstring
7.247 +
7.248 + def getCode(self):
7.249 + """Return a code object"""
7.250 + return self.graph.getCode()
7.251 +
7.252 + def mangle(self, name):
7.253 + if self.class_name is not None:
7.254 + return misc.mangle(name, self.class_name)
7.255 + else:
7.256 + return name
7.257 +
7.258 + def parseSymbols(self, tree):
7.259 + s = symbols.SymbolVisitor()
7.260 + walk(tree, s)
7.261 + return s.scopes
7.262 +
7.263 + def get_module(self):
7.264 + raise RuntimeError, "should be implemented by subclasses"
7.265 +
7.266 + # Next five methods handle name access
7.267 +
7.268 + def isLocalName(self, name):
7.269 + return self.locals.top().has_elt(name)
7.270 +
7.271 + def storeName(self, name):
7.272 + self._nameOp('STORE', name)
7.273 +
7.274 + def loadName(self, name):
7.275 + self._nameOp('LOAD', name)
7.276 +
7.277 + def delName(self, name):
7.278 + self._nameOp('DELETE', name)
7.279 +
7.280 + def _nameOp(self, prefix, name):
7.281 + name = self.mangle(name)
7.282 + scope = self.scope.check_name(name)
7.283 + if scope == SC_LOCAL:
7.284 + if not self.optimized:
7.285 + self.emit(prefix + '_NAME', name)
7.286 + else:
7.287 + self.emit(prefix + '_FAST', name)
7.288 + elif scope == SC_GLOBAL:
7.289 + if not self.optimized:
7.290 + self.emit(prefix + '_NAME', name)
7.291 + else:
7.292 + self.emit(prefix + '_GLOBAL', name)
7.293 + elif scope == SC_FREE or scope == SC_CELL:
7.294 + self.emit(prefix + '_DEREF', name)
7.295 + else:
7.296 + raise RuntimeError, "unsupported scope for var %s: %d" % \
7.297 + (name, scope)
7.298 +
7.299 + def _implicitNameOp(self, prefix, name):
7.300 + """Emit name ops for names generated implicitly by for loops
7.301 +
7.302 + The interpreter generates names that start with a period or
7.303 + dollar sign. The symbol table ignores these names because
7.304 + they aren't present in the program text.
7.305 + """
7.306 + if self.optimized:
7.307 + self.emit(prefix + '_FAST', name)
7.308 + else:
7.309 + self.emit(prefix + '_NAME', name)
7.310 +
7.311 + # The set_lineno() function and the explicit emit() calls for
7.312 + # SET_LINENO below are only used to generate the line number table.
7.313 + # As of Python 2.3, the interpreter does not have a SET_LINENO
7.314 + # instruction. pyassem treats SET_LINENO opcodes as a special case.
7.315 +
7.316 + def set_lineno(self, node, force=False):
7.317 + """Emit SET_LINENO if necessary.
7.318 +
7.319 + The instruction is considered necessary if the node has a
7.320 + lineno attribute and it is different than the last lineno
7.321 + emitted.
7.322 +
7.323 + Returns true if SET_LINENO was emitted.
7.324 +
7.325 + There are no rules for when an AST node should have a lineno
7.326 + attribute. The transformer and AST code need to be reviewed
7.327 + and a consistent policy implemented and documented. Until
7.328 + then, this method works around missing line numbers.
7.329 + """
7.330 + lineno = getattr(node, 'lineno', None)
7.331 + if lineno is not None and (lineno != self.last_lineno
7.332 + or force):
7.333 + self.emit('SET_LINENO', lineno)
7.334 + self.last_lineno = lineno
7.335 + return True
7.336 + return False
7.337 +
7.338 + # The first few visitor methods handle nodes that generator new
7.339 + # code objects. They use class attributes to determine what
7.340 + # specialized code generators to use.
7.341 +
7.342 + NameFinder = LocalNameFinder
7.343 + FunctionGen = None
7.344 + ClassGen = None
7.345 +
7.346 + def visitModule(self, node):
7.347 + self.scopes = self.parseSymbols(node)
7.348 + self.scope = self.scopes[node]
7.349 + self.emit('SET_LINENO', 0)
7.350 + if node.doc:
7.351 + self.emit('LOAD_CONST', node.doc)
7.352 + self.storeName('__doc__')
7.353 + lnf = walk(node.node, self.NameFinder(), verbose=0)
7.354 + self.locals.push(lnf.getLocals())
7.355 + self.visit(node.node)
7.356 + self.emit('LOAD_CONST', None)
7.357 + self.emit('RETURN_VALUE')
7.358 +
7.359 + def visitExpression(self, node):
7.360 + self.set_lineno(node)
7.361 + self.scopes = self.parseSymbols(node)
7.362 + self.scope = self.scopes[node]
7.363 + self.visit(node.node)
7.364 + self.emit('RETURN_VALUE')
7.365 +
7.366 + def visitFunction(self, node):
7.367 + self._visitFuncOrLambda(node, isLambda=0)
7.368 + if node.doc:
7.369 + self.setDocstring(node.doc)
7.370 + self.storeName(node.name)
7.371 +
7.372 + def visitLambda(self, node):
7.373 + self._visitFuncOrLambda(node, isLambda=1)
7.374 +
7.375 + def _visitFuncOrLambda(self, node, isLambda=0):
7.376 + if not isLambda and node.decorators:
7.377 + for decorator in node.decorators.nodes:
7.378 + self.visit(decorator)
7.379 + ndecorators = len(node.decorators.nodes)
7.380 + else:
7.381 + ndecorators = 0
7.382 +
7.383 + gen = self.FunctionGen(node, self.scopes, isLambda,
7.384 + self.class_name, self.get_module())
7.385 + walk(node.code, gen)
7.386 + gen.finish()
7.387 + self.set_lineno(node)
7.388 + for default in node.defaults:
7.389 + self.visit(default)
7.390 + self._makeClosure(gen, len(node.defaults))
7.391 + for i in range(ndecorators):
7.392 + self.emit('CALL_FUNCTION', 1)
7.393 +
7.394 + def visitClass(self, node):
7.395 + gen = self.ClassGen(node, self.scopes,
7.396 + self.get_module())
7.397 + walk(node.code, gen)
7.398 + gen.finish()
7.399 + self.set_lineno(node)
7.400 + self.emit('LOAD_CONST', node.name)
7.401 + for base in node.bases:
7.402 + self.visit(base)
7.403 + self.emit('BUILD_TUPLE', len(node.bases))
7.404 + self._makeClosure(gen, 0)
7.405 + self.emit('CALL_FUNCTION', 0)
7.406 + self.emit('BUILD_CLASS')
7.407 + self.storeName(node.name)
7.408 +
7.409 + # The rest are standard visitor methods
7.410 +
7.411 + # The next few implement control-flow statements
7.412 +
7.413 + def visitIf(self, node):
7.414 + end = self.newBlock()
7.415 + numtests = len(node.tests)
7.416 + for i in range(numtests):
7.417 + test, suite = node.tests[i]
7.418 + if is_constant_false(test):
7.419 + # XXX will need to check generator stuff here
7.420 + continue
7.421 + self.set_lineno(test)
7.422 + self.visit(test)
7.423 + nextTest = self.newBlock()
7.424 + self.emit('JUMP_IF_FALSE', nextTest)
7.425 + self.nextBlock()
7.426 + self.emit('POP_TOP')
7.427 + self.visit(suite)
7.428 + self.emit('JUMP_FORWARD', end)
7.429 + self.startBlock(nextTest)
7.430 + self.emit('POP_TOP')
7.431 + if node.else_:
7.432 + self.visit(node.else_)
7.433 + self.nextBlock(end)
7.434 +
7.435 + def visitWhile(self, node):
7.436 + self.set_lineno(node)
7.437 +
7.438 + loop = self.newBlock()
7.439 + else_ = self.newBlock()
7.440 +
7.441 + after = self.newBlock()
7.442 + self.emit('SETUP_LOOP', after)
7.443 +
7.444 + self.nextBlock(loop)
7.445 + self.setups.push((LOOP, loop))
7.446 +
7.447 + self.set_lineno(node, force=True)
7.448 + self.visit(node.test)
7.449 + self.emit('JUMP_IF_FALSE', else_ or after)
7.450 +
7.451 + self.nextBlock()
7.452 + self.emit('POP_TOP')
7.453 + self.visit(node.body)
7.454 + self.emit('JUMP_ABSOLUTE', loop)
7.455 +
7.456 + self.startBlock(else_) # or just the POPs if not else clause
7.457 + self.emit('POP_TOP')
7.458 + self.emit('POP_BLOCK')
7.459 + self.setups.pop()
7.460 + if node.else_:
7.461 + self.visit(node.else_)
7.462 + self.nextBlock(after)
7.463 +
7.464 + def visitFor(self, node):
7.465 + start = self.newBlock()
7.466 + anchor = self.newBlock()
7.467 + after = self.newBlock()
7.468 + self.setups.push((LOOP, start))
7.469 +
7.470 + self.set_lineno(node)
7.471 + self.emit('SETUP_LOOP', after)
7.472 + self.visit(node.list)
7.473 + self.emit('GET_ITER')
7.474 +
7.475 + self.nextBlock(start)
7.476 + self.set_lineno(node, force=1)
7.477 + self.emit('FOR_ITER', anchor)
7.478 + self.visit(node.assign)
7.479 + self.visit(node.body)
7.480 + self.emit('JUMP_ABSOLUTE', start)
7.481 + self.nextBlock(anchor)
7.482 + self.emit('POP_BLOCK')
7.483 + self.setups.pop()
7.484 + if node.else_:
7.485 + self.visit(node.else_)
7.486 + self.nextBlock(after)
7.487 +
7.488 + def visitBreak(self, node):
7.489 + if not self.setups:
7.490 + raise SyntaxError, "'break' outside loop (%s, %d)" % \
7.491 + (node.filename, node.lineno)
7.492 + self.set_lineno(node)
7.493 + self.emit('BREAK_LOOP')
7.494 +
7.495 + def visitContinue(self, node):
7.496 + if not self.setups:
7.497 + raise SyntaxError, "'continue' outside loop (%s, %d)" % \
7.498 + (node.filename, node.lineno)
7.499 + kind, block = self.setups.top()
7.500 + if kind == LOOP:
7.501 + self.set_lineno(node)
7.502 + self.emit('JUMP_ABSOLUTE', block)
7.503 + self.nextBlock()
7.504 + elif kind == EXCEPT or kind == TRY_FINALLY:
7.505 + self.set_lineno(node)
7.506 + # find the block that starts the loop
7.507 + top = len(self.setups)
7.508 + while top > 0:
7.509 + top = top - 1
7.510 + kind, loop_block = self.setups[top]
7.511 + if kind == LOOP:
7.512 + break
7.513 + if kind != LOOP:
7.514 + raise SyntaxError, "'continue' outside loop (%s, %d)" % \
7.515 + (node.filename, node.lineno)
7.516 + self.emit('CONTINUE_LOOP', loop_block)
7.517 + self.nextBlock()
7.518 + elif kind == END_FINALLY:
7.519 + msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
7.520 + raise SyntaxError, msg % (node.filename, node.lineno)
7.521 +
7.522 + def visitTest(self, node, jump):
7.523 + end = self.newBlock()
7.524 + for child in node.nodes[:-1]:
7.525 + self.visit(child)
7.526 + self.emit(jump, end)
7.527 + self.nextBlock()
7.528 + self.emit('POP_TOP')
7.529 + self.visit(node.nodes[-1])
7.530 + self.nextBlock(end)
7.531 +
7.532 + def visitAnd(self, node):
7.533 + self.visitTest(node, 'JUMP_IF_FALSE')
7.534 +
7.535 + def visitOr(self, node):
7.536 + self.visitTest(node, 'JUMP_IF_TRUE')
7.537 +
7.538 + def visitIfExp(self, node):
7.539 + endblock = self.newBlock()
7.540 + elseblock = self.newBlock()
7.541 + self.visit(node.test)
7.542 + self.emit('JUMP_IF_FALSE', elseblock)
7.543 + self.emit('POP_TOP')
7.544 + self.visit(node.then)
7.545 + self.emit('JUMP_FORWARD', endblock)
7.546 + self.nextBlock(elseblock)
7.547 + self.emit('POP_TOP')
7.548 + self.visit(node.else_)
7.549 + self.nextBlock(endblock)
7.550 +
7.551 + def visitCompare(self, node):
7.552 + self.visit(node.expr)
7.553 + cleanup = self.newBlock()
7.554 + for op, code in node.ops[:-1]:
7.555 + self.visit(code)
7.556 + self.emit('DUP_TOP')
7.557 + self.emit('ROT_THREE')
7.558 + self.emit('COMPARE_OP', op)
7.559 + self.emit('JUMP_IF_FALSE', cleanup)
7.560 + self.nextBlock()
7.561 + self.emit('POP_TOP')
7.562 + # now do the last comparison
7.563 + if node.ops:
7.564 + op, code = node.ops[-1]
7.565 + self.visit(code)
7.566 + self.emit('COMPARE_OP', op)
7.567 + if len(node.ops) > 1:
7.568 + end = self.newBlock()
7.569 + self.emit('JUMP_FORWARD', end)
7.570 + self.startBlock(cleanup)
7.571 + self.emit('ROT_TWO')
7.572 + self.emit('POP_TOP')
7.573 + self.nextBlock(end)
7.574 +
7.575 + # list comprehensions
7.576 + __list_count = 0
7.577 +
7.578 + def visitListComp(self, node):
7.579 + self.set_lineno(node)
7.580 + # setup list
7.581 + tmpname = "$list%d" % self.__list_count
7.582 + self.__list_count = self.__list_count + 1
7.583 + self.emit('BUILD_LIST', 0)
7.584 + self.emit('DUP_TOP')
7.585 + self._implicitNameOp('STORE', tmpname)
7.586 +
7.587 + stack = []
7.588 + for i, for_ in zip(range(len(node.quals)), node.quals):
7.589 + start, anchor = self.visit(for_)
7.590 + cont = None
7.591 + for if_ in for_.ifs:
7.592 + if cont is None:
7.593 + cont = self.newBlock()
7.594 + self.visit(if_, cont)
7.595 + stack.insert(0, (start, cont, anchor))
7.596 +
7.597 + self._implicitNameOp('LOAD', tmpname)
7.598 + self.visit(node.expr)
7.599 + self.emit('LIST_APPEND')
7.600 +
7.601 + for start, cont, anchor in stack:
7.602 + if cont:
7.603 + skip_one = self.newBlock()
7.604 + self.emit('JUMP_FORWARD', skip_one)
7.605 + self.startBlock(cont)
7.606 + self.emit('POP_TOP')
7.607 + self.nextBlock(skip_one)
7.608 + self.emit('JUMP_ABSOLUTE', start)
7.609 + self.startBlock(anchor)
7.610 + self._implicitNameOp('DELETE', tmpname)
7.611 +
7.612 + self.__list_count = self.__list_count - 1
7.613 +
7.614 + def visitListCompFor(self, node):
7.615 + start = self.newBlock()
7.616 + anchor = self.newBlock()
7.617 +
7.618 + self.visit(node.list)
7.619 + self.emit('GET_ITER')
7.620 + self.nextBlock(start)
7.621 + self.set_lineno(node, force=True)
7.622 + self.emit('FOR_ITER', anchor)
7.623 + self.nextBlock()
7.624 + self.visit(node.assign)
7.625 + return start, anchor
7.626 +
7.627 + def visitListCompIf(self, node, branch):
7.628 + self.set_lineno(node, force=True)
7.629 + self.visit(node.test)
7.630 + self.emit('JUMP_IF_FALSE', branch)
7.631 + self.newBlock()
7.632 + self.emit('POP_TOP')
7.633 +
7.634 + def _makeClosure(self, gen, args):
7.635 + frees = gen.scope.get_free_vars()
7.636 + if frees:
7.637 + for name in frees:
7.638 + self.emit('LOAD_CLOSURE', name)
7.639 + self.emit('BUILD_TUPLE', len(frees))
7.640 + self.emit('LOAD_CONST', gen)
7.641 + self.emit('MAKE_CLOSURE', args)
7.642 + else:
7.643 + self.emit('LOAD_CONST', gen)
7.644 + self.emit('MAKE_FUNCTION', args)
7.645 +
7.646 + def visitGenExpr(self, node):
7.647 + gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
7.648 + self.get_module())
7.649 + walk(node.code, gen)
7.650 + gen.finish()
7.651 + self.set_lineno(node)
7.652 + self._makeClosure(gen, 0)
7.653 + # precomputation of outmost iterable
7.654 + self.visit(node.code.quals[0].iter)
7.655 + self.emit('GET_ITER')
7.656 + self.emit('CALL_FUNCTION', 1)
7.657 +
7.658 + def visitGenExprInner(self, node):
7.659 + self.set_lineno(node)
7.660 + # setup list
7.661 +
7.662 + stack = []
7.663 + for i, for_ in zip(range(len(node.quals)), node.quals):
7.664 + start, anchor, end = self.visit(for_)
7.665 + cont = None
7.666 + for if_ in for_.ifs:
7.667 + if cont is None:
7.668 + cont = self.newBlock()
7.669 + self.visit(if_, cont)
7.670 + stack.insert(0, (start, cont, anchor, end))
7.671 +
7.672 + self.visit(node.expr)
7.673 + self.emit('YIELD_VALUE')
7.674 + self.emit('POP_TOP')
7.675 +
7.676 + for start, cont, anchor, end in stack:
7.677 + if cont:
7.678 + skip_one = self.newBlock()
7.679 + self.emit('JUMP_FORWARD', skip_one)
7.680 + self.startBlock(cont)
7.681 + self.emit('POP_TOP')
7.682 + self.nextBlock(skip_one)
7.683 + self.emit('JUMP_ABSOLUTE', start)
7.684 + self.startBlock(anchor)
7.685 + self.emit('POP_BLOCK')
7.686 + self.setups.pop()
7.687 + self.startBlock(end)
7.688 +
7.689 + self.emit('LOAD_CONST', None)
7.690 +
7.691 + def visitGenExprFor(self, node):
7.692 + start = self.newBlock()
7.693 + anchor = self.newBlock()
7.694 + end = self.newBlock()
7.695 +
7.696 + self.setups.push((LOOP, start))
7.697 + self.emit('SETUP_LOOP', end)
7.698 +
7.699 + if node.is_outmost:
7.700 + self.loadName('.0')
7.701 + else:
7.702 + self.visit(node.iter)
7.703 + self.emit('GET_ITER')
7.704 +
7.705 + self.nextBlock(start)
7.706 + self.set_lineno(node, force=True)
7.707 + self.emit('FOR_ITER', anchor)
7.708 + self.nextBlock()
7.709 + self.visit(node.assign)
7.710 + return start, anchor, end
7.711 +
7.712 + def visitGenExprIf(self, node, branch):
7.713 + self.set_lineno(node, force=True)
7.714 + self.visit(node.test)
7.715 + self.emit('JUMP_IF_FALSE', branch)
7.716 + self.newBlock()
7.717 + self.emit('POP_TOP')
7.718 +
7.719 + # exception related
7.720 +
7.721 + def visitAssert(self, node):
7.722 + # XXX would be interesting to implement this via a
7.723 + # transformation of the AST before this stage
7.724 + if __debug__:
7.725 + end = self.newBlock()
7.726 + self.set_lineno(node)
7.727 + # XXX AssertionError appears to be special case -- it is always
7.728 + # loaded as a global even if there is a local name. I guess this
7.729 + # is a sort of renaming op.
7.730 + self.nextBlock()
7.731 + self.visit(node.test)
7.732 + self.emit('JUMP_IF_TRUE', end)
7.733 + self.nextBlock()
7.734 + self.emit('POP_TOP')
7.735 + self.emit('LOAD_GLOBAL', 'AssertionError')
7.736 + if node.fail:
7.737 + self.visit(node.fail)
7.738 + self.emit('RAISE_VARARGS', 2)
7.739 + else:
7.740 + self.emit('RAISE_VARARGS', 1)
7.741 + self.nextBlock(end)
7.742 + self.emit('POP_TOP')
7.743 +
7.744 + def visitRaise(self, node):
7.745 + self.set_lineno(node)
7.746 + n = 0
7.747 + if node.expr1:
7.748 + self.visit(node.expr1)
7.749 + n = n + 1
7.750 + if node.expr2:
7.751 + self.visit(node.expr2)
7.752 + n = n + 1
7.753 + if node.expr3:
7.754 + self.visit(node.expr3)
7.755 + n = n + 1
7.756 + self.emit('RAISE_VARARGS', n)
7.757 +
7.758 + def visitTryExcept(self, node):
7.759 + body = self.newBlock()
7.760 + handlers = self.newBlock()
7.761 + end = self.newBlock()
7.762 + if node.else_:
7.763 + lElse = self.newBlock()
7.764 + else:
7.765 + lElse = end
7.766 + self.set_lineno(node)
7.767 + self.emit('SETUP_EXCEPT', handlers)
7.768 + self.nextBlock(body)
7.769 + self.setups.push((EXCEPT, body))
7.770 + self.visit(node.body)
7.771 + self.emit('POP_BLOCK')
7.772 + self.setups.pop()
7.773 + self.emit('JUMP_FORWARD', lElse)
7.774 + self.startBlock(handlers)
7.775 +
7.776 + last = len(node.handlers) - 1
7.777 + for i in range(len(node.handlers)):
7.778 + expr, target, body = node.handlers[i]
7.779 + self.set_lineno(expr)
7.780 + if expr:
7.781 + self.emit('DUP_TOP')
7.782 + self.visit(expr)
7.783 + self.emit('COMPARE_OP', 'exception match')
7.784 + next = self.newBlock()
7.785 + self.emit('JUMP_IF_FALSE', next)
7.786 + self.nextBlock()
7.787 + self.emit('POP_TOP')
7.788 + self.emit('POP_TOP')
7.789 + if target:
7.790 + self.visit(target)
7.791 + else:
7.792 + self.emit('POP_TOP')
7.793 + self.emit('POP_TOP')
7.794 + self.visit(body)
7.795 + self.emit('JUMP_FORWARD', end)
7.796 + if expr:
7.797 + self.nextBlock(next)
7.798 + else:
7.799 + self.nextBlock()
7.800 + if expr: # XXX
7.801 + self.emit('POP_TOP')
7.802 + self.emit('END_FINALLY')
7.803 + if node.else_:
7.804 + self.nextBlock(lElse)
7.805 + self.visit(node.else_)
7.806 + self.nextBlock(end)
7.807 +
7.808 + def visitTryFinally(self, node):
7.809 + body = self.newBlock()
7.810 + final = self.newBlock()
7.811 + self.set_lineno(node)
7.812 + self.emit('SETUP_FINALLY', final)
7.813 + self.nextBlock(body)
7.814 + self.setups.push((TRY_FINALLY, body))
7.815 + self.visit(node.body)
7.816 + self.emit('POP_BLOCK')
7.817 + self.setups.pop()
7.818 + self.emit('LOAD_CONST', None)
7.819 + self.nextBlock(final)
7.820 + self.setups.push((END_FINALLY, final))
7.821 + self.visit(node.final)
7.822 + self.emit('END_FINALLY')
7.823 + self.setups.pop()
7.824 +
7.825 + __with_count = 0
7.826 +
7.827 + def visitWith(self, node):
7.828 + body = self.newBlock()
7.829 + final = self.newBlock()
7.830 + valuevar = "$value%d" % self.__with_count
7.831 + self.__with_count += 1
7.832 + self.set_lineno(node)
7.833 + self.visit(node.expr)
7.834 + self.emit('DUP_TOP')
7.835 + self.emit('LOAD_ATTR', '__exit__')
7.836 + self.emit('ROT_TWO')
7.837 + self.emit('LOAD_ATTR', '__enter__')
7.838 + self.emit('CALL_FUNCTION', 0)
7.839 + if node.vars is None:
7.840 + self.emit('POP_TOP')
7.841 + else:
7.842 + self._implicitNameOp('STORE', valuevar)
7.843 + self.emit('SETUP_FINALLY', final)
7.844 + self.nextBlock(body)
7.845 + self.setups.push((TRY_FINALLY, body))
7.846 + if node.vars is not None:
7.847 + self._implicitNameOp('LOAD', valuevar)
7.848 + self._implicitNameOp('DELETE', valuevar)
7.849 + self.visit(node.vars)
7.850 + self.visit(node.body)
7.851 + self.emit('POP_BLOCK')
7.852 + self.setups.pop()
7.853 + self.emit('LOAD_CONST', None)
7.854 + self.nextBlock(final)
7.855 + self.setups.push((END_FINALLY, final))
7.856 + self.emit('WITH_CLEANUP')
7.857 + self.emit('END_FINALLY')
7.858 + self.setups.pop()
7.859 + self.__with_count -= 1
7.860 +
7.861 + # misc
7.862 +
7.863 + def visitDiscard(self, node):
7.864 + self.set_lineno(node)
7.865 + self.visit(node.expr)
7.866 + self.emit('POP_TOP')
7.867 +
7.868 + def visitConst(self, node):
7.869 + self.emit('LOAD_CONST', node.value)
7.870 +
7.871 + def visitKeyword(self, node):
7.872 + self.emit('LOAD_CONST', node.name)
7.873 + self.visit(node.expr)
7.874 +
7.875 + def visitGlobal(self, node):
7.876 + # no code to generate
7.877 + pass
7.878 +
7.879 + def visitName(self, node):
7.880 + self.set_lineno(node)
7.881 + self.loadName(node.name)
7.882 +
7.883 + def visitPass(self, node):
7.884 + self.set_lineno(node)
7.885 +
7.886 + def visitImport(self, node):
7.887 + self.set_lineno(node)
7.888 + level = 0 if self.graph.checkFlag(CO_FUTURE_ABSIMPORT) else -1
7.889 + for name, alias in node.names:
7.890 + if VERSION > 1:
7.891 + self.emit('LOAD_CONST', level)
7.892 + self.emit('LOAD_CONST', None)
7.893 + self.emit('IMPORT_NAME', name)
7.894 + mod = name.split(".")[0]
7.895 + if alias:
7.896 + self._resolveDots(name)
7.897 + self.storeName(alias)
7.898 + else:
7.899 + self.storeName(mod)
7.900 +
7.901 + def visitFrom(self, node):
7.902 + self.set_lineno(node)
7.903 + level = node.level
7.904 + if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT):
7.905 + level = -1
7.906 + fromlist = tuple(name for (name, alias) in node.names)
7.907 + if VERSION > 1:
7.908 + self.emit('LOAD_CONST', level)
7.909 + self.emit('LOAD_CONST', fromlist)
7.910 + self.emit('IMPORT_NAME', node.modname)
7.911 + for name, alias in node.names:
7.912 + if VERSION > 1:
7.913 + if name == '*':
7.914 + self.namespace = 0
7.915 + self.emit('IMPORT_STAR')
7.916 + # There can only be one name w/ from ... import *
7.917 + assert len(node.names) == 1
7.918 + return
7.919 + else:
7.920 + self.emit('IMPORT_FROM', name)
7.921 + self._resolveDots(name)
7.922 + self.storeName(alias or name)
7.923 + else:
7.924 + self.emit('IMPORT_FROM', name)
7.925 + self.emit('POP_TOP')
7.926 +
7.927 + def _resolveDots(self, name):
7.928 + elts = name.split(".")
7.929 + if len(elts) == 1:
7.930 + return
7.931 + for elt in elts[1:]:
7.932 + self.emit('LOAD_ATTR', elt)
7.933 +
7.934 + def visitGetattr(self, node):
7.935 + self.visit(node.expr)
7.936 + self.emit('LOAD_ATTR', self.mangle(node.attrname))
7.937 +
7.938 + # next five implement assignments
7.939 +
7.940 + def visitAssign(self, node):
7.941 + self.set_lineno(node)
7.942 + self.visit(node.expr)
7.943 + dups = len(node.nodes) - 1
7.944 + for i in range(len(node.nodes)):
7.945 + elt = node.nodes[i]
7.946 + if i < dups:
7.947 + self.emit('DUP_TOP')
7.948 + if isinstance(elt, ast.Node):
7.949 + self.visit(elt)
7.950 +
7.951 + def visitAssName(self, node):
7.952 + if node.flags == 'OP_ASSIGN':
7.953 + self.storeName(node.name)
7.954 + elif node.flags == 'OP_DELETE':
7.955 + self.set_lineno(node)
7.956 + self.delName(node.name)
7.957 + else:
7.958 + print "oops", node.flags
7.959 +
7.960 + def visitAssAttr(self, node):
7.961 + self.visit(node.expr)
7.962 + if node.flags == 'OP_ASSIGN':
7.963 + self.emit('STORE_ATTR', self.mangle(node.attrname))
7.964 + elif node.flags == 'OP_DELETE':
7.965 + self.emit('DELETE_ATTR', self.mangle(node.attrname))
7.966 + else:
7.967 + print "warning: unexpected flags:", node.flags
7.968 + print node
7.969 +
7.970 + def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
7.971 + if findOp(node) != 'OP_DELETE':
7.972 + self.emit(op, len(node.nodes))
7.973 + for child in node.nodes:
7.974 + self.visit(child)
7.975 +
7.976 + if VERSION > 1:
7.977 + visitAssTuple = _visitAssSequence
7.978 + visitAssList = _visitAssSequence
7.979 + else:
7.980 + def visitAssTuple(self, node):
7.981 + self._visitAssSequence(node, 'UNPACK_TUPLE')
7.982 +
7.983 + def visitAssList(self, node):
7.984 + self._visitAssSequence(node, 'UNPACK_LIST')
7.985 +
7.986 + # augmented assignment
7.987 +
7.988 + def visitAugAssign(self, node):
7.989 + self.set_lineno(node)
7.990 + aug_node = wrap_aug(node.node)
7.991 + self.visit(aug_node, "load")
7.992 + self.visit(node.expr)
7.993 + self.emit(self._augmented_opcode[node.op])
7.994 + self.visit(aug_node, "store")
7.995 +
7.996 + _augmented_opcode = {
7.997 + '+=' : 'INPLACE_ADD',
7.998 + '-=' : 'INPLACE_SUBTRACT',
7.999 + '*=' : 'INPLACE_MULTIPLY',
7.1000 + '/=' : 'INPLACE_DIVIDE',
7.1001 + '//=': 'INPLACE_FLOOR_DIVIDE',
7.1002 + '%=' : 'INPLACE_MODULO',
7.1003 + '**=': 'INPLACE_POWER',
7.1004 + '>>=': 'INPLACE_RSHIFT',
7.1005 + '<<=': 'INPLACE_LSHIFT',
7.1006 + '&=' : 'INPLACE_AND',
7.1007 + '^=' : 'INPLACE_XOR',
7.1008 + '|=' : 'INPLACE_OR',
7.1009 + }
7.1010 +
7.1011 + def visitAugName(self, node, mode):
7.1012 + if mode == "load":
7.1013 + self.loadName(node.name)
7.1014 + elif mode == "store":
7.1015 + self.storeName(node.name)
7.1016 +
7.1017 + def visitAugGetattr(self, node, mode):
7.1018 + if mode == "load":
7.1019 + self.visit(node.expr)
7.1020 + self.emit('DUP_TOP')
7.1021 + self.emit('LOAD_ATTR', self.mangle(node.attrname))
7.1022 + elif mode == "store":
7.1023 + self.emit('ROT_TWO')
7.1024 + self.emit('STORE_ATTR', self.mangle(node.attrname))
7.1025 +
7.1026 + def visitAugSlice(self, node, mode):
7.1027 + if mode == "load":
7.1028 + self.visitSlice(node, 1)
7.1029 + elif mode == "store":
7.1030 + slice = 0
7.1031 + if node.lower:
7.1032 + slice = slice | 1
7.1033 + if node.upper:
7.1034 + slice = slice | 2
7.1035 + if slice == 0:
7.1036 + self.emit('ROT_TWO')
7.1037 + elif slice == 3:
7.1038 + self.emit('ROT_FOUR')
7.1039 + else:
7.1040 + self.emit('ROT_THREE')
7.1041 + self.emit('STORE_SLICE+%d' % slice)
7.1042 +
7.1043 + def visitAugSubscript(self, node, mode):
7.1044 + if mode == "load":
7.1045 + self.visitSubscript(node, 1)
7.1046 + elif mode == "store":
7.1047 + self.emit('ROT_THREE')
7.1048 + self.emit('STORE_SUBSCR')
7.1049 +
7.1050 + def visitExec(self, node):
7.1051 + self.visit(node.expr)
7.1052 + if node.locals is None:
7.1053 + self.emit('LOAD_CONST', None)
7.1054 + else:
7.1055 + self.visit(node.locals)
7.1056 + if node.globals is None:
7.1057 + self.emit('DUP_TOP')
7.1058 + else:
7.1059 + self.visit(node.globals)
7.1060 + self.emit('EXEC_STMT')
7.1061 +
7.1062 + def visitCallFunc(self, node):
7.1063 + pos = 0
7.1064 + kw = 0
7.1065 + self.set_lineno(node)
7.1066 + self.visit(node.node)
7.1067 + for arg in node.args:
7.1068 + self.visit(arg)
7.1069 + if isinstance(arg, ast.Keyword):
7.1070 + kw = kw + 1
7.1071 + else:
7.1072 + pos = pos + 1
7.1073 + if node.star_args is not None:
7.1074 + self.visit(node.star_args)
7.1075 + if node.dstar_args is not None:
7.1076 + self.visit(node.dstar_args)
7.1077 + have_star = node.star_args is not None
7.1078 + have_dstar = node.dstar_args is not None
7.1079 + opcode = callfunc_opcode_info[have_star, have_dstar]
7.1080 + self.emit(opcode, kw << 8 | pos)
7.1081 +
7.1082 + def visitPrint(self, node, newline=0):
7.1083 + self.set_lineno(node)
7.1084 + if node.dest:
7.1085 + self.visit(node.dest)
7.1086 + for child in node.nodes:
7.1087 + if node.dest:
7.1088 + self.emit('DUP_TOP')
7.1089 + self.visit(child)
7.1090 + if node.dest:
7.1091 + self.emit('ROT_TWO')
7.1092 + self.emit('PRINT_ITEM_TO')
7.1093 + else:
7.1094 + self.emit('PRINT_ITEM')
7.1095 + if node.dest and not newline:
7.1096 + self.emit('POP_TOP')
7.1097 +
7.1098 + def visitPrintnl(self, node):
7.1099 + self.visitPrint(node, newline=1)
7.1100 + if node.dest:
7.1101 + self.emit('PRINT_NEWLINE_TO')
7.1102 + else:
7.1103 + self.emit('PRINT_NEWLINE')
7.1104 +
7.1105 + def visitReturn(self, node):
7.1106 + self.set_lineno(node)
7.1107 + self.visit(node.value)
7.1108 + self.emit('RETURN_VALUE')
7.1109 +
7.1110 + def visitYield(self, node):
7.1111 + self.set_lineno(node)
7.1112 + self.visit(node.value)
7.1113 + self.emit('YIELD_VALUE')
7.1114 +
7.1115 + # slice and subscript stuff
7.1116 +
7.1117 + def visitSlice(self, node, aug_flag=None):
7.1118 + # aug_flag is used by visitAugSlice
7.1119 + self.visit(node.expr)
7.1120 + slice = 0
7.1121 + if node.lower:
7.1122 + self.visit(node.lower)
7.1123 + slice = slice | 1
7.1124 + if node.upper:
7.1125 + self.visit(node.upper)
7.1126 + slice = slice | 2
7.1127 + if aug_flag:
7.1128 + if slice == 0:
7.1129 + self.emit('DUP_TOP')
7.1130 + elif slice == 3:
7.1131 + self.emit('DUP_TOPX', 3)
7.1132 + else:
7.1133 + self.emit('DUP_TOPX', 2)
7.1134 + if node.flags == 'OP_APPLY':
7.1135 + self.emit('SLICE+%d' % slice)
7.1136 + elif node.flags == 'OP_ASSIGN':
7.1137 + self.emit('STORE_SLICE+%d' % slice)
7.1138 + elif node.flags == 'OP_DELETE':
7.1139 + self.emit('DELETE_SLICE+%d' % slice)
7.1140 + else:
7.1141 + print "weird slice", node.flags
7.1142 + raise
7.1143 +
7.1144 + def visitSubscript(self, node, aug_flag=None):
7.1145 + self.visit(node.expr)
7.1146 + for sub in node.subs:
7.1147 + self.visit(sub)
7.1148 + if len(node.subs) > 1:
7.1149 + self.emit('BUILD_TUPLE', len(node.subs))
7.1150 + if aug_flag:
7.1151 + self.emit('DUP_TOPX', 2)
7.1152 + if node.flags == 'OP_APPLY':
7.1153 + self.emit('BINARY_SUBSCR')
7.1154 + elif node.flags == 'OP_ASSIGN':
7.1155 + self.emit('STORE_SUBSCR')
7.1156 + elif node.flags == 'OP_DELETE':
7.1157 + self.emit('DELETE_SUBSCR')
7.1158 +
7.1159 + # binary ops
7.1160 +
7.1161 + def binaryOp(self, node, op):
7.1162 + self.visit(node.left)
7.1163 + self.visit(node.right)
7.1164 + self.emit(op)
7.1165 +
7.1166 + def visitAdd(self, node):
7.1167 + return self.binaryOp(node, 'BINARY_ADD')
7.1168 +
7.1169 + def visitSub(self, node):
7.1170 + return self.binaryOp(node, 'BINARY_SUBTRACT')
7.1171 +
7.1172 + def visitMul(self, node):
7.1173 + return self.binaryOp(node, 'BINARY_MULTIPLY')
7.1174 +
7.1175 + def visitDiv(self, node):
7.1176 + return self.binaryOp(node, self._div_op)
7.1177 +
7.1178 + def visitFloorDiv(self, node):
7.1179 + return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
7.1180 +
7.1181 + def visitMod(self, node):
7.1182 + return self.binaryOp(node, 'BINARY_MODULO')
7.1183 +
7.1184 + def visitPower(self, node):
7.1185 + return self.binaryOp(node, 'BINARY_POWER')
7.1186 +
7.1187 + def visitLeftShift(self, node):
7.1188 + return self.binaryOp(node, 'BINARY_LSHIFT')
7.1189 +
7.1190 + def visitRightShift(self, node):
7.1191 + return self.binaryOp(node, 'BINARY_RSHIFT')
7.1192 +
7.1193 + # unary ops
7.1194 +
7.1195 + def unaryOp(self, node, op):
7.1196 + self.visit(node.expr)
7.1197 + self.emit(op)
7.1198 +
7.1199 + def visitInvert(self, node):
7.1200 + return self.unaryOp(node, 'UNARY_INVERT')
7.1201 +
7.1202 + def visitUnarySub(self, node):
7.1203 + return self.unaryOp(node, 'UNARY_NEGATIVE')
7.1204 +
7.1205 + def visitUnaryAdd(self, node):
7.1206 + return self.unaryOp(node, 'UNARY_POSITIVE')
7.1207 +
7.1208 + def visitUnaryInvert(self, node):
7.1209 + return self.unaryOp(node, 'UNARY_INVERT')
7.1210 +
7.1211 + def visitNot(self, node):
7.1212 + return self.unaryOp(node, 'UNARY_NOT')
7.1213 +
7.1214 + def visitBackquote(self, node):
7.1215 + return self.unaryOp(node, 'UNARY_CONVERT')
7.1216 +
7.1217 + # bit ops
7.1218 +
7.1219 + def bitOp(self, nodes, op):
7.1220 + self.visit(nodes[0])
7.1221 + for node in nodes[1:]:
7.1222 + self.visit(node)
7.1223 + self.emit(op)
7.1224 +
7.1225 + def visitBitand(self, node):
7.1226 + return self.bitOp(node.nodes, 'BINARY_AND')
7.1227 +
7.1228 + def visitBitor(self, node):
7.1229 + return self.bitOp(node.nodes, 'BINARY_OR')
7.1230 +
7.1231 + def visitBitxor(self, node):
7.1232 + return self.bitOp(node.nodes, 'BINARY_XOR')
7.1233 +
7.1234 + # object constructors
7.1235 +
7.1236 + def visitEllipsis(self, node):
7.1237 + self.emit('LOAD_CONST', Ellipsis)
7.1238 +
7.1239 + def visitTuple(self, node):
7.1240 + self.set_lineno(node)
7.1241 + for elt in node.nodes:
7.1242 + self.visit(elt)
7.1243 + self.emit('BUILD_TUPLE', len(node.nodes))
7.1244 +
7.1245 + def visitList(self, node):
7.1246 + self.set_lineno(node)
7.1247 + for elt in node.nodes:
7.1248 + self.visit(elt)
7.1249 + self.emit('BUILD_LIST', len(node.nodes))
7.1250 +
7.1251 + def visitSliceobj(self, node):
7.1252 + for child in node.nodes:
7.1253 + self.visit(child)
7.1254 + self.emit('BUILD_SLICE', len(node.nodes))
7.1255 +
7.1256 + def visitDict(self, node):
7.1257 + self.set_lineno(node)
7.1258 + self.emit('BUILD_MAP', 0)
7.1259 + for k, v in node.items:
7.1260 + self.emit('DUP_TOP')
7.1261 + self.visit(k)
7.1262 + self.visit(v)
7.1263 + self.emit('ROT_THREE')
7.1264 + self.emit('STORE_SUBSCR')
7.1265 +
7.1266 +class NestedScopeMixin:
7.1267 + """Defines initClass() for nested scoping (Python 2.2-compatible)"""
7.1268 + def initClass(self):
7.1269 + self.__class__.NameFinder = LocalNameFinder
7.1270 + self.__class__.FunctionGen = FunctionCodeGenerator
7.1271 + self.__class__.ClassGen = ClassCodeGenerator
7.1272 +
7.1273 +class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
7.1274 + __super_init = CodeGenerator.__init__
7.1275 +
7.1276 + scopes = None
7.1277 +
7.1278 + def __init__(self, tree):
7.1279 + self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
7.1280 + self.futures = future.find_futures(tree)
7.1281 + self.__super_init()
7.1282 + walk(tree, self)
7.1283 +
7.1284 + def get_module(self):
7.1285 + return self
7.1286 +
7.1287 +class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
7.1288 + __super_init = CodeGenerator.__init__
7.1289 +
7.1290 + scopes = None
7.1291 + futures = ()
7.1292 +
7.1293 + def __init__(self, tree):
7.1294 + self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
7.1295 + self.__super_init()
7.1296 + walk(tree, self)
7.1297 +
7.1298 + def get_module(self):
7.1299 + return self
7.1300 +
7.1301 +class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
7.1302 +
7.1303 + __super_init = CodeGenerator.__init__
7.1304 +
7.1305 + scopes = None
7.1306 + futures = ()
7.1307 +
7.1308 + def __init__(self, tree):
7.1309 + self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
7.1310 + self.__super_init()
7.1311 + self.set_lineno(tree)
7.1312 + walk(tree, self)
7.1313 + self.emit('RETURN_VALUE')
7.1314 +
7.1315 + def get_module(self):
7.1316 + return self
7.1317 +
7.1318 + def visitDiscard(self, node):
7.1319 + # XXX Discard means it's an expression. Perhaps this is a bad
7.1320 + # name.
7.1321 + self.visit(node.expr)
7.1322 + self.emit('PRINT_EXPR')
7.1323 +
7.1324 +class AbstractFunctionCode:
7.1325 + optimized = 1
7.1326 + lambdaCount = 0
7.1327 +
7.1328 + def __init__(self, func, scopes, isLambda, class_name, mod):
7.1329 + self.class_name = class_name
7.1330 + self.module = mod
7.1331 + if isLambda:
7.1332 + klass = FunctionCodeGenerator
7.1333 + name = "<lambda.%d>" % klass.lambdaCount
7.1334 + klass.lambdaCount = klass.lambdaCount + 1
7.1335 + else:
7.1336 + name = func.name
7.1337 +
7.1338 + args, hasTupleArg = generateArgList(func.argnames)
7.1339 + self.graph = pyassem.PyFlowGraph(name, func.filename, args,
7.1340 + optimized=1)
7.1341 + self.isLambda = isLambda
7.1342 + self.super_init()
7.1343 +
7.1344 + if not isLambda and func.doc:
7.1345 + self.setDocstring(func.doc)
7.1346 +
7.1347 + lnf = walk(func.code, self.NameFinder(args), verbose=0)
7.1348 + self.locals.push(lnf.getLocals())
7.1349 + if func.varargs:
7.1350 + self.graph.setFlag(CO_VARARGS)
7.1351 + if func.kwargs:
7.1352 + self.graph.setFlag(CO_VARKEYWORDS)
7.1353 + self.set_lineno(func)
7.1354 + if hasTupleArg:
7.1355 + self.generateArgUnpack(func.argnames)
7.1356 +
7.1357 + def get_module(self):
7.1358 + return self.module
7.1359 +
7.1360 + def finish(self):
7.1361 + self.graph.startExitBlock()
7.1362 + if not self.isLambda:
7.1363 + self.emit('LOAD_CONST', None)
7.1364 + self.emit('RETURN_VALUE')
7.1365 +
7.1366 + def generateArgUnpack(self, args):
7.1367 + for i in range(len(args)):
7.1368 + arg = args[i]
7.1369 + if isinstance(arg, tuple):
7.1370 + self.emit('LOAD_FAST', '.%d' % (i * 2))
7.1371 + self.unpackSequence(arg)
7.1372 +
7.1373 + def unpackSequence(self, tup):
7.1374 + if VERSION > 1:
7.1375 + self.emit('UNPACK_SEQUENCE', len(tup))
7.1376 + else:
7.1377 + self.emit('UNPACK_TUPLE', len(tup))
7.1378 + for elt in tup:
7.1379 + if isinstance(elt, tuple):
7.1380 + self.unpackSequence(elt)
7.1381 + else:
7.1382 + self._nameOp('STORE', elt)
7.1383 +
7.1384 + unpackTuple = unpackSequence
7.1385 +
7.1386 +class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
7.1387 + CodeGenerator):
7.1388 + super_init = CodeGenerator.__init__ # call be other init
7.1389 + scopes = None
7.1390 +
7.1391 + __super_init = AbstractFunctionCode.__init__
7.1392 +
7.1393 + def __init__(self, func, scopes, isLambda, class_name, mod):
7.1394 + self.scopes = scopes
7.1395 + self.scope = scopes[func]
7.1396 + self.__super_init(func, scopes, isLambda, class_name, mod)
7.1397 + self.graph.setFreeVars(self.scope.get_free_vars())
7.1398 + self.graph.setCellVars(self.scope.get_cell_vars())
7.1399 + if self.scope.generator is not None:
7.1400 + self.graph.setFlag(CO_GENERATOR)
7.1401 +
7.1402 +class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
7.1403 + CodeGenerator):
7.1404 + super_init = CodeGenerator.__init__ # call be other init
7.1405 + scopes = None
7.1406 +
7.1407 + __super_init = AbstractFunctionCode.__init__
7.1408 +
7.1409 + def __init__(self, gexp, scopes, class_name, mod):
7.1410 + self.scopes = scopes
7.1411 + self.scope = scopes[gexp]
7.1412 + self.__super_init(gexp, scopes, 1, class_name, mod)
7.1413 + self.graph.setFreeVars(self.scope.get_free_vars())
7.1414 + self.graph.setCellVars(self.scope.get_cell_vars())
7.1415 + self.graph.setFlag(CO_GENERATOR)
7.1416 +
7.1417 +class AbstractClassCode:
7.1418 +
7.1419 + def __init__(self, klass, scopes, module):
7.1420 + self.class_name = klass.name
7.1421 + self.module = module
7.1422 + self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
7.1423 + optimized=0, klass=1)
7.1424 + self.super_init()
7.1425 + lnf = walk(klass.code, self.NameFinder(), verbose=0)
7.1426 + self.locals.push(lnf.getLocals())
7.1427 + self.graph.setFlag(CO_NEWLOCALS)
7.1428 + if klass.doc:
7.1429 + self.setDocstring(klass.doc)
7.1430 +
7.1431 + def get_module(self):
7.1432 + return self.module
7.1433 +
7.1434 + def finish(self):
7.1435 + self.graph.startExitBlock()
7.1436 + self.emit('LOAD_LOCALS')
7.1437 + self.emit('RETURN_VALUE')
7.1438 +
7.1439 +class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
7.1440 + super_init = CodeGenerator.__init__
7.1441 + scopes = None
7.1442 +
7.1443 + __super_init = AbstractClassCode.__init__
7.1444 +
7.1445 + def __init__(self, klass, scopes, module):
7.1446 + self.scopes = scopes
7.1447 + self.scope = scopes[klass]
7.1448 + self.__super_init(klass, scopes, module)
7.1449 + self.graph.setFreeVars(self.scope.get_free_vars())
7.1450 + self.graph.setCellVars(self.scope.get_cell_vars())
7.1451 + self.set_lineno(klass)
7.1452 + self.emit("LOAD_GLOBAL", "__name__")
7.1453 + self.storeName("__module__")
7.1454 + if klass.doc:
7.1455 + self.emit("LOAD_CONST", klass.doc)
7.1456 + self.storeName('__doc__')
7.1457 +
7.1458 +def generateArgList(arglist):
7.1459 + """Generate an arg list marking TupleArgs"""
7.1460 + args = []
7.1461 + extra = []
7.1462 + count = 0
7.1463 + for i in range(len(arglist)):
7.1464 + elt = arglist[i]
7.1465 + if isinstance(elt, str):
7.1466 + args.append(elt)
7.1467 + elif isinstance(elt, tuple):
7.1468 + args.append(TupleArg(i * 2, elt))
7.1469 + extra.extend(misc.flatten(elt))
7.1470 + count = count + 1
7.1471 + else:
7.1472 + raise ValueError, "unexpect argument type:", elt
7.1473 + return args + extra, count
7.1474 +
7.1475 +def findOp(node):
7.1476 + """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
7.1477 + v = OpFinder()
7.1478 + walk(node, v, verbose=0)
7.1479 + return v.op
7.1480 +
7.1481 +class OpFinder:
7.1482 + def __init__(self):
7.1483 + self.op = None
7.1484 + def visitAssName(self, node):
7.1485 + if self.op is None:
7.1486 + self.op = node.flags
7.1487 + elif self.op != node.flags:
7.1488 + raise ValueError, "mixed ops in stmt"
7.1489 + visitAssAttr = visitAssName
7.1490 + visitSubscript = visitAssName
7.1491 +
7.1492 +class Delegator:
7.1493 + """Base class to support delegation for augmented assignment nodes
7.1494 +
7.1495 + To generator code for augmented assignments, we use the following
7.1496 + wrapper classes. In visitAugAssign, the left-hand expression node
7.1497 + is visited twice. The first time the visit uses the normal method
7.1498 + for that node . The second time the visit uses a different method
7.1499 + that generates the appropriate code to perform the assignment.
7.1500 + These delegator classes wrap the original AST nodes in order to
7.1501 + support the variant visit methods.
7.1502 + """
7.1503 + def __init__(self, obj):
7.1504 + self.obj = obj
7.1505 +
7.1506 + def __getattr__(self, attr):
7.1507 + return getattr(self.obj, attr)
7.1508 +
7.1509 +class AugGetattr(Delegator):
7.1510 + pass
7.1511 +
7.1512 +class AugName(Delegator):
7.1513 + pass
7.1514 +
7.1515 +class AugSlice(Delegator):
7.1516 + pass
7.1517 +
7.1518 +class AugSubscript(Delegator):
7.1519 + pass
7.1520 +
7.1521 +wrapper = {
7.1522 + ast.Getattr: AugGetattr,
7.1523 + ast.Name: AugName,
7.1524 + ast.Slice: AugSlice,
7.1525 + ast.Subscript: AugSubscript,
7.1526 + }
7.1527 +
7.1528 +def wrap_aug(node):
7.1529 + return wrapper[node.__class__](node)
7.1530 +
7.1531 +if __name__ == "__main__":
7.1532 + for file in sys.argv[1:]:
7.1533 + compileFile(file)
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/compiler/symbols.py Fri May 18 20:51:41 2012 +0200
8.3 @@ -0,0 +1,461 @@
8.4 +"""Module symbol-table generator"""
8.5 +
8.6 +from compiler import ast
8.7 +from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
8.8 +from compiler.misc import mangle
8.9 +import types
8.10 +
8.11 +
8.12 +import sys
8.13 +
8.14 +MANGLE_LEN = 256
8.15 +
8.16 +class Scope:
8.17 + # XXX how much information do I need about each name?
8.18 + def __init__(self, name, module, klass=None):
8.19 + self.name = name
8.20 + self.module = module
8.21 + self.defs = {}
8.22 + self.uses = {}
8.23 + self.globals = {}
8.24 + self.params = {}
8.25 + self.frees = {}
8.26 + self.cells = {}
8.27 + self.children = []
8.28 + # nested is true if the class could contain free variables,
8.29 + # i.e. if it is nested within another function.
8.30 + self.nested = None
8.31 + self.generator = None
8.32 + self.klass = None
8.33 + if klass is not None:
8.34 + for i in range(len(klass)):
8.35 + if klass[i] != '_':
8.36 + self.klass = klass[i:]
8.37 + break
8.38 +
8.39 + def __repr__(self):
8.40 + return "<%s: %s>" % (self.__class__.__name__, self.name)
8.41 +
8.42 + def mangle(self, name):
8.43 + if self.klass is None:
8.44 + return name
8.45 + return mangle(name, self.klass)
8.46 +
8.47 + def add_def(self, name):
8.48 + self.defs[self.mangle(name)] = 1
8.49 +
8.50 + def add_use(self, name):
8.51 + self.uses[self.mangle(name)] = 1
8.52 +
8.53 + def add_global(self, name):
8.54 + name = self.mangle(name)
8.55 + if name in self.uses or name in self.defs:
8.56 + pass # XXX warn about global following def/use
8.57 + if name in self.params:
8.58 + raise SyntaxError, "%s in %s is global and parameter" % \
8.59 + (name, self.name)
8.60 + self.globals[name] = 1
8.61 + self.module.add_def(name)
8.62 +
8.63 + def add_param(self, name):
8.64 + name = self.mangle(name)
8.65 + self.defs[name] = 1
8.66 + self.params[name] = 1
8.67 +
8.68 + def get_names(self):
8.69 + d = {}
8.70 + d.update(self.defs)
8.71 + d.update(self.uses)
8.72 + d.update(self.globals)
8.73 + return d.keys()
8.74 +
8.75 + def add_child(self, child):
8.76 + self.children.append(child)
8.77 +
8.78 + def get_children(self):
8.79 + return self.children
8.80 +
8.81 + def DEBUG(self):
8.82 + print >> sys.stderr, self.name, self.nested and "nested" or ""
8.83 + print >> sys.stderr, "\tglobals: ", self.globals
8.84 + print >> sys.stderr, "\tcells: ", self.cells
8.85 + print >> sys.stderr, "\tdefs: ", self.defs
8.86 + print >> sys.stderr, "\tuses: ", self.uses
8.87 + print >> sys.stderr, "\tfrees:", self.frees
8.88 +
8.89 + def check_name(self, name):
8.90 + """Return scope of name.
8.91 +
8.92 + The scope of a name could be LOCAL, GLOBAL, FREE, or CELL.
8.93 + """
8.94 + if name in self.globals:
8.95 + return SC_GLOBAL
8.96 + if name in self.cells:
8.97 + return SC_CELL
8.98 + if name in self.defs:
8.99 + return SC_LOCAL
8.100 + if self.nested and (name in self.frees or name in self.uses):
8.101 + return SC_FREE
8.102 + if self.nested:
8.103 + return SC_UNKNOWN
8.104 + else:
8.105 + return SC_GLOBAL
8.106 +
8.107 + def get_free_vars(self):
8.108 + if not self.nested:
8.109 + return ()
8.110 + free = {}
8.111 + free.update(self.frees)
8.112 + for name in self.uses.keys():
8.113 + if name not in self.defs and name not in self.globals:
8.114 + free[name] = 1
8.115 + return free.keys()
8.116 +
8.117 + def handle_children(self):
8.118 + for child in self.children:
8.119 + frees = child.get_free_vars()
8.120 + globals = self.add_frees(frees)
8.121 + for name in globals:
8.122 + child.force_global(name)
8.123 +
8.124 + def force_global(self, name):
8.125 + """Force name to be global in scope.
8.126 +
8.127 + Some child of the current node had a free reference to name.
8.128 + When the child was processed, it was labelled a free
8.129 + variable. Now that all its enclosing scope have been
8.130 + processed, the name is known to be a global or builtin. So
8.131 + walk back down the child chain and set the name to be global
8.132 + rather than free.
8.133 +
8.134 + Be careful to stop if a child does not think the name is
8.135 + free.
8.136 + """
8.137 + self.globals[name] = 1
8.138 + if name in self.frees:
8.139 + del self.frees[name]
8.140 + for child in self.children:
8.141 + if child.check_name(name) == SC_FREE:
8.142 + child.force_global(name)
8.143 +
8.144 + def add_frees(self, names):
8.145 + """Process list of free vars from nested scope.
8.146 +
8.147 + Returns a list of names that are either 1) declared global in the
8.148 + parent or 2) undefined in a top-level parent. In either case,
8.149 + the nested scope should treat them as globals.
8.150 + """
8.151 + child_globals = []
8.152 + for name in names:
8.153 + sc = self.check_name(name)
8.154 + if self.nested:
8.155 + if sc == SC_UNKNOWN or sc == SC_FREE \
8.156 + or isinstance(self, ClassScope):
8.157 + self.frees[name] = 1
8.158 + elif sc == SC_GLOBAL:
8.159 + child_globals.append(name)
8.160 + elif isinstance(self, FunctionScope) and sc == SC_LOCAL:
8.161 + self.cells[name] = 1
8.162 + elif sc != SC_CELL:
8.163 + child_globals.append(name)
8.164 + else:
8.165 + if sc == SC_LOCAL:
8.166 + self.cells[name] = 1
8.167 + elif sc != SC_CELL:
8.168 + child_globals.append(name)
8.169 + return child_globals
8.170 +
8.171 + def get_cell_vars(self):
8.172 + return self.cells.keys()
8.173 +
8.174 +class ModuleScope(Scope):
8.175 + __super_init = Scope.__init__
8.176 +
8.177 + def __init__(self):
8.178 + self.__super_init("global", self)
8.179 +
8.180 +class FunctionScope(Scope):
8.181 + pass
8.182 +
8.183 +class GenExprScope(Scope):
8.184 + __super_init = Scope.__init__
8.185 +
8.186 + __counter = 1
8.187 +
8.188 + def __init__(self, module, klass=None):
8.189 + i = self.__counter
8.190 + self.__counter += 1
8.191 + self.__super_init("generator expression<%d>"%i, module, klass)
8.192 + self.add_param('.0')
8.193 +
8.194 + def get_names(self):
8.195 + keys = Scope.get_names(self)
8.196 + return keys
8.197 +
8.198 +class LambdaScope(FunctionScope):
8.199 + __super_init = Scope.__init__
8.200 +
8.201 + __counter = 1
8.202 +
8.203 + def __init__(self, module, klass=None):
8.204 + i = self.__counter
8.205 + self.__counter += 1
8.206 + self.__super_init("lambda.%d" % i, module, klass)
8.207 +
8.208 +class ClassScope(Scope):
8.209 + __super_init = Scope.__init__
8.210 +
8.211 + def __init__(self, name, module):
8.212 + self.__super_init(name, module, name)
8.213 +
8.214 +class SymbolVisitor:
8.215 + def __init__(self):
8.216 + self.scopes = {}
8.217 + self.klass = None
8.218 +
8.219 + # node that define new scopes
8.220 +
8.221 + def visitModule(self, node):
8.222 + scope = self.module = self.scopes[node] = ModuleScope()
8.223 + self.visit(node.node, scope)
8.224 +
8.225 + visitExpression = visitModule
8.226 +
8.227 + def visitFunction(self, node, parent):
8.228 + if node.decorators:
8.229 + self.visit(node.decorators, parent)
8.230 + parent.add_def(node.name)
8.231 + for n in node.defaults:
8.232 + self.visit(n, parent)
8.233 + scope = FunctionScope(node.name, self.module, self.klass)
8.234 + if parent.nested or isinstance(parent, FunctionScope):
8.235 + scope.nested = 1
8.236 + self.scopes[node] = scope
8.237 + self._do_args(scope, node.argnames)
8.238 + self.visit(node.code, scope)
8.239 + self.handle_free_vars(scope, parent)
8.240 +
8.241 + def visitGenExpr(self, node, parent):
8.242 + scope = GenExprScope(self.module, self.klass);
8.243 + if parent.nested or isinstance(parent, FunctionScope) \
8.244 + or isinstance(parent, GenExprScope):
8.245 + scope.nested = 1
8.246 +
8.247 + self.scopes[node] = scope
8.248 + self.visit(node.code, scope)
8.249 +
8.250 + self.handle_free_vars(scope, parent)
8.251 +
8.252 + def visitGenExprInner(self, node, scope):
8.253 + for genfor in node.quals:
8.254 + self.visit(genfor, scope)
8.255 +
8.256 + self.visit(node.expr, scope)
8.257 +
8.258 + def visitGenExprFor(self, node, scope):
8.259 + self.visit(node.assign, scope, 1)
8.260 + self.visit(node.iter, scope)
8.261 + for if_ in node.ifs:
8.262 + self.visit(if_, scope)
8.263 +
8.264 + def visitGenExprIf(self, node, scope):
8.265 + self.visit(node.test, scope)
8.266 +
8.267 + def visitLambda(self, node, parent, assign=0):
8.268 + # Lambda is an expression, so it could appear in an expression
8.269 + # context where assign is passed. The transformer should catch
8.270 + # any code that has a lambda on the left-hand side.
8.271 + assert not assign
8.272 +
8.273 + for n in node.defaults:
8.274 + self.visit(n, parent)
8.275 + scope = LambdaScope(self.module, self.klass)
8.276 + if parent.nested or isinstance(parent, FunctionScope):
8.277 + scope.nested = 1
8.278 + self.scopes[node] = scope
8.279 + self._do_args(scope, node.argnames)
8.280 + self.visit(node.code, scope)
8.281 + self.handle_free_vars(scope, parent)
8.282 +
8.283 + def _do_args(self, scope, args):
8.284 + for name in args:
8.285 + if type(name) == types.TupleType:
8.286 + self._do_args(scope, name)
8.287 + else:
8.288 + scope.add_param(name)
8.289 +
8.290 + def handle_free_vars(self, scope, parent):
8.291 + parent.add_child(scope)
8.292 + scope.handle_children()
8.293 +
8.294 + def visitClass(self, node, parent):
8.295 + parent.add_def(node.name)
8.296 + for n in node.bases:
8.297 + self.visit(n, parent)
8.298 + scope = ClassScope(node.name, self.module)
8.299 + if parent.nested or isinstance(parent, FunctionScope):
8.300 + scope.nested = 1
8.301 + if node.doc is not None:
8.302 + scope.add_def('__doc__')
8.303 + scope.add_def('__module__')
8.304 + self.scopes[node] = scope
8.305 + prev = self.klass
8.306 + self.klass = node.name
8.307 + self.visit(node.code, scope)
8.308 + self.klass = prev
8.309 + self.handle_free_vars(scope, parent)
8.310 +
8.311 + # name can be a def or a use
8.312 +
8.313 + # XXX a few calls and nodes expect a third "assign" arg that is
8.314 + # true if the name is being used as an assignment. only
8.315 + # expressions contained within statements may have the assign arg.
8.316 +
8.317 + def visitName(self, node, scope, assign=0):
8.318 + if assign:
8.319 + scope.add_def(node.name)
8.320 + else:
8.321 + scope.add_use(node.name)
8.322 +
8.323 + # operations that bind new names
8.324 +
8.325 + def visitFor(self, node, scope):
8.326 + self.visit(node.assign, scope, 1)
8.327 + self.visit(node.list, scope)
8.328 + self.visit(node.body, scope)
8.329 + if node.else_:
8.330 + self.visit(node.else_, scope)
8.331 +
8.332 + def visitFrom(self, node, scope):
8.333 + for name, asname in node.names:
8.334 + if name == "*":
8.335 + continue
8.336 + scope.add_def(asname or name)
8.337 +
8.338 + def visitImport(self, node, scope):
8.339 + for name, asname in node.names:
8.340 + i = name.find(".")
8.341 + if i > -1:
8.342 + name = name[:i]
8.343 + scope.add_def(asname or name)
8.344 +
8.345 + def visitGlobal(self, node, scope):
8.346 + for name in node.names:
8.347 + scope.add_global(name)
8.348 +
8.349 + def visitAssign(self, node, scope):
8.350 + """Propagate assignment flag down to child nodes.
8.351 +
8.352 + The Assign node doesn't itself contains the variables being
8.353 + assigned to. Instead, the children in node.nodes are visited
8.354 + with the assign flag set to true. When the names occur in
8.355 + those nodes, they are marked as defs.
8.356 +
8.357 + Some names that occur in an assignment target are not bound by
8.358 + the assignment, e.g. a name occurring inside a slice. The
8.359 + visitor handles these nodes specially; they do not propagate
8.360 + the assign flag to their children.
8.361 + """
8.362 + for n in node.nodes:
8.363 + self.visit(n, scope, 1)
8.364 + self.visit(node.expr, scope)
8.365 +
8.366 + def visitAssName(self, node, scope, assign=1):
8.367 + scope.add_def(node.name)
8.368 +
8.369 + def visitAssAttr(self, node, scope, assign=0):
8.370 + self.visit(node.expr, scope, 0)
8.371 +
8.372 + def visitSubscript(self, node, scope, assign=0):
8.373 + self.visit(node.expr, scope, 0)
8.374 + for n in node.subs:
8.375 + self.visit(n, scope, 0)
8.376 +
8.377 + def visitSlice(self, node, scope, assign=0):
8.378 + self.visit(node.expr, scope, 0)
8.379 + if node.lower:
8.380 + self.visit(node.lower, scope, 0)
8.381 + if node.upper:
8.382 + self.visit(node.upper, scope, 0)
8.383 +
8.384 + def visitAugAssign(self, node, scope):
8.385 + # If the LHS is a name, then this counts as assignment.
8.386 + # Otherwise, it's just use.
8.387 + self.visit(node.node, scope)
8.388 + if isinstance(node.node, ast.Name):
8.389 + self.visit(node.node, scope, 1) # XXX worry about this
8.390 + self.visit(node.expr, scope)
8.391 +
8.392 + # prune if statements if tests are false
8.393 +
8.394 + _const_types = types.StringType, types.IntType, types.FloatType
8.395 +
8.396 + def visitIf(self, node, scope):
8.397 + for test, body in node.tests:
8.398 + if isinstance(test, ast.Const):
8.399 + if type(test.value) in self._const_types:
8.400 + if not test.value:
8.401 + continue
8.402 + self.visit(test, scope)
8.403 + self.visit(body, scope)
8.404 + if node.else_:
8.405 + self.visit(node.else_, scope)
8.406 +
8.407 + # a yield statement signals a generator
8.408 +
8.409 + def visitYield(self, node, scope):
8.410 + scope.generator = 1
8.411 + self.visit(node.value, scope)
8.412 +
8.413 +def list_eq(l1, l2):
8.414 + return sorted(l1) == sorted(l2)
8.415 +
8.416 +if __name__ == "__main__":
8.417 + import sys
8.418 + from compiler import parseFile, walk
8.419 + import symtable
8.420 +
8.421 + def get_names(syms):
8.422 + return [s for s in [s.get_name() for s in syms.get_symbols()]
8.423 + if not (s.startswith('_[') or s.startswith('.'))]
8.424 +
8.425 + for file in sys.argv[1:]:
8.426 + print file
8.427 + f = open(file)
8.428 + buf = f.read()
8.429 + f.close()
8.430 + syms = symtable.symtable(buf, file, "exec")
8.431 + mod_names = get_names(syms)
8.432 + tree = parseFile(file)
8.433 + s = SymbolVisitor()
8.434 + walk(tree, s)
8.435 +
8.436 + # compare module-level symbols
8.437 + names2 = s.scopes[tree].get_names()
8.438 +
8.439 + if not list_eq(mod_names, names2):
8.440 + print
8.441 + print "oops", file
8.442 + print sorted(mod_names)
8.443 + print sorted(names2)
8.444 + sys.exit(-1)
8.445 +
8.446 + d = {}
8.447 + d.update(s.scopes)
8.448 + del d[tree]
8.449 + scopes = d.values()
8.450 + del d
8.451 +
8.452 + for s in syms.get_symbols():
8.453 + if s.is_namespace():
8.454 + l = [sc for sc in scopes
8.455 + if sc.name == s.get_name()]
8.456 + if len(l) > 1:
8.457 + print "skipping", s.get_name()
8.458 + else:
8.459 + if not list_eq(get_names(s.get_namespace()),
8.460 + l[0].get_names()):
8.461 + print s.get_name()
8.462 + print sorted(get_names(s.get_namespace()))
8.463 + print sorted(l[0].get_names())
8.464 + sys.exit(-1)
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/compiler/syntax.py Fri May 18 20:51:41 2012 +0200
9.3 @@ -0,0 +1,46 @@
9.4 +"""Check for errs in the AST.
9.5 +
9.6 +The Python parser does not catch all syntax errors. Others, like
9.7 +assignments with invalid targets, are caught in the code generation
9.8 +phase.
9.9 +
9.10 +The compiler package catches some errors in the transformer module.
9.11 +But it seems clearer to write checkers that use the AST to detect
9.12 +errors.
9.13 +"""
9.14 +
9.15 +from compiler import ast, walk
9.16 +
9.17 +def check(tree, multi=None):
9.18 + v = SyntaxErrorChecker(multi)
9.19 + walk(tree, v)
9.20 + return v.errors
9.21 +
9.22 +class SyntaxErrorChecker:
9.23 + """A visitor to find syntax errors in the AST."""
9.24 +
9.25 + def __init__(self, multi=None):
9.26 + """Create new visitor object.
9.27 +
9.28 + If optional argument multi is not None, then print messages
9.29 + for each error rather than raising a SyntaxError for the
9.30 + first.
9.31 + """
9.32 + self.multi = multi
9.33 + self.errors = 0
9.34 +
9.35 + def error(self, node, msg):
9.36 + self.errors = self.errors + 1
9.37 + if self.multi is not None:
9.38 + print "%s:%s: %s" % (node.filename, node.lineno, msg)
9.39 + else:
9.40 + raise SyntaxError, "%s (%s:%s)" % (msg, node.filename, node.lineno)
9.41 +
9.42 + def visitAssign(self, node):
9.43 + # the transformer module handles many of these
9.44 + pass
9.45 +## for target in node.nodes:
9.46 +## if isinstance(target, ast.AssList):
9.47 +## if target.lineno is None:
9.48 +## target.lineno = node.lineno
9.49 +## self.error(target, "can't assign to list comprehension")
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/compiler/transformer.py Fri May 18 20:51:41 2012 +0200
10.3 @@ -0,0 +1,1499 @@
10.4 +"""Parse tree transformation module.
10.5 +
10.6 +Transforms Python source code into an abstract syntax tree (AST)
10.7 +defined in the ast module.
10.8 +
10.9 +The simplest ways to invoke this module are via parse and parseFile.
10.10 +parse(buf) -> AST
10.11 +parseFile(path) -> AST
10.12 +"""
10.13 +
10.14 +# Original version written by Greg Stein (gstein@lyra.org)
10.15 +# and Bill Tutt (rassilon@lima.mudlib.org)
10.16 +# February 1997.
10.17 +#
10.18 +# Modifications and improvements for Python 2.0 by Jeremy Hylton and
10.19 +# Mark Hammond
10.20 +#
10.21 +# Some fixes to try to have correct line number on almost all nodes
10.22 +# (except Module, Discard and Stmt) added by Sylvain Thenault
10.23 +#
10.24 +# Portions of this file are:
10.25 +# Copyright (C) 1997-1998 Greg Stein. All Rights Reserved.
10.26 +#
10.27 +# This module is provided under a BSD-ish license. See
10.28 +# http://www.opensource.org/licenses/bsd-license.html
10.29 +# and replace OWNER, ORGANIZATION, and YEAR as appropriate.
10.30 +
10.31 +from compiler.ast import *
10.32 +import parser
10.33 +import symbol
10.34 +import token
10.35 +
10.36 +class WalkerError(StandardError):
10.37 + pass
10.38 +
10.39 +from compiler.consts import CO_VARARGS, CO_VARKEYWORDS
10.40 +from compiler.consts import OP_ASSIGN, OP_DELETE, OP_APPLY
10.41 +
10.42 +def parseFile(path):
10.43 + f = open(path, "U")
10.44 + # XXX The parser API tolerates files without a trailing newline,
10.45 + # but not strings without a trailing newline. Always add an extra
10.46 + # newline to the file contents, since we're going through the string
10.47 + # version of the API.
10.48 + src = f.read() + "\n"
10.49 + f.close()
10.50 + return parse(src)
10.51 +
10.52 +def parse(buf, mode="exec"):
10.53 + if mode == "exec" or mode == "single":
10.54 + return Transformer().parsesuite(buf)
10.55 + elif mode == "eval":
10.56 + return Transformer().parseexpr(buf)
10.57 + else:
10.58 + raise ValueError("compile() arg 3 must be"
10.59 + " 'exec' or 'eval' or 'single'")
10.60 +
10.61 +def asList(nodes):
10.62 + l = []
10.63 + for item in nodes:
10.64 + if hasattr(item, "asList"):
10.65 + l.append(item.asList())
10.66 + else:
10.67 + if type(item) is type( (None, None) ):
10.68 + l.append(tuple(asList(item)))
10.69 + elif type(item) is type( [] ):
10.70 + l.append(asList(item))
10.71 + else:
10.72 + l.append(item)
10.73 + return l
10.74 +
10.75 +def extractLineNo(ast):
10.76 + if not isinstance(ast[1], tuple):
10.77 + # get a terminal node
10.78 + return ast[2]
10.79 + for child in ast[1:]:
10.80 + if isinstance(child, tuple):
10.81 + lineno = extractLineNo(child)
10.82 + if lineno is not None:
10.83 + return lineno
10.84 +
10.85 +def Node(*args):
10.86 + kind = args[0]
10.87 + if kind in nodes:
10.88 + try:
10.89 + return nodes[kind](*args[1:])
10.90 + except TypeError:
10.91 + print nodes[kind], len(args), args
10.92 + raise
10.93 + else:
10.94 + raise WalkerError, "Can't find appropriate Node type: %s" % str(args)
10.95 + #return apply(ast.Node, args)
10.96 +
10.97 +class Transformer:
10.98 + """Utility object for transforming Python parse trees.
10.99 +
10.100 + Exposes the following methods:
10.101 + tree = transform(ast_tree)
10.102 + tree = parsesuite(text)
10.103 + tree = parseexpr(text)
10.104 + tree = parsefile(fileob | filename)
10.105 + """
10.106 +
10.107 + def __init__(self):
10.108 + self._dispatch = {}
10.109 + for value, name in symbol.sym_name.items():
10.110 + if hasattr(self, name):
10.111 + self._dispatch[value] = getattr(self, name)
10.112 + self._dispatch[token.NEWLINE] = self.com_NEWLINE
10.113 + self._atom_dispatch = {token.LPAR: self.atom_lpar,
10.114 + token.LSQB: self.atom_lsqb,
10.115 + token.LBRACE: self.atom_lbrace,
10.116 + token.BACKQUOTE: self.atom_backquote,
10.117 + token.NUMBER: self.atom_number,
10.118 + token.STRING: self.atom_string,
10.119 + token.NAME: self.atom_name,
10.120 + }
10.121 + self.encoding = None
10.122 +
10.123 + def transform(self, tree):
10.124 + """Transform an AST into a modified parse tree."""
10.125 + if not (isinstance(tree, tuple) or isinstance(tree, list)):
10.126 + tree = parser.st2tuple(tree, line_info=1)
10.127 + return self.compile_node(tree)
10.128 +
10.129 + def parsesuite(self, text):
10.130 + """Return a modified parse tree for the given suite text."""
10.131 + return self.transform(parser.suite(text))
10.132 +
10.133 + def parseexpr(self, text):
10.134 + """Return a modified parse tree for the given expression text."""
10.135 + return self.transform(parser.expr(text))
10.136 +
10.137 + def parsefile(self, file):
10.138 + """Return a modified parse tree for the contents of the given file."""
10.139 + if type(file) == type(''):
10.140 + file = open(file)
10.141 + return self.parsesuite(file.read())
10.142 +
10.143 + # --------------------------------------------------------------
10.144 + #
10.145 + # PRIVATE METHODS
10.146 + #
10.147 +
10.148 + def compile_node(self, node):
10.149 + ### emit a line-number node?
10.150 + n = node[0]
10.151 +
10.152 + if n == symbol.encoding_decl:
10.153 + self.encoding = node[2]
10.154 + node = node[1]
10.155 + n = node[0]
10.156 +
10.157 + if n == symbol.single_input:
10.158 + return self.single_input(node[1:])
10.159 + if n == symbol.file_input:
10.160 + return self.file_input(node[1:])
10.161 + if n == symbol.eval_input:
10.162 + return self.eval_input(node[1:])
10.163 + if n == symbol.lambdef:
10.164 + return self.lambdef(node[1:])
10.165 + if n == symbol.funcdef:
10.166 + return self.funcdef(node[1:])
10.167 + if n == symbol.classdef:
10.168 + return self.classdef(node[1:])
10.169 +
10.170 + raise WalkerError, ('unexpected node type', n)
10.171 +
10.172 + def single_input(self, node):
10.173 + ### do we want to do anything about being "interactive" ?
10.174 +
10.175 + # NEWLINE | simple_stmt | compound_stmt NEWLINE
10.176 + n = node[0][0]
10.177 + if n != token.NEWLINE:
10.178 + return self.com_stmt(node[0])
10.179 +
10.180 + return Pass()
10.181 +
10.182 + def file_input(self, nodelist):
10.183 + doc = self.get_docstring(nodelist, symbol.file_input)
10.184 + if doc is not None:
10.185 + i = 1
10.186 + else:
10.187 + i = 0
10.188 + stmts = []
10.189 + for node in nodelist[i:]:
10.190 + if node[0] != token.ENDMARKER and node[0] != token.NEWLINE:
10.191 + self.com_append_stmt(stmts, node)
10.192 + return Module(doc, Stmt(stmts))
10.193 +
10.194 + def eval_input(self, nodelist):
10.195 + # from the built-in function input()
10.196 + ### is this sufficient?
10.197 + return Expression(self.com_node(nodelist[0]))
10.198 +
10.199 + def decorator_name(self, nodelist):
10.200 + listlen = len(nodelist)
10.201 + assert listlen >= 1 and listlen % 2 == 1
10.202 +
10.203 + item = self.atom_name(nodelist)
10.204 + i = 1
10.205 + while i < listlen:
10.206 + assert nodelist[i][0] == token.DOT
10.207 + assert nodelist[i + 1][0] == token.NAME
10.208 + item = Getattr(item, nodelist[i + 1][1])
10.209 + i += 2
10.210 +
10.211 + return item
10.212 +
10.213 + def decorator(self, nodelist):
10.214 + # '@' dotted_name [ '(' [arglist] ')' ]
10.215 + assert len(nodelist) in (3, 5, 6)
10.216 + assert nodelist[0][0] == token.AT
10.217 + assert nodelist[-1][0] == token.NEWLINE
10.218 +
10.219 + assert nodelist[1][0] == symbol.dotted_name
10.220 + funcname = self.decorator_name(nodelist[1][1:])
10.221 +
10.222 + if len(nodelist) > 3:
10.223 + assert nodelist[2][0] == token.LPAR
10.224 + expr = self.com_call_function(funcname, nodelist[3])
10.225 + else:
10.226 + expr = funcname
10.227 +
10.228 + return expr
10.229 +
10.230 + def decorators(self, nodelist):
10.231 + # decorators: decorator ([NEWLINE] decorator)* NEWLINE
10.232 + items = []
10.233 + for dec_nodelist in nodelist:
10.234 + assert dec_nodelist[0] == symbol.decorator
10.235 + items.append(self.decorator(dec_nodelist[1:]))
10.236 + return Decorators(items)
10.237 +
10.238 + def decorated(self, nodelist):
10.239 + assert nodelist[0][0] == symbol.decorators
10.240 + if nodelist[1][0] == symbol.funcdef:
10.241 + n = [nodelist[0]] + list(nodelist[1][1:])
10.242 + return self.funcdef(n)
10.243 + elif nodelist[1][0] == symbol.classdef:
10.244 + decorators = self.decorators(nodelist[0][1:])
10.245 + cls = self.classdef(nodelist[1][1:])
10.246 + cls.decorators = decorators
10.247 + return cls
10.248 + raise WalkerError()
10.249 +
10.250 + def funcdef(self, nodelist):
10.251 + # -6 -5 -4 -3 -2 -1
10.252 + # funcdef: [decorators] 'def' NAME parameters ':' suite
10.253 + # parameters: '(' [varargslist] ')'
10.254 +
10.255 + if len(nodelist) == 6:
10.256 + assert nodelist[0][0] == symbol.decorators
10.257 + decorators = self.decorators(nodelist[0][1:])
10.258 + else:
10.259 + assert len(nodelist) == 5
10.260 + decorators = None
10.261 +
10.262 + lineno = nodelist[-4][2]
10.263 + name = nodelist[-4][1]
10.264 + args = nodelist[-3][2]
10.265 +
10.266 + if args[0] == symbol.varargslist:
10.267 + names, defaults, flags = self.com_arglist(args[1:])
10.268 + else:
10.269 + names = defaults = ()
10.270 + flags = 0
10.271 + doc = self.get_docstring(nodelist[-1])
10.272 +
10.273 + # code for function
10.274 + code = self.com_node(nodelist[-1])
10.275 +
10.276 + if doc is not None:
10.277 + assert isinstance(code, Stmt)
10.278 + assert isinstance(code.nodes[0], Discard)
10.279 + del code.nodes[0]
10.280 + return Function(decorators, name, names, defaults, flags, doc, code,
10.281 + lineno=lineno)
10.282 +
10.283 + def lambdef(self, nodelist):
10.284 + # lambdef: 'lambda' [varargslist] ':' test
10.285 + if nodelist[2][0] == symbol.varargslist:
10.286 + names, defaults, flags = self.com_arglist(nodelist[2][1:])
10.287 + else:
10.288 + names = defaults = ()
10.289 + flags = 0
10.290 +
10.291 + # code for lambda
10.292 + code = self.com_node(nodelist[-1])
10.293 +
10.294 + return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
10.295 + old_lambdef = lambdef
10.296 +
10.297 + def classdef(self, nodelist):
10.298 + # classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
10.299 +
10.300 + name = nodelist[1][1]
10.301 + doc = self.get_docstring(nodelist[-1])
10.302 + if nodelist[2][0] == token.COLON:
10.303 + bases = []
10.304 + elif nodelist[3][0] == token.RPAR:
10.305 + bases = []
10.306 + else:
10.307 + bases = self.com_bases(nodelist[3])
10.308 +
10.309 + # code for class
10.310 + code = self.com_node(nodelist[-1])
10.311 +
10.312 + if doc is not None:
10.313 + assert isinstance(code, Stmt)
10.314 + assert isinstance(code.nodes[0], Discard)
10.315 + del code.nodes[0]
10.316 +
10.317 + return Class(name, bases, doc, code, lineno=nodelist[1][2])
10.318 +
10.319 + def stmt(self, nodelist):
10.320 + return self.com_stmt(nodelist[0])
10.321 +
10.322 + small_stmt = stmt
10.323 + flow_stmt = stmt
10.324 + compound_stmt = stmt
10.325 +
10.326 + def simple_stmt(self, nodelist):
10.327 + # small_stmt (';' small_stmt)* [';'] NEWLINE
10.328 + stmts = []
10.329 + for i in range(0, len(nodelist), 2):
10.330 + self.com_append_stmt(stmts, nodelist[i])
10.331 + return Stmt(stmts)
10.332 +
10.333 + def parameters(self, nodelist):
10.334 + raise WalkerError
10.335 +
10.336 + def varargslist(self, nodelist):
10.337 + raise WalkerError
10.338 +
10.339 + def fpdef(self, nodelist):
10.340 + raise WalkerError
10.341 +
10.342 + def fplist(self, nodelist):
10.343 + raise WalkerError
10.344 +
10.345 + def dotted_name(self, nodelist):
10.346 + raise WalkerError
10.347 +
10.348 + def comp_op(self, nodelist):
10.349 + raise WalkerError
10.350 +
10.351 + def trailer(self, nodelist):
10.352 + raise WalkerError
10.353 +
10.354 + def sliceop(self, nodelist):
10.355 + raise WalkerError
10.356 +
10.357 + def argument(self, nodelist):
10.358 + raise WalkerError
10.359 +
10.360 + # --------------------------------------------------------------
10.361 + #
10.362 + # STATEMENT NODES (invoked by com_node())
10.363 + #
10.364 +
10.365 + def expr_stmt(self, nodelist):
10.366 + # augassign testlist | testlist ('=' testlist)*
10.367 + en = nodelist[-1]
10.368 + exprNode = self.lookup_node(en)(en[1:])
10.369 + if len(nodelist) == 1:
10.370 + return Discard(exprNode, lineno=exprNode.lineno)
10.371 + if nodelist[1][0] == token.EQUAL:
10.372 + nodesl = []
10.373 + for i in range(0, len(nodelist) - 2, 2):
10.374 + nodesl.append(self.com_assign(nodelist[i], OP_ASSIGN))
10.375 + return Assign(nodesl, exprNode, lineno=nodelist[1][2])
10.376 + else:
10.377 + lval = self.com_augassign(nodelist[0])
10.378 + op = self.com_augassign_op(nodelist[1])
10.379 + return AugAssign(lval, op[1], exprNode, lineno=op[2])
10.380 + raise WalkerError, "can't get here"
10.381 +
10.382 + def print_stmt(self, nodelist):
10.383 + # print ([ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ])
10.384 + items = []
10.385 + if len(nodelist) == 1:
10.386 + start = 1
10.387 + dest = None
10.388 + elif nodelist[1][0] == token.RIGHTSHIFT:
10.389 + assert len(nodelist) == 3 \
10.390 + or nodelist[3][0] == token.COMMA
10.391 + dest = self.com_node(nodelist[2])
10.392 + start = 4
10.393 + else:
10.394 + dest = None
10.395 + start = 1
10.396 + for i in range(start, len(nodelist), 2):
10.397 + items.append(self.com_node(nodelist[i]))
10.398 + if nodelist[-1][0] == token.COMMA:
10.399 + return Print(items, dest, lineno=nodelist[0][2])
10.400 + return Printnl(items, dest, lineno=nodelist[0][2])
10.401 +
10.402 + def del_stmt(self, nodelist):
10.403 + return self.com_assign(nodelist[1], OP_DELETE)
10.404 +
10.405 + def pass_stmt(self, nodelist):
10.406 + return Pass(lineno=nodelist[0][2])
10.407 +
10.408 + def break_stmt(self, nodelist):
10.409 + return Break(lineno=nodelist[0][2])
10.410 +
10.411 + def continue_stmt(self, nodelist):
10.412 + return Continue(lineno=nodelist[0][2])
10.413 +
10.414 + def return_stmt(self, nodelist):
10.415 + # return: [testlist]
10.416 + if len(nodelist) < 2:
10.417 + return Return(Const(None), lineno=nodelist[0][2])
10.418 + return Return(self.com_node(nodelist[1]), lineno=nodelist[0][2])
10.419 +
10.420 + def yield_stmt(self, nodelist):
10.421 + expr = self.com_node(nodelist[0])
10.422 + return Discard(expr, lineno=expr.lineno)
10.423 +
10.424 + def yield_expr(self, nodelist):
10.425 + if len(nodelist) > 1:
10.426 + value = self.com_node(nodelist[1])
10.427 + else:
10.428 + value = Const(None)
10.429 + return Yield(value, lineno=nodelist[0][2])
10.430 +
10.431 + def raise_stmt(self, nodelist):
10.432 + # raise: [test [',' test [',' test]]]
10.433 + if len(nodelist) > 5:
10.434 + expr3 = self.com_node(nodelist[5])
10.435 + else:
10.436 + expr3 = None
10.437 + if len(nodelist) > 3:
10.438 + expr2 = self.com_node(nodelist[3])
10.439 + else:
10.440 + expr2 = None
10.441 + if len(nodelist) > 1:
10.442 + expr1 = self.com_node(nodelist[1])
10.443 + else:
10.444 + expr1 = None
10.445 + return Raise(expr1, expr2, expr3, lineno=nodelist[0][2])
10.446 +
10.447 + def import_stmt(self, nodelist):
10.448 + # import_stmt: import_name | import_from
10.449 + assert len(nodelist) == 1
10.450 + return self.com_node(nodelist[0])
10.451 +
10.452 + def import_name(self, nodelist):
10.453 + # import_name: 'import' dotted_as_names
10.454 + return Import(self.com_dotted_as_names(nodelist[1]),
10.455 + lineno=nodelist[0][2])
10.456 +
10.457 + def import_from(self, nodelist):
10.458 + # import_from: 'from' ('.'* dotted_name | '.') 'import' ('*' |
10.459 + # '(' import_as_names ')' | import_as_names)
10.460 + assert nodelist[0][1] == 'from'
10.461 + idx = 1
10.462 + while nodelist[idx][1] == '.':
10.463 + idx += 1
10.464 + level = idx - 1
10.465 + if nodelist[idx][0] == symbol.dotted_name:
10.466 + fromname = self.com_dotted_name(nodelist[idx])
10.467 + idx += 1
10.468 + else:
10.469 + fromname = ""
10.470 + assert nodelist[idx][1] == 'import'
10.471 + if nodelist[idx + 1][0] == token.STAR:
10.472 + return From(fromname, [('*', None)], level,
10.473 + lineno=nodelist[0][2])
10.474 + else:
10.475 + node = nodelist[idx + 1 + (nodelist[idx + 1][0] == token.LPAR)]
10.476 + return From(fromname, self.com_import_as_names(node), level,
10.477 + lineno=nodelist[0][2])
10.478 +
10.479 + def global_stmt(self, nodelist):
10.480 + # global: NAME (',' NAME)*
10.481 + names = []
10.482 + for i in range(1, len(nodelist), 2):
10.483 + names.append(nodelist[i][1])
10.484 + return Global(names, lineno=nodelist[0][2])
10.485 +
10.486 + def exec_stmt(self, nodelist):
10.487 + # exec_stmt: 'exec' expr ['in' expr [',' expr]]
10.488 + expr1 = self.com_node(nodelist[1])
10.489 + if len(nodelist) >= 4:
10.490 + expr2 = self.com_node(nodelist[3])
10.491 + if len(nodelist) >= 6:
10.492 + expr3 = self.com_node(nodelist[5])
10.493 + else:
10.494 + expr3 = None
10.495 + else:
10.496 + expr2 = expr3 = None
10.497 +
10.498 + return Exec(expr1, expr2, expr3, lineno=nodelist[0][2])
10.499 +
10.500 + def assert_stmt(self, nodelist):
10.501 + # 'assert': test, [',' test]
10.502 + expr1 = self.com_node(nodelist[1])
10.503 + if (len(nodelist) == 4):
10.504 + expr2 = self.com_node(nodelist[3])
10.505 + else:
10.506 + expr2 = None
10.507 + return Assert(expr1, expr2, lineno=nodelist[0][2])
10.508 +
10.509 + def if_stmt(self, nodelist):
10.510 + # if: test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
10.511 + tests = []
10.512 + for i in range(0, len(nodelist) - 3, 4):
10.513 + testNode = self.com_node(nodelist[i + 1])
10.514 + suiteNode = self.com_node(nodelist[i + 3])
10.515 + tests.append((testNode, suiteNode))
10.516 +
10.517 + if len(nodelist) % 4 == 3:
10.518 + elseNode = self.com_node(nodelist[-1])
10.519 +## elseNode.lineno = nodelist[-1][1][2]
10.520 + else:
10.521 + elseNode = None
10.522 + return If(tests, elseNode, lineno=nodelist[0][2])
10.523 +
10.524 + def while_stmt(self, nodelist):
10.525 + # 'while' test ':' suite ['else' ':' suite]
10.526 +
10.527 + testNode = self.com_node(nodelist[1])
10.528 + bodyNode = self.com_node(nodelist[3])
10.529 +
10.530 + if len(nodelist) > 4:
10.531 + elseNode = self.com_node(nodelist[6])
10.532 + else:
10.533 + elseNode = None
10.534 +
10.535 + return While(testNode, bodyNode, elseNode, lineno=nodelist[0][2])
10.536 +
10.537 + def for_stmt(self, nodelist):
10.538 + # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
10.539 +
10.540 + assignNode = self.com_assign(nodelist[1], OP_ASSIGN)
10.541 + listNode = self.com_node(nodelist[3])
10.542 + bodyNode = self.com_node(nodelist[5])
10.543 +
10.544 + if len(nodelist) > 8:
10.545 + elseNode = self.com_node(nodelist[8])
10.546 + else:
10.547 + elseNode = None
10.548 +
10.549 + return For(assignNode, listNode, bodyNode, elseNode,
10.550 + lineno=nodelist[0][2])
10.551 +
10.552 + def try_stmt(self, nodelist):
10.553 + return self.com_try_except_finally(nodelist)
10.554 +
10.555 + def with_stmt(self, nodelist):
10.556 + return self.com_with(nodelist)
10.557 +
10.558 + def with_var(self, nodelist):
10.559 + return self.com_with_var(nodelist)
10.560 +
10.561 + def suite(self, nodelist):
10.562 + # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
10.563 + if len(nodelist) == 1:
10.564 + return self.com_stmt(nodelist[0])
10.565 +
10.566 + stmts = []
10.567 + for node in nodelist:
10.568 + if node[0] == symbol.stmt:
10.569 + self.com_append_stmt(stmts, node)
10.570 + return Stmt(stmts)
10.571 +
10.572 + # --------------------------------------------------------------
10.573 + #
10.574 + # EXPRESSION NODES (invoked by com_node())
10.575 + #
10.576 +
10.577 + def testlist(self, nodelist):
10.578 + # testlist: expr (',' expr)* [',']
10.579 + # testlist_safe: test [(',' test)+ [',']]
10.580 + # exprlist: expr (',' expr)* [',']
10.581 + return self.com_binary(Tuple, nodelist)
10.582 +
10.583 + testlist_safe = testlist # XXX
10.584 + testlist1 = testlist
10.585 + exprlist = testlist
10.586 +
10.587 + def testlist_gexp(self, nodelist):
10.588 + if len(nodelist) == 2 and nodelist[1][0] == symbol.gen_for:
10.589 + test = self.com_node(nodelist[0])
10.590 + return self.com_generator_expression(test, nodelist[1])
10.591 + return self.testlist(nodelist)
10.592 +
10.593 + def test(self, nodelist):
10.594 + # or_test ['if' or_test 'else' test] | lambdef
10.595 + if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
10.596 + return self.lambdef(nodelist[0])
10.597 + then = self.com_node(nodelist[0])
10.598 + if len(nodelist) > 1:
10.599 + assert len(nodelist) == 5
10.600 + assert nodelist[1][1] == 'if'
10.601 + assert nodelist[3][1] == 'else'
10.602 + test = self.com_node(nodelist[2])
10.603 + else_ = self.com_node(nodelist[4])
10.604 + return IfExp(test, then, else_, lineno=nodelist[1][2])
10.605 + return then
10.606 +
10.607 + def or_test(self, nodelist):
10.608 + # and_test ('or' and_test)* | lambdef
10.609 + if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
10.610 + return self.lambdef(nodelist[0])
10.611 + return self.com_binary(Or, nodelist)
10.612 + old_test = or_test
10.613 +
10.614 + def and_test(self, nodelist):
10.615 + # not_test ('and' not_test)*
10.616 + return self.com_binary(And, nodelist)
10.617 +
10.618 + def not_test(self, nodelist):
10.619 + # 'not' not_test | comparison
10.620 + result = self.com_node(nodelist[-1])
10.621 + if len(nodelist) == 2:
10.622 + return Not(result, lineno=nodelist[0][2])
10.623 + return result
10.624 +
10.625 + def comparison(self, nodelist):
10.626 + # comparison: expr (comp_op expr)*
10.627 + node = self.com_node(nodelist[0])
10.628 + if len(nodelist) == 1:
10.629 + return node
10.630 +
10.631 + results = []
10.632 + for i in range(2, len(nodelist), 2):
10.633 + nl = nodelist[i-1]
10.634 +
10.635 + # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
10.636 + # | 'in' | 'not' 'in' | 'is' | 'is' 'not'
10.637 + n = nl[1]
10.638 + if n[0] == token.NAME:
10.639 + type = n[1]
10.640 + if len(nl) == 3:
10.641 + if type == 'not':
10.642 + type = 'not in'
10.643 + else:
10.644 + type = 'is not'
10.645 + else:
10.646 + type = _cmp_types[n[0]]
10.647 +
10.648 + lineno = nl[1][2]
10.649 + results.append((type, self.com_node(nodelist[i])))
10.650 +
10.651 + # we need a special "compare" node so that we can distinguish
10.652 + # 3 < x < 5 from (3 < x) < 5
10.653 + # the two have very different semantics and results (note that the
10.654 + # latter form is always true)
10.655 +
10.656 + return Compare(node, results, lineno=lineno)
10.657 +
10.658 + def expr(self, nodelist):
10.659 + # xor_expr ('|' xor_expr)*
10.660 + return self.com_binary(Bitor, nodelist)
10.661 +
10.662 + def xor_expr(self, nodelist):
10.663 + # xor_expr ('^' xor_expr)*
10.664 + return self.com_binary(Bitxor, nodelist)
10.665 +
10.666 + def and_expr(self, nodelist):
10.667 + # xor_expr ('&' xor_expr)*
10.668 + return self.com_binary(Bitand, nodelist)
10.669 +
10.670 + def shift_expr(self, nodelist):
10.671 + # shift_expr ('<<'|'>>' shift_expr)*
10.672 + node = self.com_node(nodelist[0])
10.673 + for i in range(2, len(nodelist), 2):
10.674 + right = self.com_node(nodelist[i])
10.675 + if nodelist[i-1][0] == token.LEFTSHIFT:
10.676 + node = LeftShift([node, right], lineno=nodelist[1][2])
10.677 + elif nodelist[i-1][0] == token.RIGHTSHIFT:
10.678 + node = RightShift([node, right], lineno=nodelist[1][2])
10.679 + else:
10.680 + raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
10.681 + return node
10.682 +
10.683 + def arith_expr(self, nodelist):
10.684 + node = self.com_node(nodelist[0])
10.685 + for i in range(2, len(nodelist), 2):
10.686 + right = self.com_node(nodelist[i])
10.687 + if nodelist[i-1][0] == token.PLUS:
10.688 + node = Add([node, right], lineno=nodelist[1][2])
10.689 + elif nodelist[i-1][0] == token.MINUS:
10.690 + node = Sub([node, right], lineno=nodelist[1][2])
10.691 + else:
10.692 + raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
10.693 + return node
10.694 +
10.695 + def term(self, nodelist):
10.696 + node = self.com_node(nodelist[0])
10.697 + for i in range(2, len(nodelist), 2):
10.698 + right = self.com_node(nodelist[i])
10.699 + t = nodelist[i-1][0]
10.700 + if t == token.STAR:
10.701 + node = Mul([node, right])
10.702 + elif t == token.SLASH:
10.703 + node = Div([node, right])
10.704 + elif t == token.PERCENT:
10.705 + node = Mod([node, right])
10.706 + elif t == token.DOUBLESLASH:
10.707 + node = FloorDiv([node, right])
10.708 + else:
10.709 + raise ValueError, "unexpected token: %s" % t
10.710 + node.lineno = nodelist[1][2]
10.711 + return node
10.712 +
10.713 + def factor(self, nodelist):
10.714 + elt = nodelist[0]
10.715 + t = elt[0]
10.716 + node = self.lookup_node(nodelist[-1])(nodelist[-1][1:])
10.717 + # need to handle (unary op)constant here...
10.718 + if t == token.PLUS:
10.719 + return UnaryAdd(node, lineno=elt[2])
10.720 + elif t == token.MINUS:
10.721 + return UnarySub(node, lineno=elt[2])
10.722 + elif t == token.TILDE:
10.723 + node = Invert(node, lineno=elt[2])
10.724 + return node
10.725 +
10.726 + def power(self, nodelist):
10.727 + # power: atom trailer* ('**' factor)*
10.728 + node = self.com_node(nodelist[0])
10.729 + for i in range(1, len(nodelist)):
10.730 + elt = nodelist[i]
10.731 + if elt[0] == token.DOUBLESTAR:
10.732 + return Power([node, self.com_node(nodelist[i+1])],
10.733 + lineno=elt[2])
10.734 +
10.735 + node = self.com_apply_trailer(node, elt)
10.736 +
10.737 + return node
10.738 +
10.739 + def atom(self, nodelist):
10.740 + return self._atom_dispatch[nodelist[0][0]](nodelist)
10.741 +
10.742 + def atom_lpar(self, nodelist):
10.743 + if nodelist[1][0] == token.RPAR:
10.744 + return Tuple((), lineno=nodelist[0][2])
10.745 + return self.com_node(nodelist[1])
10.746 +
10.747 + def atom_lsqb(self, nodelist):
10.748 + if nodelist[1][0] == token.RSQB:
10.749 + return List((), lineno=nodelist[0][2])
10.750 + return self.com_list_constructor(nodelist[1])
10.751 +
10.752 + def atom_lbrace(self, nodelist):
10.753 + if nodelist[1][0] == token.RBRACE:
10.754 + return Dict((), lineno=nodelist[0][2])
10.755 + return self.com_dictmaker(nodelist[1])
10.756 +
10.757 + def atom_backquote(self, nodelist):
10.758 + return Backquote(self.com_node(nodelist[1]))
10.759 +
10.760 + def atom_number(self, nodelist):
10.761 + ### need to verify this matches compile.c
10.762 + k = eval(nodelist[0][1])
10.763 + return Const(k, lineno=nodelist[0][2])
10.764 +
10.765 + def decode_literal(self, lit):
10.766 + if self.encoding:
10.767 + # this is particularly fragile & a bit of a
10.768 + # hack... changes in compile.c:parsestr and
10.769 + # tokenizer.c must be reflected here.
10.770 + if self.encoding not in ['utf-8', 'iso-8859-1']:
10.771 + lit = unicode(lit, 'utf-8').encode(self.encoding)
10.772 + return eval("# coding: %s\n%s" % (self.encoding, lit))
10.773 + else:
10.774 + return eval(lit)
10.775 +
10.776 + def atom_string(self, nodelist):
10.777 + k = ''
10.778 + for node in nodelist:
10.779 + k += self.decode_literal(node[1])
10.780 + return Const(k, lineno=nodelist[0][2])
10.781 +
10.782 + def atom_name(self, nodelist):
10.783 + return Name(nodelist[0][1], lineno=nodelist[0][2])
10.784 +
10.785 + # --------------------------------------------------------------
10.786 + #
10.787 + # INTERNAL PARSING UTILITIES
10.788 + #
10.789 +
10.790 + # The use of com_node() introduces a lot of extra stack frames,
10.791 + # enough to cause a stack overflow compiling test.test_parser with
10.792 + # the standard interpreter recursionlimit. The com_node() is a
10.793 + # convenience function that hides the dispatch details, but comes
10.794 + # at a very high cost. It is more efficient to dispatch directly
10.795 + # in the callers. In these cases, use lookup_node() and call the
10.796 + # dispatched node directly.
10.797 +
10.798 + def lookup_node(self, node):
10.799 + return self._dispatch[node[0]]
10.800 +
10.801 + def com_node(self, node):
10.802 + # Note: compile.c has handling in com_node for del_stmt, pass_stmt,
10.803 + # break_stmt, stmt, small_stmt, flow_stmt, simple_stmt,
10.804 + # and compound_stmt.
10.805 + # We'll just dispatch them.
10.806 + return self._dispatch[node[0]](node[1:])
10.807 +
10.808 + def com_NEWLINE(self, *args):
10.809 + # A ';' at the end of a line can make a NEWLINE token appear
10.810 + # here, Render it harmless. (genc discards ('discard',
10.811 + # ('const', xxxx)) Nodes)
10.812 + return Discard(Const(None))
10.813 +
10.814 + def com_arglist(self, nodelist):
10.815 + # varargslist:
10.816 + # (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME)
10.817 + # | fpdef ['=' test] (',' fpdef ['=' test])* [',']
10.818 + # fpdef: NAME | '(' fplist ')'
10.819 + # fplist: fpdef (',' fpdef)* [',']
10.820 + names = []
10.821 + defaults = []
10.822 + flags = 0
10.823 +
10.824 + i = 0
10.825 + while i < len(nodelist):
10.826 + node = nodelist[i]
10.827 + if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
10.828 + if node[0] == token.STAR:
10.829 + node = nodelist[i+1]
10.830 + if node[0] == token.NAME:
10.831 + names.append(node[1])
10.832 + flags = flags | CO_VARARGS
10.833 + i = i + 3
10.834 +
10.835 + if i < len(nodelist):
10.836 + # should be DOUBLESTAR
10.837 + t = nodelist[i][0]
10.838 + if t == token.DOUBLESTAR:
10.839 + node = nodelist[i+1]
10.840 + else:
10.841 + raise ValueError, "unexpected token: %s" % t
10.842 + names.append(node[1])
10.843 + flags = flags | CO_VARKEYWORDS
10.844 +
10.845 + break
10.846 +
10.847 + # fpdef: NAME | '(' fplist ')'
10.848 + names.append(self.com_fpdef(node))
10.849 +
10.850 + i = i + 1
10.851 + if i < len(nodelist) and nodelist[i][0] == token.EQUAL:
10.852 + defaults.append(self.com_node(nodelist[i + 1]))
10.853 + i = i + 2
10.854 + elif len(defaults):
10.855 + # we have already seen an argument with default, but here
10.856 + # came one without
10.857 + raise SyntaxError, "non-default argument follows default argument"
10.858 +
10.859 + # skip the comma
10.860 + i = i + 1
10.861 +
10.862 + return names, defaults, flags
10.863 +
10.864 + def com_fpdef(self, node):
10.865 + # fpdef: NAME | '(' fplist ')'
10.866 + if node[1][0] == token.LPAR:
10.867 + return self.com_fplist(node[2])
10.868 + return node[1][1]
10.869 +
10.870 + def com_fplist(self, node):
10.871 + # fplist: fpdef (',' fpdef)* [',']
10.872 + if len(node) == 2:
10.873 + return self.com_fpdef(node[1])
10.874 + list = []
10.875 + for i in range(1, len(node), 2):
10.876 + list.append(self.com_fpdef(node[i]))
10.877 + return tuple(list)
10.878 +
10.879 + def com_dotted_name(self, node):
10.880 + # String together the dotted names and return the string
10.881 + name = ""
10.882 + for n in node:
10.883 + if type(n) == type(()) and n[0] == 1:
10.884 + name = name + n[1] + '.'
10.885 + return name[:-1]
10.886 +
10.887 + def com_dotted_as_name(self, node):
10.888 + assert node[0] == symbol.dotted_as_name
10.889 + node = node[1:]
10.890 + dot = self.com_dotted_name(node[0][1:])
10.891 + if len(node) == 1:
10.892 + return dot, None
10.893 + assert node[1][1] == 'as'
10.894 + assert node[2][0] == token.NAME
10.895 + return dot, node[2][1]
10.896 +
10.897 + def com_dotted_as_names(self, node):
10.898 + assert node[0] == symbol.dotted_as_names
10.899 + node = node[1:]
10.900 + names = [self.com_dotted_as_name(node[0])]
10.901 + for i in range(2, len(node), 2):
10.902 + names.append(self.com_dotted_as_name(node[i]))
10.903 + return names
10.904 +
10.905 + def com_import_as_name(self, node):
10.906 + assert node[0] == symbol.import_as_name
10.907 + node = node[1:]
10.908 + assert node[0][0] == token.NAME
10.909 + if len(node) == 1:
10.910 + return node[0][1], None
10.911 + assert node[1][1] == 'as', node
10.912 + assert node[2][0] == token.NAME
10.913 + return node[0][1], node[2][1]
10.914 +
10.915 + def com_import_as_names(self, node):
10.916 + assert node[0] == symbol.import_as_names
10.917 + node = node[1:]
10.918 + names = [self.com_import_as_name(node[0])]
10.919 + for i in range(2, len(node), 2):
10.920 + names.append(self.com_import_as_name(node[i]))
10.921 + return names
10.922 +
10.923 + def com_bases(self, node):
10.924 + bases = []
10.925 + for i in range(1, len(node), 2):
10.926 + bases.append(self.com_node(node[i]))
10.927 + return bases
10.928 +
10.929 + def com_try_except_finally(self, nodelist):
10.930 + # ('try' ':' suite
10.931 + # ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite]
10.932 + # | 'finally' ':' suite))
10.933 +
10.934 + if nodelist[3][0] == token.NAME:
10.935 + # first clause is a finally clause: only try-finally
10.936 + return TryFinally(self.com_node(nodelist[2]),
10.937 + self.com_node(nodelist[5]),
10.938 + lineno=nodelist[0][2])
10.939 +
10.940 + #tryexcept: [TryNode, [except_clauses], elseNode)]
10.941 + clauses = []
10.942 + elseNode = None
10.943 + finallyNode = None
10.944 + for i in range(3, len(nodelist), 3):
10.945 + node = nodelist[i]
10.946 + if node[0] == symbol.except_clause:
10.947 + # except_clause: 'except' [expr [(',' | 'as') expr]] */
10.948 + if len(node) > 2:
10.949 + expr1 = self.com_node(node[2])
10.950 + if len(node) > 4:
10.951 + expr2 = self.com_assign(node[4], OP_ASSIGN)
10.952 + else:
10.953 + expr2 = None
10.954 + else:
10.955 + expr1 = expr2 = None
10.956 + clauses.append((expr1, expr2, self.com_node(nodelist[i+2])))
10.957 +
10.958 + if node[0] == token.NAME:
10.959 + if node[1] == 'else':
10.960 + elseNode = self.com_node(nodelist[i+2])
10.961 + elif node[1] == 'finally':
10.962 + finallyNode = self.com_node(nodelist[i+2])
10.963 + try_except = TryExcept(self.com_node(nodelist[2]), clauses, elseNode,
10.964 + lineno=nodelist[0][2])
10.965 + if finallyNode:
10.966 + return TryFinally(try_except, finallyNode, lineno=nodelist[0][2])
10.967 + else:
10.968 + return try_except
10.969 +
10.970 + def com_with(self, nodelist):
10.971 + # with_stmt: 'with' expr [with_var] ':' suite
10.972 + expr = self.com_node(nodelist[1])
10.973 + body = self.com_node(nodelist[-1])
10.974 + if nodelist[2][0] == token.COLON:
10.975 + var = None
10.976 + else:
10.977 + var = self.com_assign(nodelist[2][2], OP_ASSIGN)
10.978 + return With(expr, var, body, lineno=nodelist[0][2])
10.979 +
10.980 + def com_with_var(self, nodelist):
10.981 + # with_var: 'as' expr
10.982 + return self.com_node(nodelist[1])
10.983 +
10.984 + def com_augassign_op(self, node):
10.985 + assert node[0] == symbol.augassign
10.986 + return node[1]
10.987 +
10.988 + def com_augassign(self, node):
10.989 + """Return node suitable for lvalue of augmented assignment
10.990 +
10.991 + Names, slices, and attributes are the only allowable nodes.
10.992 + """
10.993 + l = self.com_node(node)
10.994 + if l.__class__ in (Name, Slice, Subscript, Getattr):
10.995 + return l
10.996 + raise SyntaxError, "can't assign to %s" % l.__class__.__name__
10.997 +
10.998 + def com_assign(self, node, assigning):
10.999 + # return a node suitable for use as an "lvalue"
10.1000 + # loop to avoid trivial recursion
10.1001 + while 1:
10.1002 + t = node[0]
10.1003 + if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_gexp):
10.1004 + if len(node) > 2:
10.1005 + return self.com_assign_tuple(node, assigning)
10.1006 + node = node[1]
10.1007 + elif t in _assign_types:
10.1008 + if len(node) > 2:
10.1009 + raise SyntaxError, "can't assign to operator"
10.1010 + node = node[1]
10.1011 + elif t == symbol.power:
10.1012 + if node[1][0] != symbol.atom:
10.1013 + raise SyntaxError, "can't assign to operator"
10.1014 + if len(node) > 2:
10.1015 + primary = self.com_node(node[1])
10.1016 + for i in range(2, len(node)-1):
10.1017 + ch = node[i]
10.1018 + if ch[0] == token.DOUBLESTAR:
10.1019 + raise SyntaxError, "can't assign to operator"
10.1020 + primary = self.com_apply_trailer(primary, ch)
10.1021 + return self.com_assign_trailer(primary, node[-1],
10.1022 + assigning)
10.1023 + node = node[1]
10.1024 + elif t == symbol.atom:
10.1025 + t = node[1][0]
10.1026 + if t == token.LPAR:
10.1027 + node = node[2]
10.1028 + if node[0] == token.RPAR:
10.1029 + raise SyntaxError, "can't assign to ()"
10.1030 + elif t == token.LSQB:
10.1031 + node = node[2]
10.1032 + if node[0] == token.RSQB:
10.1033 + raise SyntaxError, "can't assign to []"
10.1034 + return self.com_assign_list(node, assigning)
10.1035 + elif t == token.NAME:
10.1036 + return self.com_assign_name(node[1], assigning)
10.1037 + else:
10.1038 + raise SyntaxError, "can't assign to literal"
10.1039 + else:
10.1040 + raise SyntaxError, "bad assignment (%s)" % t
10.1041 +
10.1042 + def com_assign_tuple(self, node, assigning):
10.1043 + assigns = []
10.1044 + for i in range(1, len(node), 2):
10.1045 + assigns.append(self.com_assign(node[i], assigning))
10.1046 + return AssTuple(assigns, lineno=extractLineNo(node))
10.1047 +
10.1048 + def com_assign_list(self, node, assigning):
10.1049 + assigns = []
10.1050 + for i in range(1, len(node), 2):
10.1051 + if i + 1 < len(node):
10.1052 + if node[i + 1][0] == symbol.list_for:
10.1053 + raise SyntaxError, "can't assign to list comprehension"
10.1054 + assert node[i + 1][0] == token.COMMA, node[i + 1]
10.1055 + assigns.append(self.com_assign(node[i], assigning))
10.1056 + return AssList(assigns, lineno=extractLineNo(node))
10.1057 +
10.1058 + def com_assign_name(self, node, assigning):
10.1059 + return AssName(node[1], assigning, lineno=node[2])
10.1060 +
10.1061 + def com_assign_trailer(self, primary, node, assigning):
10.1062 + t = node[1][0]
10.1063 + if t == token.DOT:
10.1064 + return self.com_assign_attr(primary, node[2], assigning)
10.1065 + if t == token.LSQB:
10.1066 + return self.com_subscriptlist(primary, node[2], assigning)
10.1067 + if t == token.LPAR:
10.1068 + raise SyntaxError, "can't assign to function call"
10.1069 + raise SyntaxError, "unknown trailer type: %s" % t
10.1070 +
10.1071 + def com_assign_attr(self, primary, node, assigning):
10.1072 + return AssAttr(primary, node[1], assigning, lineno=node[-1])
10.1073 +
10.1074 + def com_binary(self, constructor, nodelist):
10.1075 + "Compile 'NODE (OP NODE)*' into (type, [ node1, ..., nodeN ])."
10.1076 + l = len(nodelist)
10.1077 + if l == 1:
10.1078 + n = nodelist[0]
10.1079 + return self.lookup_node(n)(n[1:])
10.1080 + items = []
10.1081 + for i in range(0, l, 2):
10.1082 + n = nodelist[i]
10.1083 + items.append(self.lookup_node(n)(n[1:]))
10.1084 + return constructor(items, lineno=extractLineNo(nodelist))
10.1085 +
10.1086 + def com_stmt(self, node):
10.1087 + result = self.lookup_node(node)(node[1:])
10.1088 + assert result is not None
10.1089 + if isinstance(result, Stmt):
10.1090 + return result
10.1091 + return Stmt([result])
10.1092 +
10.1093 + def com_append_stmt(self, stmts, node):
10.1094 + result = self.lookup_node(node)(node[1:])
10.1095 + assert result is not None
10.1096 + if isinstance(result, Stmt):
10.1097 + stmts.extend(result.nodes)
10.1098 + else:
10.1099 + stmts.append(result)
10.1100 +
10.1101 + if hasattr(symbol, 'list_for'):
10.1102 + def com_list_constructor(self, nodelist):
10.1103 + # listmaker: test ( list_for | (',' test)* [','] )
10.1104 + values = []
10.1105 + for i in range(1, len(nodelist)):
10.1106 + if nodelist[i][0] == symbol.list_for:
10.1107 + assert len(nodelist[i:]) == 1
10.1108 + return self.com_list_comprehension(values[0],
10.1109 + nodelist[i])
10.1110 + elif nodelist[i][0] == token.COMMA:
10.1111 + continue
10.1112 + values.append(self.com_node(nodelist[i]))
10.1113 + return List(values, lineno=values[0].lineno)
10.1114 +
10.1115 + def com_list_comprehension(self, expr, node):
10.1116 + # list_iter: list_for | list_if
10.1117 + # list_for: 'for' exprlist 'in' testlist [list_iter]
10.1118 + # list_if: 'if' test [list_iter]
10.1119 +
10.1120 + # XXX should raise SyntaxError for assignment
10.1121 +
10.1122 + lineno = node[1][2]
10.1123 + fors = []
10.1124 + while node:
10.1125 + t = node[1][1]
10.1126 + if t == 'for':
10.1127 + assignNode = self.com_assign(node[2], OP_ASSIGN)
10.1128 + listNode = self.com_node(node[4])
10.1129 + newfor = ListCompFor(assignNode, listNode, [])
10.1130 + newfor.lineno = node[1][2]
10.1131 + fors.append(newfor)
10.1132 + if len(node) == 5:
10.1133 + node = None
10.1134 + else:
10.1135 + node = self.com_list_iter(node[5])
10.1136 + elif t == 'if':
10.1137 + test = self.com_node(node[2])
10.1138 + newif = ListCompIf(test, lineno=node[1][2])
10.1139 + newfor.ifs.append(newif)
10.1140 + if len(node) == 3:
10.1141 + node = None
10.1142 + else:
10.1143 + node = self.com_list_iter(node[3])
10.1144 + else:
10.1145 + raise SyntaxError, \
10.1146 + ("unexpected list comprehension element: %s %d"
10.1147 + % (node, lineno))
10.1148 + return ListComp(expr, fors, lineno=lineno)
10.1149 +
10.1150 + def com_list_iter(self, node):
10.1151 + assert node[0] == symbol.list_iter
10.1152 + return node[1]
10.1153 + else:
10.1154 + def com_list_constructor(self, nodelist):
10.1155 + values = []
10.1156 + for i in range(1, len(nodelist), 2):
10.1157 + values.append(self.com_node(nodelist[i]))
10.1158 + return List(values, lineno=values[0].lineno)
10.1159 +
10.1160 + if hasattr(symbol, 'gen_for'):
10.1161 + def com_generator_expression(self, expr, node):
10.1162 + # gen_iter: gen_for | gen_if
10.1163 + # gen_for: 'for' exprlist 'in' test [gen_iter]
10.1164 + # gen_if: 'if' test [gen_iter]
10.1165 +
10.1166 + lineno = node[1][2]
10.1167 + fors = []
10.1168 + while node:
10.1169 + t = node[1][1]
10.1170 + if t == 'for':
10.1171 + assignNode = self.com_assign(node[2], OP_ASSIGN)
10.1172 + genNode = self.com_node(node[4])
10.1173 + newfor = GenExprFor(assignNode, genNode, [],
10.1174 + lineno=node[1][2])
10.1175 + fors.append(newfor)
10.1176 + if (len(node)) == 5:
10.1177 + node = None
10.1178 + else:
10.1179 + node = self.com_gen_iter(node[5])
10.1180 + elif t == 'if':
10.1181 + test = self.com_node(node[2])
10.1182 + newif = GenExprIf(test, lineno=node[1][2])
10.1183 + newfor.ifs.append(newif)
10.1184 + if len(node) == 3:
10.1185 + node = None
10.1186 + else:
10.1187 + node = self.com_gen_iter(node[3])
10.1188 + else:
10.1189 + raise SyntaxError, \
10.1190 + ("unexpected generator expression element: %s %d"
10.1191 + % (node, lineno))
10.1192 + fors[0].is_outmost = True
10.1193 + return GenExpr(GenExprInner(expr, fors), lineno=lineno)
10.1194 +
10.1195 + def com_gen_iter(self, node):
10.1196 + assert node[0] == symbol.gen_iter
10.1197 + return node[1]
10.1198 +
10.1199 + def com_dictmaker(self, nodelist):
10.1200 + # dictmaker: test ':' test (',' test ':' value)* [',']
10.1201 + items = []
10.1202 + for i in range(1, len(nodelist), 4):
10.1203 + items.append((self.com_node(nodelist[i]),
10.1204 + self.com_node(nodelist[i+2])))
10.1205 + return Dict(items, lineno=items[0][0].lineno)
10.1206 +
10.1207 + def com_apply_trailer(self, primaryNode, nodelist):
10.1208 + t = nodelist[1][0]
10.1209 + if t == token.LPAR:
10.1210 + return self.com_call_function(primaryNode, nodelist[2])
10.1211 + if t == token.DOT:
10.1212 + return self.com_select_member(primaryNode, nodelist[2])
10.1213 + if t == token.LSQB:
10.1214 + return self.com_subscriptlist(primaryNode, nodelist[2], OP_APPLY)
10.1215 +
10.1216 + raise SyntaxError, 'unknown node type: %s' % t
10.1217 +
10.1218 + def com_select_member(self, primaryNode, nodelist):
10.1219 + if nodelist[0] != token.NAME:
10.1220 + raise SyntaxError, "member must be a name"
10.1221 + return Getattr(primaryNode, nodelist[1], lineno=nodelist[2])
10.1222 +
10.1223 + def com_call_function(self, primaryNode, nodelist):
10.1224 + if nodelist[0] == token.RPAR:
10.1225 + return CallFunc(primaryNode, [], lineno=extractLineNo(nodelist))
10.1226 + args = []
10.1227 + kw = 0
10.1228 + star_node = dstar_node = None
10.1229 + len_nodelist = len(nodelist)
10.1230 + i = 1
10.1231 + while i < len_nodelist:
10.1232 + node = nodelist[i]
10.1233 +
10.1234 + if node[0]==token.STAR:
10.1235 + if star_node is not None:
10.1236 + raise SyntaxError, 'already have the varargs indentifier'
10.1237 + star_node = self.com_node(nodelist[i+1])
10.1238 + i = i + 3
10.1239 + continue
10.1240 + elif node[0]==token.DOUBLESTAR:
10.1241 + if dstar_node is not None:
10.1242 + raise SyntaxError, 'already have the kwargs indentifier'
10.1243 + dstar_node = self.com_node(nodelist[i+1])
10.1244 + i = i + 3
10.1245 + continue
10.1246 +
10.1247 + # positional or named parameters
10.1248 + kw, result = self.com_argument(node, kw, star_node)
10.1249 +
10.1250 + if len_nodelist != 2 and isinstance(result, GenExpr) \
10.1251 + and len(node) == 3 and node[2][0] == symbol.gen_for:
10.1252 + # allow f(x for x in y), but reject f(x for x in y, 1)
10.1253 + # should use f((x for x in y), 1) instead of f(x for x in y, 1)
10.1254 + raise SyntaxError, 'generator expression needs parenthesis'
10.1255 +
10.1256 + args.append(result)
10.1257 + i = i + 2
10.1258 +
10.1259 + return CallFunc(primaryNode, args, star_node, dstar_node,
10.1260 + lineno=extractLineNo(nodelist))
10.1261 +
10.1262 + def com_argument(self, nodelist, kw, star_node):
10.1263 + if len(nodelist) == 3 and nodelist[2][0] == symbol.gen_for:
10.1264 + test = self.com_node(nodelist[1])
10.1265 + return 0, self.com_generator_expression(test, nodelist[2])
10.1266 + if len(nodelist) == 2:
10.1267 + if kw:
10.1268 + raise SyntaxError, "non-keyword arg after keyword arg"
10.1269 + if star_node:
10.1270 + raise SyntaxError, "only named arguments may follow *expression"
10.1271 + return 0, self.com_node(nodelist[1])
10.1272 + result = self.com_node(nodelist[3])
10.1273 + n = nodelist[1]
10.1274 + while len(n) == 2 and n[0] != token.NAME:
10.1275 + n = n[1]
10.1276 + if n[0] != token.NAME:
10.1277 + raise SyntaxError, "keyword can't be an expression (%s)"%n[0]
10.1278 + node = Keyword(n[1], result, lineno=n[2])
10.1279 + return 1, node
10.1280 +
10.1281 + def com_subscriptlist(self, primary, nodelist, assigning):
10.1282 + # slicing: simple_slicing | extended_slicing
10.1283 + # simple_slicing: primary "[" short_slice "]"
10.1284 + # extended_slicing: primary "[" slice_list "]"
10.1285 + # slice_list: slice_item ("," slice_item)* [","]
10.1286 +
10.1287 + # backwards compat slice for '[i:j]'
10.1288 + if len(nodelist) == 2:
10.1289 + sub = nodelist[1]
10.1290 + if (sub[1][0] == token.COLON or \
10.1291 + (len(sub) > 2 and sub[2][0] == token.COLON)) and \
10.1292 + sub[-1][0] != symbol.sliceop:
10.1293 + return self.com_slice(primary, sub, assigning)
10.1294 +
10.1295 + subscripts = []
10.1296 + for i in range(1, len(nodelist), 2):
10.1297 + subscripts.append(self.com_subscript(nodelist[i]))
10.1298 + return Subscript(primary, assigning, subscripts,
10.1299 + lineno=extractLineNo(nodelist))
10.1300 +
10.1301 + def com_subscript(self, node):
10.1302 + # slice_item: expression | proper_slice | ellipsis
10.1303 + ch = node[1]
10.1304 + t = ch[0]
10.1305 + if t == token.DOT and node[2][0] == token.DOT:
10.1306 + return Ellipsis()
10.1307 + if t == token.COLON or len(node) > 2:
10.1308 + return self.com_sliceobj(node)
10.1309 + return self.com_node(ch)
10.1310 +
10.1311 + def com_sliceobj(self, node):
10.1312 + # proper_slice: short_slice | long_slice
10.1313 + # short_slice: [lower_bound] ":" [upper_bound]
10.1314 + # long_slice: short_slice ":" [stride]
10.1315 + # lower_bound: expression
10.1316 + # upper_bound: expression
10.1317 + # stride: expression
10.1318 + #
10.1319 + # Note: a stride may be further slicing...
10.1320 +
10.1321 + items = []
10.1322 +
10.1323 + if node[1][0] == token.COLON:
10.1324 + items.append(Const(None))
10.1325 + i = 2
10.1326 + else:
10.1327 + items.append(self.com_node(node[1]))
10.1328 + # i == 2 is a COLON
10.1329 + i = 3
10.1330 +
10.1331 + if i < len(node) and node[i][0] == symbol.test:
10.1332 + items.append(self.com_node(node[i]))
10.1333 + i = i + 1
10.1334 + else:
10.1335 + items.append(Const(None))
10.1336 +
10.1337 + # a short_slice has been built. look for long_slice now by looking
10.1338 + # for strides...
10.1339 + for j in range(i, len(node)):
10.1340 + ch = node[j]
10.1341 + if len(ch) == 2:
10.1342 + items.append(Const(None))
10.1343 + else:
10.1344 + items.append(self.com_node(ch[2]))
10.1345 + return Sliceobj(items, lineno=extractLineNo(node))
10.1346 +
10.1347 + def com_slice(self, primary, node, assigning):
10.1348 + # short_slice: [lower_bound] ":" [upper_bound]
10.1349 + lower = upper = None
10.1350 + if len(node) == 3:
10.1351 + if node[1][0] == token.COLON:
10.1352 + upper = self.com_node(node[2])
10.1353 + else:
10.1354 + lower = self.com_node(node[1])
10.1355 + elif len(node) == 4:
10.1356 + lower = self.com_node(node[1])
10.1357 + upper = self.com_node(node[3])
10.1358 + return Slice(primary, assigning, lower, upper,
10.1359 + lineno=extractLineNo(node))
10.1360 +
10.1361 + def get_docstring(self, node, n=None):
10.1362 + if n is None:
10.1363 + n = node[0]
10.1364 + node = node[1:]
10.1365 + if n == symbol.suite:
10.1366 + if len(node) == 1:
10.1367 + return self.get_docstring(node[0])
10.1368 + for sub in node:
10.1369 + if sub[0] == symbol.stmt:
10.1370 + return self.get_docstring(sub)
10.1371 + return None
10.1372 + if n == symbol.file_input:
10.1373 + for sub in node:
10.1374 + if sub[0] == symbol.stmt:
10.1375 + return self.get_docstring(sub)
10.1376 + return None
10.1377 + if n == symbol.atom:
10.1378 + if node[0][0] == token.STRING:
10.1379 + s = ''
10.1380 + for t in node:
10.1381 + s = s + eval(t[1])
10.1382 + return s
10.1383 + return None
10.1384 + if n == symbol.stmt or n == symbol.simple_stmt \
10.1385 + or n == symbol.small_stmt:
10.1386 + return self.get_docstring(node[0])
10.1387 + if n in _doc_nodes and len(node) == 1:
10.1388 + return self.get_docstring(node[0])
10.1389 + return None
10.1390 +
10.1391 +
10.1392 +_doc_nodes = [
10.1393 + symbol.expr_stmt,
10.1394 + symbol.testlist,
10.1395 + symbol.testlist_safe,
10.1396 + symbol.test,
10.1397 + symbol.or_test,
10.1398 + symbol.and_test,
10.1399 + symbol.not_test,
10.1400 + symbol.comparison,
10.1401 + symbol.expr,
10.1402 + symbol.xor_expr,
10.1403 + symbol.and_expr,
10.1404 + symbol.shift_expr,
10.1405 + symbol.arith_expr,
10.1406 + symbol.term,
10.1407 + symbol.factor,
10.1408 + symbol.power,
10.1409 + ]
10.1410 +
10.1411 +# comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
10.1412 +# | 'in' | 'not' 'in' | 'is' | 'is' 'not'
10.1413 +_cmp_types = {
10.1414 + token.LESS : '<',
10.1415 + token.GREATER : '>',
10.1416 + token.EQEQUAL : '==',
10.1417 + token.EQUAL : '==',
10.1418 + token.LESSEQUAL : '<=',
10.1419 + token.GREATEREQUAL : '>=',
10.1420 + token.NOTEQUAL : '!=',
10.1421 + }
10.1422 +
10.1423 +_legal_node_types = [
10.1424 + symbol.funcdef,
10.1425 + symbol.classdef,
10.1426 + symbol.stmt,
10.1427 + symbol.small_stmt,
10.1428 + symbol.flow_stmt,
10.1429 + symbol.simple_stmt,
10.1430 + symbol.compound_stmt,
10.1431 + symbol.expr_stmt,
10.1432 + symbol.print_stmt,
10.1433 + symbol.del_stmt,
10.1434 + symbol.pass_stmt,
10.1435 + symbol.break_stmt,
10.1436 + symbol.continue_stmt,
10.1437 + symbol.return_stmt,
10.1438 + symbol.raise_stmt,
10.1439 + symbol.import_stmt,
10.1440 + symbol.global_stmt,
10.1441 + symbol.exec_stmt,
10.1442 + symbol.assert_stmt,
10.1443 + symbol.if_stmt,
10.1444 + symbol.while_stmt,
10.1445 + symbol.for_stmt,
10.1446 + symbol.try_stmt,
10.1447 + symbol.with_stmt,
10.1448 + symbol.suite,
10.1449 + symbol.testlist,
10.1450 + symbol.testlist_safe,
10.1451 + symbol.test,
10.1452 + symbol.and_test,
10.1453 + symbol.not_test,
10.1454 + symbol.comparison,
10.1455 + symbol.exprlist,
10.1456 + symbol.expr,
10.1457 + symbol.xor_expr,
10.1458 + symbol.and_expr,
10.1459 + symbol.shift_expr,
10.1460 + symbol.arith_expr,
10.1461 + symbol.term,
10.1462 + symbol.factor,
10.1463 + symbol.power,
10.1464 + symbol.atom,
10.1465 + ]
10.1466 +
10.1467 +if hasattr(symbol, 'yield_stmt'):
10.1468 + _legal_node_types.append(symbol.yield_stmt)
10.1469 +if hasattr(symbol, 'yield_expr'):
10.1470 + _legal_node_types.append(symbol.yield_expr)
10.1471 +
10.1472 +_assign_types = [
10.1473 + symbol.test,
10.1474 + symbol.or_test,
10.1475 + symbol.and_test,
10.1476 + symbol.not_test,
10.1477 + symbol.comparison,
10.1478 + symbol.expr,
10.1479 + symbol.xor_expr,
10.1480 + symbol.and_expr,
10.1481 + symbol.shift_expr,
10.1482 + symbol.arith_expr,
10.1483 + symbol.term,
10.1484 + symbol.factor,
10.1485 + ]
10.1486 +
10.1487 +_names = {}
10.1488 +for k, v in symbol.sym_name.items():
10.1489 + _names[k] = v
10.1490 +for k, v in token.tok_name.items():
10.1491 + _names[k] = v
10.1492 +
10.1493 +def debug_tree(tree):
10.1494 + l = []
10.1495 + for elt in tree:
10.1496 + if isinstance(elt, int):
10.1497 + l.append(_names.get(elt, elt))
10.1498 + elif isinstance(elt, str):
10.1499 + l.append(elt)
10.1500 + else:
10.1501 + l.append(debug_tree(elt))
10.1502 + return l
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/compiler/visitor.py Fri May 18 20:51:41 2012 +0200
11.3 @@ -0,0 +1,113 @@
11.4 +from compiler import ast
11.5 +
11.6 +# XXX should probably rename ASTVisitor to ASTWalker
11.7 +# XXX can it be made even more generic?
11.8 +
11.9 +class ASTVisitor:
11.10 + """Performs a depth-first walk of the AST
11.11 +
11.12 + The ASTVisitor will walk the AST, performing either a preorder or
11.13 + postorder traversal depending on which method is called.
11.14 +
11.15 + methods:
11.16 + preorder(tree, visitor)
11.17 + postorder(tree, visitor)
11.18 + tree: an instance of ast.Node
11.19 + visitor: an instance with visitXXX methods
11.20 +
11.21 + The ASTVisitor is responsible for walking over the tree in the
11.22 + correct order. For each node, it checks the visitor argument for
11.23 + a method named 'visitNodeType' where NodeType is the name of the
11.24 + node's class, e.g. Class. If the method exists, it is called
11.25 + with the node as its sole argument.
11.26 +
11.27 + The visitor method for a particular node type can control how
11.28 + child nodes are visited during a preorder walk. (It can't control
11.29 + the order during a postorder walk, because it is called _after_
11.30 + the walk has occurred.) The ASTVisitor modifies the visitor
11.31 + argument by adding a visit method to the visitor; this method can
11.32 + be used to visit a child node of arbitrary type.
11.33 + """
11.34 +
11.35 + VERBOSE = 0
11.36 +
11.37 + def __init__(self):
11.38 + self.node = None
11.39 + self._cache = {}
11.40 +
11.41 + def default(self, node, *args):
11.42 + for child in node.getChildNodes():
11.43 + self.dispatch(child, *args)
11.44 +
11.45 + def dispatch(self, node, *args):
11.46 + self.node = node
11.47 + klass = node.__class__
11.48 + meth = self._cache.get(klass, None)
11.49 + if meth is None:
11.50 + className = klass.__name__
11.51 + meth = getattr(self.visitor, 'visit' + className, self.default)
11.52 + self._cache[klass] = meth
11.53 +## if self.VERBOSE > 0:
11.54 +## className = klass.__name__
11.55 +## if self.VERBOSE == 1:
11.56 +## if meth == 0:
11.57 +## print "dispatch", className
11.58 +## else:
11.59 +## print "dispatch", className, (meth and meth.__name__ or '')
11.60 + return meth(node, *args)
11.61 +
11.62 + def preorder(self, tree, visitor, *args):
11.63 + """Do preorder walk of tree using visitor"""
11.64 + self.visitor = visitor
11.65 + visitor.visit = self.dispatch
11.66 + self.dispatch(tree, *args) # XXX *args make sense?
11.67 +
11.68 +class ExampleASTVisitor(ASTVisitor):
11.69 + """Prints examples of the nodes that aren't visited
11.70 +
11.71 + This visitor-driver is only useful for development, when it's
11.72 + helpful to develop a visitor incrementally, and get feedback on what
11.73 + you still have to do.
11.74 + """
11.75 + examples = {}
11.76 +
11.77 + def dispatch(self, node, *args):
11.78 + self.node = node
11.79 + meth = self._cache.get(node.__class__, None)
11.80 + className = node.__class__.__name__
11.81 + if meth is None:
11.82 + meth = getattr(self.visitor, 'visit' + className, 0)
11.83 + self._cache[node.__class__] = meth
11.84 + if self.VERBOSE > 1:
11.85 + print "dispatch", className, (meth and meth.__name__ or '')
11.86 + if meth:
11.87 + meth(node, *args)
11.88 + elif self.VERBOSE > 0:
11.89 + klass = node.__class__
11.90 + if klass not in self.examples:
11.91 + self.examples[klass] = klass
11.92 + print
11.93 + print self.visitor
11.94 + print klass
11.95 + for attr in dir(node):
11.96 + if attr[0] != '_':
11.97 + print "\t", "%-12.12s" % attr, getattr(node, attr)
11.98 + print
11.99 + return self.default(node, *args)
11.100 +
11.101 +# XXX this is an API change
11.102 +
11.103 +_walker = ASTVisitor
11.104 +def walk(tree, visitor, walker=None, verbose=None):
11.105 + if walker is None:
11.106 + walker = _walker()
11.107 + if verbose is not None:
11.108 + walker.VERBOSE = verbose
11.109 + walker.preorder(tree, visitor)
11.110 + return walker.visitor
11.111 +
11.112 +def dumpNode(node):
11.113 + print node.__class__
11.114 + for attr in dir(node):
11.115 + if attr[0] != '_':
11.116 + print "\t", "%-10.10s" % attr, getattr(node, attr)
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/docs/COPYRIGHT Fri May 18 20:51:41 2012 +0200
12.3 @@ -0,0 +1,24 @@
12.4 +Copyright information from Python 2.6.8
12.5 +---------------------------------------
12.6 +
12.7 +Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
12.8 + 2011, 2012
12.9 +Python Software Foundation.
12.10 +All rights reserved.
12.11 +
12.12 +Copyright (c) 2000 BeOpen.com.
12.13 +All rights reserved.
12.14 +
12.15 +Copyright (c) 1995-2001 Corporation for National Research Initiatives.
12.16 +All rights reserved.
12.17 +
12.18 +Copyright (c) 1991-1995 Stichting Mathematisch Centrum.
12.19 +All rights reserved.
12.20 +
12.21 +
12.22 +License information
12.23 +-------------------
12.24 +
12.25 +See the file "LICENSE" for information on the history of this
12.26 +software, terms & conditions for usage, and a DISCLAIMER OF ALL
12.27 +WARRANTIES.
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/docs/LICENSE Fri May 18 20:51:41 2012 +0200
13.3 @@ -0,0 +1,281 @@
13.4 +A. HISTORY OF THE SOFTWARE
13.5 +==========================
13.6 +
13.7 +Python was created in the early 1990s by Guido van Rossum at Stichting
13.8 +Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
13.9 +as a successor of a language called ABC. Guido remains Python's
13.10 +principal author, although it includes many contributions from others.
13.11 +
13.12 +In 1995, Guido continued his work on Python at the Corporation for
13.13 +National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
13.14 +in Reston, Virginia where he released several versions of the
13.15 +software.
13.16 +
13.17 +In May 2000, Guido and the Python core development team moved to
13.18 +BeOpen.com to form the BeOpen PythonLabs team. In October of the same
13.19 +year, the PythonLabs team moved to Digital Creations (now Zope
13.20 +Corporation, see http://www.zope.com). In 2001, the Python Software
13.21 +Foundation (PSF, see http://www.python.org/psf/) was formed, a
13.22 +non-profit organization created specifically to own Python-related
13.23 +Intellectual Property. Zope Corporation is a sponsoring member of
13.24 +the PSF.
13.25 +
13.26 +All Python releases are Open Source (see http://www.opensource.org for
13.27 +the Open Source Definition). Historically, most, but not all, Python
13.28 +releases have also been GPL-compatible; the table below summarizes
13.29 +the various releases.
13.30 +
13.31 + Release Derived Year Owner GPL-
13.32 + from compatible? (1)
13.33 +
13.34 + 0.9.0 thru 1.2 1991-1995 CWI yes
13.35 + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
13.36 + 1.6 1.5.2 2000 CNRI no
13.37 + 2.0 1.6 2000 BeOpen.com no
13.38 + 1.6.1 1.6 2001 CNRI yes (2)
13.39 + 2.1 2.0+1.6.1 2001 PSF no
13.40 + 2.0.1 2.0+1.6.1 2001 PSF yes
13.41 + 2.1.1 2.1+2.0.1 2001 PSF yes
13.42 + 2.2 2.1.1 2001 PSF yes
13.43 + 2.1.2 2.1.1 2002 PSF yes
13.44 + 2.1.3 2.1.2 2002 PSF yes
13.45 + 2.2.1 2.2 2002 PSF yes
13.46 + 2.2.2 2.2.1 2002 PSF yes
13.47 + 2.2.3 2.2.2 2003 PSF yes
13.48 + 2.3 2.2.2 2002-2003 PSF yes
13.49 + 2.3.1 2.3 2002-2003 PSF yes
13.50 + 2.3.2 2.3.1 2002-2003 PSF yes
13.51 + 2.3.3 2.3.2 2002-2003 PSF yes
13.52 + 2.3.4 2.3.3 2004 PSF yes
13.53 + 2.3.5 2.3.4 2005 PSF yes
13.54 + 2.4 2.3 2004 PSF yes
13.55 + 2.4.1 2.4 2005 PSF yes
13.56 + 2.4.2 2.4.1 2005 PSF yes
13.57 + 2.4.3 2.4.2 2006 PSF yes
13.58 + 2.4.4 2.4.3 2006 PSF yes
13.59 + 2.5 2.4 2006 PSF yes
13.60 + 2.5.1 2.5 2007 PSF yes
13.61 + 2.5.2 2.5.1 2008 PSF yes
13.62 + 2.5.3 2.5.2 2008 PSF yes
13.63 + 2.6 2.5 2008 PSF yes
13.64 + 2.6.1 2.6 2008 PSF yes
13.65 + 2.6.2 2.6.1 2009 PSF yes
13.66 + 2.6.3 2.6.2 2009 PSF yes
13.67 + 2.6.4 2.6.3 2009 PSF yes
13.68 + 2.6.5 2.6.4 2010 PSF yes
13.69 + 2.6.6 2.6.5 2010 PSF yes
13.70 + 2.6.7 2.6.6 2011 PSF yes
13.71 + 2.6.8 2.6.7 2012 PSF yes
13.72 +
13.73 +Footnotes:
13.74 +
13.75 +(1) GPL-compatible doesn't mean that we're distributing Python under
13.76 + the GPL. All Python licenses, unlike the GPL, let you distribute
13.77 + a modified version without making your changes open source. The
13.78 + GPL-compatible licenses make it possible to combine Python with
13.79 + other software that is released under the GPL; the others don't.
13.80 +
13.81 +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
13.82 + because its license has a choice of law clause. According to
13.83 + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
13.84 + is "not incompatible" with the GPL.
13.85 +
13.86 +Thanks to the many outside volunteers who have worked under Guido's
13.87 +direction to make these releases possible.
13.88 +
13.89 +
13.90 +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
13.91 +===============================================================
13.92 +
13.93 +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
13.94 +--------------------------------------------
13.95 +
13.96 +1. This LICENSE AGREEMENT is between the Python Software Foundation
13.97 +("PSF"), and the Individual or Organization ("Licensee") accessing and
13.98 +otherwise using this software ("Python") in source or binary form and
13.99 +its associated documentation.
13.100 +
13.101 +2. Subject to the terms and conditions of this License Agreement, PSF hereby
13.102 +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
13.103 +analyze, test, perform and/or display publicly, prepare derivative works,
13.104 +distribute, and otherwise use Python alone or in any derivative version,
13.105 +provided, however, that PSF's License Agreement and PSF's notice of copyright,
13.106 +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
13.107 +Python Software Foundation; All Rights Reserved" are retained in Python alone or
13.108 +in any derivative version prepared by Licensee.
13.109 +
13.110 +3. In the event Licensee prepares a derivative work that is based on
13.111 +or incorporates Python or any part thereof, and wants to make
13.112 +the derivative work available to others as provided herein, then
13.113 +Licensee hereby agrees to include in any such work a brief summary of
13.114 +the changes made to Python.
13.115 +
13.116 +4. PSF is making Python available to Licensee on an "AS IS"
13.117 +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
13.118 +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
13.119 +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
13.120 +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
13.121 +INFRINGE ANY THIRD PARTY RIGHTS.
13.122 +
13.123 +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
13.124 +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
13.125 +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
13.126 +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
13.127 +
13.128 +6. This License Agreement will automatically terminate upon a material
13.129 +breach of its terms and conditions.
13.130 +
13.131 +7. Nothing in this License Agreement shall be deemed to create any
13.132 +relationship of agency, partnership, or joint venture between PSF and
13.133 +Licensee. This License Agreement does not grant permission to use PSF
13.134 +trademarks or trade name in a trademark sense to endorse or promote
13.135 +products or services of Licensee, or any third party.
13.136 +
13.137 +8. By copying, installing or otherwise using Python, Licensee
13.138 +agrees to be bound by the terms and conditions of this License
13.139 +Agreement.
13.140 +
13.141 +
13.142 +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
13.143 +-------------------------------------------
13.144 +
13.145 +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
13.146 +
13.147 +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
13.148 +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
13.149 +Individual or Organization ("Licensee") accessing and otherwise using
13.150 +this software in source or binary form and its associated
13.151 +documentation ("the Software").
13.152 +
13.153 +2. Subject to the terms and conditions of this BeOpen Python License
13.154 +Agreement, BeOpen hereby grants Licensee a non-exclusive,
13.155 +royalty-free, world-wide license to reproduce, analyze, test, perform
13.156 +and/or display publicly, prepare derivative works, distribute, and
13.157 +otherwise use the Software alone or in any derivative version,
13.158 +provided, however, that the BeOpen Python License is retained in the
13.159 +Software, alone or in any derivative version prepared by Licensee.
13.160 +
13.161 +3. BeOpen is making the Software available to Licensee on an "AS IS"
13.162 +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
13.163 +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
13.164 +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
13.165 +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
13.166 +INFRINGE ANY THIRD PARTY RIGHTS.
13.167 +
13.168 +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
13.169 +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
13.170 +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
13.171 +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
13.172 +
13.173 +5. This License Agreement will automatically terminate upon a material
13.174 +breach of its terms and conditions.
13.175 +
13.176 +6. This License Agreement shall be governed by and interpreted in all
13.177 +respects by the law of the State of California, excluding conflict of
13.178 +law provisions. Nothing in this License Agreement shall be deemed to
13.179 +create any relationship of agency, partnership, or joint venture
13.180 +between BeOpen and Licensee. This License Agreement does not grant
13.181 +permission to use BeOpen trademarks or trade names in a trademark
13.182 +sense to endorse or promote products or services of Licensee, or any
13.183 +third party. As an exception, the "BeOpen Python" logos available at
13.184 +http://www.pythonlabs.com/logos.html may be used according to the
13.185 +permissions granted on that web page.
13.186 +
13.187 +7. By copying, installing or otherwise using the software, Licensee
13.188 +agrees to be bound by the terms and conditions of this License
13.189 +Agreement.
13.190 +
13.191 +
13.192 +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
13.193 +---------------------------------------
13.194 +
13.195 +1. This LICENSE AGREEMENT is between the Corporation for National
13.196 +Research Initiatives, having an office at 1895 Preston White Drive,
13.197 +Reston, VA 20191 ("CNRI"), and the Individual or Organization
13.198 +("Licensee") accessing and otherwise using Python 1.6.1 software in
13.199 +source or binary form and its associated documentation.
13.200 +
13.201 +2. Subject to the terms and conditions of this License Agreement, CNRI
13.202 +hereby grants Licensee a nonexclusive, royalty-free, world-wide
13.203 +license to reproduce, analyze, test, perform and/or display publicly,
13.204 +prepare derivative works, distribute, and otherwise use Python 1.6.1
13.205 +alone or in any derivative version, provided, however, that CNRI's
13.206 +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
13.207 +1995-2001 Corporation for National Research Initiatives; All Rights
13.208 +Reserved" are retained in Python 1.6.1 alone or in any derivative
13.209 +version prepared by Licensee. Alternately, in lieu of CNRI's License
13.210 +Agreement, Licensee may substitute the following text (omitting the
13.211 +quotes): "Python 1.6.1 is made available subject to the terms and
13.212 +conditions in CNRI's License Agreement. This Agreement together with
13.213 +Python 1.6.1 may be located on the Internet using the following
13.214 +unique, persistent identifier (known as a handle): 1895.22/1013. This
13.215 +Agreement may also be obtained from a proxy server on the Internet
13.216 +using the following URL: http://hdl.handle.net/1895.22/1013".
13.217 +
13.218 +3. In the event Licensee prepares a derivative work that is based on
13.219 +or incorporates Python 1.6.1 or any part thereof, and wants to make
13.220 +the derivative work available to others as provided herein, then
13.221 +Licensee hereby agrees to include in any such work a brief summary of
13.222 +the changes made to Python 1.6.1.
13.223 +
13.224 +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
13.225 +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
13.226 +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
13.227 +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
13.228 +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
13.229 +INFRINGE ANY THIRD PARTY RIGHTS.
13.230 +
13.231 +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
13.232 +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
13.233 +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
13.234 +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
13.235 +
13.236 +6. This License Agreement will automatically terminate upon a material
13.237 +breach of its terms and conditions.
13.238 +
13.239 +7. This License Agreement shall be governed by the federal
13.240 +intellectual property law of the United States, including without
13.241 +limitation the federal copyright law, and, to the extent such
13.242 +U.S. federal law does not apply, by the law of the Commonwealth of
13.243 +Virginia, excluding Virginia's conflict of law provisions.
13.244 +Notwithstanding the foregoing, with regard to derivative works based
13.245 +on Python 1.6.1 that incorporate non-separable material that was
13.246 +previously distributed under the GNU General Public License (GPL), the
13.247 +law of the Commonwealth of Virginia shall govern this License
13.248 +Agreement only as to issues arising under or with respect to
13.249 +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
13.250 +License Agreement shall be deemed to create any relationship of
13.251 +agency, partnership, or joint venture between CNRI and Licensee. This
13.252 +License Agreement does not grant permission to use CNRI trademarks or
13.253 +trade name in a trademark sense to endorse or promote products or
13.254 +services of Licensee, or any third party.
13.255 +
13.256 +8. By clicking on the "ACCEPT" button where indicated, or by copying,
13.257 +installing or otherwise using Python 1.6.1, Licensee agrees to be
13.258 +bound by the terms and conditions of this License Agreement.
13.259 +
13.260 + ACCEPT
13.261 +
13.262 +
13.263 +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
13.264 +--------------------------------------------------
13.265 +
13.266 +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
13.267 +The Netherlands. All rights reserved.
13.268 +
13.269 +Permission to use, copy, modify, and distribute this software and its
13.270 +documentation for any purpose and without fee is hereby granted,
13.271 +provided that the above copyright notice appear in all copies and that
13.272 +both that copyright notice and this permission notice appear in
13.273 +supporting documentation, and that the name of Stichting Mathematisch
13.274 +Centrum or CWI not be used in advertising or publicity pertaining to
13.275 +distribution of the software without specific, written prior
13.276 +permission.
13.277 +
13.278 +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
13.279 +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13.280 +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
13.281 +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.282 +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13.283 +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13.284 +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.