Commit 88e43ac0 authored by Dylan Trotter's avatar Dylan Trotter Committed by GitHub

Fix continue/break in else block behavior (#146)

Fixes: https://github.com/google/grumpy/issues/123
parent 8f3ca94c
......@@ -173,6 +173,8 @@ class StatementVisitor(ast.NodeVisitor):
self._tie_target(target, value.expr)
def visit_Break(self, node):
if not self.block.loop_stack:
raise util.ParseError(node, "'break' not in loop")
self._write_py_context(node.lineno)
self.writer.write('goto Label{}'.format(self.block.top_loop().end_label))
......@@ -242,6 +244,8 @@ class StatementVisitor(ast.NodeVisitor):
self.block.bind_var(self.writer, node.name, type_.expr)
def visit_Continue(self, node):
if not self.block.loop_stack:
raise util.ParseError(node, "'continue' not in loop")
self._write_py_context(node.lineno)
self.writer.write('goto Label{}'.format(self.block.top_loop().start_label))
......@@ -296,13 +300,13 @@ class StatementVisitor(ast.NodeVisitor):
self._visit_each(node.body)
self.writer.write('goto Label{}'.format(loop.start_label))
self.block.pop_loop()
if node.orelse:
self.writer.write_label(orelse_label)
self._visit_each(node.orelse)
# Avoid label "defined and not used" in case there's no break statements.
self.writer.write('goto Label{}'.format(loop.end_label))
self.writer.write_label(loop.end_label)
self.block.pop_loop()
def visit_FunctionDef(self, node):
self._write_py_context(node.lineno)
......
......@@ -202,6 +202,16 @@ class StatementVisitorTest(unittest.TestCase):
else:
print 'bar'""")))
def testForElseBreakNotNested(self):
self.assertRaisesRegexp(
util.ParseError, "'continue' not in loop",
_ParseAndVisit, 'for i in (1,):\n pass\nelse:\n continue')
def testForElseContinueNotNested(self):
self.assertRaisesRegexp(
util.ParseError, "'continue' not in loop",
_ParseAndVisit, 'for i in (1,):\n pass\nelse:\n continue')
def testFunctionDef(self):
self.assertEqual((0, 'bar baz\n'), _GrumpRun(textwrap.dedent("""\
def foo(a, b):
......
......@@ -51,3 +51,26 @@ for i, j in [('a', 1), ('b', 2)]:
l.append(i)
l.append(j)
assert l == ['a', 1, 'b', 2]
# break and continue statements in an else clause applies to the outer loop.
# See: https://github.com/google/grumpy/issues/123
l = []
for i in range(2):
l.append(i)
for j in range(10, 12):
l.append(j)
else:
l.append(12)
continue
l.append(-1)
assert l == [0, 10, 11, 12, 1, 10, 11, 12]
l = []
for i in range(10):
l.append(i)
for j in range(10, 12):
l.append(j)
else:
break
l.append(-1)
assert l == [0, 10, 11]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment