return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_))
class From(Node):
- def __init__(self, modname, names, lineno=None):
+ def __init__(self, modname, names, level, lineno=None):
self.modname = modname
self.names = names
+ self.level = level
self.lineno = lineno
def getChildren(self):
- return self.modname, self.names
+ return self.modname, self.names, self.level
def getChildNodes(self):
return ()
def __repr__(self):
- return "From(%s, %s)" % (repr(self.modname), repr(self.names))
+ return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level))
class Function(Node):
def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None):
self.varargs = 1
if flags & CO_VARKEYWORDS:
self.kwargs = 1
-
+
def getChildren(self):
self.lineno = lineno
self.argnames = ['[outmost-iterable]']
self.varargs = self.kwargs = None
-
+
def getChildren(self):
def __repr__(self):
return "If(%s, %s)" % (repr(self.tests), repr(self.else_))
+class IfExp(Node):
+ def __init__(self, test, then, else_, lineno=None):
+ self.test = test
+ self.then = then
+ self.else_ = else_
+ self.lineno = lineno
+
+ def getChildren(self):
+ return self.test, self.then, self.else_
+
+ def getChildNodes(self):
+ return self.test, self.then, self.else_
+
+ def __repr__(self):
+ return "IfExp(%s, %s, %s)" % (repr(self.test), repr(self.then), repr(self.else_))
+
class Import(Node):
def __init__(self, names, lineno=None):
self.names = names
self.varargs = 1
if flags & CO_VARKEYWORDS:
self.kwargs = 1
-
+
def getChildren(self):
CO_GENERATOR = 0x0020
CO_GENERATOR_ALLOWED = 0x1000
CO_FUTURE_DIVISION = 0x2000
+CO_FUTURE_ABSIMPORT = 0x4000
+CO_FUTURE_WITH_STATEMENT = 0x8000
'COMPARE_OP': -1,
'STORE_FAST': -1,
'IMPORT_STAR': -1,
- 'IMPORT_NAME': 0,
+ 'IMPORT_NAME': -1,
'IMPORT_FROM': 1,
'LOAD_ATTR': 0, # unlike other loads
# close enough...
from compiler import ast, parse, walk, syntax
from compiler import pyassem, misc, future, symbols
from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
-from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
- CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
+from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,
+ CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION,
+ CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT)
from compiler.pyassem import TupleArg
# XXX The version-specific code can go, since this code only works with 2.x.
self._div_op = "BINARY_TRUE_DIVIDE"
elif feature == "generators":
self.graph.setFlag(CO_GENERATOR_ALLOWED)
+ elif feature == "absolute_import":
+ self.graph.setFlag(CO_FUTURE_ABSIMPORT)
+ elif feature == "with_statement":
+ self.graph.setFlag(CO_FUTURE_WITH_STATEMENT)
def initClass(self):
"""This method is called once for each class"""
def visitOr(self, node):
self.visitTest(node, 'JUMP_IF_TRUE')
+ def visitIfExp(self, node):
+ endblock = self.newBlock()
+ elseblock = self.newBlock()
+ self.visit(node.test)
+ self.emit('JUMP_IF_FALSE', elseblock)
+ self.emit('POP_TOP')
+ self.visit(node.then)
+ self.emit('JUMP_FORWARD', endblock)
+ self.nextBlock(elseblock)
+ self.emit('POP_TOP')
+ self.visit(node.else_)
+ self.nextBlock(endblock)
+
def visitCompare(self, node):
self.visit(node.expr)
cleanup = self.newBlock()
def visitImport(self, node):
self.set_lineno(node)
+ level = 0 if "absolute_import" in self.futures else -1
for name, alias in node.names:
if VERSION > 1:
+ self.emit('LOAD_CONST', level)
self.emit('LOAD_CONST', None)
self.emit('IMPORT_NAME', name)
mod = name.split(".")[0]
def visitFrom(self, node):
self.set_lineno(node)
+ level = node.level
+ if level == 0 and "absolute_import" not in self.futures:
+ level = -1
fromlist = map(lambda (name, alias): name, node.names)
if VERSION > 1:
+ self.emit('LOAD_CONST', level)
self.emit('LOAD_CONST', tuple(fromlist))
self.emit('IMPORT_NAME', node.modname)
for name, alias in node.names:
lineno=nodelist[0][2])
def import_from(self, nodelist):
- # import_from: 'from' dotted_name 'import' ('*' |
+ # import_from: 'from' ('.'* dotted_name | '.') 'import' ('*' |
# '(' import_as_names ')' | import_as_names)
assert nodelist[0][1] == 'from'
- assert nodelist[1][0] == symbol.dotted_name
- assert nodelist[2][1] == 'import'
- fromname = self.com_dotted_name(nodelist[1])
- if nodelist[3][0] == token.STAR:
- return From(fromname, [('*', None)],
+ idx = 1
+ while nodelist[idx][1] == '.':
+ idx += 1
+ level = idx - 1
+ if nodelist[idx][0] == symbol.dotted_name:
+ fromname = self.com_dotted_name(nodelist[idx])
+ idx += 1
+ else:
+ fromname = ""
+ assert nodelist[idx][1] == 'import'
+ if nodelist[idx + 1][0] == token.STAR:
+ return From(fromname, [('*', None)], level,
lineno=nodelist[0][2])
else:
- node = nodelist[3 + (nodelist[3][0] == token.LPAR)]
- return From(fromname, self.com_import_as_names(node),
+ node = nodelist[idx + 1 + (nodelist[idx + 1][0] == token.LPAR)]
+ return From(fromname, self.com_import_as_names(node), level,
lineno=nodelist[0][2])
def global_stmt(self, nodelist):
return self.testlist(nodelist)
def test(self, nodelist):
+ # or_test ['if' or_test 'else' test] | lambdef
+ if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
+ return self.lambdef(nodelist[0])
+ then = self.com_node(nodelist[0])
+ if len(nodelist) > 1:
+ assert len(nodelist) == 5
+ assert nodelist[1][1] == 'if'
+ assert nodelist[3][1] == 'else'
+ test = self.com_node(nodelist[2])
+ else_ = self.com_node(nodelist[4])
+ return IfExp(test, then, else_, lineno=nodelist[1][2])
+ return then
+
+ def or_test(self, nodelist):
# and_test ('or' and_test)* | lambdef
if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
return self.lambdef(nodelist[0])
return self.com_binary(Or, nodelist)
- or_test = test
- old_test = test
+ old_test = or_test
def and_test(self, nodelist):
# not_test ('and' not_test)*