Exemple #1
0
def handle_line(line: str, stmt_index: int):
  """Runs a single user-provided line as a REPL input."""
  fn_name = f'repl_{stmt_index}'
  module_text = f"""
  import std
  fn {fn_name}() -> () {{
    {line}
  }}
  """

  # For error reporting we use a helper that puts this into a fake filesystem
  # location.
  def make_fakefs_open():
    fs = fake_filesystem.FakeFilesystem()
    fs.CreateFile(FILENAME, module_text)
    return fake_filesystem.FakeFileOpen(fs)

  importer = import_helpers.Importer()

  while True:
    try:
      fake_module = parser.Parser(
          scanner.Scanner(FILENAME, module_text), fn_name).parse_module()
    except span.PositionalError as e:
      parser_helpers.pprint_positional_error(e, fs_open=make_fakefs_open())
      return

    # First attempt at type checking, we expect this may fail the first time
    # around and we'll substitute the real return type we observe.
    try:
      type_info = typecheck.check_module(fake_module, f_import=importer)
    except XlsTypeError as e:
      # We use nil as a placeholder, and swap it with the type that was expected
      # and retry once we determine what that should be.
      if e.rhs_type == concrete_type_mod.ConcreteType.NIL:
        module_text = module_text.replace(' -> ()', ' -> ' + str(e.lhs_type))
        continue
      # Any other errors are likely real type errors in the code and we should
      # report them.
      parser_helpers.pprint_positional_error(e, fs_open=make_fakefs_open())
      return

    # It type checked ok, and we can proceed.
    break

  # Interpret the line and print the result.
  # TODO(leary): 2020-06-20 No let bindings for the moment, just useful for
  # evaluating expressions -- could put them into the module scope as consts.
  interpreter = interpreter_mod.Interpreter(
      fake_module,
      type_info,
      importer.typecheck,
      importer.cache,
      trace_all=False)
  result = interpreter.run_function(fn_name, args=())
  print(result)
  type_info.clear_type_info_refs_for_gc()
  return result
Exemple #2
0
def main(argv):
    if len(argv) != 2:
        raise app.UsageError('Too many command-line arguments.')

    f_import = import_helpers.Importer()

    text = argv[1]
    p = convert_helpers.convert_dslx_to_package(text,
                                                name='cli',
                                                f_import=f_import)
    entry = p.get_function_names()[0]
    opt_ir = convert_helpers.optimize_and_dump(p)
    benchmark_main_path = runfiles.get_path(BENCHMARK_MAIN_PATH)
    with tempfile.NamedTemporaryFile() as f:
        f.write(opt_ir.encode('utf-8'))
        f.flush()
        subprocess.check_call(
            [benchmark_main_path, f.name, '--entry={}'.format(entry)])
Exemple #3
0
def main(argv):
    binary = os.path.basename(argv[0])
    if len(argv) < 2:
        raise app.UsageError('Wrong number of command-line arguments; '
                             'expect %s <input-file>' % binary)

    init_xls.init_xls(sys.argv)

    path = argv[1]
    with open(path, 'r') as f:
        text = f.read()

    name = os.path.basename(path)
    name, _ = os.path.splitext(name)
    module = parser_helpers.parse_text(text,
                                       name,
                                       print_on_error=True,
                                       filename=path)

    importer = import_helpers.Importer(tuple(FLAGS.dslx_path))
    type_info = None

    try:
        type_info = cpp_typecheck.check_module(
            module, importer.cache, importer.additional_search_paths)
        if FLAGS.entry:
            print(
                ir_converter.convert_one_function(module, FLAGS.entry,
                                                  type_info))
        else:
            print(ir_converter.convert_module(module, type_info))
    except (PositionalError, cpp_parser.CppParseError) as e:
        parser_helpers.pprint_positional_error(e)
        if FLAGS.raise_exception:
            raise
        else:
            sys.exit(1)
    finally:
        if type_info is not None:
            type_info.clear_type_info_refs_for_gc()
