Update the compiler package to compile the with-statement.
Jeremy, please review!
This commit is contained in:
parent
40d8459dbf
commit
7ad94f011e
|
@ -807,6 +807,47 @@ class CodeGenerator:
|
||||||
self.emit('END_FINALLY')
|
self.emit('END_FINALLY')
|
||||||
self.setups.pop()
|
self.setups.pop()
|
||||||
|
|
||||||
|
__with_count = 0
|
||||||
|
|
||||||
|
def visitWith(self, node):
|
||||||
|
body = self.newBlock()
|
||||||
|
final = self.newBlock()
|
||||||
|
exitvar = "$exit%d" % self.__with_count
|
||||||
|
valuevar = "$value%d" % self.__with_count
|
||||||
|
self.__with_count += 1
|
||||||
|
self.set_lineno(node)
|
||||||
|
self.visit(node.expr)
|
||||||
|
self.emit('LOAD_ATTR', '__context__')
|
||||||
|
self.emit('CALL_FUNCTION', 0)
|
||||||
|
self.emit('DUP_TOP')
|
||||||
|
self.emit('LOAD_ATTR', '__exit__')
|
||||||
|
self._implicitNameOp('STORE', exitvar)
|
||||||
|
self.emit('LOAD_ATTR', '__enter__')
|
||||||
|
self.emit('CALL_FUNCTION', 0)
|
||||||
|
if node.vars is None:
|
||||||
|
self.emit('POP_TOP')
|
||||||
|
else:
|
||||||
|
self._implicitNameOp('STORE', valuevar)
|
||||||
|
self.emit('SETUP_FINALLY', final)
|
||||||
|
self.nextBlock(body)
|
||||||
|
self.setups.push((TRY_FINALLY, body))
|
||||||
|
if node.vars is not None:
|
||||||
|
self._implicitNameOp('LOAD', valuevar)
|
||||||
|
self._implicitNameOp('DELETE', valuevar)
|
||||||
|
self.visit(node.vars)
|
||||||
|
self.visit(node.body)
|
||||||
|
self.emit('POP_BLOCK')
|
||||||
|
self.setups.pop()
|
||||||
|
self.emit('LOAD_CONST', None)
|
||||||
|
self.nextBlock(final)
|
||||||
|
self.setups.push((END_FINALLY, final))
|
||||||
|
self.emit('WITH_CLEANUP')
|
||||||
|
self.emit('CALL_FUNCTION', 3)
|
||||||
|
self.emit('POP_TOP')
|
||||||
|
self.emit('END_FINALLY')
|
||||||
|
self.setups.pop()
|
||||||
|
self.__with_count -= 1
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
|
|
||||||
def visitDiscard(self, node):
|
def visitDiscard(self, node):
|
||||||
|
|
|
@ -536,6 +536,12 @@ class Transformer:
|
||||||
|
|
||||||
return self.com_try_except(nodelist)
|
return self.com_try_except(nodelist)
|
||||||
|
|
||||||
|
def with_stmt(self, nodelist):
|
||||||
|
return self.com_with(nodelist)
|
||||||
|
|
||||||
|
def with_var(self, nodelist):
|
||||||
|
return self.com_with_var(nodelist)
|
||||||
|
|
||||||
def suite(self, nodelist):
|
def suite(self, nodelist):
|
||||||
# simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
|
# simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
|
||||||
if len(nodelist) == 1:
|
if len(nodelist) == 1:
|
||||||
|
@ -926,6 +932,20 @@ class Transformer:
|
||||||
return TryExcept(self.com_node(nodelist[2]), clauses, elseNode,
|
return TryExcept(self.com_node(nodelist[2]), clauses, elseNode,
|
||||||
lineno=nodelist[0][2])
|
lineno=nodelist[0][2])
|
||||||
|
|
||||||
|
def com_with(self, nodelist):
|
||||||
|
# with_stmt: 'with' expr [with_var] ':' suite
|
||||||
|
expr = self.com_node(nodelist[1])
|
||||||
|
body = self.com_node(nodelist[-1])
|
||||||
|
if nodelist[2][0] == token.COLON:
|
||||||
|
var = None
|
||||||
|
else:
|
||||||
|
var = self.com_node(nodelist[2])
|
||||||
|
return With(expr, var, body, lineno=nodelist[0][2])
|
||||||
|
|
||||||
|
def com_with_var(self, nodelist):
|
||||||
|
# with_var: 'as' expr
|
||||||
|
return self.com_node(nodelist[1])
|
||||||
|
|
||||||
def com_augassign_op(self, node):
|
def com_augassign_op(self, node):
|
||||||
assert node[0] == symbol.augassign
|
assert node[0] == symbol.augassign
|
||||||
return node[1]
|
return node[1]
|
||||||
|
@ -1390,6 +1410,7 @@ _legal_node_types = [
|
||||||
symbol.while_stmt,
|
symbol.while_stmt,
|
||||||
symbol.for_stmt,
|
symbol.for_stmt,
|
||||||
symbol.try_stmt,
|
symbol.try_stmt,
|
||||||
|
symbol.with_stmt,
|
||||||
symbol.suite,
|
symbol.suite,
|
||||||
symbol.testlist,
|
symbol.testlist,
|
||||||
symbol.testlist_safe,
|
symbol.testlist_safe,
|
||||||
|
|
|
@ -20,7 +20,7 @@ class CompilerTest(unittest.TestCase):
|
||||||
for basename in os.listdir(dir):
|
for basename in os.listdir(dir):
|
||||||
if not basename.endswith(".py"):
|
if not basename.endswith(".py"):
|
||||||
continue
|
continue
|
||||||
if not TEST_ALL and random() < 0.98:
|
if not TEST_ALL and random() < 0.98 and basename != "test_with.py":
|
||||||
continue
|
continue
|
||||||
path = os.path.join(dir, basename)
|
path = os.path.join(dir, basename)
|
||||||
if test.test_support.verbose:
|
if test.test_support.verbose:
|
||||||
|
|
Loading…
Reference in New Issue