# HG changeset patch # User Paul Boddie # Date 1341525111 -7200 # Node ID 0e461c6cca7fcfaf85eca4575dbfc9164bdba013 # Parent 3dea01325c0d4fb0b9451edc5933f9bb4101de8b Added string "display" representations for the nodes, allowing ASTs to be printed and appear as source code. diff -r 3dea01325c0d -r 0e461c6cca7f compiler/ast.py --- a/compiler/ast.py Tue Jun 12 00:17:27 2012 +0200 +++ b/compiler/ast.py Thu Jul 05 23:51:51 2012 +0200 @@ -18,6 +18,26 @@ def flatten_nodes(seq): return [n for n in flatten(seq) if isinstance(n, Node)] +def indent(s): + return s.replace("\n", "\n\t") + +def decode_function(node): + star = (node.flags & 4 != 0) and 1 or 0 + dstar = (node.flags & 8 != 0) and 1 or 0 + argnames = node.argnames[:] + + # Add stars to star and dstar parameters. + + if star: + argnames[-dstar-star] = "*%s" % argnames[-dstar-star] + if dstar: + argnames[-dstar] = "**%s" % argnames[-dstar] + + # Map defaults to parameters. + + defaults = [None] * (len(node.argnames) - star - dstar - len(node.defaults)) + list(node.defaults) + [None] * (star + dstar) + return [(default and "%s=%s" % (argname, default) or argname) for (argname, default) in zip(argnames, defaults)] + nodes = {} class Node: @@ -52,6 +72,9 @@ def __repr__(self): return "Expression(%r)" % (self.node,) + def __str__(self): + return str(self.node) + def visit(self, visitor, *args): return visitor.visitExpression(self, *args) @@ -70,6 +93,9 @@ def __repr__(self): return "Add((%r, %r))" % (self.left, self.right) + def __str__(self): + return "%s + %s" % (self.left, self.right) + def visit(self, visitor, *args): return visitor.visitAdd(self, *args) @@ -89,6 +115,9 @@ def __repr__(self): return "And(%r)" % (self.nodes,) + def __str__(self): + return " and ".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitAnd(self, *args) @@ -108,6 +137,9 @@ def __repr__(self): return "AssAttr(%r, %r, %r)" % (self.expr, self.attrname, self.flags) + def __str__(self): + return "%s.%s" % (self.expr, self.attrname) # NOTE: self.flags not used + def visit(self, visitor, *args): return visitor.visitAssAttr(self, *args) @@ -127,6 +159,9 @@ def __repr__(self): return "AssList(%r)" % (self.nodes,) + def __str__(self): + return "[%s]" % ", ".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitAssList(self, *args) @@ -145,6 +180,9 @@ def __repr__(self): return "AssName(%r, %r)" % (self.name, self.flags) + def __str__(self): + return str(self.name) # NOTE: self.flags not used + def visit(self, visitor, *args): return visitor.visitAssName(self, *args) @@ -164,6 +202,9 @@ def __repr__(self): return "AssTuple(%r)" % (self.nodes,) + def __str__(self): + return "(%s)" % ", ".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitAssTuple(self, *args) @@ -189,6 +230,9 @@ def __repr__(self): return "Assert(%r, %r)" % (self.test, self.fail) + def __str__(self): + return "assert %s%s" % (self.test, self.fail and ", %s" % self.fail or "") + def visit(self, visitor, *args): return visitor.visitAssert(self, *args) @@ -213,6 +257,9 @@ def __repr__(self): return "Assign(%r, %r)" % (self.nodes, self.expr) + def __str__(self): + return "%s = %s" % (", ".join(map(str, self.nodes)), self.expr) + def visit(self, visitor, *args): return visitor.visitAssign(self, *args) @@ -232,6 +279,9 @@ def __repr__(self): return "AugAssign(%r, %r, %r)" % (self.node, self.op, self.expr) + def __str__(self): + return "%s %s %s" % (self.node, self.op, self.expr) + def visit(self, visitor, *args): return visitor.visitAugAssign(self, *args) @@ -249,6 +299,9 @@ def __repr__(self): return "Backquote(%r)" % (self.expr,) + def __str__(self): + return "`%s`" % self.expr + def visit(self, visitor, *args): return visitor.visitBackquote(self, *args) @@ -268,6 +321,9 @@ def __repr__(self): return "Bitand(%r)" % (self.nodes,) + def __str__(self): + return " & ".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitBitand(self, *args) @@ -287,6 +343,9 @@ def __repr__(self): return "Bitor(%r)" % (self.nodes,) + def __str__(self): + return " | ".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitBitor(self, *args) @@ -306,6 +365,9 @@ def __repr__(self): return "Bitxor(%r)" % (self.nodes,) + def __str__(self): + return " ^ ".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitBitxor(self, *args) @@ -322,6 +384,9 @@ def __repr__(self): return "Break()" + def __str__(self): + return "break" + def visit(self, visitor, *args): return visitor.visitBreak(self, *args) @@ -354,6 +419,11 @@ def __repr__(self): return "CallFunc(%r, %r, %r, %r)" % (self.node, self.args, self.star_args, self.dstar_args) + def __str__(self): + star_args = self.star_args and ["*%s" % self.star_args] or [] + dstar_args = self.dstar_args and ["**%s" % self.dstar_args] or [] + return "%s(%s)" % (self.node, ", ".join(map(str, self.args + star_args + dstar_args))) + def visit(self, visitor, *args): return visitor.visitCallFunc(self, *args) @@ -386,6 +456,15 @@ def __repr__(self): return "Class(%r, %r, %r, %r, %r)" % (self.name, self.bases, self.doc, self.code, self.decorators) + def __str__(self): + return "%sclass %s%s:%s%s" % ( + self.decorators and "%s\n" % "\n".join([("@%s" % decorator) for decorator in self.decorators]) or "", + self.name, + self.bases and "(%s)" % ", ".join(map(str, self.bases)) or "", + indent(self.doc and "\n%r" % self.doc or ""), + indent("\n%s" % self.code) + ) + def visit(self, visitor, *args): return visitor.visitClass(self, *args) @@ -410,6 +489,9 @@ def __repr__(self): return "Compare(%r, %r)" % (self.expr, self.ops) + def __str__(self): + return "%s %s" % (self.expr, " ".join([("%s %s" % op) for op in self.ops])) + def visit(self, visitor, *args): return visitor.visitCompare(self, *args) @@ -427,6 +509,9 @@ def __repr__(self): return "Const(%r)" % (self.value,) + def __str__(self): + return repr(self.value) + def visit(self, visitor, *args): return visitor.visitConst(self, *args) @@ -443,6 +528,9 @@ def __repr__(self): return "Continue()" + def __str__(self): + return "continue" + def visit(self, visitor, *args): return visitor.visitContinue(self, *args) @@ -462,6 +550,9 @@ def __repr__(self): return "Decorators(%r)" % (self.nodes,) + def __str__(self): + return "\n".join([("@%s" % node) for node in self.nodes]) + def visit(self, visitor, *args): return visitor.visitDecorators(self, *args) @@ -481,6 +572,9 @@ def __repr__(self): return "Dict(%r)" % (self.items,) + def __str__(self): + return "{%s}" % ", ".join(map(str, self.items)) + def visit(self, visitor, *args): return visitor.visitDict(self, *args) @@ -498,6 +592,9 @@ def __repr__(self): return "Discard(%r)" % (self.expr,) + def __str__(self): + return str(self.expr) + def visit(self, visitor, *args): return visitor.visitDiscard(self, *args) @@ -516,6 +613,9 @@ def __repr__(self): return "Div((%r, %r))" % (self.left, self.right) + def __str__(self): + return "%s / %s" % (self.left, self.right) + def visit(self, visitor, *args): return visitor.visitDiv(self, *args) @@ -532,6 +632,9 @@ def __repr__(self): return "Ellipsis()" + def __str__(self): + return "..." + def visit(self, visitor, *args): return visitor.visitEllipsis(self, *args) @@ -561,6 +664,10 @@ def __repr__(self): return "Exec(%r, %r, %r)" % (self.expr, self.locals, self.globals) + def __str__(self): + return "exec %s%s%s" % (self.expr, self.locals and ", %s" % self.locals or "", + self.globals and ", %s" % self.globals or "") + def visit(self, visitor, *args): return visitor.visitExec(self, *args) @@ -579,6 +686,9 @@ def __repr__(self): return "FloorDiv((%r, %r))" % (self.left, self.right) + def __str__(self): + return "%s // %s" % (self.left, self.right) + def visit(self, visitor, *args): return visitor.visitFloorDiv(self, *args) @@ -610,6 +720,13 @@ def __repr__(self): return "For(%r, %r, %r, %r)" % (self.assign, self.list, self.body, self.else_) + def __str__(self): + return "for %s in %s:%s%s" % ( + self.assign, self.list, + indent("\n%s" % self.body), + self.else_ and "\nelse:%s" % indent("\n%s" % self.else_) or "" + ) + def visit(self, visitor, *args): return visitor.visitFor(self, *args) @@ -629,6 +746,10 @@ def __repr__(self): return "From(%r, %r, %r)" % (self.modname, self.names, self.level) + def __str__(self): + return "from %s import %s" % (self.modname, + ", ".join([(alias and "%s as %s" % (name, alias) or name) for (name, alias) in self.names])) + def visit(self, visitor, *args): return visitor.visitFrom(self, *args) @@ -648,7 +769,6 @@ if flags & CO_VARKEYWORDS: self.kwargs = 1 - def getChildren(self): children = [] children.append(self.decorators) @@ -671,6 +791,17 @@ def __repr__(self): return "Function(%r, %r, %r, %r, %r, %r, %r)" % (self.decorators, self.name, self.argnames, self.defaults, self.flags, self.doc, self.code) + def __str__(self): + parameters = decode_function(self) + + return "%sdef %s(%s):%s%s" % ( + self.decorators and "%s\n" % "\n".join([("@%s" % decorator) for decorator in self.decorators]) or "", + self.name, + ", ".join(parameters), + indent(self.doc and "\n%r" % self.doc or ""), + indent("\n%s" % self.code) + ) + def visit(self, visitor, *args): return visitor.visitFunction(self, *args) @@ -681,7 +812,6 @@ self.argnames = ['.0'] self.varargs = self.kwargs = None - def getChildren(self): return self.code, @@ -691,6 +821,9 @@ def __repr__(self): return "GenExpr(%r)" % (self.code,) + def __str__(self): + return str(self.code) + def visit(self, visitor, *args): return visitor.visitGenExpr(self, *args) @@ -719,6 +852,12 @@ def __repr__(self): return "GenExprFor(%r, %r, %r)" % (self.assign, self.iter, self.ifs) + def __str__(self): + return "for %s in %s%s" % ( + self.assign, self.iter, + self.ifs and " ".join(map(str, self.ifs)) or "" + ) + def visit(self, visitor, *args): return visitor.visitGenExprFor(self, *args) @@ -736,6 +875,9 @@ def __repr__(self): return "GenExprIf(%r)" % (self.test,) + def __str__(self): + return "if %s" % self.test + def visit(self, visitor, *args): return visitor.visitGenExprIf(self, *args) @@ -760,6 +902,9 @@ def __repr__(self): return "GenExprInner(%r, %r)" % (self.expr, self.quals) + def __str__(self): + return "%s %s" % (self.expr, " ".join(map(str, self.quals))) + def visit(self, visitor, *args): return visitor.visitGenExprInner(self, *args) @@ -778,6 +923,9 @@ def __repr__(self): return "Getattr(%r, %r)" % (self.expr, self.attrname) + def __str__(self): + return "%s.%s" % (self.expr, self.attrname) + def visit(self, visitor, *args): return visitor.visitGetattr(self, *args) @@ -795,6 +943,9 @@ def __repr__(self): return "Global(%r)" % (self.names,) + def __str__(self): + return "global %s" % ", ".join(map(str, self.names)) + def visit(self, visitor, *args): return visitor.visitGlobal(self, *args) @@ -820,6 +971,13 @@ def __repr__(self): return "If(%r, %r)" % (self.tests, self.else_) + def __str__(self): + tests = [("%sif %s:%s" % (i > 0 and "el" or "", test, indent("\n%s" % body))) for (i, (test, body)) in enumerate(self.tests)] + return "%s%s" % ( + "\n".join(tests), + self.else_ and "\nelse:%s" % indent("\n%s" % self.else_) or "" + ) + def visit(self, visitor, *args): return visitor.visitIf(self, *args) @@ -839,6 +997,9 @@ def __repr__(self): return "IfExp(%r, %r, %r)" % (self.test, self.then, self.else_) + def __str__(self): + return "%s if %s else %s" % (self.then, self.test, self.else_) + def visit(self, visitor, *args): return visitor.visitIfExp(self, *args) @@ -856,6 +1017,10 @@ def __repr__(self): return "Import(%r)" % (self.names,) + def __str__(self): + return "import %s" % ( + ", ".join([(alias and "%s as %s" % (name, alias) or name) for (name, alias) in self.names])) + def visit(self, visitor, *args): return visitor.visitImport(self, *args) @@ -873,6 +1038,9 @@ def __repr__(self): return "Invert(%r)" % (self.expr,) + def __str__(self): + return "~%s" % self.expr + def visit(self, visitor, *args): return visitor.visitInvert(self, *args) @@ -891,6 +1059,9 @@ def __repr__(self): return "Keyword(%r, %r)" % (self.name, self.expr) + def __str__(self): + return "%s=%s" % (self.name, self.expr) + def visit(self, visitor, *args): return visitor.visitKeyword(self, *args) @@ -907,7 +1078,6 @@ if flags & CO_VARKEYWORDS: self.kwargs = 1 - def getChildren(self): children = [] children.append(self.argnames) @@ -925,6 +1095,10 @@ def __repr__(self): return "Lambda(%r, %r, %r, %r)" % (self.argnames, self.defaults, self.flags, self.code) + def __str__(self): + parameters = decode_function(self) + return "lambda %s: %s" % (", ".join(parameters), self.code) + def visit(self, visitor, *args): return visitor.visitLambda(self, *args) @@ -943,6 +1117,9 @@ def __repr__(self): return "LeftShift((%r, %r))" % (self.left, self.right) + def __str__(self): + return "%s << %s" % (self.left, self.right) + def visit(self, visitor, *args): return visitor.visitLeftShift(self, *args) @@ -962,6 +1139,9 @@ def __repr__(self): return "List(%r)" % (self.nodes,) + def __str__(self): + return "[%s]" % ", ".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitList(self, *args) @@ -986,6 +1166,9 @@ def __repr__(self): return "ListComp(%r, %r)" % (self.expr, self.quals) + def __str__(self): + return "%s %s" % (self.expr, " ".join(map(str, self.quals))) + def visit(self, visitor, *args): return visitor.visitListComp(self, *args) @@ -1013,6 +1196,12 @@ def __repr__(self): return "ListCompFor(%r, %r, %r)" % (self.assign, self.list, self.ifs) + def __str__(self): + return "for %s in %s%s" % ( + self.assign, self.list, + self.ifs and " ".join(map(str, self.ifs)) or "" + ) + def visit(self, visitor, *args): return visitor.visitListCompFor(self, *args) @@ -1030,6 +1219,9 @@ def __repr__(self): return "ListCompIf(%r)" % (self.test,) + def __str__(self): + return "if %s" % self.test + def visit(self, visitor, *args): return visitor.visitListCompIf(self, *args) @@ -1048,6 +1240,9 @@ def __repr__(self): return "Mod((%r, %r))" % (self.left, self.right) + def __str__(self): + return "%s %% %s" % (self.left, self.right) + def visit(self, visitor, *args): return visitor.visitMod(self, *args) @@ -1066,6 +1261,9 @@ def __repr__(self): return "Module(%r, %r)" % (self.doc, self.node) + def __str__(self): + return "%s%s" % (self.doc and "%r\n" % self.doc or "", self.node) + def visit(self, visitor, *args): return visitor.visitModule(self, *args) @@ -1084,6 +1282,9 @@ def __repr__(self): return "Mul((%r, %r))" % (self.left, self.right) + def __str__(self): + return "%s * %s" % (self.left, self.right) + def visit(self, visitor, *args): return visitor.visitMul(self, *args) @@ -1101,6 +1302,9 @@ def __repr__(self): return "Name(%r)" % (self.name,) + def __str__(self): + return str(self.name) + def visit(self, visitor, *args): return visitor.visitName(self, *args) @@ -1118,6 +1322,9 @@ def __repr__(self): return "Not(%r)" % (self.expr,) + def __str__(self): + return "not %s" % self.expr + def visit(self, visitor, *args): return visitor.visitNot(self, *args) @@ -1137,6 +1344,9 @@ def __repr__(self): return "Or(%r)" % (self.nodes,) + def __str__(self): + return " or ".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitOr(self, *args) @@ -1153,6 +1363,9 @@ def __repr__(self): return "Pass()" + def __str__(self): + return "pass" + def visit(self, visitor, *args): return visitor.visitPass(self, *args) @@ -1171,6 +1384,9 @@ def __repr__(self): return "Power((%r, %r))" % (self.left, self.right) + def __str__(self): + return "%s ** %s" % (self.left, self.right) + def visit(self, visitor, *args): return visitor.visitPower(self, *args) @@ -1196,6 +1412,10 @@ def __repr__(self): return "Print(%r, %r)" % (self.nodes, self.dest) + def __str__(self): + dest = self.dest and [">>%s" % self.dest] or [] + return "print %s," % ", ".join(map(str, dest + self.nodes)) + def visit(self, visitor, *args): return visitor.visitPrint(self, *args) @@ -1221,6 +1441,10 @@ def __repr__(self): return "Printnl(%r, %r)" % (self.nodes, self.dest) + def __str__(self): + dest = self.dest and [">>%s" % self.dest] or [] + return "print %s" % ", ".join(map(str, dest + self.nodes)) + def visit(self, visitor, *args): return visitor.visitPrintnl(self, *args) @@ -1251,6 +1475,12 @@ def __repr__(self): return "Raise(%r, %r, %r)" % (self.expr1, self.expr2, self.expr3) + def __str__(self): + args = self.expr1 and [self.expr1] or [] + args += self.expr2 and [self.expr2] or [] + args += self.expr3 and [self.expr3] or [] + return "raise %s" % ", ".join(map(str, args)) + def visit(self, visitor, *args): return visitor.visitRaise(self, *args) @@ -1268,6 +1498,9 @@ def __repr__(self): return "Return(%r)" % (self.value,) + def __str__(self): + return "return %s" % self.value + def visit(self, visitor, *args): return visitor.visitReturn(self, *args) @@ -1286,6 +1519,9 @@ def __repr__(self): return "RightShift((%r, %r))" % (self.left, self.right) + def __str__(self): + return "%s >> %s" % (self.left, self.right) + def visit(self, visitor, *args): return visitor.visitRightShift(self, *args) @@ -1317,6 +1553,12 @@ def __repr__(self): return "Slice(%r, %r, %r, %r)" % (self.expr, self.flags, self.lower, self.upper) + def __str__(self): + args = [] + args = self.lower is not None and [self.lower] or [] + args = self.upper is not None and [self.upper] or [] + return "%s[%s]" % (self.expr, ":".join(map(str, args))) + def visit(self, visitor, *args): return visitor.visitSlice(self, *args) @@ -1336,6 +1578,9 @@ def __repr__(self): return "Sliceobj(%r)" % (self.nodes,) + def __str__(self): + return ":".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitSliceobj(self, *args) @@ -1355,6 +1600,9 @@ def __repr__(self): return "Stmt(%r)" % (self.nodes,) + def __str__(self): + return "\n".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitStmt(self, *args) @@ -1373,6 +1621,9 @@ def __repr__(self): return "Sub((%r, %r))" % (self.left, self.right) + def __str__(self): + return "%s - %s" % (self.left, self.right) + def visit(self, visitor, *args): return visitor.visitSub(self, *args) @@ -1399,6 +1650,9 @@ def __repr__(self): return "Subscript(%r, %r, %r)" % (self.expr, self.flags, self.subs) + def __str__(self): + return "%s[%s]" % (self.expr, ",".join(map(str, self.subs))) + def visit(self, visitor, *args): return visitor.visitSubscript(self, *args) @@ -1427,6 +1681,18 @@ def __repr__(self): return "TryExcept(%r, %r, %r)" % (self.body, self.handlers, self.else_) + def __str__(self): + handlers = [ + ("\nexcept%s%s:%s" % (spec and " %s" % spec or "", assign and ", %s" % assign or "", indent("\n%s" % statement))) + for (spec, assign, statement) in self.handlers + ] + + return "try:%s%s%s" % ( + indent("\n%s" % self.body), + "".join(handlers), + self.else_ and "\nelse:%s" % indent("\n%s" % self.else_) or "" + ) + def visit(self, visitor, *args): return visitor.visitTryExcept(self, *args) @@ -1445,6 +1711,12 @@ def __repr__(self): return "TryFinally(%r, %r)" % (self.body, self.final) + def __str__(self): + return "try:%s\nfinally:%s" % ( + indent("\n%s" % self.body), + indent("\n%s" % self.final) + ) + def visit(self, visitor, *args): return visitor.visitTryFinally(self, *args) @@ -1464,6 +1736,9 @@ def __repr__(self): return "Tuple(%r)" % (self.nodes,) + def __str__(self): + return "(%s)" % ", ".join(map(str, self.nodes)) + def visit(self, visitor, *args): return visitor.visitTuple(self, *args) @@ -1481,6 +1756,9 @@ def __repr__(self): return "UnaryAdd(%r)" % (self.expr,) + def __str__(self): + return "+%s" % self.expr + def visit(self, visitor, *args): return visitor.visitUnaryAdd(self, *args) @@ -1498,6 +1776,9 @@ def __repr__(self): return "UnarySub(%r)" % (self.expr,) + def __str__(self): + return "-%s" % self.expr + def visit(self, visitor, *args): return visitor.visitUnarySub(self, *args) @@ -1526,6 +1807,13 @@ def __repr__(self): return "While(%r, %r, %r)" % (self.test, self.body, self.else_) + def __str__(self): + return "while %s:%s%s" % ( + self.test, + indent("\n%s" % self.body), + self.else_ and "\nelse:%s" % indent("\n%s" % self.else_) or "" + ) + def visit(self, visitor, *args): return visitor.visitWhile(self, *args) @@ -1554,6 +1842,13 @@ def __repr__(self): return "With(%r, %r, %r)" % (self.expr, self.vars, self.body) + def __str__(self): + return "with %s%s:%s" % ( + self.expr, + self.vars and " as %s" % ", ".join(map(str, self.vars)), + indent("\n%s" % self.body), + ) + def visit(self, visitor, *args): return visitor.visitWith(self, *args) @@ -1571,6 +1866,9 @@ def __repr__(self): return "Yield(%r)" % (self.value,) + def __str__(self): + return "yield %s" % self.value + def visit(self, visitor, *args): return visitor.visitYield(self, *args)