1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/compiler/__init__.py Tue May 01 22:04:53 2012 +0200
1.3 @@ -0,0 +1,26 @@
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 +
1.27 +from compiler.transformer import parse, parseFile
1.28 +from compiler.visitor import walk
1.29 +from compiler.pycodegen import compile, compileFile
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/compiler/ast.py Tue May 01 22:04:53 2012 +0200
2.3 @@ -0,0 +1,1356 @@
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, (left, right), lineno=None):
2.58 + self.left = left
2.59 + self.right = right
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, 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.lineno = lineno
2.320 +
2.321 + def getChildren(self):
2.322 + children = []
2.323 + children.append(self.name)
2.324 + children.extend(flatten(self.bases))
2.325 + children.append(self.doc)
2.326 + children.append(self.code)
2.327 + return tuple(children)
2.328 +
2.329 + def getChildNodes(self):
2.330 + nodelist = []
2.331 + nodelist.extend(flatten_nodes(self.bases))
2.332 + nodelist.append(self.code)
2.333 + return tuple(nodelist)
2.334 +
2.335 + def __repr__(self):
2.336 + return "Class(%s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code))
2.337 +
2.338 +class Compare(Node):
2.339 + def __init__(self, expr, ops, lineno=None):
2.340 + self.expr = expr
2.341 + self.ops = ops
2.342 + self.lineno = lineno
2.343 +
2.344 + def getChildren(self):
2.345 + children = []
2.346 + children.append(self.expr)
2.347 + children.extend(flatten(self.ops))
2.348 + return tuple(children)
2.349 +
2.350 + def getChildNodes(self):
2.351 + nodelist = []
2.352 + nodelist.append(self.expr)
2.353 + nodelist.extend(flatten_nodes(self.ops))
2.354 + return tuple(nodelist)
2.355 +
2.356 + def __repr__(self):
2.357 + return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops))
2.358 +
2.359 +class Const(Node):
2.360 + def __init__(self, value, lineno=None):
2.361 + self.value = value
2.362 + self.lineno = lineno
2.363 +
2.364 + def getChildren(self):
2.365 + return self.value,
2.366 +
2.367 + def getChildNodes(self):
2.368 + return ()
2.369 +
2.370 + def __repr__(self):
2.371 + return "Const(%s)" % (repr(self.value),)
2.372 +
2.373 +class Continue(Node):
2.374 + def __init__(self, lineno=None):
2.375 + self.lineno = lineno
2.376 +
2.377 + def getChildren(self):
2.378 + return ()
2.379 +
2.380 + def getChildNodes(self):
2.381 + return ()
2.382 +
2.383 + def __repr__(self):
2.384 + return "Continue()"
2.385 +
2.386 +class Decorators(Node):
2.387 + def __init__(self, nodes, lineno=None):
2.388 + self.nodes = nodes
2.389 + self.lineno = lineno
2.390 +
2.391 + def getChildren(self):
2.392 + return tuple(flatten(self.nodes))
2.393 +
2.394 + def getChildNodes(self):
2.395 + nodelist = []
2.396 + nodelist.extend(flatten_nodes(self.nodes))
2.397 + return tuple(nodelist)
2.398 +
2.399 + def __repr__(self):
2.400 + return "Decorators(%s)" % (repr(self.nodes),)
2.401 +
2.402 +class Dict(Node):
2.403 + def __init__(self, items, lineno=None):
2.404 + self.items = items
2.405 + self.lineno = lineno
2.406 +
2.407 + def getChildren(self):
2.408 + return tuple(flatten(self.items))
2.409 +
2.410 + def getChildNodes(self):
2.411 + nodelist = []
2.412 + nodelist.extend(flatten_nodes(self.items))
2.413 + return tuple(nodelist)
2.414 +
2.415 + def __repr__(self):
2.416 + return "Dict(%s)" % (repr(self.items),)
2.417 +
2.418 +class Discard(Node):
2.419 + def __init__(self, expr, lineno=None):
2.420 + self.expr = expr
2.421 + self.lineno = lineno
2.422 +
2.423 + def getChildren(self):
2.424 + return self.expr,
2.425 +
2.426 + def getChildNodes(self):
2.427 + return self.expr,
2.428 +
2.429 + def __repr__(self):
2.430 + return "Discard(%s)" % (repr(self.expr),)
2.431 +
2.432 +class Div(Node):
2.433 + def __init__(self, (left, right), lineno=None):
2.434 + self.left = left
2.435 + self.right = right
2.436 + self.lineno = lineno
2.437 +
2.438 + def getChildren(self):
2.439 + return self.left, self.right
2.440 +
2.441 + def getChildNodes(self):
2.442 + return self.left, self.right
2.443 +
2.444 + def __repr__(self):
2.445 + return "Div((%s, %s))" % (repr(self.left), repr(self.right))
2.446 +
2.447 +class Ellipsis(Node):
2.448 + def __init__(self, lineno=None):
2.449 + self.lineno = lineno
2.450 +
2.451 + def getChildren(self):
2.452 + return ()
2.453 +
2.454 + def getChildNodes(self):
2.455 + return ()
2.456 +
2.457 + def __repr__(self):
2.458 + return "Ellipsis()"
2.459 +
2.460 +class Exec(Node):
2.461 + def __init__(self, expr, locals, globals, lineno=None):
2.462 + self.expr = expr
2.463 + self.locals = locals
2.464 + self.globals = globals
2.465 + self.lineno = lineno
2.466 +
2.467 + def getChildren(self):
2.468 + children = []
2.469 + children.append(self.expr)
2.470 + children.append(self.locals)
2.471 + children.append(self.globals)
2.472 + return tuple(children)
2.473 +
2.474 + def getChildNodes(self):
2.475 + nodelist = []
2.476 + nodelist.append(self.expr)
2.477 + if self.locals is not None:
2.478 + nodelist.append(self.locals)
2.479 + if self.globals is not None:
2.480 + nodelist.append(self.globals)
2.481 + return tuple(nodelist)
2.482 +
2.483 + def __repr__(self):
2.484 + return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals))
2.485 +
2.486 +class FloorDiv(Node):
2.487 + def __init__(self, (left, right), lineno=None):
2.488 + self.left = left
2.489 + self.right = right
2.490 + self.lineno = lineno
2.491 +
2.492 + def getChildren(self):
2.493 + return self.left, self.right
2.494 +
2.495 + def getChildNodes(self):
2.496 + return self.left, self.right
2.497 +
2.498 + def __repr__(self):
2.499 + return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right))
2.500 +
2.501 +class For(Node):
2.502 + def __init__(self, assign, list, body, else_, lineno=None):
2.503 + self.assign = assign
2.504 + self.list = list
2.505 + self.body = body
2.506 + self.else_ = else_
2.507 + self.lineno = lineno
2.508 +
2.509 + def getChildren(self):
2.510 + children = []
2.511 + children.append(self.assign)
2.512 + children.append(self.list)
2.513 + children.append(self.body)
2.514 + children.append(self.else_)
2.515 + return tuple(children)
2.516 +
2.517 + def getChildNodes(self):
2.518 + nodelist = []
2.519 + nodelist.append(self.assign)
2.520 + nodelist.append(self.list)
2.521 + nodelist.append(self.body)
2.522 + if self.else_ is not None:
2.523 + nodelist.append(self.else_)
2.524 + return tuple(nodelist)
2.525 +
2.526 + def __repr__(self):
2.527 + return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_))
2.528 +
2.529 +class From(Node):
2.530 + def __init__(self, modname, names, level, lineno=None):
2.531 + self.modname = modname
2.532 + self.names = names
2.533 + self.level = level
2.534 + self.lineno = lineno
2.535 +
2.536 + def getChildren(self):
2.537 + return self.modname, self.names, self.level
2.538 +
2.539 + def getChildNodes(self):
2.540 + return ()
2.541 +
2.542 + def __repr__(self):
2.543 + return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level))
2.544 +
2.545 +class Function(Node):
2.546 + def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None):
2.547 + self.decorators = decorators
2.548 + self.name = name
2.549 + self.argnames = argnames
2.550 + self.defaults = defaults
2.551 + self.flags = flags
2.552 + self.doc = doc
2.553 + self.code = code
2.554 + self.lineno = lineno
2.555 + self.varargs = self.kwargs = None
2.556 + if flags & CO_VARARGS:
2.557 + self.varargs = 1
2.558 + if flags & CO_VARKEYWORDS:
2.559 + self.kwargs = 1
2.560 +
2.561 +
2.562 +
2.563 + def getChildren(self):
2.564 + children = []
2.565 + children.append(self.decorators)
2.566 + children.append(self.name)
2.567 + children.append(self.argnames)
2.568 + children.extend(flatten(self.defaults))
2.569 + children.append(self.flags)
2.570 + children.append(self.doc)
2.571 + children.append(self.code)
2.572 + return tuple(children)
2.573 +
2.574 + def getChildNodes(self):
2.575 + nodelist = []
2.576 + if self.decorators is not None:
2.577 + nodelist.append(self.decorators)
2.578 + nodelist.extend(flatten_nodes(self.defaults))
2.579 + nodelist.append(self.code)
2.580 + return tuple(nodelist)
2.581 +
2.582 + def __repr__(self):
2.583 + 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.584 +
2.585 +class GenExpr(Node):
2.586 + def __init__(self, code, lineno=None):
2.587 + self.code = code
2.588 + self.lineno = lineno
2.589 + self.argnames = ['.0']
2.590 + self.varargs = self.kwargs = None
2.591 +
2.592 + def getChildren(self):
2.593 + return self.code,
2.594 +
2.595 + def getChildNodes(self):
2.596 + return self.code,
2.597 +
2.598 + def __repr__(self):
2.599 + return "GenExpr(%s)" % (repr(self.code),)
2.600 +
2.601 +class GenExprFor(Node):
2.602 + def __init__(self, assign, iter, ifs, lineno=None):
2.603 + self.assign = assign
2.604 + self.iter = iter
2.605 + self.ifs = ifs
2.606 + self.lineno = lineno
2.607 + self.is_outmost = False
2.608 +
2.609 +
2.610 + def getChildren(self):
2.611 + children = []
2.612 + children.append(self.assign)
2.613 + children.append(self.iter)
2.614 + children.extend(flatten(self.ifs))
2.615 + return tuple(children)
2.616 +
2.617 + def getChildNodes(self):
2.618 + nodelist = []
2.619 + nodelist.append(self.assign)
2.620 + nodelist.append(self.iter)
2.621 + nodelist.extend(flatten_nodes(self.ifs))
2.622 + return tuple(nodelist)
2.623 +
2.624 + def __repr__(self):
2.625 + return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs))
2.626 +
2.627 +class GenExprIf(Node):
2.628 + def __init__(self, test, lineno=None):
2.629 + self.test = test
2.630 + self.lineno = lineno
2.631 +
2.632 + def getChildren(self):
2.633 + return self.test,
2.634 +
2.635 + def getChildNodes(self):
2.636 + return self.test,
2.637 +
2.638 + def __repr__(self):
2.639 + return "GenExprIf(%s)" % (repr(self.test),)
2.640 +
2.641 +class GenExprInner(Node):
2.642 + def __init__(self, expr, quals, lineno=None):
2.643 + self.expr = expr
2.644 + self.quals = quals
2.645 + self.lineno = lineno
2.646 +
2.647 + def getChildren(self):
2.648 + children = []
2.649 + children.append(self.expr)
2.650 + children.extend(flatten(self.quals))
2.651 + return tuple(children)
2.652 +
2.653 + def getChildNodes(self):
2.654 + nodelist = []
2.655 + nodelist.append(self.expr)
2.656 + nodelist.extend(flatten_nodes(self.quals))
2.657 + return tuple(nodelist)
2.658 +
2.659 + def __repr__(self):
2.660 + return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals))
2.661 +
2.662 +class Getattr(Node):
2.663 + def __init__(self, expr, attrname, lineno=None):
2.664 + self.expr = expr
2.665 + self.attrname = attrname
2.666 + self.lineno = lineno
2.667 +
2.668 + def getChildren(self):
2.669 + return self.expr, self.attrname
2.670 +
2.671 + def getChildNodes(self):
2.672 + return self.expr,
2.673 +
2.674 + def __repr__(self):
2.675 + return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname))
2.676 +
2.677 +class Global(Node):
2.678 + def __init__(self, names, lineno=None):
2.679 + self.names = names
2.680 + self.lineno = lineno
2.681 +
2.682 + def getChildren(self):
2.683 + return self.names,
2.684 +
2.685 + def getChildNodes(self):
2.686 + return ()
2.687 +
2.688 + def __repr__(self):
2.689 + return "Global(%s)" % (repr(self.names),)
2.690 +
2.691 +class If(Node):
2.692 + def __init__(self, tests, else_, lineno=None):
2.693 + self.tests = tests
2.694 + self.else_ = else_
2.695 + self.lineno = lineno
2.696 +
2.697 + def getChildren(self):
2.698 + children = []
2.699 + children.extend(flatten(self.tests))
2.700 + children.append(self.else_)
2.701 + return tuple(children)
2.702 +
2.703 + def getChildNodes(self):
2.704 + nodelist = []
2.705 + nodelist.extend(flatten_nodes(self.tests))
2.706 + if self.else_ is not None:
2.707 + nodelist.append(self.else_)
2.708 + return tuple(nodelist)
2.709 +
2.710 + def __repr__(self):
2.711 + return "If(%s, %s)" % (repr(self.tests), repr(self.else_))
2.712 +
2.713 +class IfExp(Node):
2.714 + def __init__(self, test, then, else_, lineno=None):
2.715 + self.test = test
2.716 + self.then = then
2.717 + self.else_ = else_
2.718 + self.lineno = lineno
2.719 +
2.720 + def getChildren(self):
2.721 + return self.test, self.then, self.else_
2.722 +
2.723 + def getChildNodes(self):
2.724 + return self.test, self.then, self.else_
2.725 +
2.726 + def __repr__(self):
2.727 + return "IfExp(%s, %s, %s)" % (repr(self.test), repr(self.then), repr(self.else_))
2.728 +
2.729 +class Import(Node):
2.730 + def __init__(self, names, lineno=None):
2.731 + self.names = names
2.732 + self.lineno = lineno
2.733 +
2.734 + def getChildren(self):
2.735 + return self.names,
2.736 +
2.737 + def getChildNodes(self):
2.738 + return ()
2.739 +
2.740 + def __repr__(self):
2.741 + return "Import(%s)" % (repr(self.names),)
2.742 +
2.743 +class Invert(Node):
2.744 + def __init__(self, expr, lineno=None):
2.745 + self.expr = expr
2.746 + self.lineno = lineno
2.747 +
2.748 + def getChildren(self):
2.749 + return self.expr,
2.750 +
2.751 + def getChildNodes(self):
2.752 + return self.expr,
2.753 +
2.754 + def __repr__(self):
2.755 + return "Invert(%s)" % (repr(self.expr),)
2.756 +
2.757 +class Keyword(Node):
2.758 + def __init__(self, name, expr, lineno=None):
2.759 + self.name = name
2.760 + self.expr = expr
2.761 + self.lineno = lineno
2.762 +
2.763 + def getChildren(self):
2.764 + return self.name, self.expr
2.765 +
2.766 + def getChildNodes(self):
2.767 + return self.expr,
2.768 +
2.769 + def __repr__(self):
2.770 + return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
2.771 +
2.772 +class Lambda(Node):
2.773 + def __init__(self, argnames, defaults, flags, code, lineno=None):
2.774 + self.argnames = argnames
2.775 + self.defaults = defaults
2.776 + self.flags = flags
2.777 + self.code = code
2.778 + self.lineno = lineno
2.779 + self.varargs = self.kwargs = None
2.780 + if flags & CO_VARARGS:
2.781 + self.varargs = 1
2.782 + if flags & CO_VARKEYWORDS:
2.783 + self.kwargs = 1
2.784 +
2.785 +
2.786 +
2.787 + def getChildren(self):
2.788 + children = []
2.789 + children.append(self.argnames)
2.790 + children.extend(flatten(self.defaults))
2.791 + children.append(self.flags)
2.792 + children.append(self.code)
2.793 + return tuple(children)
2.794 +
2.795 + def getChildNodes(self):
2.796 + nodelist = []
2.797 + nodelist.extend(flatten_nodes(self.defaults))
2.798 + nodelist.append(self.code)
2.799 + return tuple(nodelist)
2.800 +
2.801 + def __repr__(self):
2.802 + return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code))
2.803 +
2.804 +class LeftShift(Node):
2.805 + def __init__(self, (left, right), lineno=None):
2.806 + self.left = left
2.807 + self.right = right
2.808 + self.lineno = lineno
2.809 +
2.810 + def getChildren(self):
2.811 + return self.left, self.right
2.812 +
2.813 + def getChildNodes(self):
2.814 + return self.left, self.right
2.815 +
2.816 + def __repr__(self):
2.817 + return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right))
2.818 +
2.819 +class List(Node):
2.820 + def __init__(self, nodes, lineno=None):
2.821 + self.nodes = nodes
2.822 + self.lineno = lineno
2.823 +
2.824 + def getChildren(self):
2.825 + return tuple(flatten(self.nodes))
2.826 +
2.827 + def getChildNodes(self):
2.828 + nodelist = []
2.829 + nodelist.extend(flatten_nodes(self.nodes))
2.830 + return tuple(nodelist)
2.831 +
2.832 + def __repr__(self):
2.833 + return "List(%s)" % (repr(self.nodes),)
2.834 +
2.835 +class ListComp(Node):
2.836 + def __init__(self, expr, quals, lineno=None):
2.837 + self.expr = expr
2.838 + self.quals = quals
2.839 + self.lineno = lineno
2.840 +
2.841 + def getChildren(self):
2.842 + children = []
2.843 + children.append(self.expr)
2.844 + children.extend(flatten(self.quals))
2.845 + return tuple(children)
2.846 +
2.847 + def getChildNodes(self):
2.848 + nodelist = []
2.849 + nodelist.append(self.expr)
2.850 + nodelist.extend(flatten_nodes(self.quals))
2.851 + return tuple(nodelist)
2.852 +
2.853 + def __repr__(self):
2.854 + return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals))
2.855 +
2.856 +class ListCompFor(Node):
2.857 + def __init__(self, assign, list, ifs, lineno=None):
2.858 + self.assign = assign
2.859 + self.list = list
2.860 + self.ifs = ifs
2.861 + self.lineno = lineno
2.862 +
2.863 + def getChildren(self):
2.864 + children = []
2.865 + children.append(self.assign)
2.866 + children.append(self.list)
2.867 + children.extend(flatten(self.ifs))
2.868 + return tuple(children)
2.869 +
2.870 + def getChildNodes(self):
2.871 + nodelist = []
2.872 + nodelist.append(self.assign)
2.873 + nodelist.append(self.list)
2.874 + nodelist.extend(flatten_nodes(self.ifs))
2.875 + return tuple(nodelist)
2.876 +
2.877 + def __repr__(self):
2.878 + return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs))
2.879 +
2.880 +class ListCompIf(Node):
2.881 + def __init__(self, test, lineno=None):
2.882 + self.test = test
2.883 + self.lineno = lineno
2.884 +
2.885 + def getChildren(self):
2.886 + return self.test,
2.887 +
2.888 + def getChildNodes(self):
2.889 + return self.test,
2.890 +
2.891 + def __repr__(self):
2.892 + return "ListCompIf(%s)" % (repr(self.test),)
2.893 +
2.894 +class Mod(Node):
2.895 + def __init__(self, (left, right), lineno=None):
2.896 + self.left = left
2.897 + self.right = right
2.898 + self.lineno = lineno
2.899 +
2.900 + def getChildren(self):
2.901 + return self.left, self.right
2.902 +
2.903 + def getChildNodes(self):
2.904 + return self.left, self.right
2.905 +
2.906 + def __repr__(self):
2.907 + return "Mod((%s, %s))" % (repr(self.left), repr(self.right))
2.908 +
2.909 +class Module(Node):
2.910 + def __init__(self, doc, node, lineno=None):
2.911 + self.doc = doc
2.912 + self.node = node
2.913 + self.lineno = lineno
2.914 +
2.915 + def getChildren(self):
2.916 + return self.doc, self.node
2.917 +
2.918 + def getChildNodes(self):
2.919 + return self.node,
2.920 +
2.921 + def __repr__(self):
2.922 + return "Module(%s, %s)" % (repr(self.doc), repr(self.node))
2.923 +
2.924 +class Mul(Node):
2.925 + def __init__(self, (left, right), lineno=None):
2.926 + self.left = left
2.927 + self.right = right
2.928 + self.lineno = lineno
2.929 +
2.930 + def getChildren(self):
2.931 + return self.left, self.right
2.932 +
2.933 + def getChildNodes(self):
2.934 + return self.left, self.right
2.935 +
2.936 + def __repr__(self):
2.937 + return "Mul((%s, %s))" % (repr(self.left), repr(self.right))
2.938 +
2.939 +class Name(Node):
2.940 + def __init__(self, name, lineno=None):
2.941 + self.name = name
2.942 + self.lineno = lineno
2.943 +
2.944 + def getChildren(self):
2.945 + return self.name,
2.946 +
2.947 + def getChildNodes(self):
2.948 + return ()
2.949 +
2.950 + def __repr__(self):
2.951 + return "Name(%s)" % (repr(self.name),)
2.952 +
2.953 +class Not(Node):
2.954 + def __init__(self, expr, lineno=None):
2.955 + self.expr = expr
2.956 + self.lineno = lineno
2.957 +
2.958 + def getChildren(self):
2.959 + return self.expr,
2.960 +
2.961 + def getChildNodes(self):
2.962 + return self.expr,
2.963 +
2.964 + def __repr__(self):
2.965 + return "Not(%s)" % (repr(self.expr),)
2.966 +
2.967 +class Or(Node):
2.968 + def __init__(self, nodes, lineno=None):
2.969 + self.nodes = nodes
2.970 + self.lineno = lineno
2.971 +
2.972 + def getChildren(self):
2.973 + return tuple(flatten(self.nodes))
2.974 +
2.975 + def getChildNodes(self):
2.976 + nodelist = []
2.977 + nodelist.extend(flatten_nodes(self.nodes))
2.978 + return tuple(nodelist)
2.979 +
2.980 + def __repr__(self):
2.981 + return "Or(%s)" % (repr(self.nodes),)
2.982 +
2.983 +class Pass(Node):
2.984 + def __init__(self, lineno=None):
2.985 + self.lineno = lineno
2.986 +
2.987 + def getChildren(self):
2.988 + return ()
2.989 +
2.990 + def getChildNodes(self):
2.991 + return ()
2.992 +
2.993 + def __repr__(self):
2.994 + return "Pass()"
2.995 +
2.996 +class Power(Node):
2.997 + def __init__(self, (left, right), lineno=None):
2.998 + self.left = left
2.999 + self.right = right
2.1000 + self.lineno = lineno
2.1001 +
2.1002 + def getChildren(self):
2.1003 + return self.left, self.right
2.1004 +
2.1005 + def getChildNodes(self):
2.1006 + return self.left, self.right
2.1007 +
2.1008 + def __repr__(self):
2.1009 + return "Power((%s, %s))" % (repr(self.left), repr(self.right))
2.1010 +
2.1011 +class Print(Node):
2.1012 + def __init__(self, nodes, dest, lineno=None):
2.1013 + self.nodes = nodes
2.1014 + self.dest = dest
2.1015 + self.lineno = lineno
2.1016 +
2.1017 + def getChildren(self):
2.1018 + children = []
2.1019 + children.extend(flatten(self.nodes))
2.1020 + children.append(self.dest)
2.1021 + return tuple(children)
2.1022 +
2.1023 + def getChildNodes(self):
2.1024 + nodelist = []
2.1025 + nodelist.extend(flatten_nodes(self.nodes))
2.1026 + if self.dest is not None:
2.1027 + nodelist.append(self.dest)
2.1028 + return tuple(nodelist)
2.1029 +
2.1030 + def __repr__(self):
2.1031 + return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest))
2.1032 +
2.1033 +class Printnl(Node):
2.1034 + def __init__(self, nodes, dest, lineno=None):
2.1035 + self.nodes = nodes
2.1036 + self.dest = dest
2.1037 + self.lineno = lineno
2.1038 +
2.1039 + def getChildren(self):
2.1040 + children = []
2.1041 + children.extend(flatten(self.nodes))
2.1042 + children.append(self.dest)
2.1043 + return tuple(children)
2.1044 +
2.1045 + def getChildNodes(self):
2.1046 + nodelist = []
2.1047 + nodelist.extend(flatten_nodes(self.nodes))
2.1048 + if self.dest is not None:
2.1049 + nodelist.append(self.dest)
2.1050 + return tuple(nodelist)
2.1051 +
2.1052 + def __repr__(self):
2.1053 + return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest))
2.1054 +
2.1055 +class Raise(Node):
2.1056 + def __init__(self, expr1, expr2, expr3, lineno=None):
2.1057 + self.expr1 = expr1
2.1058 + self.expr2 = expr2
2.1059 + self.expr3 = expr3
2.1060 + self.lineno = lineno
2.1061 +
2.1062 + def getChildren(self):
2.1063 + children = []
2.1064 + children.append(self.expr1)
2.1065 + children.append(self.expr2)
2.1066 + children.append(self.expr3)
2.1067 + return tuple(children)
2.1068 +
2.1069 + def getChildNodes(self):
2.1070 + nodelist = []
2.1071 + if self.expr1 is not None:
2.1072 + nodelist.append(self.expr1)
2.1073 + if self.expr2 is not None:
2.1074 + nodelist.append(self.expr2)
2.1075 + if self.expr3 is not None:
2.1076 + nodelist.append(self.expr3)
2.1077 + return tuple(nodelist)
2.1078 +
2.1079 + def __repr__(self):
2.1080 + return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3))
2.1081 +
2.1082 +class Return(Node):
2.1083 + def __init__(self, value, lineno=None):
2.1084 + self.value = value
2.1085 + self.lineno = lineno
2.1086 +
2.1087 + def getChildren(self):
2.1088 + return self.value,
2.1089 +
2.1090 + def getChildNodes(self):
2.1091 + return self.value,
2.1092 +
2.1093 + def __repr__(self):
2.1094 + return "Return(%s)" % (repr(self.value),)
2.1095 +
2.1096 +class RightShift(Node):
2.1097 + def __init__(self, (left, right), lineno=None):
2.1098 + self.left = left
2.1099 + self.right = right
2.1100 + self.lineno = lineno
2.1101 +
2.1102 + def getChildren(self):
2.1103 + return self.left, self.right
2.1104 +
2.1105 + def getChildNodes(self):
2.1106 + return self.left, self.right
2.1107 +
2.1108 + def __repr__(self):
2.1109 + return "RightShift((%s, %s))" % (repr(self.left), repr(self.right))
2.1110 +
2.1111 +class Slice(Node):
2.1112 + def __init__(self, expr, flags, lower, upper, lineno=None):
2.1113 + self.expr = expr
2.1114 + self.flags = flags
2.1115 + self.lower = lower
2.1116 + self.upper = upper
2.1117 + self.lineno = lineno
2.1118 +
2.1119 + def getChildren(self):
2.1120 + children = []
2.1121 + children.append(self.expr)
2.1122 + children.append(self.flags)
2.1123 + children.append(self.lower)
2.1124 + children.append(self.upper)
2.1125 + return tuple(children)
2.1126 +
2.1127 + def getChildNodes(self):
2.1128 + nodelist = []
2.1129 + nodelist.append(self.expr)
2.1130 + if self.lower is not None:
2.1131 + nodelist.append(self.lower)
2.1132 + if self.upper is not None:
2.1133 + nodelist.append(self.upper)
2.1134 + return tuple(nodelist)
2.1135 +
2.1136 + def __repr__(self):
2.1137 + return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper))
2.1138 +
2.1139 +class Sliceobj(Node):
2.1140 + def __init__(self, nodes, lineno=None):
2.1141 + self.nodes = nodes
2.1142 + self.lineno = lineno
2.1143 +
2.1144 + def getChildren(self):
2.1145 + return tuple(flatten(self.nodes))
2.1146 +
2.1147 + def getChildNodes(self):
2.1148 + nodelist = []
2.1149 + nodelist.extend(flatten_nodes(self.nodes))
2.1150 + return tuple(nodelist)
2.1151 +
2.1152 + def __repr__(self):
2.1153 + return "Sliceobj(%s)" % (repr(self.nodes),)
2.1154 +
2.1155 +class Stmt(Node):
2.1156 + def __init__(self, nodes, lineno=None):
2.1157 + self.nodes = nodes
2.1158 + self.lineno = lineno
2.1159 +
2.1160 + def getChildren(self):
2.1161 + return tuple(flatten(self.nodes))
2.1162 +
2.1163 + def getChildNodes(self):
2.1164 + nodelist = []
2.1165 + nodelist.extend(flatten_nodes(self.nodes))
2.1166 + return tuple(nodelist)
2.1167 +
2.1168 + def __repr__(self):
2.1169 + return "Stmt(%s)" % (repr(self.nodes),)
2.1170 +
2.1171 +class Sub(Node):
2.1172 + def __init__(self, (left, right), lineno=None):
2.1173 + self.left = left
2.1174 + self.right = right
2.1175 + self.lineno = lineno
2.1176 +
2.1177 + def getChildren(self):
2.1178 + return self.left, self.right
2.1179 +
2.1180 + def getChildNodes(self):
2.1181 + return self.left, self.right
2.1182 +
2.1183 + def __repr__(self):
2.1184 + return "Sub((%s, %s))" % (repr(self.left), repr(self.right))
2.1185 +
2.1186 +class Subscript(Node):
2.1187 + def __init__(self, expr, flags, subs, lineno=None):
2.1188 + self.expr = expr
2.1189 + self.flags = flags
2.1190 + self.subs = subs
2.1191 + self.lineno = lineno
2.1192 +
2.1193 + def getChildren(self):
2.1194 + children = []
2.1195 + children.append(self.expr)
2.1196 + children.append(self.flags)
2.1197 + children.extend(flatten(self.subs))
2.1198 + return tuple(children)
2.1199 +
2.1200 + def getChildNodes(self):
2.1201 + nodelist = []
2.1202 + nodelist.append(self.expr)
2.1203 + nodelist.extend(flatten_nodes(self.subs))
2.1204 + return tuple(nodelist)
2.1205 +
2.1206 + def __repr__(self):
2.1207 + return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs))
2.1208 +
2.1209 +class TryExcept(Node):
2.1210 + def __init__(self, body, handlers, else_, lineno=None):
2.1211 + self.body = body
2.1212 + self.handlers = handlers
2.1213 + self.else_ = else_
2.1214 + self.lineno = lineno
2.1215 +
2.1216 + def getChildren(self):
2.1217 + children = []
2.1218 + children.append(self.body)
2.1219 + children.extend(flatten(self.handlers))
2.1220 + children.append(self.else_)
2.1221 + return tuple(children)
2.1222 +
2.1223 + def getChildNodes(self):
2.1224 + nodelist = []
2.1225 + nodelist.append(self.body)
2.1226 + nodelist.extend(flatten_nodes(self.handlers))
2.1227 + if self.else_ is not None:
2.1228 + nodelist.append(self.else_)
2.1229 + return tuple(nodelist)
2.1230 +
2.1231 + def __repr__(self):
2.1232 + return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_))
2.1233 +
2.1234 +class TryFinally(Node):
2.1235 + def __init__(self, body, final, lineno=None):
2.1236 + self.body = body
2.1237 + self.final = final
2.1238 + self.lineno = lineno
2.1239 +
2.1240 + def getChildren(self):
2.1241 + return self.body, self.final
2.1242 +
2.1243 + def getChildNodes(self):
2.1244 + return self.body, self.final
2.1245 +
2.1246 + def __repr__(self):
2.1247 + return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final))
2.1248 +
2.1249 +class Tuple(Node):
2.1250 + def __init__(self, nodes, lineno=None):
2.1251 + self.nodes = nodes
2.1252 + self.lineno = lineno
2.1253 +
2.1254 + def getChildren(self):
2.1255 + return tuple(flatten(self.nodes))
2.1256 +
2.1257 + def getChildNodes(self):
2.1258 + nodelist = []
2.1259 + nodelist.extend(flatten_nodes(self.nodes))
2.1260 + return tuple(nodelist)
2.1261 +
2.1262 + def __repr__(self):
2.1263 + return "Tuple(%s)" % (repr(self.nodes),)
2.1264 +
2.1265 +class UnaryAdd(Node):
2.1266 + def __init__(self, expr, lineno=None):
2.1267 + self.expr = expr
2.1268 + self.lineno = lineno
2.1269 +
2.1270 + def getChildren(self):
2.1271 + return self.expr,
2.1272 +
2.1273 + def getChildNodes(self):
2.1274 + return self.expr,
2.1275 +
2.1276 + def __repr__(self):
2.1277 + return "UnaryAdd(%s)" % (repr(self.expr),)
2.1278 +
2.1279 +class UnarySub(Node):
2.1280 + def __init__(self, expr, lineno=None):
2.1281 + self.expr = expr
2.1282 + self.lineno = lineno
2.1283 +
2.1284 + def getChildren(self):
2.1285 + return self.expr,
2.1286 +
2.1287 + def getChildNodes(self):
2.1288 + return self.expr,
2.1289 +
2.1290 + def __repr__(self):
2.1291 + return "UnarySub(%s)" % (repr(self.expr),)
2.1292 +
2.1293 +class While(Node):
2.1294 + def __init__(self, test, body, else_, lineno=None):
2.1295 + self.test = test
2.1296 + self.body = body
2.1297 + self.else_ = else_
2.1298 + self.lineno = lineno
2.1299 +
2.1300 + def getChildren(self):
2.1301 + children = []
2.1302 + children.append(self.test)
2.1303 + children.append(self.body)
2.1304 + children.append(self.else_)
2.1305 + return tuple(children)
2.1306 +
2.1307 + def getChildNodes(self):
2.1308 + nodelist = []
2.1309 + nodelist.append(self.test)
2.1310 + nodelist.append(self.body)
2.1311 + if self.else_ is not None:
2.1312 + nodelist.append(self.else_)
2.1313 + return tuple(nodelist)
2.1314 +
2.1315 + def __repr__(self):
2.1316 + return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_))
2.1317 +
2.1318 +class With(Node):
2.1319 + def __init__(self, expr, vars, body, lineno=None):
2.1320 + self.expr = expr
2.1321 + self.vars = vars
2.1322 + self.body = body
2.1323 + self.lineno = lineno
2.1324 +
2.1325 + def getChildren(self):
2.1326 + children = []
2.1327 + children.append(self.expr)
2.1328 + children.append(self.vars)
2.1329 + children.append(self.body)
2.1330 + return tuple(children)
2.1331 +
2.1332 + def getChildNodes(self):
2.1333 + nodelist = []
2.1334 + nodelist.append(self.expr)
2.1335 + if self.vars is not None:
2.1336 + nodelist.append(self.vars)
2.1337 + nodelist.append(self.body)
2.1338 + return tuple(nodelist)
2.1339 +
2.1340 + def __repr__(self):
2.1341 + return "With(%s, %s, %s)" % (repr(self.expr), repr(self.vars), repr(self.body))
2.1342 +
2.1343 +class Yield(Node):
2.1344 + def __init__(self, value, lineno=None):
2.1345 + self.value = value
2.1346 + self.lineno = lineno
2.1347 +
2.1348 + def getChildren(self):
2.1349 + return self.value,
2.1350 +
2.1351 + def getChildNodes(self):
2.1352 + return self.value,
2.1353 +
2.1354 + def __repr__(self):
2.1355 + return "Yield(%s)" % (repr(self.value),)
2.1356 +
2.1357 +for name, obj in globals().items():
2.1358 + if isinstance(obj, type) and issubclass(obj, Node):
2.1359 + nodes[name.lower()] = obj
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/compiler/consts.py Tue May 01 22:04:53 2012 +0200
3.3 @@ -0,0 +1,21 @@
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
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/compiler/future.py Tue May 01 22:04:53 2012 +0200
4.3 @@ -0,0 +1,73 @@
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")
4.23 +
4.24 + def __init__(self):
4.25 + self.found = {} # set
4.26 +
4.27 + def visitModule(self, node):
4.28 + stmt = node.node
4.29 + for s in stmt.nodes:
4.30 + if not self.check_stmt(s):
4.31 + break
4.32 +
4.33 + def check_stmt(self, stmt):
4.34 + if is_future(stmt):
4.35 + for name, asname in stmt.names:
4.36 + if name in self.features:
4.37 + self.found[name] = 1
4.38 + else:
4.39 + raise SyntaxError, \
4.40 + "future feature %s is not defined" % name
4.41 + stmt.valid_future = 1
4.42 + return 1
4.43 + return 0
4.44 +
4.45 + def get_features(self):
4.46 + """Return list of features enabled by future statements"""
4.47 + return self.found.keys()
4.48 +
4.49 +class BadFutureParser:
4.50 + """Check for invalid future statements"""
4.51 +
4.52 + def visitFrom(self, node):
4.53 + if hasattr(node, 'valid_future'):
4.54 + return
4.55 + if node.modname != "__future__":
4.56 + return
4.57 + raise SyntaxError, "invalid future statement " + repr(node)
4.58 +
4.59 +def find_futures(node):
4.60 + p1 = FutureParser()
4.61 + p2 = BadFutureParser()
4.62 + walk(node, p1)
4.63 + walk(node, p2)
4.64 + return p1.get_features()
4.65 +
4.66 +if __name__ == "__main__":
4.67 + import sys
4.68 + from compiler import parseFile, walk
4.69 +
4.70 + for file in sys.argv[1:]:
4.71 + print file
4.72 + tree = parseFile(file)
4.73 + v = FutureParser()
4.74 + walk(tree, v)
4.75 + print v.found
4.76 + print
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/compiler/misc.py Tue May 01 22:04:53 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 self.elts.has_key(elt)
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 self.elts.has_key(elt)
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 Tue May 01 22:04:53 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 new
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 seen.has_key(c):
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 seen.has_key(b):
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 cells.has_key(name)]
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 new.code(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 Tue May 01 22:04:53 2012 +0200
7.3 @@ -0,0 +1,1533 @@
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)
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 +
7.225 + def initClass(self):
7.226 + """This method is called once for each class"""
7.227 +
7.228 + def checkClass(self):
7.229 + """Verify that class is constructed correctly"""
7.230 + try:
7.231 + assert hasattr(self, 'graph')
7.232 + assert getattr(self, 'NameFinder')
7.233 + assert getattr(self, 'FunctionGen')
7.234 + assert getattr(self, 'ClassGen')
7.235 + except AssertionError, msg:
7.236 + intro = "Bad class construction for %s" % self.__class__.__name__
7.237 + raise AssertionError, intro
7.238 +
7.239 + def _setupGraphDelegation(self):
7.240 + self.emit = self.graph.emit
7.241 + self.newBlock = self.graph.newBlock
7.242 + self.startBlock = self.graph.startBlock
7.243 + self.nextBlock = self.graph.nextBlock
7.244 + self.setDocstring = self.graph.setDocstring
7.245 +
7.246 + def getCode(self):
7.247 + """Return a code object"""
7.248 + return self.graph.getCode()
7.249 +
7.250 + def mangle(self, name):
7.251 + if self.class_name is not None:
7.252 + return misc.mangle(name, self.class_name)
7.253 + else:
7.254 + return name
7.255 +
7.256 + def parseSymbols(self, tree):
7.257 + s = symbols.SymbolVisitor()
7.258 + walk(tree, s)
7.259 + return s.scopes
7.260 +
7.261 + def get_module(self):
7.262 + raise RuntimeError, "should be implemented by subclasses"
7.263 +
7.264 + # Next five methods handle name access
7.265 +
7.266 + def isLocalName(self, name):
7.267 + return self.locals.top().has_elt(name)
7.268 +
7.269 + def storeName(self, name):
7.270 + self._nameOp('STORE', name)
7.271 +
7.272 + def loadName(self, name):
7.273 + self._nameOp('LOAD', name)
7.274 +
7.275 + def delName(self, name):
7.276 + self._nameOp('DELETE', name)
7.277 +
7.278 + def _nameOp(self, prefix, name):
7.279 + name = self.mangle(name)
7.280 + scope = self.scope.check_name(name)
7.281 + if scope == SC_LOCAL:
7.282 + if not self.optimized:
7.283 + self.emit(prefix + '_NAME', name)
7.284 + else:
7.285 + self.emit(prefix + '_FAST', name)
7.286 + elif scope == SC_GLOBAL:
7.287 + if not self.optimized:
7.288 + self.emit(prefix + '_NAME', name)
7.289 + else:
7.290 + self.emit(prefix + '_GLOBAL', name)
7.291 + elif scope == SC_FREE or scope == SC_CELL:
7.292 + self.emit(prefix + '_DEREF', name)
7.293 + else:
7.294 + raise RuntimeError, "unsupported scope for var %s: %d" % \
7.295 + (name, scope)
7.296 +
7.297 + def _implicitNameOp(self, prefix, name):
7.298 + """Emit name ops for names generated implicitly by for loops
7.299 +
7.300 + The interpreter generates names that start with a period or
7.301 + dollar sign. The symbol table ignores these names because
7.302 + they aren't present in the program text.
7.303 + """
7.304 + if self.optimized:
7.305 + self.emit(prefix + '_FAST', name)
7.306 + else:
7.307 + self.emit(prefix + '_NAME', name)
7.308 +
7.309 + # The set_lineno() function and the explicit emit() calls for
7.310 + # SET_LINENO below are only used to generate the line number table.
7.311 + # As of Python 2.3, the interpreter does not have a SET_LINENO
7.312 + # instruction. pyassem treats SET_LINENO opcodes as a special case.
7.313 +
7.314 + def set_lineno(self, node, force=False):
7.315 + """Emit SET_LINENO if necessary.
7.316 +
7.317 + The instruction is considered necessary if the node has a
7.318 + lineno attribute and it is different than the last lineno
7.319 + emitted.
7.320 +
7.321 + Returns true if SET_LINENO was emitted.
7.322 +
7.323 + There are no rules for when an AST node should have a lineno
7.324 + attribute. The transformer and AST code need to be reviewed
7.325 + and a consistent policy implemented and documented. Until
7.326 + then, this method works around missing line numbers.
7.327 + """
7.328 + lineno = getattr(node, 'lineno', None)
7.329 + if lineno is not None and (lineno != self.last_lineno
7.330 + or force):
7.331 + self.emit('SET_LINENO', lineno)
7.332 + self.last_lineno = lineno
7.333 + return True
7.334 + return False
7.335 +
7.336 + # The first few visitor methods handle nodes that generator new
7.337 + # code objects. They use class attributes to determine what
7.338 + # specialized code generators to use.
7.339 +
7.340 + NameFinder = LocalNameFinder
7.341 + FunctionGen = None
7.342 + ClassGen = None
7.343 +
7.344 + def visitModule(self, node):
7.345 + self.scopes = self.parseSymbols(node)
7.346 + self.scope = self.scopes[node]
7.347 + self.emit('SET_LINENO', 0)
7.348 + if node.doc:
7.349 + self.emit('LOAD_CONST', node.doc)
7.350 + self.storeName('__doc__')
7.351 + lnf = walk(node.node, self.NameFinder(), verbose=0)
7.352 + self.locals.push(lnf.getLocals())
7.353 + self.visit(node.node)
7.354 + self.emit('LOAD_CONST', None)
7.355 + self.emit('RETURN_VALUE')
7.356 +
7.357 + def visitExpression(self, node):
7.358 + self.set_lineno(node)
7.359 + self.scopes = self.parseSymbols(node)
7.360 + self.scope = self.scopes[node]
7.361 + self.visit(node.node)
7.362 + self.emit('RETURN_VALUE')
7.363 +
7.364 + def visitFunction(self, node):
7.365 + self._visitFuncOrLambda(node, isLambda=0)
7.366 + if node.doc:
7.367 + self.setDocstring(node.doc)
7.368 + self.storeName(node.name)
7.369 +
7.370 + def visitLambda(self, node):
7.371 + self._visitFuncOrLambda(node, isLambda=1)
7.372 +
7.373 + def _visitFuncOrLambda(self, node, isLambda=0):
7.374 + if not isLambda and node.decorators:
7.375 + for decorator in node.decorators.nodes:
7.376 + self.visit(decorator)
7.377 + ndecorators = len(node.decorators.nodes)
7.378 + else:
7.379 + ndecorators = 0
7.380 +
7.381 + gen = self.FunctionGen(node, self.scopes, isLambda,
7.382 + self.class_name, self.get_module())
7.383 + walk(node.code, gen)
7.384 + gen.finish()
7.385 + self.set_lineno(node)
7.386 + for default in node.defaults:
7.387 + self.visit(default)
7.388 + self._makeClosure(gen, len(node.defaults))
7.389 + for i in range(ndecorators):
7.390 + self.emit('CALL_FUNCTION', 1)
7.391 +
7.392 + def visitClass(self, node):
7.393 + gen = self.ClassGen(node, self.scopes,
7.394 + self.get_module())
7.395 + walk(node.code, gen)
7.396 + gen.finish()
7.397 + self.set_lineno(node)
7.398 + self.emit('LOAD_CONST', node.name)
7.399 + for base in node.bases:
7.400 + self.visit(base)
7.401 + self.emit('BUILD_TUPLE', len(node.bases))
7.402 + self._makeClosure(gen, 0)
7.403 + self.emit('CALL_FUNCTION', 0)
7.404 + self.emit('BUILD_CLASS')
7.405 + self.storeName(node.name)
7.406 +
7.407 + # The rest are standard visitor methods
7.408 +
7.409 + # The next few implement control-flow statements
7.410 +
7.411 + def visitIf(self, node):
7.412 + end = self.newBlock()
7.413 + numtests = len(node.tests)
7.414 + for i in range(numtests):
7.415 + test, suite = node.tests[i]
7.416 + if is_constant_false(test):
7.417 + # XXX will need to check generator stuff here
7.418 + continue
7.419 + self.set_lineno(test)
7.420 + self.visit(test)
7.421 + nextTest = self.newBlock()
7.422 + self.emit('JUMP_IF_FALSE', nextTest)
7.423 + self.nextBlock()
7.424 + self.emit('POP_TOP')
7.425 + self.visit(suite)
7.426 + self.emit('JUMP_FORWARD', end)
7.427 + self.startBlock(nextTest)
7.428 + self.emit('POP_TOP')
7.429 + if node.else_:
7.430 + self.visit(node.else_)
7.431 + self.nextBlock(end)
7.432 +
7.433 + def visitWhile(self, node):
7.434 + self.set_lineno(node)
7.435 +
7.436 + loop = self.newBlock()
7.437 + else_ = self.newBlock()
7.438 +
7.439 + after = self.newBlock()
7.440 + self.emit('SETUP_LOOP', after)
7.441 +
7.442 + self.nextBlock(loop)
7.443 + self.setups.push((LOOP, loop))
7.444 +
7.445 + self.set_lineno(node, force=True)
7.446 + self.visit(node.test)
7.447 + self.emit('JUMP_IF_FALSE', else_ or after)
7.448 +
7.449 + self.nextBlock()
7.450 + self.emit('POP_TOP')
7.451 + self.visit(node.body)
7.452 + self.emit('JUMP_ABSOLUTE', loop)
7.453 +
7.454 + self.startBlock(else_) # or just the POPs if not else clause
7.455 + self.emit('POP_TOP')
7.456 + self.emit('POP_BLOCK')
7.457 + self.setups.pop()
7.458 + if node.else_:
7.459 + self.visit(node.else_)
7.460 + self.nextBlock(after)
7.461 +
7.462 + def visitFor(self, node):
7.463 + start = self.newBlock()
7.464 + anchor = self.newBlock()
7.465 + after = self.newBlock()
7.466 + self.setups.push((LOOP, start))
7.467 +
7.468 + self.set_lineno(node)
7.469 + self.emit('SETUP_LOOP', after)
7.470 + self.visit(node.list)
7.471 + self.emit('GET_ITER')
7.472 +
7.473 + self.nextBlock(start)
7.474 + self.set_lineno(node, force=1)
7.475 + self.emit('FOR_ITER', anchor)
7.476 + self.visit(node.assign)
7.477 + self.visit(node.body)
7.478 + self.emit('JUMP_ABSOLUTE', start)
7.479 + self.nextBlock(anchor)
7.480 + self.emit('POP_BLOCK')
7.481 + self.setups.pop()
7.482 + if node.else_:
7.483 + self.visit(node.else_)
7.484 + self.nextBlock(after)
7.485 +
7.486 + def visitBreak(self, node):
7.487 + if not self.setups:
7.488 + raise SyntaxError, "'break' outside loop (%s, %d)" % \
7.489 + (node.filename, node.lineno)
7.490 + self.set_lineno(node)
7.491 + self.emit('BREAK_LOOP')
7.492 +
7.493 + def visitContinue(self, node):
7.494 + if not self.setups:
7.495 + raise SyntaxError, "'continue' outside loop (%s, %d)" % \
7.496 + (node.filename, node.lineno)
7.497 + kind, block = self.setups.top()
7.498 + if kind == LOOP:
7.499 + self.set_lineno(node)
7.500 + self.emit('JUMP_ABSOLUTE', block)
7.501 + self.nextBlock()
7.502 + elif kind == EXCEPT or kind == TRY_FINALLY:
7.503 + self.set_lineno(node)
7.504 + # find the block that starts the loop
7.505 + top = len(self.setups)
7.506 + while top > 0:
7.507 + top = top - 1
7.508 + kind, loop_block = self.setups[top]
7.509 + if kind == LOOP:
7.510 + break
7.511 + if kind != LOOP:
7.512 + raise SyntaxError, "'continue' outside loop (%s, %d)" % \
7.513 + (node.filename, node.lineno)
7.514 + self.emit('CONTINUE_LOOP', loop_block)
7.515 + self.nextBlock()
7.516 + elif kind == END_FINALLY:
7.517 + msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
7.518 + raise SyntaxError, msg % (node.filename, node.lineno)
7.519 +
7.520 + def visitTest(self, node, jump):
7.521 + end = self.newBlock()
7.522 + for child in node.nodes[:-1]:
7.523 + self.visit(child)
7.524 + self.emit(jump, end)
7.525 + self.nextBlock()
7.526 + self.emit('POP_TOP')
7.527 + self.visit(node.nodes[-1])
7.528 + self.nextBlock(end)
7.529 +
7.530 + def visitAnd(self, node):
7.531 + self.visitTest(node, 'JUMP_IF_FALSE')
7.532 +
7.533 + def visitOr(self, node):
7.534 + self.visitTest(node, 'JUMP_IF_TRUE')
7.535 +
7.536 + def visitIfExp(self, node):
7.537 + endblock = self.newBlock()
7.538 + elseblock = self.newBlock()
7.539 + self.visit(node.test)
7.540 + self.emit('JUMP_IF_FALSE', elseblock)
7.541 + self.emit('POP_TOP')
7.542 + self.visit(node.then)
7.543 + self.emit('JUMP_FORWARD', endblock)
7.544 + self.nextBlock(elseblock)
7.545 + self.emit('POP_TOP')
7.546 + self.visit(node.else_)
7.547 + self.nextBlock(endblock)
7.548 +
7.549 + def visitCompare(self, node):
7.550 + self.visit(node.expr)
7.551 + cleanup = self.newBlock()
7.552 + for op, code in node.ops[:-1]:
7.553 + self.visit(code)
7.554 + self.emit('DUP_TOP')
7.555 + self.emit('ROT_THREE')
7.556 + self.emit('COMPARE_OP', op)
7.557 + self.emit('JUMP_IF_FALSE', cleanup)
7.558 + self.nextBlock()
7.559 + self.emit('POP_TOP')
7.560 + # now do the last comparison
7.561 + if node.ops:
7.562 + op, code = node.ops[-1]
7.563 + self.visit(code)
7.564 + self.emit('COMPARE_OP', op)
7.565 + if len(node.ops) > 1:
7.566 + end = self.newBlock()
7.567 + self.emit('JUMP_FORWARD', end)
7.568 + self.startBlock(cleanup)
7.569 + self.emit('ROT_TWO')
7.570 + self.emit('POP_TOP')
7.571 + self.nextBlock(end)
7.572 +
7.573 + # list comprehensions
7.574 + __list_count = 0
7.575 +
7.576 + def visitListComp(self, node):
7.577 + self.set_lineno(node)
7.578 + # setup list
7.579 + append = "$append%d" % self.__list_count
7.580 + self.__list_count = self.__list_count + 1
7.581 + self.emit('BUILD_LIST', 0)
7.582 + self.emit('DUP_TOP')
7.583 + self.emit('LOAD_ATTR', 'append')
7.584 + self._implicitNameOp('STORE', append)
7.585 +
7.586 + stack = []
7.587 + for i, for_ in zip(range(len(node.quals)), node.quals):
7.588 + start, anchor = self.visit(for_)
7.589 + cont = None
7.590 + for if_ in for_.ifs:
7.591 + if cont is None:
7.592 + cont = self.newBlock()
7.593 + self.visit(if_, cont)
7.594 + stack.insert(0, (start, cont, anchor))
7.595 +
7.596 + self._implicitNameOp('LOAD', append)
7.597 + self.visit(node.expr)
7.598 + self.emit('CALL_FUNCTION', 1)
7.599 + self.emit('POP_TOP')
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', append)
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 + exitvar = "$exit%d" % self.__with_count
7.831 + valuevar = "$value%d" % self.__with_count
7.832 + self.__with_count += 1
7.833 + self.set_lineno(node)
7.834 + self.visit(node.expr)
7.835 + self.emit('DUP_TOP')
7.836 + self.emit('LOAD_ATTR', '__exit__')
7.837 + self._implicitNameOp('STORE', exitvar)
7.838 + self.emit('LOAD_ATTR', '__enter__')
7.839 + self.emit('CALL_FUNCTION', 0)
7.840 + if node.vars is None:
7.841 + self.emit('POP_TOP')
7.842 + else:
7.843 + self._implicitNameOp('STORE', valuevar)
7.844 + self.emit('SETUP_FINALLY', final)
7.845 + self.nextBlock(body)
7.846 + self.setups.push((TRY_FINALLY, body))
7.847 + if node.vars is not None:
7.848 + self._implicitNameOp('LOAD', valuevar)
7.849 + self._implicitNameOp('DELETE', valuevar)
7.850 + self.visit(node.vars)
7.851 + self.visit(node.body)
7.852 + self.emit('POP_BLOCK')
7.853 + self.setups.pop()
7.854 + self.emit('LOAD_CONST', None)
7.855 + self.nextBlock(final)
7.856 + self.setups.push((END_FINALLY, final))
7.857 + self._implicitNameOp('LOAD', exitvar)
7.858 + self._implicitNameOp('DELETE', exitvar)
7.859 + self.emit('WITH_CLEANUP')
7.860 + self.emit('END_FINALLY')
7.861 + self.setups.pop()
7.862 + self.__with_count -= 1
7.863 +
7.864 + # misc
7.865 +
7.866 + def visitDiscard(self, node):
7.867 + self.set_lineno(node)
7.868 + self.visit(node.expr)
7.869 + self.emit('POP_TOP')
7.870 +
7.871 + def visitConst(self, node):
7.872 + self.emit('LOAD_CONST', node.value)
7.873 +
7.874 + def visitKeyword(self, node):
7.875 + self.emit('LOAD_CONST', node.name)
7.876 + self.visit(node.expr)
7.877 +
7.878 + def visitGlobal(self, node):
7.879 + # no code to generate
7.880 + pass
7.881 +
7.882 + def visitName(self, node):
7.883 + self.set_lineno(node)
7.884 + self.loadName(node.name)
7.885 +
7.886 + def visitPass(self, node):
7.887 + self.set_lineno(node)
7.888 +
7.889 + def visitImport(self, node):
7.890 + self.set_lineno(node)
7.891 + level = 0 if self.graph.checkFlag(CO_FUTURE_ABSIMPORT) else -1
7.892 + for name, alias in node.names:
7.893 + if VERSION > 1:
7.894 + self.emit('LOAD_CONST', level)
7.895 + self.emit('LOAD_CONST', None)
7.896 + self.emit('IMPORT_NAME', name)
7.897 + mod = name.split(".")[0]
7.898 + if alias:
7.899 + self._resolveDots(name)
7.900 + self.storeName(alias)
7.901 + else:
7.902 + self.storeName(mod)
7.903 +
7.904 + def visitFrom(self, node):
7.905 + self.set_lineno(node)
7.906 + level = node.level
7.907 + if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT):
7.908 + level = -1
7.909 + fromlist = map(lambda (name, alias): name, node.names)
7.910 + if VERSION > 1:
7.911 + self.emit('LOAD_CONST', level)
7.912 + self.emit('LOAD_CONST', tuple(fromlist))
7.913 + self.emit('IMPORT_NAME', node.modname)
7.914 + for name, alias in node.names:
7.915 + if VERSION > 1:
7.916 + if name == '*':
7.917 + self.namespace = 0
7.918 + self.emit('IMPORT_STAR')
7.919 + # There can only be one name w/ from ... import *
7.920 + assert len(node.names) == 1
7.921 + return
7.922 + else:
7.923 + self.emit('IMPORT_FROM', name)
7.924 + self._resolveDots(name)
7.925 + self.storeName(alias or name)
7.926 + else:
7.927 + self.emit('IMPORT_FROM', name)
7.928 + self.emit('POP_TOP')
7.929 +
7.930 + def _resolveDots(self, name):
7.931 + elts = name.split(".")
7.932 + if len(elts) == 1:
7.933 + return
7.934 + for elt in elts[1:]:
7.935 + self.emit('LOAD_ATTR', elt)
7.936 +
7.937 + def visitGetattr(self, node):
7.938 + self.visit(node.expr)
7.939 + self.emit('LOAD_ATTR', self.mangle(node.attrname))
7.940 +
7.941 + # next five implement assignments
7.942 +
7.943 + def visitAssign(self, node):
7.944 + self.set_lineno(node)
7.945 + self.visit(node.expr)
7.946 + dups = len(node.nodes) - 1
7.947 + for i in range(len(node.nodes)):
7.948 + elt = node.nodes[i]
7.949 + if i < dups:
7.950 + self.emit('DUP_TOP')
7.951 + if isinstance(elt, ast.Node):
7.952 + self.visit(elt)
7.953 +
7.954 + def visitAssName(self, node):
7.955 + if node.flags == 'OP_ASSIGN':
7.956 + self.storeName(node.name)
7.957 + elif node.flags == 'OP_DELETE':
7.958 + self.set_lineno(node)
7.959 + self.delName(node.name)
7.960 + else:
7.961 + print "oops", node.flags
7.962 +
7.963 + def visitAssAttr(self, node):
7.964 + self.visit(node.expr)
7.965 + if node.flags == 'OP_ASSIGN':
7.966 + self.emit('STORE_ATTR', self.mangle(node.attrname))
7.967 + elif node.flags == 'OP_DELETE':
7.968 + self.emit('DELETE_ATTR', self.mangle(node.attrname))
7.969 + else:
7.970 + print "warning: unexpected flags:", node.flags
7.971 + print node
7.972 +
7.973 + def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
7.974 + if findOp(node) != 'OP_DELETE':
7.975 + self.emit(op, len(node.nodes))
7.976 + for child in node.nodes:
7.977 + self.visit(child)
7.978 +
7.979 + if VERSION > 1:
7.980 + visitAssTuple = _visitAssSequence
7.981 + visitAssList = _visitAssSequence
7.982 + else:
7.983 + def visitAssTuple(self, node):
7.984 + self._visitAssSequence(node, 'UNPACK_TUPLE')
7.985 +
7.986 + def visitAssList(self, node):
7.987 + self._visitAssSequence(node, 'UNPACK_LIST')
7.988 +
7.989 + # augmented assignment
7.990 +
7.991 + def visitAugAssign(self, node):
7.992 + self.set_lineno(node)
7.993 + aug_node = wrap_aug(node.node)
7.994 + self.visit(aug_node, "load")
7.995 + self.visit(node.expr)
7.996 + self.emit(self._augmented_opcode[node.op])
7.997 + self.visit(aug_node, "store")
7.998 +
7.999 + _augmented_opcode = {
7.1000 + '+=' : 'INPLACE_ADD',
7.1001 + '-=' : 'INPLACE_SUBTRACT',
7.1002 + '*=' : 'INPLACE_MULTIPLY',
7.1003 + '/=' : 'INPLACE_DIVIDE',
7.1004 + '//=': 'INPLACE_FLOOR_DIVIDE',
7.1005 + '%=' : 'INPLACE_MODULO',
7.1006 + '**=': 'INPLACE_POWER',
7.1007 + '>>=': 'INPLACE_RSHIFT',
7.1008 + '<<=': 'INPLACE_LSHIFT',
7.1009 + '&=' : 'INPLACE_AND',
7.1010 + '^=' : 'INPLACE_XOR',
7.1011 + '|=' : 'INPLACE_OR',
7.1012 + }
7.1013 +
7.1014 + def visitAugName(self, node, mode):
7.1015 + if mode == "load":
7.1016 + self.loadName(node.name)
7.1017 + elif mode == "store":
7.1018 + self.storeName(node.name)
7.1019 +
7.1020 + def visitAugGetattr(self, node, mode):
7.1021 + if mode == "load":
7.1022 + self.visit(node.expr)
7.1023 + self.emit('DUP_TOP')
7.1024 + self.emit('LOAD_ATTR', self.mangle(node.attrname))
7.1025 + elif mode == "store":
7.1026 + self.emit('ROT_TWO')
7.1027 + self.emit('STORE_ATTR', self.mangle(node.attrname))
7.1028 +
7.1029 + def visitAugSlice(self, node, mode):
7.1030 + if mode == "load":
7.1031 + self.visitSlice(node, 1)
7.1032 + elif mode == "store":
7.1033 + slice = 0
7.1034 + if node.lower:
7.1035 + slice = slice | 1
7.1036 + if node.upper:
7.1037 + slice = slice | 2
7.1038 + if slice == 0:
7.1039 + self.emit('ROT_TWO')
7.1040 + elif slice == 3:
7.1041 + self.emit('ROT_FOUR')
7.1042 + else:
7.1043 + self.emit('ROT_THREE')
7.1044 + self.emit('STORE_SLICE+%d' % slice)
7.1045 +
7.1046 + def visitAugSubscript(self, node, mode):
7.1047 + if mode == "load":
7.1048 + self.visitSubscript(node, 1)
7.1049 + elif mode == "store":
7.1050 + self.emit('ROT_THREE')
7.1051 + self.emit('STORE_SUBSCR')
7.1052 +
7.1053 + def visitExec(self, node):
7.1054 + self.visit(node.expr)
7.1055 + if node.locals is None:
7.1056 + self.emit('LOAD_CONST', None)
7.1057 + else:
7.1058 + self.visit(node.locals)
7.1059 + if node.globals is None:
7.1060 + self.emit('DUP_TOP')
7.1061 + else:
7.1062 + self.visit(node.globals)
7.1063 + self.emit('EXEC_STMT')
7.1064 +
7.1065 + def visitCallFunc(self, node):
7.1066 + pos = 0
7.1067 + kw = 0
7.1068 + self.set_lineno(node)
7.1069 + self.visit(node.node)
7.1070 + for arg in node.args:
7.1071 + self.visit(arg)
7.1072 + if isinstance(arg, ast.Keyword):
7.1073 + kw = kw + 1
7.1074 + else:
7.1075 + pos = pos + 1
7.1076 + if node.star_args is not None:
7.1077 + self.visit(node.star_args)
7.1078 + if node.dstar_args is not None:
7.1079 + self.visit(node.dstar_args)
7.1080 + have_star = node.star_args is not None
7.1081 + have_dstar = node.dstar_args is not None
7.1082 + opcode = callfunc_opcode_info[have_star, have_dstar]
7.1083 + self.emit(opcode, kw << 8 | pos)
7.1084 +
7.1085 + def visitPrint(self, node, newline=0):
7.1086 + self.set_lineno(node)
7.1087 + if node.dest:
7.1088 + self.visit(node.dest)
7.1089 + for child in node.nodes:
7.1090 + if node.dest:
7.1091 + self.emit('DUP_TOP')
7.1092 + self.visit(child)
7.1093 + if node.dest:
7.1094 + self.emit('ROT_TWO')
7.1095 + self.emit('PRINT_ITEM_TO')
7.1096 + else:
7.1097 + self.emit('PRINT_ITEM')
7.1098 + if node.dest and not newline:
7.1099 + self.emit('POP_TOP')
7.1100 +
7.1101 + def visitPrintnl(self, node):
7.1102 + self.visitPrint(node, newline=1)
7.1103 + if node.dest:
7.1104 + self.emit('PRINT_NEWLINE_TO')
7.1105 + else:
7.1106 + self.emit('PRINT_NEWLINE')
7.1107 +
7.1108 + def visitReturn(self, node):
7.1109 + self.set_lineno(node)
7.1110 + self.visit(node.value)
7.1111 + self.emit('RETURN_VALUE')
7.1112 +
7.1113 + def visitYield(self, node):
7.1114 + self.set_lineno(node)
7.1115 + self.visit(node.value)
7.1116 + self.emit('YIELD_VALUE')
7.1117 +
7.1118 + # slice and subscript stuff
7.1119 +
7.1120 + def visitSlice(self, node, aug_flag=None):
7.1121 + # aug_flag is used by visitAugSlice
7.1122 + self.visit(node.expr)
7.1123 + slice = 0
7.1124 + if node.lower:
7.1125 + self.visit(node.lower)
7.1126 + slice = slice | 1
7.1127 + if node.upper:
7.1128 + self.visit(node.upper)
7.1129 + slice = slice | 2
7.1130 + if aug_flag:
7.1131 + if slice == 0:
7.1132 + self.emit('DUP_TOP')
7.1133 + elif slice == 3:
7.1134 + self.emit('DUP_TOPX', 3)
7.1135 + else:
7.1136 + self.emit('DUP_TOPX', 2)
7.1137 + if node.flags == 'OP_APPLY':
7.1138 + self.emit('SLICE+%d' % slice)
7.1139 + elif node.flags == 'OP_ASSIGN':
7.1140 + self.emit('STORE_SLICE+%d' % slice)
7.1141 + elif node.flags == 'OP_DELETE':
7.1142 + self.emit('DELETE_SLICE+%d' % slice)
7.1143 + else:
7.1144 + print "weird slice", node.flags
7.1145 + raise
7.1146 +
7.1147 + def visitSubscript(self, node, aug_flag=None):
7.1148 + self.visit(node.expr)
7.1149 + for sub in node.subs:
7.1150 + self.visit(sub)
7.1151 + if len(node.subs) > 1:
7.1152 + self.emit('BUILD_TUPLE', len(node.subs))
7.1153 + if aug_flag:
7.1154 + self.emit('DUP_TOPX', 2)
7.1155 + if node.flags == 'OP_APPLY':
7.1156 + self.emit('BINARY_SUBSCR')
7.1157 + elif node.flags == 'OP_ASSIGN':
7.1158 + self.emit('STORE_SUBSCR')
7.1159 + elif node.flags == 'OP_DELETE':
7.1160 + self.emit('DELETE_SUBSCR')
7.1161 +
7.1162 + # binary ops
7.1163 +
7.1164 + def binaryOp(self, node, op):
7.1165 + self.visit(node.left)
7.1166 + self.visit(node.right)
7.1167 + self.emit(op)
7.1168 +
7.1169 + def visitAdd(self, node):
7.1170 + return self.binaryOp(node, 'BINARY_ADD')
7.1171 +
7.1172 + def visitSub(self, node):
7.1173 + return self.binaryOp(node, 'BINARY_SUBTRACT')
7.1174 +
7.1175 + def visitMul(self, node):
7.1176 + return self.binaryOp(node, 'BINARY_MULTIPLY')
7.1177 +
7.1178 + def visitDiv(self, node):
7.1179 + return self.binaryOp(node, self._div_op)
7.1180 +
7.1181 + def visitFloorDiv(self, node):
7.1182 + return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
7.1183 +
7.1184 + def visitMod(self, node):
7.1185 + return self.binaryOp(node, 'BINARY_MODULO')
7.1186 +
7.1187 + def visitPower(self, node):
7.1188 + return self.binaryOp(node, 'BINARY_POWER')
7.1189 +
7.1190 + def visitLeftShift(self, node):
7.1191 + return self.binaryOp(node, 'BINARY_LSHIFT')
7.1192 +
7.1193 + def visitRightShift(self, node):
7.1194 + return self.binaryOp(node, 'BINARY_RSHIFT')
7.1195 +
7.1196 + # unary ops
7.1197 +
7.1198 + def unaryOp(self, node, op):
7.1199 + self.visit(node.expr)
7.1200 + self.emit(op)
7.1201 +
7.1202 + def visitInvert(self, node):
7.1203 + return self.unaryOp(node, 'UNARY_INVERT')
7.1204 +
7.1205 + def visitUnarySub(self, node):
7.1206 + return self.unaryOp(node, 'UNARY_NEGATIVE')
7.1207 +
7.1208 + def visitUnaryAdd(self, node):
7.1209 + return self.unaryOp(node, 'UNARY_POSITIVE')
7.1210 +
7.1211 + def visitUnaryInvert(self, node):
7.1212 + return self.unaryOp(node, 'UNARY_INVERT')
7.1213 +
7.1214 + def visitNot(self, node):
7.1215 + return self.unaryOp(node, 'UNARY_NOT')
7.1216 +
7.1217 + def visitBackquote(self, node):
7.1218 + return self.unaryOp(node, 'UNARY_CONVERT')
7.1219 +
7.1220 + # bit ops
7.1221 +
7.1222 + def bitOp(self, nodes, op):
7.1223 + self.visit(nodes[0])
7.1224 + for node in nodes[1:]:
7.1225 + self.visit(node)
7.1226 + self.emit(op)
7.1227 +
7.1228 + def visitBitand(self, node):
7.1229 + return self.bitOp(node.nodes, 'BINARY_AND')
7.1230 +
7.1231 + def visitBitor(self, node):
7.1232 + return self.bitOp(node.nodes, 'BINARY_OR')
7.1233 +
7.1234 + def visitBitxor(self, node):
7.1235 + return self.bitOp(node.nodes, 'BINARY_XOR')
7.1236 +
7.1237 + # object constructors
7.1238 +
7.1239 + def visitEllipsis(self, node):
7.1240 + self.emit('LOAD_CONST', Ellipsis)
7.1241 +
7.1242 + def visitTuple(self, node):
7.1243 + self.set_lineno(node)
7.1244 + for elt in node.nodes:
7.1245 + self.visit(elt)
7.1246 + self.emit('BUILD_TUPLE', len(node.nodes))
7.1247 +
7.1248 + def visitList(self, node):
7.1249 + self.set_lineno(node)
7.1250 + for elt in node.nodes:
7.1251 + self.visit(elt)
7.1252 + self.emit('BUILD_LIST', len(node.nodes))
7.1253 +
7.1254 + def visitSliceobj(self, node):
7.1255 + for child in node.nodes:
7.1256 + self.visit(child)
7.1257 + self.emit('BUILD_SLICE', len(node.nodes))
7.1258 +
7.1259 + def visitDict(self, node):
7.1260 + self.set_lineno(node)
7.1261 + self.emit('BUILD_MAP', 0)
7.1262 + for k, v in node.items:
7.1263 + self.emit('DUP_TOP')
7.1264 + self.visit(k)
7.1265 + self.visit(v)
7.1266 + self.emit('ROT_THREE')
7.1267 + self.emit('STORE_SUBSCR')
7.1268 +
7.1269 +class NestedScopeMixin:
7.1270 + """Defines initClass() for nested scoping (Python 2.2-compatible)"""
7.1271 + def initClass(self):
7.1272 + self.__class__.NameFinder = LocalNameFinder
7.1273 + self.__class__.FunctionGen = FunctionCodeGenerator
7.1274 + self.__class__.ClassGen = ClassCodeGenerator
7.1275 +
7.1276 +class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
7.1277 + __super_init = CodeGenerator.__init__
7.1278 +
7.1279 + scopes = None
7.1280 +
7.1281 + def __init__(self, tree):
7.1282 + self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
7.1283 + self.futures = future.find_futures(tree)
7.1284 + self.__super_init()
7.1285 + walk(tree, self)
7.1286 +
7.1287 + def get_module(self):
7.1288 + return self
7.1289 +
7.1290 +class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
7.1291 + __super_init = CodeGenerator.__init__
7.1292 +
7.1293 + scopes = None
7.1294 + futures = ()
7.1295 +
7.1296 + def __init__(self, tree):
7.1297 + self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
7.1298 + self.__super_init()
7.1299 + walk(tree, self)
7.1300 +
7.1301 + def get_module(self):
7.1302 + return self
7.1303 +
7.1304 +class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
7.1305 +
7.1306 + __super_init = CodeGenerator.__init__
7.1307 +
7.1308 + scopes = None
7.1309 + futures = ()
7.1310 +
7.1311 + def __init__(self, tree):
7.1312 + self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
7.1313 + self.__super_init()
7.1314 + self.set_lineno(tree)
7.1315 + walk(tree, self)
7.1316 + self.emit('RETURN_VALUE')
7.1317 +
7.1318 + def get_module(self):
7.1319 + return self
7.1320 +
7.1321 + def visitDiscard(self, node):
7.1322 + # XXX Discard means it's an expression. Perhaps this is a bad
7.1323 + # name.
7.1324 + self.visit(node.expr)
7.1325 + self.emit('PRINT_EXPR')
7.1326 +
7.1327 +class AbstractFunctionCode:
7.1328 + optimized = 1
7.1329 + lambdaCount = 0
7.1330 +
7.1331 + def __init__(self, func, scopes, isLambda, class_name, mod):
7.1332 + self.class_name = class_name
7.1333 + self.module = mod
7.1334 + if isLambda:
7.1335 + klass = FunctionCodeGenerator
7.1336 + name = "<lambda.%d>" % klass.lambdaCount
7.1337 + klass.lambdaCount = klass.lambdaCount + 1
7.1338 + else:
7.1339 + name = func.name
7.1340 +
7.1341 + args, hasTupleArg = generateArgList(func.argnames)
7.1342 + self.graph = pyassem.PyFlowGraph(name, func.filename, args,
7.1343 + optimized=1)
7.1344 + self.isLambda = isLambda
7.1345 + self.super_init()
7.1346 +
7.1347 + if not isLambda and func.doc:
7.1348 + self.setDocstring(func.doc)
7.1349 +
7.1350 + lnf = walk(func.code, self.NameFinder(args), verbose=0)
7.1351 + self.locals.push(lnf.getLocals())
7.1352 + if func.varargs:
7.1353 + self.graph.setFlag(CO_VARARGS)
7.1354 + if func.kwargs:
7.1355 + self.graph.setFlag(CO_VARKEYWORDS)
7.1356 + self.set_lineno(func)
7.1357 + if hasTupleArg:
7.1358 + self.generateArgUnpack(func.argnames)
7.1359 +
7.1360 + def get_module(self):
7.1361 + return self.module
7.1362 +
7.1363 + def finish(self):
7.1364 + self.graph.startExitBlock()
7.1365 + if not self.isLambda:
7.1366 + self.emit('LOAD_CONST', None)
7.1367 + self.emit('RETURN_VALUE')
7.1368 +
7.1369 + def generateArgUnpack(self, args):
7.1370 + for i in range(len(args)):
7.1371 + arg = args[i]
7.1372 + if isinstance(arg, tuple):
7.1373 + self.emit('LOAD_FAST', '.%d' % (i * 2))
7.1374 + self.unpackSequence(arg)
7.1375 +
7.1376 + def unpackSequence(self, tup):
7.1377 + if VERSION > 1:
7.1378 + self.emit('UNPACK_SEQUENCE', len(tup))
7.1379 + else:
7.1380 + self.emit('UNPACK_TUPLE', len(tup))
7.1381 + for elt in tup:
7.1382 + if isinstance(elt, tuple):
7.1383 + self.unpackSequence(elt)
7.1384 + else:
7.1385 + self._nameOp('STORE', elt)
7.1386 +
7.1387 + unpackTuple = unpackSequence
7.1388 +
7.1389 +class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
7.1390 + CodeGenerator):
7.1391 + super_init = CodeGenerator.__init__ # call be other init
7.1392 + scopes = None
7.1393 +
7.1394 + __super_init = AbstractFunctionCode.__init__
7.1395 +
7.1396 + def __init__(self, func, scopes, isLambda, class_name, mod):
7.1397 + self.scopes = scopes
7.1398 + self.scope = scopes[func]
7.1399 + self.__super_init(func, scopes, isLambda, class_name, mod)
7.1400 + self.graph.setFreeVars(self.scope.get_free_vars())
7.1401 + self.graph.setCellVars(self.scope.get_cell_vars())
7.1402 + if self.scope.generator is not None:
7.1403 + self.graph.setFlag(CO_GENERATOR)
7.1404 +
7.1405 +class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
7.1406 + CodeGenerator):
7.1407 + super_init = CodeGenerator.__init__ # call be other init
7.1408 + scopes = None
7.1409 +
7.1410 + __super_init = AbstractFunctionCode.__init__
7.1411 +
7.1412 + def __init__(self, gexp, scopes, class_name, mod):
7.1413 + self.scopes = scopes
7.1414 + self.scope = scopes[gexp]
7.1415 + self.__super_init(gexp, scopes, 1, class_name, mod)
7.1416 + self.graph.setFreeVars(self.scope.get_free_vars())
7.1417 + self.graph.setCellVars(self.scope.get_cell_vars())
7.1418 + self.graph.setFlag(CO_GENERATOR)
7.1419 +
7.1420 +class AbstractClassCode:
7.1421 +
7.1422 + def __init__(self, klass, scopes, module):
7.1423 + self.class_name = klass.name
7.1424 + self.module = module
7.1425 + self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
7.1426 + optimized=0, klass=1)
7.1427 + self.super_init()
7.1428 + lnf = walk(klass.code, self.NameFinder(), verbose=0)
7.1429 + self.locals.push(lnf.getLocals())
7.1430 + self.graph.setFlag(CO_NEWLOCALS)
7.1431 + if klass.doc:
7.1432 + self.setDocstring(klass.doc)
7.1433 +
7.1434 + def get_module(self):
7.1435 + return self.module
7.1436 +
7.1437 + def finish(self):
7.1438 + self.graph.startExitBlock()
7.1439 + self.emit('LOAD_LOCALS')
7.1440 + self.emit('RETURN_VALUE')
7.1441 +
7.1442 +class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
7.1443 + super_init = CodeGenerator.__init__
7.1444 + scopes = None
7.1445 +
7.1446 + __super_init = AbstractClassCode.__init__
7.1447 +
7.1448 + def __init__(self, klass, scopes, module):
7.1449 + self.scopes = scopes
7.1450 + self.scope = scopes[klass]
7.1451 + self.__super_init(klass, scopes, module)
7.1452 + self.graph.setFreeVars(self.scope.get_free_vars())
7.1453 + self.graph.setCellVars(self.scope.get_cell_vars())
7.1454 + self.set_lineno(klass)
7.1455 + self.emit("LOAD_GLOBAL", "__name__")
7.1456 + self.storeName("__module__")
7.1457 + if klass.doc:
7.1458 + self.emit("LOAD_CONST", klass.doc)
7.1459 + self.storeName('__doc__')
7.1460 +
7.1461 +def generateArgList(arglist):
7.1462 + """Generate an arg list marking TupleArgs"""
7.1463 + args = []
7.1464 + extra = []
7.1465 + count = 0
7.1466 + for i in range(len(arglist)):
7.1467 + elt = arglist[i]
7.1468 + if isinstance(elt, str):
7.1469 + args.append(elt)
7.1470 + elif isinstance(elt, tuple):
7.1471 + args.append(TupleArg(i * 2, elt))
7.1472 + extra.extend(misc.flatten(elt))
7.1473 + count = count + 1
7.1474 + else:
7.1475 + raise ValueError, "unexpect argument type:", elt
7.1476 + return args + extra, count
7.1477 +
7.1478 +def findOp(node):
7.1479 + """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
7.1480 + v = OpFinder()
7.1481 + walk(node, v, verbose=0)
7.1482 + return v.op
7.1483 +
7.1484 +class OpFinder:
7.1485 + def __init__(self):
7.1486 + self.op = None
7.1487 + def visitAssName(self, node):
7.1488 + if self.op is None:
7.1489 + self.op = node.flags
7.1490 + elif self.op != node.flags:
7.1491 + raise ValueError, "mixed ops in stmt"
7.1492 + visitAssAttr = visitAssName
7.1493 + visitSubscript = visitAssName
7.1494 +
7.1495 +class Delegator:
7.1496 + """Base class to support delegation for augmented assignment nodes
7.1497 +
7.1498 + To generator code for augmented assignments, we use the following
7.1499 + wrapper classes. In visitAugAssign, the left-hand expression node
7.1500 + is visited twice. The first time the visit uses the normal method
7.1501 + for that node . The second time the visit uses a different method
7.1502 + that generates the appropriate code to perform the assignment.
7.1503 + These delegator classes wrap the original AST nodes in order to
7.1504 + support the variant visit methods.
7.1505 + """
7.1506 + def __init__(self, obj):
7.1507 + self.obj = obj
7.1508 +
7.1509 + def __getattr__(self, attr):
7.1510 + return getattr(self.obj, attr)
7.1511 +
7.1512 +class AugGetattr(Delegator):
7.1513 + pass
7.1514 +
7.1515 +class AugName(Delegator):
7.1516 + pass
7.1517 +
7.1518 +class AugSlice(Delegator):
7.1519 + pass
7.1520 +
7.1521 +class AugSubscript(Delegator):
7.1522 + pass
7.1523 +
7.1524 +wrapper = {
7.1525 + ast.Getattr: AugGetattr,
7.1526 + ast.Name: AugName,
7.1527 + ast.Slice: AugSlice,
7.1528 + ast.Subscript: AugSubscript,
7.1529 + }
7.1530 +
7.1531 +def wrap_aug(node):
7.1532 + return wrapper[node.__class__](node)
7.1533 +
7.1534 +if __name__ == "__main__":
7.1535 + for file in sys.argv[1:]:
7.1536 + compileFile(file)
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/compiler/symbols.py Tue May 01 22:04:53 2012 +0200
8.3 @@ -0,0 +1,463 @@
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 self.uses.has_key(name) or self.defs.has_key(name):
8.56 + pass # XXX warn about global following def/use
8.57 + if self.params.has_key(name):
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 self.globals.has_key(name):
8.95 + return SC_GLOBAL
8.96 + if self.cells.has_key(name):
8.97 + return SC_CELL
8.98 + if self.defs.has_key(name):
8.99 + return SC_LOCAL
8.100 + if self.nested and (self.frees.has_key(name) or
8.101 + self.uses.has_key(name)):
8.102 + return SC_FREE
8.103 + if self.nested:
8.104 + return SC_UNKNOWN
8.105 + else:
8.106 + return SC_GLOBAL
8.107 +
8.108 + def get_free_vars(self):
8.109 + if not self.nested:
8.110 + return ()
8.111 + free = {}
8.112 + free.update(self.frees)
8.113 + for name in self.uses.keys():
8.114 + if not (self.defs.has_key(name) or
8.115 + self.globals.has_key(name)):
8.116 + free[name] = 1
8.117 + return free.keys()
8.118 +
8.119 + def handle_children(self):
8.120 + for child in self.children:
8.121 + frees = child.get_free_vars()
8.122 + globals = self.add_frees(frees)
8.123 + for name in globals:
8.124 + child.force_global(name)
8.125 +
8.126 + def force_global(self, name):
8.127 + """Force name to be global in scope.
8.128 +
8.129 + Some child of the current node had a free reference to name.
8.130 + When the child was processed, it was labelled a free
8.131 + variable. Now that all its enclosing scope have been
8.132 + processed, the name is known to be a global or builtin. So
8.133 + walk back down the child chain and set the name to be global
8.134 + rather than free.
8.135 +
8.136 + Be careful to stop if a child does not think the name is
8.137 + free.
8.138 + """
8.139 + self.globals[name] = 1
8.140 + if self.frees.has_key(name):
8.141 + del self.frees[name]
8.142 + for child in self.children:
8.143 + if child.check_name(name) == SC_FREE:
8.144 + child.force_global(name)
8.145 +
8.146 + def add_frees(self, names):
8.147 + """Process list of free vars from nested scope.
8.148 +
8.149 + Returns a list of names that are either 1) declared global in the
8.150 + parent or 2) undefined in a top-level parent. In either case,
8.151 + the nested scope should treat them as globals.
8.152 + """
8.153 + child_globals = []
8.154 + for name in names:
8.155 + sc = self.check_name(name)
8.156 + if self.nested:
8.157 + if sc == SC_UNKNOWN or sc == SC_FREE \
8.158 + or isinstance(self, ClassScope):
8.159 + self.frees[name] = 1
8.160 + elif sc == SC_GLOBAL:
8.161 + child_globals.append(name)
8.162 + elif isinstance(self, FunctionScope) and sc == SC_LOCAL:
8.163 + self.cells[name] = 1
8.164 + elif sc != SC_CELL:
8.165 + child_globals.append(name)
8.166 + else:
8.167 + if sc == SC_LOCAL:
8.168 + self.cells[name] = 1
8.169 + elif sc != SC_CELL:
8.170 + child_globals.append(name)
8.171 + return child_globals
8.172 +
8.173 + def get_cell_vars(self):
8.174 + return self.cells.keys()
8.175 +
8.176 +class ModuleScope(Scope):
8.177 + __super_init = Scope.__init__
8.178 +
8.179 + def __init__(self):
8.180 + self.__super_init("global", self)
8.181 +
8.182 +class FunctionScope(Scope):
8.183 + pass
8.184 +
8.185 +class GenExprScope(Scope):
8.186 + __super_init = Scope.__init__
8.187 +
8.188 + __counter = 1
8.189 +
8.190 + def __init__(self, module, klass=None):
8.191 + i = self.__counter
8.192 + self.__counter += 1
8.193 + self.__super_init("generator expression<%d>"%i, module, klass)
8.194 + self.add_param('.0')
8.195 +
8.196 + def get_names(self):
8.197 + keys = Scope.get_names(self)
8.198 + return keys
8.199 +
8.200 +class LambdaScope(FunctionScope):
8.201 + __super_init = Scope.__init__
8.202 +
8.203 + __counter = 1
8.204 +
8.205 + def __init__(self, module, klass=None):
8.206 + i = self.__counter
8.207 + self.__counter += 1
8.208 + self.__super_init("lambda.%d" % i, module, klass)
8.209 +
8.210 +class ClassScope(Scope):
8.211 + __super_init = Scope.__init__
8.212 +
8.213 + def __init__(self, name, module):
8.214 + self.__super_init(name, module, name)
8.215 +
8.216 +class SymbolVisitor:
8.217 + def __init__(self):
8.218 + self.scopes = {}
8.219 + self.klass = None
8.220 +
8.221 + # node that define new scopes
8.222 +
8.223 + def visitModule(self, node):
8.224 + scope = self.module = self.scopes[node] = ModuleScope()
8.225 + self.visit(node.node, scope)
8.226 +
8.227 + visitExpression = visitModule
8.228 +
8.229 + def visitFunction(self, node, parent):
8.230 + if node.decorators:
8.231 + self.visit(node.decorators, parent)
8.232 + parent.add_def(node.name)
8.233 + for n in node.defaults:
8.234 + self.visit(n, parent)
8.235 + scope = FunctionScope(node.name, self.module, self.klass)
8.236 + if parent.nested or isinstance(parent, FunctionScope):
8.237 + scope.nested = 1
8.238 + self.scopes[node] = scope
8.239 + self._do_args(scope, node.argnames)
8.240 + self.visit(node.code, scope)
8.241 + self.handle_free_vars(scope, parent)
8.242 +
8.243 + def visitGenExpr(self, node, parent):
8.244 + scope = GenExprScope(self.module, self.klass);
8.245 + if parent.nested or isinstance(parent, FunctionScope) \
8.246 + or isinstance(parent, GenExprScope):
8.247 + scope.nested = 1
8.248 +
8.249 + self.scopes[node] = scope
8.250 + self.visit(node.code, scope)
8.251 +
8.252 + self.handle_free_vars(scope, parent)
8.253 +
8.254 + def visitGenExprInner(self, node, scope):
8.255 + for genfor in node.quals:
8.256 + self.visit(genfor, scope)
8.257 +
8.258 + self.visit(node.expr, scope)
8.259 +
8.260 + def visitGenExprFor(self, node, scope):
8.261 + self.visit(node.assign, scope, 1)
8.262 + self.visit(node.iter, scope)
8.263 + for if_ in node.ifs:
8.264 + self.visit(if_, scope)
8.265 +
8.266 + def visitGenExprIf(self, node, scope):
8.267 + self.visit(node.test, scope)
8.268 +
8.269 + def visitLambda(self, node, parent, assign=0):
8.270 + # Lambda is an expression, so it could appear in an expression
8.271 + # context where assign is passed. The transformer should catch
8.272 + # any code that has a lambda on the left-hand side.
8.273 + assert not assign
8.274 +
8.275 + for n in node.defaults:
8.276 + self.visit(n, parent)
8.277 + scope = LambdaScope(self.module, self.klass)
8.278 + if parent.nested or isinstance(parent, FunctionScope):
8.279 + scope.nested = 1
8.280 + self.scopes[node] = scope
8.281 + self._do_args(scope, node.argnames)
8.282 + self.visit(node.code, scope)
8.283 + self.handle_free_vars(scope, parent)
8.284 +
8.285 + def _do_args(self, scope, args):
8.286 + for name in args:
8.287 + if type(name) == types.TupleType:
8.288 + self._do_args(scope, name)
8.289 + else:
8.290 + scope.add_param(name)
8.291 +
8.292 + def handle_free_vars(self, scope, parent):
8.293 + parent.add_child(scope)
8.294 + scope.handle_children()
8.295 +
8.296 + def visitClass(self, node, parent):
8.297 + parent.add_def(node.name)
8.298 + for n in node.bases:
8.299 + self.visit(n, parent)
8.300 + scope = ClassScope(node.name, self.module)
8.301 + if parent.nested or isinstance(parent, FunctionScope):
8.302 + scope.nested = 1
8.303 + if node.doc is not None:
8.304 + scope.add_def('__doc__')
8.305 + scope.add_def('__module__')
8.306 + self.scopes[node] = scope
8.307 + prev = self.klass
8.308 + self.klass = node.name
8.309 + self.visit(node.code, scope)
8.310 + self.klass = prev
8.311 + self.handle_free_vars(scope, parent)
8.312 +
8.313 + # name can be a def or a use
8.314 +
8.315 + # XXX a few calls and nodes expect a third "assign" arg that is
8.316 + # true if the name is being used as an assignment. only
8.317 + # expressions contained within statements may have the assign arg.
8.318 +
8.319 + def visitName(self, node, scope, assign=0):
8.320 + if assign:
8.321 + scope.add_def(node.name)
8.322 + else:
8.323 + scope.add_use(node.name)
8.324 +
8.325 + # operations that bind new names
8.326 +
8.327 + def visitFor(self, node, scope):
8.328 + self.visit(node.assign, scope, 1)
8.329 + self.visit(node.list, scope)
8.330 + self.visit(node.body, scope)
8.331 + if node.else_:
8.332 + self.visit(node.else_, scope)
8.333 +
8.334 + def visitFrom(self, node, scope):
8.335 + for name, asname in node.names:
8.336 + if name == "*":
8.337 + continue
8.338 + scope.add_def(asname or name)
8.339 +
8.340 + def visitImport(self, node, scope):
8.341 + for name, asname in node.names:
8.342 + i = name.find(".")
8.343 + if i > -1:
8.344 + name = name[:i]
8.345 + scope.add_def(asname or name)
8.346 +
8.347 + def visitGlobal(self, node, scope):
8.348 + for name in node.names:
8.349 + scope.add_global(name)
8.350 +
8.351 + def visitAssign(self, node, scope):
8.352 + """Propagate assignment flag down to child nodes.
8.353 +
8.354 + The Assign node doesn't itself contains the variables being
8.355 + assigned to. Instead, the children in node.nodes are visited
8.356 + with the assign flag set to true. When the names occur in
8.357 + those nodes, they are marked as defs.
8.358 +
8.359 + Some names that occur in an assignment target are not bound by
8.360 + the assignment, e.g. a name occurring inside a slice. The
8.361 + visitor handles these nodes specially; they do not propagate
8.362 + the assign flag to their children.
8.363 + """
8.364 + for n in node.nodes:
8.365 + self.visit(n, scope, 1)
8.366 + self.visit(node.expr, scope)
8.367 +
8.368 + def visitAssName(self, node, scope, assign=1):
8.369 + scope.add_def(node.name)
8.370 +
8.371 + def visitAssAttr(self, node, scope, assign=0):
8.372 + self.visit(node.expr, scope, 0)
8.373 +
8.374 + def visitSubscript(self, node, scope, assign=0):
8.375 + self.visit(node.expr, scope, 0)
8.376 + for n in node.subs:
8.377 + self.visit(n, scope, 0)
8.378 +
8.379 + def visitSlice(self, node, scope, assign=0):
8.380 + self.visit(node.expr, scope, 0)
8.381 + if node.lower:
8.382 + self.visit(node.lower, scope, 0)
8.383 + if node.upper:
8.384 + self.visit(node.upper, scope, 0)
8.385 +
8.386 + def visitAugAssign(self, node, scope):
8.387 + # If the LHS is a name, then this counts as assignment.
8.388 + # Otherwise, it's just use.
8.389 + self.visit(node.node, scope)
8.390 + if isinstance(node.node, ast.Name):
8.391 + self.visit(node.node, scope, 1) # XXX worry about this
8.392 + self.visit(node.expr, scope)
8.393 +
8.394 + # prune if statements if tests are false
8.395 +
8.396 + _const_types = types.StringType, types.IntType, types.FloatType
8.397 +
8.398 + def visitIf(self, node, scope):
8.399 + for test, body in node.tests:
8.400 + if isinstance(test, ast.Const):
8.401 + if type(test.value) in self._const_types:
8.402 + if not test.value:
8.403 + continue
8.404 + self.visit(test, scope)
8.405 + self.visit(body, scope)
8.406 + if node.else_:
8.407 + self.visit(node.else_, scope)
8.408 +
8.409 + # a yield statement signals a generator
8.410 +
8.411 + def visitYield(self, node, scope):
8.412 + scope.generator = 1
8.413 + self.visit(node.value, scope)
8.414 +
8.415 +def list_eq(l1, l2):
8.416 + return sorted(l1) == sorted(l2)
8.417 +
8.418 +if __name__ == "__main__":
8.419 + import sys
8.420 + from compiler import parseFile, walk
8.421 + import symtable
8.422 +
8.423 + def get_names(syms):
8.424 + return [s for s in [s.get_name() for s in syms.get_symbols()]
8.425 + if not (s.startswith('_[') or s.startswith('.'))]
8.426 +
8.427 + for file in sys.argv[1:]:
8.428 + print file
8.429 + f = open(file)
8.430 + buf = f.read()
8.431 + f.close()
8.432 + syms = symtable.symtable(buf, file, "exec")
8.433 + mod_names = get_names(syms)
8.434 + tree = parseFile(file)
8.435 + s = SymbolVisitor()
8.436 + walk(tree, s)
8.437 +
8.438 + # compare module-level symbols
8.439 + names2 = s.scopes[tree].get_names()
8.440 +
8.441 + if not list_eq(mod_names, names2):
8.442 + print
8.443 + print "oops", file
8.444 + print sorted(mod_names)
8.445 + print sorted(names2)
8.446 + sys.exit(-1)
8.447 +
8.448 + d = {}
8.449 + d.update(s.scopes)
8.450 + del d[tree]
8.451 + scopes = d.values()
8.452 + del d
8.453 +
8.454 + for s in syms.get_symbols():
8.455 + if s.is_namespace():
8.456 + l = [sc for sc in scopes
8.457 + if sc.name == s.get_name()]
8.458 + if len(l) > 1:
8.459 + print "skipping", s.get_name()
8.460 + else:
8.461 + if not list_eq(get_names(s.get_namespace()),
8.462 + l[0].get_names()):
8.463 + print s.get_name()
8.464 + print sorted(get_names(s.get_namespace()))
8.465 + print sorted(l[0].get_names())
8.466 + sys.exit(-1)
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/compiler/syntax.py Tue May 01 22:04:53 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 Tue May 01 22:04:53 2012 +0200
10.3 @@ -0,0 +1,1490 @@
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 +import sys
10.36 +
10.37 +class WalkerError(StandardError):
10.38 + pass
10.39 +
10.40 +from compiler.consts import CO_VARARGS, CO_VARKEYWORDS
10.41 +from compiler.consts import OP_ASSIGN, OP_DELETE, OP_APPLY
10.42 +
10.43 +def parseFile(path):
10.44 + f = open(path, "U")
10.45 + # XXX The parser API tolerates files without a trailing newline,
10.46 + # but not strings without a trailing newline. Always add an extra
10.47 + # newline to the file contents, since we're going through the string
10.48 + # version of the API.
10.49 + src = f.read() + "\n"
10.50 + f.close()
10.51 + return parse(src)
10.52 +
10.53 +def parse(buf, mode="exec"):
10.54 + if mode == "exec" or mode == "single":
10.55 + return Transformer().parsesuite(buf)
10.56 + elif mode == "eval":
10.57 + return Transformer().parseexpr(buf)
10.58 + else:
10.59 + raise ValueError("compile() arg 3 must be"
10.60 + " 'exec' or 'eval' or 'single'")
10.61 +
10.62 +def asList(nodes):
10.63 + l = []
10.64 + for item in nodes:
10.65 + if hasattr(item, "asList"):
10.66 + l.append(item.asList())
10.67 + else:
10.68 + if type(item) is type( (None, None) ):
10.69 + l.append(tuple(asList(item)))
10.70 + elif type(item) is type( [] ):
10.71 + l.append(asList(item))
10.72 + else:
10.73 + l.append(item)
10.74 + return l
10.75 +
10.76 +def extractLineNo(ast):
10.77 + if not isinstance(ast[1], tuple):
10.78 + # get a terminal node
10.79 + return ast[2]
10.80 + for child in ast[1:]:
10.81 + if isinstance(child, tuple):
10.82 + lineno = extractLineNo(child)
10.83 + if lineno is not None:
10.84 + return lineno
10.85 +
10.86 +def Node(*args):
10.87 + kind = args[0]
10.88 + if nodes.has_key(kind):
10.89 + try:
10.90 + return nodes[kind](*args[1:])
10.91 + except TypeError:
10.92 + print nodes[kind], len(args), args
10.93 + raise
10.94 + else:
10.95 + raise WalkerError, "Can't find appropriate Node type: %s" % str(args)
10.96 + #return apply(ast.Node, args)
10.97 +
10.98 +class Transformer:
10.99 + """Utility object for transforming Python parse trees.
10.100 +
10.101 + Exposes the following methods:
10.102 + tree = transform(ast_tree)
10.103 + tree = parsesuite(text)
10.104 + tree = parseexpr(text)
10.105 + tree = parsefile(fileob | filename)
10.106 + """
10.107 +
10.108 + def __init__(self):
10.109 + self._dispatch = {}
10.110 + for value, name in symbol.sym_name.items():
10.111 + if hasattr(self, name):
10.112 + self._dispatch[value] = getattr(self, name)
10.113 + self._dispatch[token.NEWLINE] = self.com_NEWLINE
10.114 + self._atom_dispatch = {token.LPAR: self.atom_lpar,
10.115 + token.LSQB: self.atom_lsqb,
10.116 + token.LBRACE: self.atom_lbrace,
10.117 + token.BACKQUOTE: self.atom_backquote,
10.118 + token.NUMBER: self.atom_number,
10.119 + token.STRING: self.atom_string,
10.120 + token.NAME: self.atom_name,
10.121 + }
10.122 + self.encoding = None
10.123 +
10.124 + def transform(self, tree):
10.125 + """Transform an AST into a modified parse tree."""
10.126 + if not (isinstance(tree, tuple) or isinstance(tree, list)):
10.127 + tree = parser.ast2tuple(tree, line_info=1)
10.128 + return self.compile_node(tree)
10.129 +
10.130 + def parsesuite(self, text):
10.131 + """Return a modified parse tree for the given suite text."""
10.132 + return self.transform(parser.suite(text))
10.133 +
10.134 + def parseexpr(self, text):
10.135 + """Return a modified parse tree for the given expression text."""
10.136 + return self.transform(parser.expr(text))
10.137 +
10.138 + def parsefile(self, file):
10.139 + """Return a modified parse tree for the contents of the given file."""
10.140 + if type(file) == type(''):
10.141 + file = open(file)
10.142 + return self.parsesuite(file.read())
10.143 +
10.144 + # --------------------------------------------------------------
10.145 + #
10.146 + # PRIVATE METHODS
10.147 + #
10.148 +
10.149 + def compile_node(self, node):
10.150 + ### emit a line-number node?
10.151 + n = node[0]
10.152 +
10.153 + if n == symbol.encoding_decl:
10.154 + self.encoding = node[2]
10.155 + node = node[1]
10.156 + n = node[0]
10.157 +
10.158 + if n == symbol.single_input:
10.159 + return self.single_input(node[1:])
10.160 + if n == symbol.file_input:
10.161 + return self.file_input(node[1:])
10.162 + if n == symbol.eval_input:
10.163 + return self.eval_input(node[1:])
10.164 + if n == symbol.lambdef:
10.165 + return self.lambdef(node[1:])
10.166 + if n == symbol.funcdef:
10.167 + return self.funcdef(node[1:])
10.168 + if n == symbol.classdef:
10.169 + return self.classdef(node[1:])
10.170 +
10.171 + raise WalkerError, ('unexpected node type', n)
10.172 +
10.173 + def single_input(self, node):
10.174 + ### do we want to do anything about being "interactive" ?
10.175 +
10.176 + # NEWLINE | simple_stmt | compound_stmt NEWLINE
10.177 + n = node[0][0]
10.178 + if n != token.NEWLINE:
10.179 + return self.com_stmt(node[0])
10.180 +
10.181 + return Pass()
10.182 +
10.183 + def file_input(self, nodelist):
10.184 + doc = self.get_docstring(nodelist, symbol.file_input)
10.185 + if doc is not None:
10.186 + i = 1
10.187 + else:
10.188 + i = 0
10.189 + stmts = []
10.190 + for node in nodelist[i:]:
10.191 + if node[0] != token.ENDMARKER and node[0] != token.NEWLINE:
10.192 + self.com_append_stmt(stmts, node)
10.193 + return Module(doc, Stmt(stmts))
10.194 +
10.195 + def eval_input(self, nodelist):
10.196 + # from the built-in function input()
10.197 + ### is this sufficient?
10.198 + return Expression(self.com_node(nodelist[0]))
10.199 +
10.200 + def decorator_name(self, nodelist):
10.201 + listlen = len(nodelist)
10.202 + assert listlen >= 1 and listlen % 2 == 1
10.203 +
10.204 + item = self.atom_name(nodelist)
10.205 + i = 1
10.206 + while i < listlen:
10.207 + assert nodelist[i][0] == token.DOT
10.208 + assert nodelist[i + 1][0] == token.NAME
10.209 + item = Getattr(item, nodelist[i + 1][1])
10.210 + i += 2
10.211 +
10.212 + return item
10.213 +
10.214 + def decorator(self, nodelist):
10.215 + # '@' dotted_name [ '(' [arglist] ')' ]
10.216 + assert len(nodelist) in (3, 5, 6)
10.217 + assert nodelist[0][0] == token.AT
10.218 + assert nodelist[-1][0] == token.NEWLINE
10.219 +
10.220 + assert nodelist[1][0] == symbol.dotted_name
10.221 + funcname = self.decorator_name(nodelist[1][1:])
10.222 +
10.223 + if len(nodelist) > 3:
10.224 + assert nodelist[2][0] == token.LPAR
10.225 + expr = self.com_call_function(funcname, nodelist[3])
10.226 + else:
10.227 + expr = funcname
10.228 +
10.229 + return expr
10.230 +
10.231 + def decorators(self, nodelist):
10.232 + # decorators: decorator ([NEWLINE] decorator)* NEWLINE
10.233 + items = []
10.234 + for dec_nodelist in nodelist:
10.235 + assert dec_nodelist[0] == symbol.decorator
10.236 + items.append(self.decorator(dec_nodelist[1:]))
10.237 + return Decorators(items)
10.238 +
10.239 + def funcdef(self, nodelist):
10.240 + # -6 -5 -4 -3 -2 -1
10.241 + # funcdef: [decorators] 'def' NAME parameters ':' suite
10.242 + # parameters: '(' [varargslist] ')'
10.243 +
10.244 + if len(nodelist) == 6:
10.245 + assert nodelist[0][0] == symbol.decorators
10.246 + decorators = self.decorators(nodelist[0][1:])
10.247 + else:
10.248 + assert len(nodelist) == 5
10.249 + decorators = None
10.250 +
10.251 + lineno = nodelist[-4][2]
10.252 + name = nodelist[-4][1]
10.253 + args = nodelist[-3][2]
10.254 +
10.255 + if args[0] == symbol.varargslist:
10.256 + names, defaults, flags = self.com_arglist(args[1:])
10.257 + else:
10.258 + names = defaults = ()
10.259 + flags = 0
10.260 + doc = self.get_docstring(nodelist[-1])
10.261 +
10.262 + # code for function
10.263 + code = self.com_node(nodelist[-1])
10.264 +
10.265 + if doc is not None:
10.266 + assert isinstance(code, Stmt)
10.267 + assert isinstance(code.nodes[0], Discard)
10.268 + del code.nodes[0]
10.269 + return Function(decorators, name, names, defaults, flags, doc, code,
10.270 + lineno=lineno)
10.271 +
10.272 + def lambdef(self, nodelist):
10.273 + # lambdef: 'lambda' [varargslist] ':' test
10.274 + if nodelist[2][0] == symbol.varargslist:
10.275 + names, defaults, flags = self.com_arglist(nodelist[2][1:])
10.276 + else:
10.277 + names = defaults = ()
10.278 + flags = 0
10.279 +
10.280 + # code for lambda
10.281 + code = self.com_node(nodelist[-1])
10.282 +
10.283 + return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
10.284 + old_lambdef = lambdef
10.285 +
10.286 + def classdef(self, nodelist):
10.287 + # classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
10.288 +
10.289 + name = nodelist[1][1]
10.290 + doc = self.get_docstring(nodelist[-1])
10.291 + if nodelist[2][0] == token.COLON:
10.292 + bases = []
10.293 + elif nodelist[3][0] == token.RPAR:
10.294 + bases = []
10.295 + else:
10.296 + bases = self.com_bases(nodelist[3])
10.297 +
10.298 + # code for class
10.299 + code = self.com_node(nodelist[-1])
10.300 +
10.301 + if doc is not None:
10.302 + assert isinstance(code, Stmt)
10.303 + assert isinstance(code.nodes[0], Discard)
10.304 + del code.nodes[0]
10.305 +
10.306 + return Class(name, bases, doc, code, lineno=nodelist[1][2])
10.307 +
10.308 + def stmt(self, nodelist):
10.309 + return self.com_stmt(nodelist[0])
10.310 +
10.311 + small_stmt = stmt
10.312 + flow_stmt = stmt
10.313 + compound_stmt = stmt
10.314 +
10.315 + def simple_stmt(self, nodelist):
10.316 + # small_stmt (';' small_stmt)* [';'] NEWLINE
10.317 + stmts = []
10.318 + for i in range(0, len(nodelist), 2):
10.319 + self.com_append_stmt(stmts, nodelist[i])
10.320 + return Stmt(stmts)
10.321 +
10.322 + def parameters(self, nodelist):
10.323 + raise WalkerError
10.324 +
10.325 + def varargslist(self, nodelist):
10.326 + raise WalkerError
10.327 +
10.328 + def fpdef(self, nodelist):
10.329 + raise WalkerError
10.330 +
10.331 + def fplist(self, nodelist):
10.332 + raise WalkerError
10.333 +
10.334 + def dotted_name(self, nodelist):
10.335 + raise WalkerError
10.336 +
10.337 + def comp_op(self, nodelist):
10.338 + raise WalkerError
10.339 +
10.340 + def trailer(self, nodelist):
10.341 + raise WalkerError
10.342 +
10.343 + def sliceop(self, nodelist):
10.344 + raise WalkerError
10.345 +
10.346 + def argument(self, nodelist):
10.347 + raise WalkerError
10.348 +
10.349 + # --------------------------------------------------------------
10.350 + #
10.351 + # STATEMENT NODES (invoked by com_node())
10.352 + #
10.353 +
10.354 + def expr_stmt(self, nodelist):
10.355 + # augassign testlist | testlist ('=' testlist)*
10.356 + en = nodelist[-1]
10.357 + exprNode = self.lookup_node(en)(en[1:])
10.358 + if len(nodelist) == 1:
10.359 + return Discard(exprNode, lineno=exprNode.lineno)
10.360 + if nodelist[1][0] == token.EQUAL:
10.361 + nodesl = []
10.362 + for i in range(0, len(nodelist) - 2, 2):
10.363 + nodesl.append(self.com_assign(nodelist[i], OP_ASSIGN))
10.364 + return Assign(nodesl, exprNode, lineno=nodelist[1][2])
10.365 + else:
10.366 + lval = self.com_augassign(nodelist[0])
10.367 + op = self.com_augassign_op(nodelist[1])
10.368 + return AugAssign(lval, op[1], exprNode, lineno=op[2])
10.369 + raise WalkerError, "can't get here"
10.370 +
10.371 + def print_stmt(self, nodelist):
10.372 + # print ([ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ])
10.373 + items = []
10.374 + if len(nodelist) == 1:
10.375 + start = 1
10.376 + dest = None
10.377 + elif nodelist[1][0] == token.RIGHTSHIFT:
10.378 + assert len(nodelist) == 3 \
10.379 + or nodelist[3][0] == token.COMMA
10.380 + dest = self.com_node(nodelist[2])
10.381 + start = 4
10.382 + else:
10.383 + dest = None
10.384 + start = 1
10.385 + for i in range(start, len(nodelist), 2):
10.386 + items.append(self.com_node(nodelist[i]))
10.387 + if nodelist[-1][0] == token.COMMA:
10.388 + return Print(items, dest, lineno=nodelist[0][2])
10.389 + return Printnl(items, dest, lineno=nodelist[0][2])
10.390 +
10.391 + def del_stmt(self, nodelist):
10.392 + return self.com_assign(nodelist[1], OP_DELETE)
10.393 +
10.394 + def pass_stmt(self, nodelist):
10.395 + return Pass(lineno=nodelist[0][2])
10.396 +
10.397 + def break_stmt(self, nodelist):
10.398 + return Break(lineno=nodelist[0][2])
10.399 +
10.400 + def continue_stmt(self, nodelist):
10.401 + return Continue(lineno=nodelist[0][2])
10.402 +
10.403 + def return_stmt(self, nodelist):
10.404 + # return: [testlist]
10.405 + if len(nodelist) < 2:
10.406 + return Return(Const(None), lineno=nodelist[0][2])
10.407 + return Return(self.com_node(nodelist[1]), lineno=nodelist[0][2])
10.408 +
10.409 + def yield_stmt(self, nodelist):
10.410 + expr = self.com_node(nodelist[0])
10.411 + return Discard(expr, lineno=expr.lineno)
10.412 +
10.413 + def yield_expr(self, nodelist):
10.414 + if len(nodelist) > 1:
10.415 + value = self.com_node(nodelist[1])
10.416 + else:
10.417 + value = Const(None)
10.418 + return Yield(value, lineno=nodelist[0][2])
10.419 +
10.420 + def raise_stmt(self, nodelist):
10.421 + # raise: [test [',' test [',' test]]]
10.422 + if len(nodelist) > 5:
10.423 + expr3 = self.com_node(nodelist[5])
10.424 + else:
10.425 + expr3 = None
10.426 + if len(nodelist) > 3:
10.427 + expr2 = self.com_node(nodelist[3])
10.428 + else:
10.429 + expr2 = None
10.430 + if len(nodelist) > 1:
10.431 + expr1 = self.com_node(nodelist[1])
10.432 + else:
10.433 + expr1 = None
10.434 + return Raise(expr1, expr2, expr3, lineno=nodelist[0][2])
10.435 +
10.436 + def import_stmt(self, nodelist):
10.437 + # import_stmt: import_name | import_from
10.438 + assert len(nodelist) == 1
10.439 + return self.com_node(nodelist[0])
10.440 +
10.441 + def import_name(self, nodelist):
10.442 + # import_name: 'import' dotted_as_names
10.443 + return Import(self.com_dotted_as_names(nodelist[1]),
10.444 + lineno=nodelist[0][2])
10.445 +
10.446 + def import_from(self, nodelist):
10.447 + # import_from: 'from' ('.'* dotted_name | '.') 'import' ('*' |
10.448 + # '(' import_as_names ')' | import_as_names)
10.449 + assert nodelist[0][1] == 'from'
10.450 + idx = 1
10.451 + while nodelist[idx][1] == '.':
10.452 + idx += 1
10.453 + level = idx - 1
10.454 + if nodelist[idx][0] == symbol.dotted_name:
10.455 + fromname = self.com_dotted_name(nodelist[idx])
10.456 + idx += 1
10.457 + else:
10.458 + fromname = ""
10.459 + assert nodelist[idx][1] == 'import'
10.460 + if nodelist[idx + 1][0] == token.STAR:
10.461 + return From(fromname, [('*', None)], level,
10.462 + lineno=nodelist[0][2])
10.463 + else:
10.464 + node = nodelist[idx + 1 + (nodelist[idx + 1][0] == token.LPAR)]
10.465 + return From(fromname, self.com_import_as_names(node), level,
10.466 + lineno=nodelist[0][2])
10.467 +
10.468 + def global_stmt(self, nodelist):
10.469 + # global: NAME (',' NAME)*
10.470 + names = []
10.471 + for i in range(1, len(nodelist), 2):
10.472 + names.append(nodelist[i][1])
10.473 + return Global(names, lineno=nodelist[0][2])
10.474 +
10.475 + def exec_stmt(self, nodelist):
10.476 + # exec_stmt: 'exec' expr ['in' expr [',' expr]]
10.477 + expr1 = self.com_node(nodelist[1])
10.478 + if len(nodelist) >= 4:
10.479 + expr2 = self.com_node(nodelist[3])
10.480 + if len(nodelist) >= 6:
10.481 + expr3 = self.com_node(nodelist[5])
10.482 + else:
10.483 + expr3 = None
10.484 + else:
10.485 + expr2 = expr3 = None
10.486 +
10.487 + return Exec(expr1, expr2, expr3, lineno=nodelist[0][2])
10.488 +
10.489 + def assert_stmt(self, nodelist):
10.490 + # 'assert': test, [',' test]
10.491 + expr1 = self.com_node(nodelist[1])
10.492 + if (len(nodelist) == 4):
10.493 + expr2 = self.com_node(nodelist[3])
10.494 + else:
10.495 + expr2 = None
10.496 + return Assert(expr1, expr2, lineno=nodelist[0][2])
10.497 +
10.498 + def if_stmt(self, nodelist):
10.499 + # if: test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
10.500 + tests = []
10.501 + for i in range(0, len(nodelist) - 3, 4):
10.502 + testNode = self.com_node(nodelist[i + 1])
10.503 + suiteNode = self.com_node(nodelist[i + 3])
10.504 + tests.append((testNode, suiteNode))
10.505 +
10.506 + if len(nodelist) % 4 == 3:
10.507 + elseNode = self.com_node(nodelist[-1])
10.508 +## elseNode.lineno = nodelist[-1][1][2]
10.509 + else:
10.510 + elseNode = None
10.511 + return If(tests, elseNode, lineno=nodelist[0][2])
10.512 +
10.513 + def while_stmt(self, nodelist):
10.514 + # 'while' test ':' suite ['else' ':' suite]
10.515 +
10.516 + testNode = self.com_node(nodelist[1])
10.517 + bodyNode = self.com_node(nodelist[3])
10.518 +
10.519 + if len(nodelist) > 4:
10.520 + elseNode = self.com_node(nodelist[6])
10.521 + else:
10.522 + elseNode = None
10.523 +
10.524 + return While(testNode, bodyNode, elseNode, lineno=nodelist[0][2])
10.525 +
10.526 + def for_stmt(self, nodelist):
10.527 + # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
10.528 +
10.529 + assignNode = self.com_assign(nodelist[1], OP_ASSIGN)
10.530 + listNode = self.com_node(nodelist[3])
10.531 + bodyNode = self.com_node(nodelist[5])
10.532 +
10.533 + if len(nodelist) > 8:
10.534 + elseNode = self.com_node(nodelist[8])
10.535 + else:
10.536 + elseNode = None
10.537 +
10.538 + return For(assignNode, listNode, bodyNode, elseNode,
10.539 + lineno=nodelist[0][2])
10.540 +
10.541 + def try_stmt(self, nodelist):
10.542 + return self.com_try_except_finally(nodelist)
10.543 +
10.544 + def with_stmt(self, nodelist):
10.545 + return self.com_with(nodelist)
10.546 +
10.547 + def with_var(self, nodelist):
10.548 + return self.com_with_var(nodelist)
10.549 +
10.550 + def suite(self, nodelist):
10.551 + # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
10.552 + if len(nodelist) == 1:
10.553 + return self.com_stmt(nodelist[0])
10.554 +
10.555 + stmts = []
10.556 + for node in nodelist:
10.557 + if node[0] == symbol.stmt:
10.558 + self.com_append_stmt(stmts, node)
10.559 + return Stmt(stmts)
10.560 +
10.561 + # --------------------------------------------------------------
10.562 + #
10.563 + # EXPRESSION NODES (invoked by com_node())
10.564 + #
10.565 +
10.566 + def testlist(self, nodelist):
10.567 + # testlist: expr (',' expr)* [',']
10.568 + # testlist_safe: test [(',' test)+ [',']]
10.569 + # exprlist: expr (',' expr)* [',']
10.570 + return self.com_binary(Tuple, nodelist)
10.571 +
10.572 + testlist_safe = testlist # XXX
10.573 + testlist1 = testlist
10.574 + exprlist = testlist
10.575 +
10.576 + def testlist_gexp(self, nodelist):
10.577 + if len(nodelist) == 2 and nodelist[1][0] == symbol.gen_for:
10.578 + test = self.com_node(nodelist[0])
10.579 + return self.com_generator_expression(test, nodelist[1])
10.580 + return self.testlist(nodelist)
10.581 +
10.582 + def test(self, nodelist):
10.583 + # or_test ['if' or_test 'else' test] | lambdef
10.584 + if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
10.585 + return self.lambdef(nodelist[0])
10.586 + then = self.com_node(nodelist[0])
10.587 + if len(nodelist) > 1:
10.588 + assert len(nodelist) == 5
10.589 + assert nodelist[1][1] == 'if'
10.590 + assert nodelist[3][1] == 'else'
10.591 + test = self.com_node(nodelist[2])
10.592 + else_ = self.com_node(nodelist[4])
10.593 + return IfExp(test, then, else_, lineno=nodelist[1][2])
10.594 + return then
10.595 +
10.596 + def or_test(self, nodelist):
10.597 + # and_test ('or' and_test)* | lambdef
10.598 + if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
10.599 + return self.lambdef(nodelist[0])
10.600 + return self.com_binary(Or, nodelist)
10.601 + old_test = or_test
10.602 +
10.603 + def and_test(self, nodelist):
10.604 + # not_test ('and' not_test)*
10.605 + return self.com_binary(And, nodelist)
10.606 +
10.607 + def not_test(self, nodelist):
10.608 + # 'not' not_test | comparison
10.609 + result = self.com_node(nodelist[-1])
10.610 + if len(nodelist) == 2:
10.611 + return Not(result, lineno=nodelist[0][2])
10.612 + return result
10.613 +
10.614 + def comparison(self, nodelist):
10.615 + # comparison: expr (comp_op expr)*
10.616 + node = self.com_node(nodelist[0])
10.617 + if len(nodelist) == 1:
10.618 + return node
10.619 +
10.620 + results = []
10.621 + for i in range(2, len(nodelist), 2):
10.622 + nl = nodelist[i-1]
10.623 +
10.624 + # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
10.625 + # | 'in' | 'not' 'in' | 'is' | 'is' 'not'
10.626 + n = nl[1]
10.627 + if n[0] == token.NAME:
10.628 + type = n[1]
10.629 + if len(nl) == 3:
10.630 + if type == 'not':
10.631 + type = 'not in'
10.632 + else:
10.633 + type = 'is not'
10.634 + else:
10.635 + type = _cmp_types[n[0]]
10.636 +
10.637 + lineno = nl[1][2]
10.638 + results.append((type, self.com_node(nodelist[i])))
10.639 +
10.640 + # we need a special "compare" node so that we can distinguish
10.641 + # 3 < x < 5 from (3 < x) < 5
10.642 + # the two have very different semantics and results (note that the
10.643 + # latter form is always true)
10.644 +
10.645 + return Compare(node, results, lineno=lineno)
10.646 +
10.647 + def expr(self, nodelist):
10.648 + # xor_expr ('|' xor_expr)*
10.649 + return self.com_binary(Bitor, nodelist)
10.650 +
10.651 + def xor_expr(self, nodelist):
10.652 + # xor_expr ('^' xor_expr)*
10.653 + return self.com_binary(Bitxor, nodelist)
10.654 +
10.655 + def and_expr(self, nodelist):
10.656 + # xor_expr ('&' xor_expr)*
10.657 + return self.com_binary(Bitand, nodelist)
10.658 +
10.659 + def shift_expr(self, nodelist):
10.660 + # shift_expr ('<<'|'>>' shift_expr)*
10.661 + node = self.com_node(nodelist[0])
10.662 + for i in range(2, len(nodelist), 2):
10.663 + right = self.com_node(nodelist[i])
10.664 + if nodelist[i-1][0] == token.LEFTSHIFT:
10.665 + node = LeftShift([node, right], lineno=nodelist[1][2])
10.666 + elif nodelist[i-1][0] == token.RIGHTSHIFT:
10.667 + node = RightShift([node, right], lineno=nodelist[1][2])
10.668 + else:
10.669 + raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
10.670 + return node
10.671 +
10.672 + def arith_expr(self, nodelist):
10.673 + node = self.com_node(nodelist[0])
10.674 + for i in range(2, len(nodelist), 2):
10.675 + right = self.com_node(nodelist[i])
10.676 + if nodelist[i-1][0] == token.PLUS:
10.677 + node = Add([node, right], lineno=nodelist[1][2])
10.678 + elif nodelist[i-1][0] == token.MINUS:
10.679 + node = Sub([node, right], lineno=nodelist[1][2])
10.680 + else:
10.681 + raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
10.682 + return node
10.683 +
10.684 + def term(self, nodelist):
10.685 + node = self.com_node(nodelist[0])
10.686 + for i in range(2, len(nodelist), 2):
10.687 + right = self.com_node(nodelist[i])
10.688 + t = nodelist[i-1][0]
10.689 + if t == token.STAR:
10.690 + node = Mul([node, right])
10.691 + elif t == token.SLASH:
10.692 + node = Div([node, right])
10.693 + elif t == token.PERCENT:
10.694 + node = Mod([node, right])
10.695 + elif t == token.DOUBLESLASH:
10.696 + node = FloorDiv([node, right])
10.697 + else:
10.698 + raise ValueError, "unexpected token: %s" % t
10.699 + node.lineno = nodelist[1][2]
10.700 + return node
10.701 +
10.702 + def factor(self, nodelist):
10.703 + elt = nodelist[0]
10.704 + t = elt[0]
10.705 + node = self.lookup_node(nodelist[-1])(nodelist[-1][1:])
10.706 + # need to handle (unary op)constant here...
10.707 + if t == token.PLUS:
10.708 + return UnaryAdd(node, lineno=elt[2])
10.709 + elif t == token.MINUS:
10.710 + return UnarySub(node, lineno=elt[2])
10.711 + elif t == token.TILDE:
10.712 + node = Invert(node, lineno=elt[2])
10.713 + return node
10.714 +
10.715 + def power(self, nodelist):
10.716 + # power: atom trailer* ('**' factor)*
10.717 + node = self.com_node(nodelist[0])
10.718 + for i in range(1, len(nodelist)):
10.719 + elt = nodelist[i]
10.720 + if elt[0] == token.DOUBLESTAR:
10.721 + return Power([node, self.com_node(nodelist[i+1])],
10.722 + lineno=elt[2])
10.723 +
10.724 + node = self.com_apply_trailer(node, elt)
10.725 +
10.726 + return node
10.727 +
10.728 + def atom(self, nodelist):
10.729 + return self._atom_dispatch[nodelist[0][0]](nodelist)
10.730 +
10.731 + def atom_lpar(self, nodelist):
10.732 + if nodelist[1][0] == token.RPAR:
10.733 + return Tuple((), lineno=nodelist[0][2])
10.734 + return self.com_node(nodelist[1])
10.735 +
10.736 + def atom_lsqb(self, nodelist):
10.737 + if nodelist[1][0] == token.RSQB:
10.738 + return List((), lineno=nodelist[0][2])
10.739 + return self.com_list_constructor(nodelist[1])
10.740 +
10.741 + def atom_lbrace(self, nodelist):
10.742 + if nodelist[1][0] == token.RBRACE:
10.743 + return Dict((), lineno=nodelist[0][2])
10.744 + return self.com_dictmaker(nodelist[1])
10.745 +
10.746 + def atom_backquote(self, nodelist):
10.747 + return Backquote(self.com_node(nodelist[1]))
10.748 +
10.749 + def atom_number(self, nodelist):
10.750 + ### need to verify this matches compile.c
10.751 + k = eval(nodelist[0][1])
10.752 + return Const(k, lineno=nodelist[0][2])
10.753 +
10.754 + def decode_literal(self, lit):
10.755 + if self.encoding:
10.756 + # this is particularly fragile & a bit of a
10.757 + # hack... changes in compile.c:parsestr and
10.758 + # tokenizer.c must be reflected here.
10.759 + if self.encoding not in ['utf-8', 'iso-8859-1']:
10.760 + lit = unicode(lit, 'utf-8').encode(self.encoding)
10.761 + return eval("# coding: %s\n%s" % (self.encoding, lit))
10.762 + else:
10.763 + return eval(lit)
10.764 +
10.765 + def atom_string(self, nodelist):
10.766 + k = ''
10.767 + for node in nodelist:
10.768 + k += self.decode_literal(node[1])
10.769 + return Const(k, lineno=nodelist[0][2])
10.770 +
10.771 + def atom_name(self, nodelist):
10.772 + return Name(nodelist[0][1], lineno=nodelist[0][2])
10.773 +
10.774 + # --------------------------------------------------------------
10.775 + #
10.776 + # INTERNAL PARSING UTILITIES
10.777 + #
10.778 +
10.779 + # The use of com_node() introduces a lot of extra stack frames,
10.780 + # enough to cause a stack overflow compiling test.test_parser with
10.781 + # the standard interpreter recursionlimit. The com_node() is a
10.782 + # convenience function that hides the dispatch details, but comes
10.783 + # at a very high cost. It is more efficient to dispatch directly
10.784 + # in the callers. In these cases, use lookup_node() and call the
10.785 + # dispatched node directly.
10.786 +
10.787 + def lookup_node(self, node):
10.788 + return self._dispatch[node[0]]
10.789 +
10.790 + def com_node(self, node):
10.791 + # Note: compile.c has handling in com_node for del_stmt, pass_stmt,
10.792 + # break_stmt, stmt, small_stmt, flow_stmt, simple_stmt,
10.793 + # and compound_stmt.
10.794 + # We'll just dispatch them.
10.795 + return self._dispatch[node[0]](node[1:])
10.796 +
10.797 + def com_NEWLINE(self, *args):
10.798 + # A ';' at the end of a line can make a NEWLINE token appear
10.799 + # here, Render it harmless. (genc discards ('discard',
10.800 + # ('const', xxxx)) Nodes)
10.801 + return Discard(Const(None))
10.802 +
10.803 + def com_arglist(self, nodelist):
10.804 + # varargslist:
10.805 + # (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME)
10.806 + # | fpdef ['=' test] (',' fpdef ['=' test])* [',']
10.807 + # fpdef: NAME | '(' fplist ')'
10.808 + # fplist: fpdef (',' fpdef)* [',']
10.809 + names = []
10.810 + defaults = []
10.811 + flags = 0
10.812 +
10.813 + i = 0
10.814 + while i < len(nodelist):
10.815 + node = nodelist[i]
10.816 + if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
10.817 + if node[0] == token.STAR:
10.818 + node = nodelist[i+1]
10.819 + if node[0] == token.NAME:
10.820 + names.append(node[1])
10.821 + flags = flags | CO_VARARGS
10.822 + i = i + 3
10.823 +
10.824 + if i < len(nodelist):
10.825 + # should be DOUBLESTAR
10.826 + t = nodelist[i][0]
10.827 + if t == token.DOUBLESTAR:
10.828 + node = nodelist[i+1]
10.829 + else:
10.830 + raise ValueError, "unexpected token: %s" % t
10.831 + names.append(node[1])
10.832 + flags = flags | CO_VARKEYWORDS
10.833 +
10.834 + break
10.835 +
10.836 + # fpdef: NAME | '(' fplist ')'
10.837 + names.append(self.com_fpdef(node))
10.838 +
10.839 + i = i + 1
10.840 + if i < len(nodelist) and nodelist[i][0] == token.EQUAL:
10.841 + defaults.append(self.com_node(nodelist[i + 1]))
10.842 + i = i + 2
10.843 + elif len(defaults):
10.844 + # we have already seen an argument with default, but here
10.845 + # came one without
10.846 + raise SyntaxError, "non-default argument follows default argument"
10.847 +
10.848 + # skip the comma
10.849 + i = i + 1
10.850 +
10.851 + return names, defaults, flags
10.852 +
10.853 + def com_fpdef(self, node):
10.854 + # fpdef: NAME | '(' fplist ')'
10.855 + if node[1][0] == token.LPAR:
10.856 + return self.com_fplist(node[2])
10.857 + return node[1][1]
10.858 +
10.859 + def com_fplist(self, node):
10.860 + # fplist: fpdef (',' fpdef)* [',']
10.861 + if len(node) == 2:
10.862 + return self.com_fpdef(node[1])
10.863 + list = []
10.864 + for i in range(1, len(node), 2):
10.865 + list.append(self.com_fpdef(node[i]))
10.866 + return tuple(list)
10.867 +
10.868 + def com_dotted_name(self, node):
10.869 + # String together the dotted names and return the string
10.870 + name = ""
10.871 + for n in node:
10.872 + if type(n) == type(()) and n[0] == 1:
10.873 + name = name + n[1] + '.'
10.874 + return name[:-1]
10.875 +
10.876 + def com_dotted_as_name(self, node):
10.877 + assert node[0] == symbol.dotted_as_name
10.878 + node = node[1:]
10.879 + dot = self.com_dotted_name(node[0][1:])
10.880 + if len(node) == 1:
10.881 + return dot, None
10.882 + assert node[1][1] == 'as'
10.883 + assert node[2][0] == token.NAME
10.884 + return dot, node[2][1]
10.885 +
10.886 + def com_dotted_as_names(self, node):
10.887 + assert node[0] == symbol.dotted_as_names
10.888 + node = node[1:]
10.889 + names = [self.com_dotted_as_name(node[0])]
10.890 + for i in range(2, len(node), 2):
10.891 + names.append(self.com_dotted_as_name(node[i]))
10.892 + return names
10.893 +
10.894 + def com_import_as_name(self, node):
10.895 + assert node[0] == symbol.import_as_name
10.896 + node = node[1:]
10.897 + assert node[0][0] == token.NAME
10.898 + if len(node) == 1:
10.899 + return node[0][1], None
10.900 + assert node[1][1] == 'as', node
10.901 + assert node[2][0] == token.NAME
10.902 + return node[0][1], node[2][1]
10.903 +
10.904 + def com_import_as_names(self, node):
10.905 + assert node[0] == symbol.import_as_names
10.906 + node = node[1:]
10.907 + names = [self.com_import_as_name(node[0])]
10.908 + for i in range(2, len(node), 2):
10.909 + names.append(self.com_import_as_name(node[i]))
10.910 + return names
10.911 +
10.912 + def com_bases(self, node):
10.913 + bases = []
10.914 + for i in range(1, len(node), 2):
10.915 + bases.append(self.com_node(node[i]))
10.916 + return bases
10.917 +
10.918 + def com_try_except_finally(self, nodelist):
10.919 + # ('try' ':' suite
10.920 + # ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite]
10.921 + # | 'finally' ':' suite))
10.922 +
10.923 + if nodelist[3][0] == token.NAME:
10.924 + # first clause is a finally clause: only try-finally
10.925 + return TryFinally(self.com_node(nodelist[2]),
10.926 + self.com_node(nodelist[5]),
10.927 + lineno=nodelist[0][2])
10.928 +
10.929 + #tryexcept: [TryNode, [except_clauses], elseNode)]
10.930 + clauses = []
10.931 + elseNode = None
10.932 + finallyNode = None
10.933 + for i in range(3, len(nodelist), 3):
10.934 + node = nodelist[i]
10.935 + if node[0] == symbol.except_clause:
10.936 + # except_clause: 'except' [expr [',' expr]] */
10.937 + if len(node) > 2:
10.938 + expr1 = self.com_node(node[2])
10.939 + if len(node) > 4:
10.940 + expr2 = self.com_assign(node[4], OP_ASSIGN)
10.941 + else:
10.942 + expr2 = None
10.943 + else:
10.944 + expr1 = expr2 = None
10.945 + clauses.append((expr1, expr2, self.com_node(nodelist[i+2])))
10.946 +
10.947 + if node[0] == token.NAME:
10.948 + if node[1] == 'else':
10.949 + elseNode = self.com_node(nodelist[i+2])
10.950 + elif node[1] == 'finally':
10.951 + finallyNode = self.com_node(nodelist[i+2])
10.952 + try_except = TryExcept(self.com_node(nodelist[2]), clauses, elseNode,
10.953 + lineno=nodelist[0][2])
10.954 + if finallyNode:
10.955 + return TryFinally(try_except, finallyNode, lineno=nodelist[0][2])
10.956 + else:
10.957 + return try_except
10.958 +
10.959 + def com_with(self, nodelist):
10.960 + # with_stmt: 'with' expr [with_var] ':' suite
10.961 + expr = self.com_node(nodelist[1])
10.962 + body = self.com_node(nodelist[-1])
10.963 + if nodelist[2][0] == token.COLON:
10.964 + var = None
10.965 + else:
10.966 + var = self.com_assign(nodelist[2][2], OP_ASSIGN)
10.967 + return With(expr, var, body, lineno=nodelist[0][2])
10.968 +
10.969 + def com_with_var(self, nodelist):
10.970 + # with_var: 'as' expr
10.971 + return self.com_node(nodelist[1])
10.972 +
10.973 + def com_augassign_op(self, node):
10.974 + assert node[0] == symbol.augassign
10.975 + return node[1]
10.976 +
10.977 + def com_augassign(self, node):
10.978 + """Return node suitable for lvalue of augmented assignment
10.979 +
10.980 + Names, slices, and attributes are the only allowable nodes.
10.981 + """
10.982 + l = self.com_node(node)
10.983 + if l.__class__ in (Name, Slice, Subscript, Getattr):
10.984 + return l
10.985 + raise SyntaxError, "can't assign to %s" % l.__class__.__name__
10.986 +
10.987 + def com_assign(self, node, assigning):
10.988 + # return a node suitable for use as an "lvalue"
10.989 + # loop to avoid trivial recursion
10.990 + while 1:
10.991 + t = node[0]
10.992 + if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_gexp):
10.993 + if len(node) > 2:
10.994 + return self.com_assign_tuple(node, assigning)
10.995 + node = node[1]
10.996 + elif t in _assign_types:
10.997 + if len(node) > 2:
10.998 + raise SyntaxError, "can't assign to operator"
10.999 + node = node[1]
10.1000 + elif t == symbol.power:
10.1001 + if node[1][0] != symbol.atom:
10.1002 + raise SyntaxError, "can't assign to operator"
10.1003 + if len(node) > 2:
10.1004 + primary = self.com_node(node[1])
10.1005 + for i in range(2, len(node)-1):
10.1006 + ch = node[i]
10.1007 + if ch[0] == token.DOUBLESTAR:
10.1008 + raise SyntaxError, "can't assign to operator"
10.1009 + primary = self.com_apply_trailer(primary, ch)
10.1010 + return self.com_assign_trailer(primary, node[-1],
10.1011 + assigning)
10.1012 + node = node[1]
10.1013 + elif t == symbol.atom:
10.1014 + t = node[1][0]
10.1015 + if t == token.LPAR:
10.1016 + node = node[2]
10.1017 + if node[0] == token.RPAR:
10.1018 + raise SyntaxError, "can't assign to ()"
10.1019 + elif t == token.LSQB:
10.1020 + node = node[2]
10.1021 + if node[0] == token.RSQB:
10.1022 + raise SyntaxError, "can't assign to []"
10.1023 + return self.com_assign_list(node, assigning)
10.1024 + elif t == token.NAME:
10.1025 + return self.com_assign_name(node[1], assigning)
10.1026 + else:
10.1027 + raise SyntaxError, "can't assign to literal"
10.1028 + else:
10.1029 + raise SyntaxError, "bad assignment (%s)" % t
10.1030 +
10.1031 + def com_assign_tuple(self, node, assigning):
10.1032 + assigns = []
10.1033 + for i in range(1, len(node), 2):
10.1034 + assigns.append(self.com_assign(node[i], assigning))
10.1035 + return AssTuple(assigns, lineno=extractLineNo(node))
10.1036 +
10.1037 + def com_assign_list(self, node, assigning):
10.1038 + assigns = []
10.1039 + for i in range(1, len(node), 2):
10.1040 + if i + 1 < len(node):
10.1041 + if node[i + 1][0] == symbol.list_for:
10.1042 + raise SyntaxError, "can't assign to list comprehension"
10.1043 + assert node[i + 1][0] == token.COMMA, node[i + 1]
10.1044 + assigns.append(self.com_assign(node[i], assigning))
10.1045 + return AssList(assigns, lineno=extractLineNo(node))
10.1046 +
10.1047 + def com_assign_name(self, node, assigning):
10.1048 + return AssName(node[1], assigning, lineno=node[2])
10.1049 +
10.1050 + def com_assign_trailer(self, primary, node, assigning):
10.1051 + t = node[1][0]
10.1052 + if t == token.DOT:
10.1053 + return self.com_assign_attr(primary, node[2], assigning)
10.1054 + if t == token.LSQB:
10.1055 + return self.com_subscriptlist(primary, node[2], assigning)
10.1056 + if t == token.LPAR:
10.1057 + raise SyntaxError, "can't assign to function call"
10.1058 + raise SyntaxError, "unknown trailer type: %s" % t
10.1059 +
10.1060 + def com_assign_attr(self, primary, node, assigning):
10.1061 + return AssAttr(primary, node[1], assigning, lineno=node[-1])
10.1062 +
10.1063 + def com_binary(self, constructor, nodelist):
10.1064 + "Compile 'NODE (OP NODE)*' into (type, [ node1, ..., nodeN ])."
10.1065 + l = len(nodelist)
10.1066 + if l == 1:
10.1067 + n = nodelist[0]
10.1068 + return self.lookup_node(n)(n[1:])
10.1069 + items = []
10.1070 + for i in range(0, l, 2):
10.1071 + n = nodelist[i]
10.1072 + items.append(self.lookup_node(n)(n[1:]))
10.1073 + return constructor(items, lineno=extractLineNo(nodelist))
10.1074 +
10.1075 + def com_stmt(self, node):
10.1076 + result = self.lookup_node(node)(node[1:])
10.1077 + assert result is not None
10.1078 + if isinstance(result, Stmt):
10.1079 + return result
10.1080 + return Stmt([result])
10.1081 +
10.1082 + def com_append_stmt(self, stmts, node):
10.1083 + result = self.lookup_node(node)(node[1:])
10.1084 + assert result is not None
10.1085 + if isinstance(result, Stmt):
10.1086 + stmts.extend(result.nodes)
10.1087 + else:
10.1088 + stmts.append(result)
10.1089 +
10.1090 + if hasattr(symbol, 'list_for'):
10.1091 + def com_list_constructor(self, nodelist):
10.1092 + # listmaker: test ( list_for | (',' test)* [','] )
10.1093 + values = []
10.1094 + for i in range(1, len(nodelist)):
10.1095 + if nodelist[i][0] == symbol.list_for:
10.1096 + assert len(nodelist[i:]) == 1
10.1097 + return self.com_list_comprehension(values[0],
10.1098 + nodelist[i])
10.1099 + elif nodelist[i][0] == token.COMMA:
10.1100 + continue
10.1101 + values.append(self.com_node(nodelist[i]))
10.1102 + return List(values, lineno=values[0].lineno)
10.1103 +
10.1104 + def com_list_comprehension(self, expr, node):
10.1105 + # list_iter: list_for | list_if
10.1106 + # list_for: 'for' exprlist 'in' testlist [list_iter]
10.1107 + # list_if: 'if' test [list_iter]
10.1108 +
10.1109 + # XXX should raise SyntaxError for assignment
10.1110 +
10.1111 + lineno = node[1][2]
10.1112 + fors = []
10.1113 + while node:
10.1114 + t = node[1][1]
10.1115 + if t == 'for':
10.1116 + assignNode = self.com_assign(node[2], OP_ASSIGN)
10.1117 + listNode = self.com_node(node[4])
10.1118 + newfor = ListCompFor(assignNode, listNode, [])
10.1119 + newfor.lineno = node[1][2]
10.1120 + fors.append(newfor)
10.1121 + if len(node) == 5:
10.1122 + node = None
10.1123 + else:
10.1124 + node = self.com_list_iter(node[5])
10.1125 + elif t == 'if':
10.1126 + test = self.com_node(node[2])
10.1127 + newif = ListCompIf(test, lineno=node[1][2])
10.1128 + newfor.ifs.append(newif)
10.1129 + if len(node) == 3:
10.1130 + node = None
10.1131 + else:
10.1132 + node = self.com_list_iter(node[3])
10.1133 + else:
10.1134 + raise SyntaxError, \
10.1135 + ("unexpected list comprehension element: %s %d"
10.1136 + % (node, lineno))
10.1137 + return ListComp(expr, fors, lineno=lineno)
10.1138 +
10.1139 + def com_list_iter(self, node):
10.1140 + assert node[0] == symbol.list_iter
10.1141 + return node[1]
10.1142 + else:
10.1143 + def com_list_constructor(self, nodelist):
10.1144 + values = []
10.1145 + for i in range(1, len(nodelist), 2):
10.1146 + values.append(self.com_node(nodelist[i]))
10.1147 + return List(values, lineno=values[0].lineno)
10.1148 +
10.1149 + if hasattr(symbol, 'gen_for'):
10.1150 + def com_generator_expression(self, expr, node):
10.1151 + # gen_iter: gen_for | gen_if
10.1152 + # gen_for: 'for' exprlist 'in' test [gen_iter]
10.1153 + # gen_if: 'if' test [gen_iter]
10.1154 +
10.1155 + lineno = node[1][2]
10.1156 + fors = []
10.1157 + while node:
10.1158 + t = node[1][1]
10.1159 + if t == 'for':
10.1160 + assignNode = self.com_assign(node[2], OP_ASSIGN)
10.1161 + genNode = self.com_node(node[4])
10.1162 + newfor = GenExprFor(assignNode, genNode, [],
10.1163 + lineno=node[1][2])
10.1164 + fors.append(newfor)
10.1165 + if (len(node)) == 5:
10.1166 + node = None
10.1167 + else:
10.1168 + node = self.com_gen_iter(node[5])
10.1169 + elif t == 'if':
10.1170 + test = self.com_node(node[2])
10.1171 + newif = GenExprIf(test, lineno=node[1][2])
10.1172 + newfor.ifs.append(newif)
10.1173 + if len(node) == 3:
10.1174 + node = None
10.1175 + else:
10.1176 + node = self.com_gen_iter(node[3])
10.1177 + else:
10.1178 + raise SyntaxError, \
10.1179 + ("unexpected generator expression element: %s %d"
10.1180 + % (node, lineno))
10.1181 + fors[0].is_outmost = True
10.1182 + return GenExpr(GenExprInner(expr, fors), lineno=lineno)
10.1183 +
10.1184 + def com_gen_iter(self, node):
10.1185 + assert node[0] == symbol.gen_iter
10.1186 + return node[1]
10.1187 +
10.1188 + def com_dictmaker(self, nodelist):
10.1189 + # dictmaker: test ':' test (',' test ':' value)* [',']
10.1190 + items = []
10.1191 + for i in range(1, len(nodelist), 4):
10.1192 + items.append((self.com_node(nodelist[i]),
10.1193 + self.com_node(nodelist[i+2])))
10.1194 + return Dict(items, lineno=items[0][0].lineno)
10.1195 +
10.1196 + def com_apply_trailer(self, primaryNode, nodelist):
10.1197 + t = nodelist[1][0]
10.1198 + if t == token.LPAR:
10.1199 + return self.com_call_function(primaryNode, nodelist[2])
10.1200 + if t == token.DOT:
10.1201 + return self.com_select_member(primaryNode, nodelist[2])
10.1202 + if t == token.LSQB:
10.1203 + return self.com_subscriptlist(primaryNode, nodelist[2], OP_APPLY)
10.1204 +
10.1205 + raise SyntaxError, 'unknown node type: %s' % t
10.1206 +
10.1207 + def com_select_member(self, primaryNode, nodelist):
10.1208 + if nodelist[0] != token.NAME:
10.1209 + raise SyntaxError, "member must be a name"
10.1210 + return Getattr(primaryNode, nodelist[1], lineno=nodelist[2])
10.1211 +
10.1212 + def com_call_function(self, primaryNode, nodelist):
10.1213 + if nodelist[0] == token.RPAR:
10.1214 + return CallFunc(primaryNode, [], lineno=extractLineNo(nodelist))
10.1215 + args = []
10.1216 + kw = 0
10.1217 + len_nodelist = len(nodelist)
10.1218 + for i in range(1, len_nodelist, 2):
10.1219 + node = nodelist[i]
10.1220 + if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
10.1221 + break
10.1222 + kw, result = self.com_argument(node, kw)
10.1223 +
10.1224 + if len_nodelist != 2 and isinstance(result, GenExpr) \
10.1225 + and len(node) == 3 and node[2][0] == symbol.gen_for:
10.1226 + # allow f(x for x in y), but reject f(x for x in y, 1)
10.1227 + # should use f((x for x in y), 1) instead of f(x for x in y, 1)
10.1228 + raise SyntaxError, 'generator expression needs parenthesis'
10.1229 +
10.1230 + args.append(result)
10.1231 + else:
10.1232 + # No broken by star arg, so skip the last one we processed.
10.1233 + i = i + 1
10.1234 + if i < len_nodelist and nodelist[i][0] == token.COMMA:
10.1235 + # need to accept an application that looks like "f(a, b,)"
10.1236 + i = i + 1
10.1237 + star_node = dstar_node = None
10.1238 + while i < len_nodelist:
10.1239 + tok = nodelist[i]
10.1240 + ch = nodelist[i+1]
10.1241 + i = i + 3
10.1242 + if tok[0]==token.STAR:
10.1243 + if star_node is not None:
10.1244 + raise SyntaxError, 'already have the varargs indentifier'
10.1245 + star_node = self.com_node(ch)
10.1246 + elif tok[0]==token.DOUBLESTAR:
10.1247 + if dstar_node is not None:
10.1248 + raise SyntaxError, 'already have the kwargs indentifier'
10.1249 + dstar_node = self.com_node(ch)
10.1250 + else:
10.1251 + raise SyntaxError, 'unknown node type: %s' % tok
10.1252 + return CallFunc(primaryNode, args, star_node, dstar_node,
10.1253 + lineno=extractLineNo(nodelist))
10.1254 +
10.1255 + def com_argument(self, nodelist, kw):
10.1256 + if len(nodelist) == 3 and nodelist[2][0] == symbol.gen_for:
10.1257 + test = self.com_node(nodelist[1])
10.1258 + return 0, self.com_generator_expression(test, nodelist[2])
10.1259 + if len(nodelist) == 2:
10.1260 + if kw:
10.1261 + raise SyntaxError, "non-keyword arg after keyword arg"
10.1262 + return 0, self.com_node(nodelist[1])
10.1263 + result = self.com_node(nodelist[3])
10.1264 + n = nodelist[1]
10.1265 + while len(n) == 2 and n[0] != token.NAME:
10.1266 + n = n[1]
10.1267 + if n[0] != token.NAME:
10.1268 + raise SyntaxError, "keyword can't be an expression (%s)"%n[0]
10.1269 + node = Keyword(n[1], result, lineno=n[2])
10.1270 + return 1, node
10.1271 +
10.1272 + def com_subscriptlist(self, primary, nodelist, assigning):
10.1273 + # slicing: simple_slicing | extended_slicing
10.1274 + # simple_slicing: primary "[" short_slice "]"
10.1275 + # extended_slicing: primary "[" slice_list "]"
10.1276 + # slice_list: slice_item ("," slice_item)* [","]
10.1277 +
10.1278 + # backwards compat slice for '[i:j]'
10.1279 + if len(nodelist) == 2:
10.1280 + sub = nodelist[1]
10.1281 + if (sub[1][0] == token.COLON or \
10.1282 + (len(sub) > 2 and sub[2][0] == token.COLON)) and \
10.1283 + sub[-1][0] != symbol.sliceop:
10.1284 + return self.com_slice(primary, sub, assigning)
10.1285 +
10.1286 + subscripts = []
10.1287 + for i in range(1, len(nodelist), 2):
10.1288 + subscripts.append(self.com_subscript(nodelist[i]))
10.1289 + return Subscript(primary, assigning, subscripts,
10.1290 + lineno=extractLineNo(nodelist))
10.1291 +
10.1292 + def com_subscript(self, node):
10.1293 + # slice_item: expression | proper_slice | ellipsis
10.1294 + ch = node[1]
10.1295 + t = ch[0]
10.1296 + if t == token.DOT and node[2][0] == token.DOT:
10.1297 + return Ellipsis()
10.1298 + if t == token.COLON or len(node) > 2:
10.1299 + return self.com_sliceobj(node)
10.1300 + return self.com_node(ch)
10.1301 +
10.1302 + def com_sliceobj(self, node):
10.1303 + # proper_slice: short_slice | long_slice
10.1304 + # short_slice: [lower_bound] ":" [upper_bound]
10.1305 + # long_slice: short_slice ":" [stride]
10.1306 + # lower_bound: expression
10.1307 + # upper_bound: expression
10.1308 + # stride: expression
10.1309 + #
10.1310 + # Note: a stride may be further slicing...
10.1311 +
10.1312 + items = []
10.1313 +
10.1314 + if node[1][0] == token.COLON:
10.1315 + items.append(Const(None))
10.1316 + i = 2
10.1317 + else:
10.1318 + items.append(self.com_node(node[1]))
10.1319 + # i == 2 is a COLON
10.1320 + i = 3
10.1321 +
10.1322 + if i < len(node) and node[i][0] == symbol.test:
10.1323 + items.append(self.com_node(node[i]))
10.1324 + i = i + 1
10.1325 + else:
10.1326 + items.append(Const(None))
10.1327 +
10.1328 + # a short_slice has been built. look for long_slice now by looking
10.1329 + # for strides...
10.1330 + for j in range(i, len(node)):
10.1331 + ch = node[j]
10.1332 + if len(ch) == 2:
10.1333 + items.append(Const(None))
10.1334 + else:
10.1335 + items.append(self.com_node(ch[2]))
10.1336 + return Sliceobj(items, lineno=extractLineNo(node))
10.1337 +
10.1338 + def com_slice(self, primary, node, assigning):
10.1339 + # short_slice: [lower_bound] ":" [upper_bound]
10.1340 + lower = upper = None
10.1341 + if len(node) == 3:
10.1342 + if node[1][0] == token.COLON:
10.1343 + upper = self.com_node(node[2])
10.1344 + else:
10.1345 + lower = self.com_node(node[1])
10.1346 + elif len(node) == 4:
10.1347 + lower = self.com_node(node[1])
10.1348 + upper = self.com_node(node[3])
10.1349 + return Slice(primary, assigning, lower, upper,
10.1350 + lineno=extractLineNo(node))
10.1351 +
10.1352 + def get_docstring(self, node, n=None):
10.1353 + if n is None:
10.1354 + n = node[0]
10.1355 + node = node[1:]
10.1356 + if n == symbol.suite:
10.1357 + if len(node) == 1:
10.1358 + return self.get_docstring(node[0])
10.1359 + for sub in node:
10.1360 + if sub[0] == symbol.stmt:
10.1361 + return self.get_docstring(sub)
10.1362 + return None
10.1363 + if n == symbol.file_input:
10.1364 + for sub in node:
10.1365 + if sub[0] == symbol.stmt:
10.1366 + return self.get_docstring(sub)
10.1367 + return None
10.1368 + if n == symbol.atom:
10.1369 + if node[0][0] == token.STRING:
10.1370 + s = ''
10.1371 + for t in node:
10.1372 + s = s + eval(t[1])
10.1373 + return s
10.1374 + return None
10.1375 + if n == symbol.stmt or n == symbol.simple_stmt \
10.1376 + or n == symbol.small_stmt:
10.1377 + return self.get_docstring(node[0])
10.1378 + if n in _doc_nodes and len(node) == 1:
10.1379 + return self.get_docstring(node[0])
10.1380 + return None
10.1381 +
10.1382 +
10.1383 +_doc_nodes = [
10.1384 + symbol.expr_stmt,
10.1385 + symbol.testlist,
10.1386 + symbol.testlist_safe,
10.1387 + symbol.test,
10.1388 + symbol.or_test,
10.1389 + symbol.and_test,
10.1390 + symbol.not_test,
10.1391 + symbol.comparison,
10.1392 + symbol.expr,
10.1393 + symbol.xor_expr,
10.1394 + symbol.and_expr,
10.1395 + symbol.shift_expr,
10.1396 + symbol.arith_expr,
10.1397 + symbol.term,
10.1398 + symbol.factor,
10.1399 + symbol.power,
10.1400 + ]
10.1401 +
10.1402 +# comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
10.1403 +# | 'in' | 'not' 'in' | 'is' | 'is' 'not'
10.1404 +_cmp_types = {
10.1405 + token.LESS : '<',
10.1406 + token.GREATER : '>',
10.1407 + token.EQEQUAL : '==',
10.1408 + token.EQUAL : '==',
10.1409 + token.LESSEQUAL : '<=',
10.1410 + token.GREATEREQUAL : '>=',
10.1411 + token.NOTEQUAL : '!=',
10.1412 + }
10.1413 +
10.1414 +_legal_node_types = [
10.1415 + symbol.funcdef,
10.1416 + symbol.classdef,
10.1417 + symbol.stmt,
10.1418 + symbol.small_stmt,
10.1419 + symbol.flow_stmt,
10.1420 + symbol.simple_stmt,
10.1421 + symbol.compound_stmt,
10.1422 + symbol.expr_stmt,
10.1423 + symbol.print_stmt,
10.1424 + symbol.del_stmt,
10.1425 + symbol.pass_stmt,
10.1426 + symbol.break_stmt,
10.1427 + symbol.continue_stmt,
10.1428 + symbol.return_stmt,
10.1429 + symbol.raise_stmt,
10.1430 + symbol.import_stmt,
10.1431 + symbol.global_stmt,
10.1432 + symbol.exec_stmt,
10.1433 + symbol.assert_stmt,
10.1434 + symbol.if_stmt,
10.1435 + symbol.while_stmt,
10.1436 + symbol.for_stmt,
10.1437 + symbol.try_stmt,
10.1438 + symbol.with_stmt,
10.1439 + symbol.suite,
10.1440 + symbol.testlist,
10.1441 + symbol.testlist_safe,
10.1442 + symbol.test,
10.1443 + symbol.and_test,
10.1444 + symbol.not_test,
10.1445 + symbol.comparison,
10.1446 + symbol.exprlist,
10.1447 + symbol.expr,
10.1448 + symbol.xor_expr,
10.1449 + symbol.and_expr,
10.1450 + symbol.shift_expr,
10.1451 + symbol.arith_expr,
10.1452 + symbol.term,
10.1453 + symbol.factor,
10.1454 + symbol.power,
10.1455 + symbol.atom,
10.1456 + ]
10.1457 +
10.1458 +if hasattr(symbol, 'yield_stmt'):
10.1459 + _legal_node_types.append(symbol.yield_stmt)
10.1460 +if hasattr(symbol, 'yield_expr'):
10.1461 + _legal_node_types.append(symbol.yield_expr)
10.1462 +
10.1463 +_assign_types = [
10.1464 + symbol.test,
10.1465 + symbol.or_test,
10.1466 + symbol.and_test,
10.1467 + symbol.not_test,
10.1468 + symbol.comparison,
10.1469 + symbol.expr,
10.1470 + symbol.xor_expr,
10.1471 + symbol.and_expr,
10.1472 + symbol.shift_expr,
10.1473 + symbol.arith_expr,
10.1474 + symbol.term,
10.1475 + symbol.factor,
10.1476 + ]
10.1477 +
10.1478 +_names = {}
10.1479 +for k, v in symbol.sym_name.items():
10.1480 + _names[k] = v
10.1481 +for k, v in token.tok_name.items():
10.1482 + _names[k] = v
10.1483 +
10.1484 +def debug_tree(tree):
10.1485 + l = []
10.1486 + for elt in tree:
10.1487 + if isinstance(elt, int):
10.1488 + l.append(_names.get(elt, elt))
10.1489 + elif isinstance(elt, str):
10.1490 + l.append(elt)
10.1491 + else:
10.1492 + l.append(debug_tree(elt))
10.1493 + return l
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/compiler/visitor.py Tue May 01 22:04:53 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 not self.examples.has_key(klass):
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 Tue May 01 22:04:53 2012 +0200
12.3 @@ -0,0 +1,22 @@
12.4 +Copyright information from Python 2.5.6
12.5 +---------------------------------------
12.6 +
12.7 +Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
12.8 +Python Software Foundation. All rights reserved.
12.9 +
12.10 +Copyright (c) 2000 BeOpen.com.
12.11 +All rights reserved.
12.12 +
12.13 +Copyright (c) 1995-2001 Corporation for National Research Initiatives.
12.14 +All rights reserved.
12.15 +
12.16 +Copyright (c) 1991-1995 Stichting Mathematisch Centrum.
12.17 +All rights reserved.
12.18 +
12.19 +
12.20 +License information
12.21 +-------------------
12.22 +
12.23 +See the file "LICENSE" for information on the history of this
12.24 +software, terms & conditions for usage, and a DISCLAIMER OF ALL
12.25 +WARRANTIES.
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/docs/LICENSE Tue May 01 22:04:53 2012 +0200
13.3 @@ -0,0 +1,272 @@
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.2 2008 PSF yes
13.62 +
13.63 +Footnotes:
13.64 +
13.65 +(1) GPL-compatible doesn't mean that we're distributing Python under
13.66 + the GPL. All Python licenses, unlike the GPL, let you distribute
13.67 + a modified version without making your changes open source. The
13.68 + GPL-compatible licenses make it possible to combine Python with
13.69 + other software that is released under the GPL; the others don't.
13.70 +
13.71 +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
13.72 + because its license has a choice of law clause. According to
13.73 + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
13.74 + is "not incompatible" with the GPL.
13.75 +
13.76 +Thanks to the many outside volunteers who have worked under Guido's
13.77 +direction to make these releases possible.
13.78 +
13.79 +
13.80 +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
13.81 +===============================================================
13.82 +
13.83 +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
13.84 +--------------------------------------------
13.85 +
13.86 +1. This LICENSE AGREEMENT is between the Python Software Foundation
13.87 +("PSF"), and the Individual or Organization ("Licensee") accessing and
13.88 +otherwise using this software ("Python") in source or binary form and
13.89 +its associated documentation.
13.90 +
13.91 +2. Subject to the terms and conditions of this License Agreement, PSF
13.92 +hereby grants Licensee a nonexclusive, royalty-free, world-wide
13.93 +license to reproduce, analyze, test, perform and/or display publicly,
13.94 +prepare derivative works, distribute, and otherwise use Python
13.95 +alone or in any derivative version, provided, however, that PSF's
13.96 +License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
13.97 +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Python Software Foundation;
13.98 +All Rights Reserved" are retained in Python alone or in any derivative
13.99 +version prepared by Licensee.
13.100 +
13.101 +3. In the event Licensee prepares a derivative work that is based on
13.102 +or incorporates Python or any part thereof, and wants to make
13.103 +the derivative work available to others as provided herein, then
13.104 +Licensee hereby agrees to include in any such work a brief summary of
13.105 +the changes made to Python.
13.106 +
13.107 +4. PSF is making Python available to Licensee on an "AS IS"
13.108 +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
13.109 +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
13.110 +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
13.111 +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
13.112 +INFRINGE ANY THIRD PARTY RIGHTS.
13.113 +
13.114 +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
13.115 +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
13.116 +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
13.117 +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
13.118 +
13.119 +6. This License Agreement will automatically terminate upon a material
13.120 +breach of its terms and conditions.
13.121 +
13.122 +7. Nothing in this License Agreement shall be deemed to create any
13.123 +relationship of agency, partnership, or joint venture between PSF and
13.124 +Licensee. This License Agreement does not grant permission to use PSF
13.125 +trademarks or trade name in a trademark sense to endorse or promote
13.126 +products or services of Licensee, or any third party.
13.127 +
13.128 +8. By copying, installing or otherwise using Python, Licensee
13.129 +agrees to be bound by the terms and conditions of this License
13.130 +Agreement.
13.131 +
13.132 +
13.133 +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
13.134 +-------------------------------------------
13.135 +
13.136 +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
13.137 +
13.138 +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
13.139 +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
13.140 +Individual or Organization ("Licensee") accessing and otherwise using
13.141 +this software in source or binary form and its associated
13.142 +documentation ("the Software").
13.143 +
13.144 +2. Subject to the terms and conditions of this BeOpen Python License
13.145 +Agreement, BeOpen hereby grants Licensee a non-exclusive,
13.146 +royalty-free, world-wide license to reproduce, analyze, test, perform
13.147 +and/or display publicly, prepare derivative works, distribute, and
13.148 +otherwise use the Software alone or in any derivative version,
13.149 +provided, however, that the BeOpen Python License is retained in the
13.150 +Software, alone or in any derivative version prepared by Licensee.
13.151 +
13.152 +3. BeOpen is making the Software available to Licensee on an "AS IS"
13.153 +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
13.154 +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
13.155 +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
13.156 +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
13.157 +INFRINGE ANY THIRD PARTY RIGHTS.
13.158 +
13.159 +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
13.160 +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
13.161 +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
13.162 +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
13.163 +
13.164 +5. This License Agreement will automatically terminate upon a material
13.165 +breach of its terms and conditions.
13.166 +
13.167 +6. This License Agreement shall be governed by and interpreted in all
13.168 +respects by the law of the State of California, excluding conflict of
13.169 +law provisions. Nothing in this License Agreement shall be deemed to
13.170 +create any relationship of agency, partnership, or joint venture
13.171 +between BeOpen and Licensee. This License Agreement does not grant
13.172 +permission to use BeOpen trademarks or trade names in a trademark
13.173 +sense to endorse or promote products or services of Licensee, or any
13.174 +third party. As an exception, the "BeOpen Python" logos available at
13.175 +http://www.pythonlabs.com/logos.html may be used according to the
13.176 +permissions granted on that web page.
13.177 +
13.178 +7. By copying, installing or otherwise using the software, Licensee
13.179 +agrees to be bound by the terms and conditions of this License
13.180 +Agreement.
13.181 +
13.182 +
13.183 +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
13.184 +---------------------------------------
13.185 +
13.186 +1. This LICENSE AGREEMENT is between the Corporation for National
13.187 +Research Initiatives, having an office at 1895 Preston White Drive,
13.188 +Reston, VA 20191 ("CNRI"), and the Individual or Organization
13.189 +("Licensee") accessing and otherwise using Python 1.6.1 software in
13.190 +source or binary form and its associated documentation.
13.191 +
13.192 +2. Subject to the terms and conditions of this License Agreement, CNRI
13.193 +hereby grants Licensee a nonexclusive, royalty-free, world-wide
13.194 +license to reproduce, analyze, test, perform and/or display publicly,
13.195 +prepare derivative works, distribute, and otherwise use Python 1.6.1
13.196 +alone or in any derivative version, provided, however, that CNRI's
13.197 +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
13.198 +1995-2001 Corporation for National Research Initiatives; All Rights
13.199 +Reserved" are retained in Python 1.6.1 alone or in any derivative
13.200 +version prepared by Licensee. Alternately, in lieu of CNRI's License
13.201 +Agreement, Licensee may substitute the following text (omitting the
13.202 +quotes): "Python 1.6.1 is made available subject to the terms and
13.203 +conditions in CNRI's License Agreement. This Agreement together with
13.204 +Python 1.6.1 may be located on the Internet using the following
13.205 +unique, persistent identifier (known as a handle): 1895.22/1013. This
13.206 +Agreement may also be obtained from a proxy server on the Internet
13.207 +using the following URL: http://hdl.handle.net/1895.22/1013".
13.208 +
13.209 +3. In the event Licensee prepares a derivative work that is based on
13.210 +or incorporates Python 1.6.1 or any part thereof, and wants to make
13.211 +the derivative work available to others as provided herein, then
13.212 +Licensee hereby agrees to include in any such work a brief summary of
13.213 +the changes made to Python 1.6.1.
13.214 +
13.215 +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
13.216 +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
13.217 +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
13.218 +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
13.219 +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
13.220 +INFRINGE ANY THIRD PARTY RIGHTS.
13.221 +
13.222 +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
13.223 +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
13.224 +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
13.225 +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
13.226 +
13.227 +6. This License Agreement will automatically terminate upon a material
13.228 +breach of its terms and conditions.
13.229 +
13.230 +7. This License Agreement shall be governed by the federal
13.231 +intellectual property law of the United States, including without
13.232 +limitation the federal copyright law, and, to the extent such
13.233 +U.S. federal law does not apply, by the law of the Commonwealth of
13.234 +Virginia, excluding Virginia's conflict of law provisions.
13.235 +Notwithstanding the foregoing, with regard to derivative works based
13.236 +on Python 1.6.1 that incorporate non-separable material that was
13.237 +previously distributed under the GNU General Public License (GPL), the
13.238 +law of the Commonwealth of Virginia shall govern this License
13.239 +Agreement only as to issues arising under or with respect to
13.240 +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
13.241 +License Agreement shall be deemed to create any relationship of
13.242 +agency, partnership, or joint venture between CNRI and Licensee. This
13.243 +License Agreement does not grant permission to use CNRI trademarks or
13.244 +trade name in a trademark sense to endorse or promote products or
13.245 +services of Licensee, or any third party.
13.246 +
13.247 +8. By clicking on the "ACCEPT" button where indicated, or by copying,
13.248 +installing or otherwise using Python 1.6.1, Licensee agrees to be
13.249 +bound by the terms and conditions of this License Agreement.
13.250 +
13.251 + ACCEPT
13.252 +
13.253 +
13.254 +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
13.255 +--------------------------------------------------
13.256 +
13.257 +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
13.258 +The Netherlands. All rights reserved.
13.259 +
13.260 +Permission to use, copy, modify, and distribute this software and its
13.261 +documentation for any purpose and without fee is hereby granted,
13.262 +provided that the above copyright notice appear in all copies and that
13.263 +both that copyright notice and this permission notice appear in
13.264 +supporting documentation, and that the name of Stichting Mathematisch
13.265 +Centrum or CWI not be used in advertising or publicity pertaining to
13.266 +distribution of the software without specific, written prior
13.267 +permission.
13.268 +
13.269 +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
13.270 +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13.271 +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
13.272 +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.273 +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13.274 +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13.275 +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.