Add support for Break and Continue.

This commit is contained in:
whitequark 2015-06-13 12:07:46 +03:00
parent 55551714fa
commit 4b4805265d
2 changed files with 56 additions and 9 deletions

View File

@ -284,9 +284,7 @@ class ASTTypedRewriter(algorithm.Transformer):
# stmt # stmt
visit_Assert = visit_unsupported visit_Assert = visit_unsupported
visit_Break = visit_unsupported
visit_ClassDef = visit_unsupported visit_ClassDef = visit_unsupported
visit_Continue = visit_unsupported
visit_Delete = visit_unsupported visit_Delete = visit_unsupported
visit_Import = visit_unsupported visit_Import = visit_unsupported
visit_ImportFrom = visit_unsupported visit_ImportFrom = visit_unsupported
@ -298,8 +296,8 @@ class ASTTypedRewriter(algorithm.Transformer):
class Inferencer(algorithm.Visitor): class Inferencer(algorithm.Visitor):
def __init__(self, engine): def __init__(self, engine):
self.engine = engine self.engine = engine
# currently visited function, for Return inference self.function = None # currently visited function, for Return inference
self.function = None self.in_loop = False
def _unify(self, typea, typeb, loca, locb, makenotes=None): def _unify(self, typea, typeb, loca, locb, makenotes=None):
try: try:
@ -385,11 +383,6 @@ class Inferencer(algorithm.Visitor):
node.operand.loc) node.operand.loc)
self.engine.process(diag) self.engine.process(diag)
def visit_FunctionDefT(self, node):
old_function, self.function = self.function, node
node = self.generic_visit(node)
self.function = old_function
def visit_Assign(self, node): def visit_Assign(self, node):
self.generic_visit(node) self.generic_visit(node)
if len(node.targets) > 1: if len(node.targets) > 1:
@ -405,12 +398,47 @@ class Inferencer(algorithm.Visitor):
node.target.loc, node.value.loc) node.target.loc, node.value.loc)
def visit_For(self, node): def visit_For(self, node):
old_in_loop, self.in_loop = self.in_loop, True
self.generic_visit(node) self.generic_visit(node)
self.in_loop = old_in_loop
# TODO: support more than just lists # TODO: support more than just lists
self._unify(builtins.TList(node.target.type), node.iter.type, self._unify(builtins.TList(node.target.type), node.iter.type,
node.target.loc, node.iter.loc) node.target.loc, node.iter.loc)
def visit_While(self, node):
old_in_loop, self.in_loop = self.in_loop, True
self.generic_visit(node)
self.in_loop = old_in_loop
def visit_Break(self, node):
if not self.in_loop:
diag = diagnostic.Diagnostic("error",
"break statement outside of a loop", {},
node.keyword_loc)
self.engine.process(diag)
def visit_Continue(self, node):
if not self.in_loop:
diag = diagnostic.Diagnostic("error",
"continue statement outside of a loop", {},
node.keyword_loc)
self.engine.process(diag)
def visit_FunctionDefT(self, node):
old_function, self.function = self.function, node
old_in_loop, self.in_loop = self.in_loop, False
self.generic_visit(node)
self.function = old_function
self.in_loop = old_in_loop
def visit_Return(self, node): def visit_Return(self, node):
if not self.function:
diag = diagnostic.Diagnostic("error",
"return statement outside of a function", {},
node.keyword_loc)
self.engine.process(diag)
return
self.generic_visit(node) self.generic_visit(node)
def makenotes(printer, typea, typeb, loca, locb): def makenotes(printer, typea, typeb, loca, locb):
return [ return [

View File

@ -0,0 +1,19 @@
# RUN: %python -m artiq.py2llvm.typing +diag %s >%t
# RUN: OutputCheck %s --file-to-check=%t
# CHECK-L: ${LINE:+1}: error: return statement outside of a function
return
# CHECK-L: ${LINE:+1}: error: break statement outside of a loop
break
# CHECK-L: ${LINE:+1}: error: continue statement outside of a loop
continue
while True:
def f():
# CHECK-L: ${LINE:+1}: error: break statement outside of a loop
break
# CHECK-L: ${LINE:+1}: error: continue statement outside of a loop
continue