summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/compiler/ast.py434
-rw-r--r--Lib/compiler/transformer.py287
-rw-r--r--Lib/test/test_compiler.py59
-rw-r--r--Lib/test/test_transformer.py4
-rw-r--r--Misc/ACKS1
-rw-r--r--Tools/compiler/astgen.py69
6 files changed, 407 insertions, 447 deletions
diff --git a/Lib/compiler/ast.py b/Lib/compiler/ast.py
index 6f585b7..cfc2a51 100644
--- a/Lib/compiler/ast.py
+++ b/Lib/compiler/ast.py
@@ -1,15 +1,14 @@
"""Python abstract syntax node definitions
-This file is automatically generated.
+This file is automatically generated by Tools/compiler/astgen.py
"""
-from types import TupleType, ListType
from consts import CO_VARARGS, CO_VARKEYWORDS
def flatten(list):
l = []
for elt in list:
t = type(elt)
- if t is TupleType or t is ListType:
+ if t is tuple or t is list:
for elt2 in flatten(elt):
l.append(elt2)
else:
@@ -19,29 +18,17 @@ def flatten(list):
def flatten_nodes(list):
return [n for n in flatten(list) if isinstance(n, Node)]
-def asList(nodearg):
- l = []
- for item in nodearg:
- if hasattr(item, "asList"):
- l.append(item.asList())
- else:
- t = type(item)
- if t is TupleType or t is ListType:
- l.append(tuple(asList(item)))
- else:
- l.append(item)
- return l
-
nodes = {}
-class Node: # an abstract base class
- lineno = None # provide a lineno for nodes that don't have one
- def getType(self):
- pass # implemented by subclass
+class Node:
+ """Abstract base class for ast nodes."""
def getChildren(self):
pass # implemented by subclasses
- def asList(self):
- return tuple(asList(self.getChildren()))
+ def __iter__(self):
+ for n in self.getChildren():
+ yield n
+ def asList(self): # for backwards compatibility
+ return self.getChildren()
def getChildNodes(self):
pass # implemented by subclasses
@@ -64,10 +51,10 @@ class Expression(Node):
return "Expression(%s)" % (repr(self.node))
class Add(Node):
- nodes["add"] = "Add"
- def __init__(self, (left, right)):
+ def __init__(self, (left, right), lineno=None):
self.left = left
self.right = right
+ self.lineno = lineno
def getChildren(self):
return self.left, self.right
@@ -79,14 +66,12 @@ class Add(Node):
return "Add((%s, %s))" % (repr(self.left), repr(self.right))
class And(Node):
- nodes["and"] = "And"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -97,11 +82,11 @@ class And(Node):
return "And(%s)" % (repr(self.nodes),)
class AssAttr(Node):
- nodes["assattr"] = "AssAttr"
- def __init__(self, expr, attrname, flags):
+ def __init__(self, expr, attrname, flags, lineno=None):
self.expr = expr
self.attrname = attrname
self.flags = flags
+ self.lineno = lineno
def getChildren(self):
return self.expr, self.attrname, self.flags
@@ -113,14 +98,12 @@ class AssAttr(Node):
return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags))
class AssList(Node):
- nodes["asslist"] = "AssList"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -131,10 +114,10 @@ class AssList(Node):
return "AssList(%s)" % (repr(self.nodes),)
class AssName(Node):
- nodes["assname"] = "AssName"
- def __init__(self, name, flags):
+ def __init__(self, name, flags, lineno=None):
self.name = name
self.flags = flags
+ self.lineno = lineno
def getChildren(self):
return self.name, self.flags
@@ -146,14 +129,12 @@ class AssName(Node):
return "AssName(%s, %s)" % (repr(self.name), repr(self.flags))
class AssTuple(Node):
- nodes["asstuple"] = "AssTuple"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -164,10 +145,10 @@ class AssTuple(Node):
return "AssTuple(%s)" % (repr(self.nodes),)
class Assert(Node):
- nodes["assert"] = "Assert"
- def __init__(self, test, fail):
+ def __init__(self, test, fail, lineno=None):
self.test = test
self.fail = fail
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -178,17 +159,18 @@ class Assert(Node):
def getChildNodes(self):
nodelist = []
nodelist.append(self.test)
- if self.fail is not None: nodelist.append(self.fail)
+ if self.fail is not None:
+ nodelist.append(self.fail)
return tuple(nodelist)
def __repr__(self):
return "Assert(%s, %s)" % (repr(self.test), repr(self.fail))
class Assign(Node):
- nodes["assign"] = "Assign"
- def __init__(self, nodes, expr):
+ def __init__(self, nodes, expr, lineno=None):
self.nodes = nodes
self.expr = expr
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -206,11 +188,11 @@ class Assign(Node):
return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr))
class AugAssign(Node):
- nodes["augassign"] = "AugAssign"
- def __init__(self, node, op, expr):
+ def __init__(self, node, op, expr, lineno=None):
self.node = node
self.op = op
self.expr = expr
+ self.lineno = lineno
def getChildren(self):
return self.node, self.op, self.expr
@@ -222,9 +204,9 @@ class AugAssign(Node):
return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr))
class Backquote(Node):
- nodes["backquote"] = "Backquote"
- def __init__(self, expr):
+ def __init__(self, expr, lineno=None):
self.expr = expr
+ self.lineno = lineno
def getChildren(self):
return self.expr,
@@ -236,14 +218,12 @@ class Backquote(Node):
return "Backquote(%s)" % (repr(self.expr),)
class Bitand(Node):
- nodes["bitand"] = "Bitand"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -254,14 +234,12 @@ class Bitand(Node):
return "Bitand(%s)" % (repr(self.nodes),)
class Bitor(Node):
- nodes["bitor"] = "Bitor"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -272,14 +250,12 @@ class Bitor(Node):
return "Bitor(%s)" % (repr(self.nodes),)
class Bitxor(Node):
- nodes["bitxor"] = "Bitxor"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -290,9 +266,8 @@ class Bitxor(Node):
return "Bitxor(%s)" % (repr(self.nodes),)
class Break(Node):
- nodes["break"] = "Break"
- def __init__(self, ):
- pass
+ def __init__(self, lineno=None):
+ self.lineno = lineno
def getChildren(self):
return ()
@@ -304,12 +279,12 @@ class Break(Node):
return "Break()"
class CallFunc(Node):
- nodes["callfunc"] = "CallFunc"
- def __init__(self, node, args, star_args = None, dstar_args = None):
+ def __init__(self, node, args, star_args = None, dstar_args = None, lineno=None):
self.node = node
self.args = args
self.star_args = star_args
self.dstar_args = dstar_args
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -323,20 +298,22 @@ class CallFunc(Node):
nodelist = []
nodelist.append(self.node)
nodelist.extend(flatten_nodes(self.args))
- if self.star_args is not None: nodelist.append(self.star_args)
- if self.dstar_args is not None: nodelist.append(self.dstar_args)
+ if self.star_args is not None:
+ nodelist.append(self.star_args)
+ if self.dstar_args is not None:
+ nodelist.append(self.dstar_args)
return tuple(nodelist)
def __repr__(self):
return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args))
class Class(Node):
- nodes["class"] = "Class"
- def __init__(self, name, bases, doc, code):
+ def __init__(self, name, bases, doc, code, lineno=None):
self.name = name
self.bases = bases
self.doc = doc
self.code = code
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -356,10 +333,10 @@ class Class(Node):
return "Class(%s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code))
class Compare(Node):
- nodes["compare"] = "Compare"
- def __init__(self, expr, ops):
+ def __init__(self, expr, ops, lineno=None):
self.expr = expr
self.ops = ops
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -377,9 +354,9 @@ class Compare(Node):
return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops))
class Const(Node):
- nodes["const"] = "Const"
- def __init__(self, value):
+ def __init__(self, value, lineno=None):
self.value = value
+ self.lineno = lineno
def getChildren(self):
return self.value,
@@ -391,9 +368,8 @@ class Const(Node):
return "Const(%s)" % (repr(self.value),)
class Continue(Node):
- nodes["continue"] = "Continue"
- def __init__(self, ):
- pass
+ def __init__(self, lineno=None):
+ self.lineno = lineno
def getChildren(self):
return ()
@@ -405,28 +381,28 @@ class Continue(Node):
return "Continue()"
class Decorators(Node):
- nodes["decorators"] = "Decorators"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
return tuple(flatten(self.nodes))
def getChildNodes(self):
- return flatten_nodes(self.nodes)
+ nodelist = []
+ nodelist.extend(flatten_nodes(self.nodes))
+ return tuple(nodelist)
def __repr__(self):
return "Decorators(%s)" % (repr(self.nodes),)
class Dict(Node):
- nodes["dict"] = "Dict"
- def __init__(self, items):
+ def __init__(self, items, lineno=None):
self.items = items
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.items))
- return tuple(children)
+ return tuple(flatten(self.items))
def getChildNodes(self):
nodelist = []
@@ -437,9 +413,9 @@ class Dict(Node):
return "Dict(%s)" % (repr(self.items),)
class Discard(Node):
- nodes["discard"] = "Discard"
- def __init__(self, expr):
+ def __init__(self, expr, lineno=None):
self.expr = expr
+ self.lineno = lineno
def getChildren(self):
return self.expr,
@@ -451,10 +427,10 @@ class Discard(Node):
return "Discard(%s)" % (repr(self.expr),)
class Div(Node):
- nodes["div"] = "Div"
- def __init__(self, (left, right)):
+ def __init__(self, (left, right), lineno=None):
self.left = left
self.right = right
+ self.lineno = lineno
def getChildren(self):
return self.left, self.right
@@ -466,9 +442,8 @@ class Div(Node):
return "Div((%s, %s))" % (repr(self.left), repr(self.right))
class Ellipsis(Node):
- nodes["ellipsis"] = "Ellipsis"
- def __init__(self, ):
- pass
+ def __init__(self, lineno=None):
+ self.lineno = lineno
def getChildren(self):
return ()
@@ -480,11 +455,11 @@ class Ellipsis(Node):
return "Ellipsis()"
class Exec(Node):
- nodes["exec"] = "Exec"
- def __init__(self, expr, locals, globals):
+ def __init__(self, expr, locals, globals, lineno=None):
self.expr = expr
self.locals = locals
self.globals = globals
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -496,18 +471,20 @@ class Exec(Node):
def getChildNodes(self):
nodelist = []
nodelist.append(self.expr)
- if self.locals is not None: nodelist.append(self.locals)
- if self.globals is not None: nodelist.append(self.globals)
+ if self.locals is not None:
+ nodelist.append(self.locals)
+ if self.globals is not None:
+ nodelist.append(self.globals)
return tuple(nodelist)
def __repr__(self):
return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals))
class FloorDiv(Node):
- nodes["floordiv"] = "FloorDiv"
- def __init__(self, (left, right)):
+ def __init__(self, (left, right), lineno=None):
self.left = left
self.right = right
+ self.lineno = lineno
def getChildren(self):
return self.left, self.right
@@ -519,12 +496,12 @@ class FloorDiv(Node):
return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right))
class For(Node):
- nodes["for"] = "For"
- def __init__(self, assign, list, body, else_):
+ def __init__(self, assign, list, body, else_, lineno=None):
self.assign = assign
self.list = list
self.body = body
self.else_ = else_
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -539,17 +516,18 @@ class For(Node):
nodelist.append(self.assign)
nodelist.append(self.list)
nodelist.append(self.body)
- if self.else_ is not None: nodelist.append(self.else_)
+ if self.else_ is not None:
+ nodelist.append(self.else_)
return tuple(nodelist)
def __repr__(self):
return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_))
class From(Node):
- nodes["from"] = "From"
- def __init__(self, modname, names):
+ def __init__(self, modname, names, lineno=None):
self.modname = modname
self.names = names
+ self.lineno = lineno
def getChildren(self):
return self.modname, self.names
@@ -561,8 +539,7 @@ class From(Node):
return "From(%s, %s)" % (repr(self.modname), repr(self.names))
class Function(Node):
- nodes["function"] = "Function"
- def __init__(self, decorators, name, argnames, defaults, flags, doc, code):
+ def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None):
self.decorators = decorators
self.name = name
self.argnames = argnames
@@ -570,18 +547,18 @@ class Function(Node):
self.flags = flags
self.doc = doc
self.code = code
+ self.lineno = lineno
self.varargs = self.kwargs = None
if flags & CO_VARARGS:
self.varargs = 1
if flags & CO_VARKEYWORDS:
self.kwargs = 1
-
+
def getChildren(self):
children = []
- if self.decorators:
- children.append(flatten(self.decorators.nodes))
+ children.append(self.decorators)
children.append(self.name)
children.append(self.argnames)
children.extend(flatten(self.defaults))
@@ -592,8 +569,8 @@ class Function(Node):
def getChildNodes(self):
nodelist = []
- if self.decorators:
- nodelist.extend(flatten_nodes(self.decorators.nodes))
+ if self.decorators is not None:
+ nodelist.append(self.decorators)
nodelist.extend(flatten_nodes(self.defaults))
nodelist.append(self.code)
return tuple(nodelist)
@@ -602,12 +579,12 @@ class Function(Node):
return "Function(%s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code))
class GenExpr(Node):
- nodes["genexpr"] = "GenExpr"
- def __init__(self, code):
+ def __init__(self, code, lineno=None):
self.code = code
+ self.lineno = lineno
self.argnames = ['[outmost-iterable]']
self.varargs = self.kwargs = None
-
+
def getChildren(self):
@@ -620,11 +597,11 @@ class GenExpr(Node):
return "GenExpr(%s)" % (repr(self.code),)
class GenExprFor(Node):
- nodes["genexprfor"] = "GenExprFor"
- def __init__(self, assign, iter, ifs):
+ def __init__(self, assign, iter, ifs, lineno=None):
self.assign = assign
self.iter = iter
self.ifs = ifs
+ self.lineno = lineno
self.is_outmost = False
@@ -646,9 +623,9 @@ class GenExprFor(Node):
return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs))
class GenExprIf(Node):
- nodes["genexprif"] = "GenExprIf"
- def __init__(self, test):
+ def __init__(self, test, lineno=None):
self.test = test
+ self.lineno = lineno
def getChildren(self):
return self.test,
@@ -660,10 +637,10 @@ class GenExprIf(Node):
return "GenExprIf(%s)" % (repr(self.test),)
class GenExprInner(Node):
- nodes["genexprinner"] = "GenExprInner"
- def __init__(self, expr, quals):
+ def __init__(self, expr, quals, lineno=None):
self.expr = expr
self.quals = quals
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -681,10 +658,10 @@ class GenExprInner(Node):
return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals))
class Getattr(Node):
- nodes["getattr"] = "Getattr"
- def __init__(self, expr, attrname):
+ def __init__(self, expr, attrname, lineno=None):
self.expr = expr
self.attrname = attrname
+ self.lineno = lineno
def getChildren(self):
return self.expr, self.attrname
@@ -696,9 +673,9 @@ class Getattr(Node):
return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname))
class Global(Node):
- nodes["global"] = "Global"
- def __init__(self, names):
+ def __init__(self, names, lineno=None):
self.names = names
+ self.lineno = lineno
def getChildren(self):
return self.names,
@@ -710,10 +687,10 @@ class Global(Node):
return "Global(%s)" % (repr(self.names),)
class If(Node):
- nodes["if"] = "If"
- def __init__(self, tests, else_):
+ def __init__(self, tests, else_, lineno=None):
self.tests = tests
self.else_ = else_
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -724,16 +701,17 @@ class If(Node):
def getChildNodes(self):
nodelist = []
nodelist.extend(flatten_nodes(self.tests))
- if self.else_ is not None: nodelist.append(self.else_)
+ if self.else_ is not None:
+ nodelist.append(self.else_)
return tuple(nodelist)
def __repr__(self):
return "If(%s, %s)" % (repr(self.tests), repr(self.else_))
class Import(Node):
- nodes["import"] = "Import"
- def __init__(self, names):
+ def __init__(self, names, lineno=None):
self.names = names
+ self.lineno = lineno
def getChildren(self):
return self.names,
@@ -745,9 +723,9 @@ class Import(Node):
return "Import(%s)" % (repr(self.names),)
class Invert(Node):
- nodes["invert"] = "Invert"
- def __init__(self, expr):
+ def __init__(self, expr, lineno=None):
self.expr = expr
+ self.lineno = lineno
def getChildren(self):
return self.expr,
@@ -759,10 +737,10 @@ class Invert(Node):
return "Invert(%s)" % (repr(self.expr),)
class Keyword(Node):
- nodes["keyword"] = "Keyword"
- def __init__(self, name, expr):
+ def __init__(self, name, expr, lineno=None):
self.name = name
self.expr = expr
+ self.lineno = lineno
def getChildren(self):
return self.name, self.expr
@@ -774,18 +752,18 @@ class Keyword(Node):
return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
class Lambda(Node):
- nodes["lambda"] = "Lambda"
- def __init__(self, argnames, defaults, flags, code):
+ def __init__(self, argnames, defaults, flags, code, lineno=None):
self.argnames = argnames
self.defaults = defaults
self.flags = flags
self.code = code
+ self.lineno = lineno
self.varargs = self.kwargs = None
if flags & CO_VARARGS:
self.varargs = 1
if flags & CO_VARKEYWORDS:
self.kwargs = 1
-
+
def getChildren(self):
@@ -806,10 +784,10 @@ class Lambda(Node):
return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code))
class LeftShift(Node):
- nodes["leftshift"] = "LeftShift"
- def __init__(self, (left, right)):
+ def __init__(self, (left, right), lineno=None):
self.left = left
self.right = right
+ self.lineno = lineno
def getChildren(self):
return self.left, self.right
@@ -821,14 +799,12 @@ class LeftShift(Node):
return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right))
class List(Node):
- nodes["list"] = "List"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -839,10 +815,10 @@ class List(Node):
return "List(%s)" % (repr(self.nodes),)
class ListComp(Node):
- nodes["listcomp"] = "ListComp"
- def __init__(self, expr, quals):
+ def __init__(self, expr, quals, lineno=None):
self.expr = expr
self.quals = quals
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -860,11 +836,11 @@ class ListComp(Node):
return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals))
class ListCompFor(Node):
- nodes["listcompfor"] = "ListCompFor"
- def __init__(self, assign, list, ifs):
+ def __init__(self, assign, list, ifs, lineno=None):
self.assign = assign
self.list = list
self.ifs = ifs
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -884,9 +860,9 @@ class ListCompFor(Node):
return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs))
class ListCompIf(Node):
- nodes["listcompif"] = "ListCompIf"
- def __init__(self, test):
+ def __init__(self, test, lineno=None):
self.test = test
+ self.lineno = lineno
def getChildren(self):
return self.test,
@@ -898,10 +874,10 @@ class ListCompIf(Node):
return "ListCompIf(%s)" % (repr(self.test),)
class Mod(Node):
- nodes["mod"] = "Mod"
- def __init__(self, (left, right)):
+ def __init__(self, (left, right), lineno=None):
self.left = left
self.right = right
+ self.lineno = lineno
def getChildren(self):
return self.left, self.right
@@ -913,10 +889,10 @@ class Mod(Node):
return "Mod((%s, %s))" % (repr(self.left), repr(self.right))
class Module(Node):
- nodes["module"] = "Module"
- def __init__(self, doc, node):
+ def __init__(self, doc, node, lineno=None):
self.doc = doc
self.node = node
+ self.lineno = lineno
def getChildren(self):
return self.doc, self.node
@@ -928,10 +904,10 @@ class Module(Node):
return "Module(%s, %s)" % (repr(self.doc), repr(self.node))
class Mul(Node):
- nodes["mul"] = "Mul"
- def __init__(self, (left, right)):
+ def __init__(self, (left, right), lineno=None):
self.left = left
self.right = right
+ self.lineno = lineno
def getChildren(self):
return self.left, self.right
@@ -943,9 +919,9 @@ class Mul(Node):
return "Mul((%s, %s))" % (repr(self.left), repr(self.right))
class Name(Node):
- nodes["name"] = "Name"
- def __init__(self, name):
+ def __init__(self, name, lineno=None):
self.name = name
+ self.lineno = lineno
def getChildren(self):
return self.name,
@@ -957,9 +933,9 @@ class Name(Node):
return "Name(%s)" % (repr(self.name),)
class Not(Node):
- nodes["not"] = "Not"
- def __init__(self, expr):
+ def __init__(self, expr, lineno=None):
self.expr = expr
+ self.lineno = lineno
def getChildren(self):
return self.expr,
@@ -971,14 +947,12 @@ class Not(Node):
return "Not(%s)" % (repr(self.expr),)
class Or(Node):
- nodes["or"] = "Or"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -989,9 +963,8 @@ class Or(Node):
return "Or(%s)" % (repr(self.nodes),)
class Pass(Node):
- nodes["pass"] = "Pass"
- def __init__(self, ):
- pass
+ def __init__(self, lineno=None):
+ self.lineno = lineno
def getChildren(self):
return ()
@@ -1003,10 +976,10 @@ class Pass(Node):
return "Pass()"
class Power(Node):
- nodes["power"] = "Power"
- def __init__(self, (left, right)):
+ def __init__(self, (left, right), lineno=None):
self.left = left
self.right = right
+ self.lineno = lineno
def getChildren(self):
return self.left, self.right
@@ -1018,10 +991,10 @@ class Power(Node):
return "Power((%s, %s))" % (repr(self.left), repr(self.right))
class Print(Node):
- nodes["print"] = "Print"
- def __init__(self, nodes, dest):
+ def __init__(self, nodes, dest, lineno=None):
self.nodes = nodes
self.dest = dest
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -1032,17 +1005,18 @@ class Print(Node):
def getChildNodes(self):
nodelist = []
nodelist.extend(flatten_nodes(self.nodes))
- if self.dest is not None: nodelist.append(self.dest)
+ if self.dest is not None:
+ nodelist.append(self.dest)
return tuple(nodelist)
def __repr__(self):
return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest))
class Printnl(Node):
- nodes["printnl"] = "Printnl"
- def __init__(self, nodes, dest):
+ def __init__(self, nodes, dest, lineno=None):
self.nodes = nodes
self.dest = dest
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -1053,18 +1027,19 @@ class Printnl(Node):
def getChildNodes(self):
nodelist = []
nodelist.extend(flatten_nodes(self.nodes))
- if self.dest is not None: nodelist.append(self.dest)
+ if self.dest is not None:
+ nodelist.append(self.dest)
return tuple(nodelist)
def __repr__(self):
return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest))
class Raise(Node):
- nodes["raise"] = "Raise"
- def __init__(self, expr1, expr2, expr3):
+ def __init__(self, expr1, expr2, expr3, lineno=None):
self.expr1 = expr1
self.expr2 = expr2
self.expr3 = expr3
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -1075,18 +1050,21 @@ class Raise(Node):
def getChildNodes(self):
nodelist = []
- if self.expr1 is not None: nodelist.append(self.expr1)
- if self.expr2 is not None: nodelist.append(self.expr2)
- if self.expr3 is not None: nodelist.append(self.expr3)
+ if self.expr1 is not None:
+ nodelist.append(self.expr1)
+ if self.expr2 is not None:
+ nodelist.append(self.expr2)
+ if self.expr3 is not None:
+ nodelist.append(self.expr3)
return tuple(nodelist)
def __repr__(self):
return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3))
class Return(Node):
- nodes["return"] = "Return"
- def __init__(self, value):
+ def __init__(self, value, lineno=None):
self.value = value
+ self.lineno = lineno
def getChildren(self):
return self.value,
@@ -1098,10 +1076,10 @@ class Return(Node):
return "Return(%s)" % (repr(self.value),)
class RightShift(Node):
- nodes["rightshift"] = "RightShift"
- def __init__(self, (left, right)):
+ def __init__(self, (left, right), lineno=None):
self.left = left
self.right = right
+ self.lineno = lineno
def getChildren(self):
return self.left, self.right
@@ -1113,12 +1091,12 @@ class RightShift(Node):
return "RightShift((%s, %s))" % (repr(self.left), repr(self.right))
class Slice(Node):
- nodes["slice"] = "Slice"
- def __init__(self, expr, flags, lower, upper):
+ def __init__(self, expr, flags, lower, upper, lineno=None):
self.expr = expr
self.flags = flags
self.lower = lower
self.upper = upper
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -1131,22 +1109,22 @@ class Slice(Node):
def getChildNodes(self):
nodelist = []
nodelist.append(self.expr)
- if self.lower is not None: nodelist.append(self.lower)
- if self.upper is not None: nodelist.append(self.upper)
+ if self.lower is not None:
+ nodelist.append(self.lower)
+ if self.upper is not None:
+ nodelist.append(self.upper)
return tuple(nodelist)
def __repr__(self):
return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper))
class Sliceobj(Node):
- nodes["sliceobj"] = "Sliceobj"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -1157,14 +1135,12 @@ class Sliceobj(Node):
return "Sliceobj(%s)" % (repr(self.nodes),)
class Stmt(Node):
- nodes["stmt"] = "Stmt"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -1175,10 +1151,10 @@ class Stmt(Node):
return "Stmt(%s)" % (repr(self.nodes),)
class Sub(Node):
- nodes["sub"] = "Sub"
- def __init__(self, (left, right)):
+ def __init__(self, (left, right), lineno=None):
self.left = left
self.right = right
+ self.lineno = lineno
def getChildren(self):
return self.left, self.right
@@ -1190,11 +1166,11 @@ class Sub(Node):
return "Sub((%s, %s))" % (repr(self.left), repr(self.right))
class Subscript(Node):
- nodes["subscript"] = "Subscript"
- def __init__(self, expr, flags, subs):
+ def __init__(self, expr, flags, subs, lineno=None):
self.expr = expr
self.flags = flags
self.subs = subs
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -1213,11 +1189,11 @@ class Subscript(Node):
return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs))
class TryExcept(Node):
- nodes["tryexcept"] = "TryExcept"
- def __init__(self, body, handlers, else_):
+ def __init__(self, body, handlers, else_, lineno=None):
self.body = body
self.handlers = handlers
self.else_ = else_
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -1230,17 +1206,18 @@ class TryExcept(Node):
nodelist = []
nodelist.append(self.body)
nodelist.extend(flatten_nodes(self.handlers))
- if self.else_ is not None: nodelist.append(self.else_)
+ if self.else_ is not None:
+ nodelist.append(self.else_)
return tuple(nodelist)
def __repr__(self):
return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_))
class TryFinally(Node):
- nodes["tryfinally"] = "TryFinally"
- def __init__(self, body, final):
+ def __init__(self, body, final, lineno=None):
self.body = body
self.final = final
+ self.lineno = lineno
def getChildren(self):
return self.body, self.final
@@ -1252,14 +1229,12 @@ class TryFinally(Node):
return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final))
class Tuple(Node):
- nodes["tuple"] = "Tuple"
- def __init__(self, nodes):
+ def __init__(self, nodes, lineno=None):
self.nodes = nodes
+ self.lineno = lineno
def getChildren(self):
- children = []
- children.extend(flatten(self.nodes))
- return tuple(children)
+ return tuple(flatten(self.nodes))
def getChildNodes(self):
nodelist = []
@@ -1270,9 +1245,9 @@ class Tuple(Node):
return "Tuple(%s)" % (repr(self.nodes),)
class UnaryAdd(Node):
- nodes["unaryadd"] = "UnaryAdd"
- def __init__(self, expr):
+ def __init__(self, expr, lineno=None):
self.expr = expr
+ self.lineno = lineno
def getChildren(self):
return self.expr,
@@ -1284,9 +1259,9 @@ class UnaryAdd(Node):
return "UnaryAdd(%s)" % (repr(self.expr),)
class UnarySub(Node):
- nodes["unarysub"] = "UnarySub"
- def __init__(self, expr):
+ def __init__(self, expr, lineno=None):
self.expr = expr
+ self.lineno = lineno
def getChildren(self):
return self.expr,
@@ -1298,11 +1273,11 @@ class UnarySub(Node):
return "UnarySub(%s)" % (repr(self.expr),)
class While(Node):
- nodes["while"] = "While"
- def __init__(self, test, body, else_):
+ def __init__(self, test, body, else_, lineno=None):
self.test = test
self.body = body
self.else_ = else_
+ self.lineno = lineno
def getChildren(self):
children = []
@@ -1315,16 +1290,17 @@ class While(Node):
nodelist = []
nodelist.append(self.test)
nodelist.append(self.body)
- if self.else_ is not None: nodelist.append(self.else_)
+ if self.else_ is not None:
+ nodelist.append(self.else_)
return tuple(nodelist)
def __repr__(self):
return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_))
class Yield(Node):
- nodes["yield"] = "Yield"
- def __init__(self, value):
+ def __init__(self, value, lineno=None):
self.value = value
+ self.lineno = lineno
def getChildren(self):
return self.value,
@@ -1335,6 +1311,6 @@ class Yield(Node):
def __repr__(self):
return "Yield(%s)" % (repr(self.value),)
-klasses = globals()
-for k in nodes.keys():
- nodes[k] = klasses[nodes[k]]
+for name, obj in globals().items():
+ if isinstance(obj, type) and issubclass(obj, Node):
+ nodes[name.lower()] = obj
diff --git a/Lib/compiler/transformer.py b/Lib/compiler/transformer.py
index 9fb18c2..9d2f378 100644
--- a/Lib/compiler/transformer.py
+++ b/Lib/compiler/transformer.py
@@ -14,7 +14,10 @@ parseFile(path) -> AST
#
# Modifications and improvements for Python 2.0 by Jeremy Hylton and
# Mark Hammond
-
+#
+# Some fixes to try to have correct line number on almost all nodes
+# (except Module, Discard and Stmt) added by Sylvain Thenault
+#
# Portions of this file are:
# Copyright (C) 1997-1998 Greg Stein. All Rights Reserved.
#
@@ -22,21 +25,20 @@ parseFile(path) -> AST
# http://www.opensource.org/licenses/bsd-license.html
# and replace OWNER, ORGANIZATION, and YEAR as appropriate.
-from ast import *
+from compiler.ast import *
import parser
-# Care must be taken to use only symbols and tokens defined in Python
-# 1.5.2 for code branches executed in 1.5.2
import symbol
import token
import sys
-error = 'walker.error'
+class WalkerError(StandardError):
+ pass
from consts import CO_VARARGS, CO_VARKEYWORDS
from consts import OP_ASSIGN, OP_DELETE, OP_APPLY
def parseFile(path):
- f = open(path)
+ f = open(path, "U")
# XXX The parser API tolerates files without a trailing newline,
# but not strings without a trailing newline. Always add an extra
# newline to the file contents, since we're going through the string
@@ -68,6 +70,16 @@ def asList(nodes):
l.append(item)
return l
+def extractLineNo(ast):
+ if not isinstance(ast[1], tuple):
+ # get a terminal node
+ return ast[2]
+ for child in ast[1:]:
+ if isinstance(child, tuple):
+ lineno = extractLineNo(child)
+ if lineno is not None:
+ return lineno
+
def Node(*args):
kind = args[0]
if nodes.has_key(kind):
@@ -77,7 +89,7 @@ def Node(*args):
print nodes[kind], len(args), args
raise
else:
- raise error, "Can't find appropriate Node type: %s" % str(args)
+ raise WalkerEror, "Can't find appropriate Node type: %s" % str(args)
#return apply(ast.Node, args)
class Transformer:
@@ -108,17 +120,14 @@ class Transformer:
def transform(self, tree):
"""Transform an AST into a modified parse tree."""
- if type(tree) != type(()) and type(tree) != type([]):
+ if not (isinstance(tree, tuple) or isinstance(tree, list)):
tree = parser.ast2tuple(tree, line_info=1)
return self.compile_node(tree)
def parsesuite(self, text):
"""Return a modified parse tree for the given suite text."""
- # Hack for handling non-native line endings on non-DOS like OSs.
- # this can go now we have universal newlines?
- text = text.replace('\x0d', '')
return self.transform(parser.suite(text))
-
+
def parseexpr(self, text):
"""Return a modified parse tree for the given expression text."""
return self.transform(parser.expr(text))
@@ -156,7 +165,7 @@ class Transformer:
if n == symbol.classdef:
return self.classdef(node[1:])
- raise error, ('unexpected node type', n)
+ raise WalkerEror, ('unexpected node type', n)
def single_input(self, node):
### do we want to do anything about being "interactive" ?
@@ -254,9 +263,8 @@ class Transformer:
assert isinstance(code, Stmt)
assert isinstance(code.nodes[0], Discard)
del code.nodes[0]
- n = Function(decorators, name, names, defaults, flags, doc, code)
- n.lineno = lineno
- return n
+ return Function(decorators, name, names, defaults, flags, doc, code,
+ lineno=lineno)
def lambdef(self, nodelist):
# lambdef: 'lambda' [varargslist] ':' test
@@ -269,9 +277,7 @@ class Transformer:
# code for lambda
code = self.com_node(nodelist[-1])
- n = Lambda(names, defaults, flags, code)
- n.lineno = nodelist[1][2]
- return n
+ return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
def classdef(self, nodelist):
# classdef: 'class' NAME ['(' testlist ')'] ':' suite
@@ -291,9 +297,7 @@ class Transformer:
assert isinstance(code.nodes[0], Discard)
del code.nodes[0]
- n = Class(name, bases, doc, code)
- n.lineno = nodelist[1][2]
- return n
+ return Class(name, bases, doc, code, lineno=nodelist[1][2])
def stmt(self, nodelist):
return self.com_stmt(nodelist[0])
@@ -310,31 +314,31 @@ class Transformer:
return Stmt(stmts)
def parameters(self, nodelist):
- raise error
+ raise WalkerEror
def varargslist(self, nodelist):
- raise error
+ raise WalkerEror
def fpdef(self, nodelist):
- raise error
+ raise WalkerEror
def fplist(self, nodelist):
- raise error
+ raise WalkerEror
def dotted_name(self, nodelist):
- raise error
+ raise WalkerEror
def comp_op(self, nodelist):
- raise error
+ raise WalkerEror
def trailer(self, nodelist):
- raise error
+ raise WalkerEror
def sliceop(self, nodelist):
- raise error
+ raise WalkerEror
def argument(self, nodelist):
- raise error
+ raise WalkerEror
# --------------------------------------------------------------
#
@@ -346,21 +350,17 @@ class Transformer:
en = nodelist[-1]
exprNode = self.lookup_node(en)(en[1:])
if len(nodelist) == 1:
- n = Discard(exprNode)
- n.lineno = exprNode.lineno
- return n
+ return Discard(exprNode, lineno=exprNode.lineno)
if nodelist[1][0] == token.EQUAL:
nodesl = []
for i in range(0, len(nodelist) - 2, 2):
nodesl.append(self.com_assign(nodelist[i], OP_ASSIGN))
- n = Assign(nodesl, exprNode)
- n.lineno = nodelist[1][2]
+ return Assign(nodesl, exprNode, lineno=nodelist[1][2])
else:
lval = self.com_augassign(nodelist[0])
op = self.com_augassign_op(nodelist[1])
- n = AugAssign(lval, op[1], exprNode)
- n.lineno = op[2]
- return n
+ return AugAssign(lval, op[1], exprNode, lineno=op[2])
+ raise WalkerError, "can't get here"
def print_stmt(self, nodelist):
# print ([ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ])
@@ -379,45 +379,29 @@ class Transformer:
for i in range(start, len(nodelist), 2):
items.append(self.com_node(nodelist[i]))
if nodelist[-1][0] == token.COMMA:
- n = Print(items, dest)
- n.lineno = nodelist[0][2]
- return n
- n = Printnl(items, dest)
- n.lineno = nodelist[0][2]
- return n
+ return Print(items, dest, lineno=nodelist[0][2])
+ return Printnl(items, dest, lineno=nodelist[0][2])
def del_stmt(self, nodelist):
return self.com_assign(nodelist[1], OP_DELETE)
def pass_stmt(self, nodelist):
- n = Pass()
- n.lineno = nodelist[0][2]
- return n
+ return Pass(lineno=nodelist[0][2])
def break_stmt(self, nodelist):
- n = Break()
- n.lineno = nodelist[0][2]
- return n
+ return Break(lineno=nodelist[0][2])
def continue_stmt(self, nodelist):
- n = Continue()
- n.lineno = nodelist[0][2]
- return n
+ return Continue(lineno=nodelist[0][2])
def return_stmt(self, nodelist):
# return: [testlist]
if len(nodelist) < 2:
- n = Return(Const(None))
- n.lineno = nodelist[0][2]
- return n
- n = Return(self.com_node(nodelist[1]))
- n.lineno = nodelist[0][2]
- return n
+ return Return(Const(None), lineno=nodelist[0][2])
+ return Return(self.com_node(nodelist[1]), lineno=nodelist[0][2])
def yield_stmt(self, nodelist):
- n = Yield(self.com_node(nodelist[1]))
- n.lineno = nodelist[0][2]
- return n
+ return Yield(self.com_node(nodelist[1]), lineno=nodelist[0][2])
def raise_stmt(self, nodelist):
# raise: [test [',' test [',' test]]]
@@ -433,9 +417,7 @@ class Transformer:
expr1 = self.com_node(nodelist[1])
else:
expr1 = None
- n = Raise(expr1, expr2, expr3)
- n.lineno = nodelist[0][2]
- return n
+ return Raise(expr1, expr2, expr3, lineno=nodelist[0][2])
def import_stmt(self, nodelist):
# import_stmt: import_name | import_from
@@ -444,9 +426,8 @@ class Transformer:
def import_name(self, nodelist):
# import_name: 'import' dotted_as_names
- n = Import(self.com_dotted_as_names(nodelist[1]))
- n.lineno = nodelist[0][2]
- return n
+ return Import(self.com_dotted_as_names(nodelist[1]),
+ lineno=nodelist[0][2])
def import_from(self, nodelist):
# import_from: 'from' dotted_name 'import' ('*' |
@@ -456,21 +437,19 @@ class Transformer:
assert nodelist[2][1] == 'import'
fromname = self.com_dotted_name(nodelist[1])
if nodelist[3][0] == token.STAR:
- n = From(fromname, [('*', None)])
+ # TODO(jhylton): where is the lineno?
+ return From(fromname, [('*', None)])
else:
node = nodelist[3 + (nodelist[3][0] == token.LPAR)]
- n = From(fromname, self.com_import_as_names(node))
- n.lineno = nodelist[0][2]
- return n
+ return From(fromname, self.com_import_as_names(node),
+ lineno=nodelist[0][2])
def global_stmt(self, nodelist):
# global: NAME (',' NAME)*
names = []
for i in range(1, len(nodelist), 2):
names.append(nodelist[i][1])
- n = Global(names)
- n.lineno = nodelist[0][2]
- return n
+ return Global(names, lineno=nodelist[0][2])
def exec_stmt(self, nodelist):
# exec_stmt: 'exec' expr ['in' expr [',' expr]]
@@ -484,9 +463,7 @@ class Transformer:
else:
expr2 = expr3 = None
- n = Exec(expr1, expr2, expr3)
- n.lineno = nodelist[0][2]
- return n
+ return Exec(expr1, expr2, expr3, lineno=nodelist[0][2])
def assert_stmt(self, nodelist):
# 'assert': test, [',' test]
@@ -495,9 +472,7 @@ class Transformer:
expr2 = self.com_node(nodelist[3])
else:
expr2 = None
- n = Assert(expr1, expr2)
- n.lineno = nodelist[0][2]
- return n
+ return Assert(expr1, expr2, lineno=nodelist[0][2])
def if_stmt(self, nodelist):
# if: test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
@@ -512,9 +487,7 @@ class Transformer:
## elseNode.lineno = nodelist[-1][1][2]
else:
elseNode = None
- n = If(tests, elseNode)
- n.lineno = nodelist[0][2]
- return n
+ return If(tests, elseNode, lineno=nodelist[0][2])
def while_stmt(self, nodelist):
# 'while' test ':' suite ['else' ':' suite]
@@ -527,9 +500,7 @@ class Transformer:
else:
elseNode = None
- n = While(testNode, bodyNode, elseNode)
- n.lineno = nodelist[0][2]
- return n
+ return While(testNode, bodyNode, elseNode, lineno=nodelist[0][2])
def for_stmt(self, nodelist):
# 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
@@ -543,9 +514,8 @@ class Transformer:
else:
elseNode = None
- n = For(assignNode, listNode, bodyNode, elseNode)
- n.lineno = nodelist[0][2]
- return n
+ return For(assignNode, listNode, bodyNode, elseNode,
+ lineno=nodelist[0][2])
def try_stmt(self, nodelist):
# 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
@@ -601,9 +571,7 @@ class Transformer:
# 'not' not_test | comparison
result = self.com_node(nodelist[-1])
if len(nodelist) == 2:
- n = Not(result)
- n.lineno = nodelist[0][2]
- return n
+ return Not(result, lineno=nodelist[0][2])
return result
def comparison(self, nodelist):
@@ -637,9 +605,7 @@ class Transformer:
# the two have very different semantics and results (note that the
# latter form is always true)
- n = Compare(node, results)
- n.lineno = lineno
- return n
+ return Compare(node, results, lineno=lineno)
def expr(self, nodelist):
# xor_expr ('|' xor_expr)*
@@ -659,11 +625,9 @@ class Transformer:
for i in range(2, len(nodelist), 2):
right = self.com_node(nodelist[i])
if nodelist[i-1][0] == token.LEFTSHIFT:
- node = LeftShift([node, right])
- node.lineno = nodelist[1][2]
+ node = LeftShift([node, right], lineno=nodelist[1][2])
elif nodelist[i-1][0] == token.RIGHTSHIFT:
- node = RightShift([node, right])
- node.lineno = nodelist[1][2]
+ node = RightShift([node, right], lineno=nodelist[1][2])
else:
raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
return node
@@ -673,11 +637,9 @@ class Transformer:
for i in range(2, len(nodelist), 2):
right = self.com_node(nodelist[i])
if nodelist[i-1][0] == token.PLUS:
- node = Add([node, right])
- node.lineno = nodelist[1][2]
+ node = Add([node, right], lineno=nodelist[1][2])
elif nodelist[i-1][0] == token.MINUS:
- node = Sub([node, right])
- node.lineno = nodelist[1][2]
+ node = Sub([node, right], lineno=nodelist[1][2])
else:
raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
return node
@@ -703,17 +665,14 @@ class Transformer:
def factor(self, nodelist):
elt = nodelist[0]
t = elt[0]
- node = self.com_node(nodelist[-1])
+ node = self.lookup_node(nodelist[-1])(nodelist[-1][1:])
# need to handle (unary op)constant here...
if t == token.PLUS:
- node = UnaryAdd(node)
- node.lineno = elt[2]
+ return UnaryAdd(node, lineno=elt[2])
elif t == token.MINUS:
- node = UnarySub(node)
- node.lineno = elt[2]
+ return UnarySub(node, lineno=elt[2])
elif t == token.TILDE:
- node = Invert(node)
- node.lineno = elt[2]
+ node = Invert(node, lineno=elt[2])
return node
def power(self, nodelist):
@@ -722,31 +681,26 @@ class Transformer:
for i in range(1, len(nodelist)):
elt = nodelist[i]
if elt[0] == token.DOUBLESTAR:
- n = Power([node, self.com_node(nodelist[i+1])])
- n.lineno = elt[2]
- return n
+ return Power([node, self.com_node(nodelist[i+1])],
+ lineno=elt[2])
node = self.com_apply_trailer(node, elt)
return node
def atom(self, nodelist):
- n = self._atom_dispatch[nodelist[0][0]](nodelist)
+ return self._atom_dispatch[nodelist[0][0]](nodelist)
n.lineno = nodelist[0][2]
return n
def atom_lpar(self, nodelist):
if nodelist[1][0] == token.RPAR:
- n = Tuple(())
- n.lineno = nodelist[0][2]
- return n
+ return Tuple(())
return self.com_node(nodelist[1])
def atom_lsqb(self, nodelist):
if nodelist[1][0] == token.RSQB:
- n = List(())
- n.lineno = nodelist[0][2]
- return n
+ return List(())
return self.com_list_constructor(nodelist[1])
def atom_lbrace(self, nodelist):
@@ -755,16 +709,12 @@ class Transformer:
return self.com_dictmaker(nodelist[1])
def atom_backquote(self, nodelist):
- n = Backquote(self.com_node(nodelist[1]))
- n.lineno = nodelist[0][2]
- return n
+ return Backquote(self.com_node(nodelist[1]))
def atom_number(self, nodelist):
### need to verify this matches compile.c
k = eval(nodelist[0][1])
- n = Const(k)
- n.lineno = nodelist[0][2]
- return n
+ return Const(k, lineno=nodelist[0][2])
def decode_literal(self, lit):
if self.encoding:
@@ -781,15 +731,10 @@ class Transformer:
k = ''
for node in nodelist:
k += self.decode_literal(node[1])
- n = Const(k)
- n.lineno = nodelist[0][2]
- return n
+ return Const(k, lineno=nodelist[0][2])
def atom_name(self, nodelist):
- ### any processing to do?
- n = Name(nodelist[0][1])
- n.lineno = nodelist[0][2]
- return n
+ return Name(nodelist[0][1], lineno=nodelist[0][2])
# --------------------------------------------------------------
#
@@ -807,6 +752,8 @@ class Transformer:
def lookup_node(self, node):
return self._dispatch[node[0]]
+ _callers = {}
+
def com_node(self, node):
# Note: compile.c has handling in com_node for del_stmt, pass_stmt,
# break_stmt, stmt, small_stmt, flow_stmt, simple_stmt,
@@ -865,6 +812,7 @@ class Transformer:
i = i + 2
elif len(defaults):
# Treat "(a=1, b)" as "(a=1, b=None)"
+ print nodelist[i]
defaults.append(Const(None))
i = i + 1
@@ -938,10 +886,9 @@ class Transformer:
def com_try_finally(self, nodelist):
# try_fin_stmt: "try" ":" suite "finally" ":" suite
- n = TryFinally(self.com_node(nodelist[2]),
- self.com_node(nodelist[5]))
- n.lineno = nodelist[0][2]
- return n
+ return TryFinally(self.com_node(nodelist[2]),
+ self.com_node(nodelist[5]),
+ lineno=nodelist[0][2])
def com_try_except(self, nodelist):
# try_except: 'try' ':' suite (except_clause ':' suite)* ['else' suite]
@@ -965,9 +912,8 @@ class Transformer:
if node[0] == token.NAME:
elseNode = self.com_node(nodelist[i+2])
- n = TryExcept(self.com_node(nodelist[2]), clauses, elseNode)
- n.lineno = nodelist[0][2]
- return n
+ return TryExcept(self.com_node(nodelist[2]), clauses, elseNode,
+ lineno=nodelist[0][2])
def com_augassign_op(self, node):
assert node[0] == symbol.augassign
@@ -1031,7 +977,7 @@ class Transformer:
assigns = []
for i in range(1, len(node), 2):
assigns.append(self.com_assign(node[i], assigning))
- return AssTuple(assigns)
+ return AssTuple(assigns, lineno=extractLineNo(node))
def com_assign_list(self, node, assigning):
assigns = []
@@ -1041,12 +987,10 @@ class Transformer:
raise SyntaxError, "can't assign to list comprehension"
assert node[i + 1][0] == token.COMMA, node[i + 1]
assigns.append(self.com_assign(node[i], assigning))
- return AssList(assigns)
+ return AssList(assigns, lineno=extractLineNo(node))
def com_assign_name(self, node, assigning):
- n = AssName(node[1], assigning)
- n.lineno = node[2]
- return n
+ return AssName(node[1], assigning, lineno=node[2])
def com_assign_trailer(self, primary, node, assigning):
t = node[1][0]
@@ -1059,7 +1003,7 @@ class Transformer:
raise SyntaxError, "unknown trailer type: %s" % t
def com_assign_attr(self, primary, node, assigning):
- return AssAttr(primary, node[1], assigning)
+ return AssAttr(primary, node[1], assigning, lineno=node[-1])
def com_binary(self, constructor, nodelist):
"Compile 'NODE (OP NODE)*' into (type, [ node1, ..., nodeN ])."
@@ -1071,7 +1015,7 @@ class Transformer:
for i in range(0, l, 2):
n = nodelist[i]
items.append(self.lookup_node(n)(n[1:]))
- return constructor(items)
+ return constructor(items, lineno=extractLineNo(nodelist))
def com_stmt(self, node):
result = self.lookup_node(node)(node[1:])
@@ -1081,7 +1025,7 @@ class Transformer:
return Stmt([result])
def com_append_stmt(self, stmts, node):
- result = self.com_node(node)
+ result = self.lookup_node(node)(node[1:])
assert result is not None
if isinstance(result, Stmt):
stmts.extend(result.nodes)
@@ -1100,7 +1044,7 @@ class Transformer:
elif nodelist[i][0] == token.COMMA:
continue
values.append(self.com_node(nodelist[i]))
- return List(values)
+ return List(values, lineno=values[0].lineno)
def com_list_comprehension(self, expr, node):
# list_iter: list_for | list_if
@@ -1125,8 +1069,7 @@ class Transformer:
node = self.com_list_iter(node[5])
elif t == 'if':
test = self.com_node(node[2])
- newif = ListCompIf(test)
- newif.lineno = node[1][2]
+ newif = ListCompIf(test, lineno=node[1][2])
newfor.ifs.append(newif)
if len(node) == 3:
node = None
@@ -1136,9 +1079,7 @@ class Transformer:
raise SyntaxError, \
("unexpected list comprehension element: %s %d"
% (node, lineno))
- n = ListComp(expr, fors)
- n.lineno = lineno
- return n
+ return ListComp(expr, fors, lineno=lineno)
def com_list_iter(self, node):
assert node[0] == symbol.list_iter
@@ -1163,8 +1104,8 @@ class Transformer:
if t == 'for':
assignNode = self.com_assign(node[2], OP_ASSIGN)
genNode = self.com_node(node[4])
- newfor = GenExprFor(assignNode, genNode, [])
- newfor.lineno = node[1][2]
+ newfor = GenExprFor(assignNode, genNode, [],
+ lineno=node[1][2])
fors.append(newfor)
if (len(node)) == 5:
node = None
@@ -1172,8 +1113,7 @@ class Transformer:
node = self.com_gen_iter(node[5])
elif t == 'if':
test = self.com_node(node[2])
- newif = GenExprIf(test)
- newif.lineno = node[1][2]
+ newif = GenExprIf(test, lineno=node[1][2])
newfor.ifs.append(newif)
if len(node) == 3:
node = None
@@ -1184,9 +1124,7 @@ class Transformer:
("unexpected generator expression element: %s %d"
% (node, lineno))
fors[0].is_outmost = True
- n = GenExpr(GenExprInner(expr, fors))
- n.lineno = lineno
- return n
+ return GenExpr(GenExprInner(expr, fors), lineno=lineno)
def com_gen_iter(self, node):
assert node[0] == symbol.gen_iter
@@ -1214,13 +1152,11 @@ class Transformer:
def com_select_member(self, primaryNode, nodelist):
if nodelist[0] != token.NAME:
raise SyntaxError, "member must be a name"
- n = Getattr(primaryNode, nodelist[1])
- n.lineno = nodelist[2]
- return n
+ return Getattr(primaryNode, nodelist[1], lineno=nodelist[2])
def com_call_function(self, primaryNode, nodelist):
if nodelist[0] == token.RPAR:
- return CallFunc(primaryNode, [])
+ return CallFunc(primaryNode, [], lineno=extractLineNo(nodelist))
args = []
kw = 0
len_nodelist = len(nodelist)
@@ -1253,8 +1189,8 @@ class Transformer:
dstar_node = self.com_node(ch)
else:
raise SyntaxError, 'unknown node type: %s' % tok
-
- return CallFunc(primaryNode, args, star_node, dstar_node)
+ return CallFunc(primaryNode, args, star_node, dstar_node,
+ lineno=extractLineNo(nodelist))
def com_argument(self, nodelist, kw):
if len(nodelist) == 3 and nodelist[2][0] == symbol.gen_for:
@@ -1270,8 +1206,7 @@ class Transformer:
n = n[1]
if n[0] != token.NAME:
raise SyntaxError, "keyword can't be an expression (%s)"%n[0]
- node = Keyword(n[1], result)
- node.lineno = n[2]
+ node = Keyword(n[1], result, lineno=n[2])
return 1, node
def com_subscriptlist(self, primary, nodelist, assigning):
@@ -1291,8 +1226,8 @@ class Transformer:
subscripts = []
for i in range(1, len(nodelist), 2):
subscripts.append(self.com_subscript(nodelist[i]))
-
- return Subscript(primary, assigning, subscripts)
+ return Subscript(primary, assigning, subscripts,
+ lineno=extractLineNo(nodelist))
def com_subscript(self, node):
# slice_item: expression | proper_slice | ellipsis
@@ -1338,8 +1273,7 @@ class Transformer:
items.append(Const(None))
else:
items.append(self.com_node(ch[2]))
-
- return Sliceobj(items)
+ return Sliceobj(items, lineno=extractLineNo(node))
def com_slice(self, primary, node, assigning):
# short_slice: [lower_bound] ":" [upper_bound]
@@ -1352,7 +1286,8 @@ class Transformer:
elif len(node) == 4:
lower = self.com_node(node[1])
upper = self.com_node(node[3])
- return Slice(primary, assigning, lower, upper)
+ return Slice(primary, assigning, lower, upper,
+ lineno=extractLineNo(node))
def get_docstring(self, node, n=None):
if n is None:
diff --git a/Lib/test/test_compiler.py b/Lib/test/test_compiler.py
index 63cbc00..1d77318 100644
--- a/Lib/test/test_compiler.py
+++ b/Lib/test/test_compiler.py
@@ -33,6 +33,65 @@ class CompilerTest(unittest.TestCase):
else:
compiler.compile(buf, basename, "exec")
+ def testLineNo(self):
+ # Test that all nodes except Module have a correct lineno attribute.
+ filename = __file__
+ if filename.endswith(".pyc") or filename.endswith(".pyo"):
+ filename = filename[:-1]
+ tree = compiler.parseFile(filename)
+ self.check_lineno(tree)
+
+ def check_lineno(self, node):
+ try:
+ self._check_lineno(node)
+ except AssertionError:
+ print node.__class__, node.lineno
+ raise
+
+ def _check_lineno(self, node):
+ if not node.__class__ in NOLINENO:
+ self.assert_(isinstance(node.lineno, int),
+ "lineno=%s on %s" % (node.lineno, node.__class__))
+ self.assert_(node.lineno > 0,
+ "lineno=%s on %s" % (node.lineno, node.__class__))
+ for child in node.getChildNodes():
+ self.check_lineno(child)
+
+NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard)
+
+###############################################################################
+# code below is just used to trigger some possible errors, for the benefit of
+# testLineNo
+###############################################################################
+
+class Toto:
+ """docstring"""
+ pass
+
+a, b = 2, 3
+[c, d] = 5, 6
+l = [(x, y) for x, y in zip(range(5), range(5,10))]
+l[0]
+l[3:4]
+if l:
+ pass
+else:
+ a, b = b, a
+
+try:
+ print yo
+except:
+ yo = 3
+else:
+ yo += 3
+
+try:
+ a += b
+finally:
+ b = 0
+
+###############################################################################
+
def test_main():
global TEST_ALL
TEST_ALL = test.test_support.is_resource_enabled("compiler")
diff --git a/Lib/test/test_transformer.py b/Lib/test/test_transformer.py
index 6a8c98a..909cda5 100644
--- a/Lib/test/test_transformer.py
+++ b/Lib/test/test_transformer.py
@@ -29,9 +29,7 @@ class Tests(unittest.TestCase):
assert vals['b'] == 2
def test_main():
- test_support.run_unittest(
- Tests
- )
+ test_support.run_unittest(Tests)
if __name__ == "__main__":
test_main()
diff --git a/Misc/ACKS b/Misc/ACKS
index dfdf005..1dc50a3 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -563,6 +563,7 @@ Michael Stone
Ken Stox
Daniel Stutzbach
Paul Swartz
+Thenault Sylvain
Geoff Talvola
William Tanksley
Christian Tanzer
diff --git a/Tools/compiler/astgen.py b/Tools/compiler/astgen.py
index 4fe4bbe..0156567 100644
--- a/Tools/compiler/astgen.py
+++ b/Tools/compiler/astgen.py
@@ -94,7 +94,6 @@ class NodeInfo:
def gen_source(self):
buf = StringIO()
print >> buf, "class %s(Node):" % self.name
- print >> buf, ' nodes["%s"] = "%s"' % (self.name.lower(), self.name)
self._gen_init(buf)
print >> buf
self._gen_getChildren(buf)
@@ -106,12 +105,14 @@ class NodeInfo:
return buf.read()
def _gen_init(self, buf):
- print >> buf, " def __init__(self, %s):" % self.args
+ if self.args:
+ print >> buf, " def __init__(self, %s, lineno=None):" % self.args
+ else:
+ print >> buf, " def __init__(self, lineno=None):"
if self.argnames:
for name in self.argnames:
print >> buf, " self.%s = %s" % (name, name)
- else:
- print >> buf, " pass"
+ print >> buf, " self.lineno = lineno"
if self.init:
print >> buf, "".join([" " + line for line in self.init])
@@ -128,15 +129,18 @@ class NodeInfo:
else:
print >> buf, " return %s" % clist
else:
- print >> buf, " children = []"
- template = " children.%s(%sself.%s%s)"
- for name in self.argnames:
- if self.argprops[name] == P_NESTED:
- print >> buf, template % ("extend", "flatten(",
- name, ")")
- else:
- print >> buf, template % ("append", "", name, "")
- print >> buf, " return tuple(children)"
+ if len(self.argnames) == 1:
+ print >> buf, " return tuple(flatten(self.%s))" % self.argnames[0]
+ else:
+ print >> buf, " children = []"
+ template = " children.%s(%sself.%s%s)"
+ for name in self.argnames:
+ if self.argprops[name] == P_NESTED:
+ print >> buf, template % ("extend", "flatten(",
+ name, ")")
+ else:
+ print >> buf, template % ("append", "", name, "")
+ print >> buf, " return tuple(children)"
def _gen_getChildNodes(self, buf):
print >> buf, " def getChildNodes(self):"
@@ -158,7 +162,7 @@ class NodeInfo:
template = " nodelist.%s(%sself.%s%s)"
for name in self.argnames:
if self.argprops[name] == P_NONE:
- tmp = (" if self.%s is not None:"
+ tmp = (" if self.%s is not None:\n"
" nodelist.append(self.%s)")
print >> buf, tmp % (name, name)
elif self.argprops[name] == P_NESTED:
@@ -226,16 +230,15 @@ if __name__ == "__main__":
### PROLOGUE
"""Python abstract syntax node definitions
-This file is automatically generated.
+This file is automatically generated by Tools/compiler/astgen.py
"""
-from types import TupleType, ListType
from consts import CO_VARARGS, CO_VARKEYWORDS
def flatten(list):
l = []
for elt in list:
t = type(elt)
- if t is TupleType or t is ListType:
+ if t is tuple or t is list:
for elt2 in flatten(elt):
l.append(elt2)
else:
@@ -245,29 +248,17 @@ def flatten(list):
def flatten_nodes(list):
return [n for n in flatten(list) if isinstance(n, Node)]
-def asList(nodearg):
- l = []
- for item in nodearg:
- if hasattr(item, "asList"):
- l.append(item.asList())
- else:
- t = type(item)
- if t is TupleType or t is ListType:
- l.append(tuple(asList(item)))
- else:
- l.append(item)
- return l
-
nodes = {}
-class Node: # an abstract base class
- lineno = None # provide a lineno for nodes that don't have one
- def getType(self):
- pass # implemented by subclass
+class Node:
+ """Abstract base class for ast nodes."""
def getChildren(self):
pass # implemented by subclasses
- def asList(self):
- return tuple(asList(self.getChildren()))
+ def __iter__(self):
+ for n in self.getChildren():
+ yield n
+ def asList(self): # for backwards compatibility
+ return self.getChildren()
def getChildNodes(self):
pass # implemented by subclasses
@@ -290,6 +281,6 @@ class Expression(Node):
return "Expression(%s)" % (repr(self.node))
### EPILOGUE
-klasses = globals()
-for k in nodes.keys():
- nodes[k] = klasses[nodes[k]]
+for name, obj in globals().items():
+ if isinstance(obj, type) and issubclass(obj, Node):
+ nodes[name.lower()] = obj