Exemple #4
0
def main(argv):
    init_xls.init_xls(argv)
    if len(argv) > 2:
        raise app.UsageError('Too many command-line arguments.')

    path = argv[1]
    with open(path) as f:
        text = f.read()

    name = os.path.basename(path)
    name, _ = os.path.splitext(name)

    importer = import_helpers.Importer()

    module = parse_and_typecheck.parse_text(
        text,
        name,
        filename=path,
        print_on_error=True,
        import_cache=importer.cache,
        additional_search_paths=importer.additional_search_paths)
    pprint.pprint(module)
Exemple #5
0
def parse_and_test(program: Text,
                   name: Text,
                   *,
                   filename: Text,
                   additional_search_paths: Tuple[str, ...] = (),
                   raise_on_error: bool = True,
                   test_filter: Optional[Text] = None,
                   trace_all: bool = False,
                   compare_jit: bool = True,
                   seed: Optional[int] = None) -> bool:
    """Parses program and run all tests contained inside.

  Args:
    program: The program text to parse.
    name: Name for the module.
    filename: The filename from which "program" text originates.
    additional_search_paths: Additional paths at which we search for imported
      module files.
    raise_on_error: When true, raises exceptions that happen in tests;
      otherwise, simply returns a boolean to the caller when all test have run.
    test_filter: Test filter specification (e.g. as passed from bazel test
      environment).
    trace_all: Whether or not to trace all expressions.
    compare_jit: Whether or not to assert equality between interpreted and
      JIT'd function return values.
    seed: Seed for QuickCheck random input stimulus.

  Returns:
    Whether or not an error occurred during parsing/testing.

  Raises:
    ScanError, ParseError: In case of front-end errors.
    TypeInferenceError, TypeError: In case of type errors.
    EvaluateError: In case of a runtime failure.
  """
    did_fail = False
    test_name = None
    type_info = None

    importer = import_helpers.Importer(additional_search_paths)
    ran = 0

    try:
        module = Parser(Scanner(filename, program), name).parse_module()
        type_info = cpp_typecheck.check_module(
            module, importer.cache, importer.additional_search_paths)

        ir_package = (ir_converter.convert_module_to_package(
            module, type_info, traverse_tests=True) if compare_jit else None)

        interpreter = Interpreter(module,
                                  type_info,
                                  importer.typecheck,
                                  importer.additional_search_paths,
                                  importer.cache,
                                  trace_all=trace_all,
                                  ir_package=ir_package)
        for test_name in module.get_test_names():
            if not _matches(test_name, test_filter):
                continue
            ran += 1
            print('[ RUN UNITTEST     ]', test_name, file=sys.stderr)
            interpreter.run_test(test_name)
            print('[               OK ]', test_name, file=sys.stderr)

        if ir_package and module.get_quickchecks():
            if seed is None:
                # We want to guarantee non-determinism by default. See
                # https://abseil.io/docs/cpp/guides/random#stability-of-generated-sequences
                # for rationale.
                seed = int(os.getpid() * time.time())
            print(f'[ SEED: {seed} ]')
            for quickcheck in module.get_quickchecks():
                test_name = quickcheck.f.name.identifier
                print('[ RUN QUICKCHECK   ]', test_name, file=sys.stderr)
                quickcheck_helpers.run_quickcheck(interpreter,
                                                  ir_package,
                                                  quickcheck,
                                                  seed=seed)
                print('[               OK ]', test_name, file=sys.stderr)

    except (PositionalError, FailureError, CppParseError, ScanError,
            TypeInferenceError, XlsTypeError) as e:
        did_fail = True
        parser_helpers.pprint_positional_error(e,
                                               output=cast(
                                                   io.IOBase, sys.stderr))
        if test_name:
            print('[           FAILED ]',
                  test_name,
                  e.__class__.__name__,
                  file=sys.stderr)
        if raise_on_error:
            raise
    finally:
        if type_info is not None:
            type_info.clear_type_info_refs_for_gc()

    print('[==================]', ran, 'test(s) ran.', file=sys.stderr)
    return did_fail