Add lit-based tests for type inferencer.

This commit is contained in:
whitequark 2015-06-06 16:58:23 +03:00
parent 5f06c6af10
commit 7f77632f1a
6 changed files with 85 additions and 8 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ doc/manual/_build
/*.egg-info /*.egg-info
/.coverage /.coverage
examples/master/results examples/master/results
Output/

View File

@ -129,10 +129,10 @@ class LocalExtractor(algorithm.Visitor):
class Inferencer(algorithm.Transformer): class Inferencer(algorithm.Transformer):
def __init__(self, engine): def __init__(self, engine):
self.engine = engine self.engine = engine
self.env_stack = [{}] self.env_stack = []
self.function = None # currently visited function self.function = None # currently visited function
def _unify(self, typea, typeb, loca, locb, kind): def _unify(self, typea, typeb, loca, locb, kind='generic'):
try: try:
typea.unify(typeb) typea.unify(typeb)
except types.UnificationError as e: except types.UnificationError as e:
@ -186,6 +186,13 @@ class Inferencer(algorithm.Transformer):
"name '{name}' is not bound to anything", {"name":name}, loc) "name '{name}' is not bound to anything", {"name":name}, loc)
self.engine.process(diag) self.engine.process(diag)
def visit_root(self, node):
extractor = LocalExtractor(env_stack=self.env_stack, engine=self.engine)
extractor.visit(node)
self.env_stack.append(extractor.typing_env)
return self.visit(node)
# Visitors that replace node with a typed node # Visitors that replace node with a typed node
# #
def visit_arg(self, node): def visit_arg(self, node):
@ -349,17 +356,25 @@ class Printer(algorithm.Visitor):
super().generic_visit(node) super().generic_visit(node)
def main(): def main():
import sys, fileinput import sys, fileinput, os
inference_mode = True
engine = diagnostic.Engine(all_errors_are_fatal=True) engine = diagnostic.Engine(all_errors_are_fatal=True)
try: try:
buf = source.Buffer("".join(fileinput.input()), fileinput.filename()) buf = source.Buffer("".join(fileinput.input()), os.path.basename(fileinput.filename()))
parsed = parse_buffer(buf, engine=engine) parsed, comments = parse_buffer(buf, engine=engine)
typed = Inferencer(engine=engine).visit(parsed) typed = Inferencer(engine=engine).visit_root(parsed)
printer = Printer(buf) printer = Printer(buf)
printer.visit(typed) printer.visit(typed)
for comment in comments:
if comment.text.find("CHECK") >= 0:
printer.rewriter.remove(comment.loc)
print(printer.rewrite().source) print(printer.rewrite().source)
except diagnostic.Error as e: except diagnostic.Error as e:
print("\n".join(e.diagnostic.render()), file=sys.stderr) if inference_mode:
print("\n".join(e.diagnostic.render()), file=sys.stderr)
exit(1)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

23
lit-test/harness.py Normal file
View File

@ -0,0 +1,23 @@
"""
The purpose of this harness is to emulate the behavior of
the python executable, but add the ARTIQ root to sys.path
beforehand.
This is necessary because eggs override the PYTHONPATH environment
variable, but not current directory; therefore `python -m artiq...`
ran from the ARTIQ root would work, but there is no simple way to
emulate the same behavior when invoked under lit.
"""
import sys, os, argparse, importlib
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-m', metavar='mod', type=str, help='run library module as a script')
parser.add_argument('args', type=str, nargs='+', help='arguments passed to program in sys.argv[1:]')
args = parser.parse_args(sys.argv[1:])
artiq_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.insert(1, artiq_path)
sys.argv[1:] = args.args
importlib.import_module(args.m).main()

12
lit-test/lit.cfg Normal file
View File

@ -0,0 +1,12 @@
import lit.util
import lit.formats
config.name = 'ARTIQ'
config.test_format = lit.formats.ShTest()
config.suffixes = ['.py']
config.excludes = ['harness.py']
config.test_source_root = os.path.dirname(__file__)
python_executable = 'python3'
harness = '{} {}'.format(python_executable, os.path.join(config.test_source_root, 'harness.py'))
config.substitutions.append( ('%python', harness) )

View File

@ -0,0 +1,26 @@
# RUN: %python -m artiq.py2llvm.typing %s >%t
# RUN: OutputCheck %s --file-to-check=%t
a = 1
# CHECK-L: a:int(width='a)
b = a
# CHECK-L: b:int(width='a)
c = True
# CHECK-L: c:bool
d = False
# CHECK-L: d:bool
e = None
# CHECK-L: e:NoneType
f = 1.0
# CHECK-L: f:float
g = []
# CHECK-L: g:list(elt='b)
h = [1]
# CHECK-L: h:list(elt=int(width='c))

View File

@ -6,7 +6,7 @@ from setuptools import setup, find_packages
requirements = [ requirements = [
"sphinx", "sphinx-argparse", "pyserial", "numpy", "scipy", "sphinx", "sphinx-argparse", "pyserial", "numpy", "scipy",
"python-dateutil", "prettytable", "h5py", "pydaqmx", "pyelftools", "python-dateutil", "prettytable", "h5py", "pydaqmx", "pyelftools",
"quamash", "pyqtgraph", "pythonparser" "quamash", "pyqtgraph", "pythonparser", "lit", "OutputCheck"
] ]
scripts = [ scripts = [