Exemplo n.º 1
0
Arquivo: repl.py Projeto: hixio-mh/xls
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)

    import_cache = import_routines.ImportCache()

    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:
            f_import = functools.partial(import_routines.do_import,
                                         cache=import_cache)
            type_info = typecheck.check_module(fake_module, f_import=f_import)
        except xls_type_error.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,
                                              f_import=f_import,
                                              trace_all=False)
    result = interpreter.run_function(fn_name, args=())
    print(result)
    return result
Exemplo n.º 2
0
def interpret_expr(module: ast.Module,
                   type_info: type_info_mod.TypeInfo,
                   env: Dict[str, int],
                   bit_widths: Dict[str, int],
                   expr: ast.Expr,
                   f_import: Optional[deduce.ImportFn],
                   fn_ctx=Tuple[str, str, SymbolicBindings]) -> int:
    """Interprets expr using env and module's top level bindings.

  Args:
    module: The module that this expression is inside of.
    type_info: Mapping from AST node to its deduced/checked type.
    env: Mapping from symbols to their integer values.
    bit_widths: Mapping from symbols to their bitwidths.
    expr: Expression to evaluate using the values from env and top level
      bindings (e.g. constants, other functions).
    f_import: Import routine callback for the interpreter to use.
    fn_ctx: The (module name, function name, symbolic bindings) we are currently
      using.

  Returns:
    The integer value of the interpreted expression.

  Raises:
    KeyError: Occurs when the interpreter encounters a symbol that isn't in env.
  """
    interp = interpreter.Interpreter(module, type_info, f_import=f_import)
    bindings = interp._make_top_level_bindings(module)  # pylint: disable=protected-access
    bindings.fn_ctx = FnCtx(*fn_ctx)
    for ident, val in env.items():
        bindings.add_value(
            ident,
            interpreter.Value.make_ubits(value=val,
                                         bit_count=bit_widths[ident]))
    return interp.evaluate_expr(expr, bindings).bits_payload.value