mirror of https://github.com/m-labs/artiq.git
Add tests for all diagnostics and unifications.
This commit is contained in:
parent
a8ff9d0152
commit
159692339d
|
@ -84,21 +84,25 @@ class LocalExtractor(algorithm.Visitor):
|
||||||
|
|
||||||
def _check_not_in(self, name, names, curkind, newkind, loc):
|
def _check_not_in(self, name, names, curkind, newkind, loc):
|
||||||
if name in names:
|
if name in names:
|
||||||
diag = diagnostic.Diagnostic("fatal",
|
diag = diagnostic.Diagnostic("error",
|
||||||
"name '{name}' cannot be {curkind} and {newkind} simultaneously",
|
"name '{name}' cannot be {curkind} and {newkind} simultaneously",
|
||||||
{"name": name, "curkind": curkind, "newkind": newkind}, loc)
|
{"name": name, "curkind": curkind, "newkind": newkind}, loc)
|
||||||
self.engine.process(diag)
|
self.engine.process(diag)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def visit_Global(self, node):
|
def visit_Global(self, node):
|
||||||
for name, loc in zip(node.names, node.name_locs):
|
for name, loc in zip(node.names, node.name_locs):
|
||||||
self._check_not_in(name, self.nonlocal_, "nonlocal", "global", loc)
|
if self._check_not_in(name, self.nonlocal_, "nonlocal", "global", loc) or \
|
||||||
self._check_not_in(name, self.params, "a parameter", "global", loc)
|
self._check_not_in(name, self.params, "a parameter", "global", loc):
|
||||||
|
continue
|
||||||
self.global_.add(name)
|
self.global_.add(name)
|
||||||
|
|
||||||
def visit_Nonlocal(self, node):
|
def visit_Nonlocal(self, node):
|
||||||
for name, loc in zip(node.names, node.name_locs):
|
for name, loc in zip(node.names, node.name_locs):
|
||||||
self._check_not_in(name, self.global_, "global", "nonlocal", loc)
|
if self._check_not_in(name, self.global_, "global", "nonlocal", loc) or \
|
||||||
self._check_not_in(name, self.params, "a parameter", "nonlocal", loc)
|
self._check_not_in(name, self.params, "a parameter", "nonlocal", loc):
|
||||||
|
continue
|
||||||
|
|
||||||
found = False
|
found = False
|
||||||
for outer_env in reversed(self.env_stack):
|
for outer_env in reversed(self.env_stack):
|
||||||
|
@ -106,11 +110,12 @@ class LocalExtractor(algorithm.Visitor):
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
if not found:
|
if not found:
|
||||||
diag = diagnostic.Diagnostic("fatal",
|
diag = diagnostic.Diagnostic("error",
|
||||||
"can't declare name '{name}' as nonlocal: it is not bound in any outer scope",
|
"can't declare name '{name}' as nonlocal: it is not bound in any outer scope",
|
||||||
{"name": name},
|
{"name": name},
|
||||||
loc, [node.keyword_loc])
|
loc, [node.keyword_loc])
|
||||||
self.engine.process(diag)
|
self.engine.process(diag)
|
||||||
|
continue
|
||||||
|
|
||||||
self.nonlocal_.add(name)
|
self.nonlocal_.add(name)
|
||||||
|
|
||||||
|
@ -355,27 +360,29 @@ def main():
|
||||||
|
|
||||||
if sys.argv[1] == '+diag':
|
if sys.argv[1] == '+diag':
|
||||||
del sys.argv[1]
|
del sys.argv[1]
|
||||||
inference_mode = False
|
def process_diagnostic(diag):
|
||||||
|
print("\n".join(diag.render(only_line=True)))
|
||||||
|
if diag.level == 'fatal':
|
||||||
|
exit()
|
||||||
else:
|
else:
|
||||||
inference_mode = True
|
def process_diagnostic(diag):
|
||||||
|
print("\n".join(diag.render()))
|
||||||
|
if diag.level == 'fatal':
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
engine = diagnostic.Engine()
|
||||||
|
engine.process = process_diagnostic
|
||||||
|
|
||||||
|
buf = source.Buffer("".join(fileinput.input()), os.path.basename(fileinput.filename()))
|
||||||
|
parsed, comments = parse_buffer(buf, engine=engine)
|
||||||
|
typed = Inferencer(engine=engine).visit_root(parsed)
|
||||||
|
printer = Printer(buf)
|
||||||
|
printer.visit(typed)
|
||||||
|
for comment in comments:
|
||||||
|
if comment.text.find("CHECK") >= 0:
|
||||||
|
printer.rewriter.remove(comment.loc)
|
||||||
|
print(printer.rewrite().source)
|
||||||
|
|
||||||
engine = diagnostic.Engine(all_errors_are_fatal=True)
|
|
||||||
try:
|
|
||||||
buf = source.Buffer("".join(fileinput.input()), os.path.basename(fileinput.filename()))
|
|
||||||
parsed, comments = parse_buffer(buf, engine=engine)
|
|
||||||
typed = Inferencer(engine=engine).visit_root(parsed)
|
|
||||||
printer = Printer(buf)
|
|
||||||
printer.visit(typed)
|
|
||||||
for comment in comments:
|
|
||||||
if comment.text.find("CHECK") >= 0:
|
|
||||||
printer.rewriter.remove(comment.loc)
|
|
||||||
print(printer.rewrite().source)
|
|
||||||
except diagnostic.Error as e:
|
|
||||||
if inference_mode:
|
|
||||||
print("\n".join(e.diagnostic.render()), file=sys.stderr)
|
|
||||||
exit(1)
|
|
||||||
else:
|
|
||||||
print("\n".join(e.diagnostic.render(only_line=True)))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# RUN: %python -m artiq.py2llvm.typing +diag %s >%t
|
||||||
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
|
# CHECK-L: ${LINE:+1}: fatal: name 'x' is not bound to anything
|
||||||
|
x
|
|
@ -0,0 +1,25 @@
|
||||||
|
# RUN: %python -m artiq.py2llvm.typing +diag %s >%t
|
||||||
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
|
def a():
|
||||||
|
# CHECK-L: ${LINE:+1}: error: can't declare name 'x' as nonlocal: it is not bound in any outer scope
|
||||||
|
nonlocal x
|
||||||
|
|
||||||
|
x = 1
|
||||||
|
def b():
|
||||||
|
nonlocal x
|
||||||
|
# CHECK-L: ${LINE:+1}: error: name 'x' cannot be nonlocal and global simultaneously
|
||||||
|
global x
|
||||||
|
|
||||||
|
def c():
|
||||||
|
global x
|
||||||
|
# CHECK-L: ${LINE:+1}: error: name 'x' cannot be global and nonlocal simultaneously
|
||||||
|
nonlocal x
|
||||||
|
|
||||||
|
def d(x):
|
||||||
|
# CHECK-L: ${LINE:+1}: error: name 'x' cannot be a parameter and global simultaneously
|
||||||
|
global x
|
||||||
|
|
||||||
|
def d(x):
|
||||||
|
# CHECK-L: ${LINE:+1}: error: name 'x' cannot be a parameter and nonlocal simultaneously
|
||||||
|
nonlocal x
|
|
@ -24,3 +24,11 @@ g = []
|
||||||
|
|
||||||
h = [1]
|
h = [1]
|
||||||
# CHECK-L: h:list(elt=int(width='c))
|
# CHECK-L: h:list(elt=int(width='c))
|
||||||
|
|
||||||
|
i = []
|
||||||
|
i[0] = 1
|
||||||
|
# CHECK-L: i:list(elt=int(width='d))
|
||||||
|
|
||||||
|
j = []
|
||||||
|
j += [1.0]
|
||||||
|
# CHECK-L: j:list(elt=float)
|
||||||
|
|
Loading…
Reference in New Issue