예제 #1
0
def value_from_string(s: str) -> Value:
    scanner = Scanner('<text>', s)
    try:
        return value_from_scanner(scanner)
    except ScanError as e:
        raise ValueParseError(
            'Could not parse value from string {!r}: {}'.format(s, e))
예제 #2
0
def _bit_value_from_scanner(s: Scanner, signed: bool) -> Value:
  s.drop_or_error(TokenKind.OBRACK)
  bit_count_tok = s.pop_or_error(TokenKind.NUMBER)
  s.drop_or_error(TokenKind.CBRACK)
  s.drop_or_error(TokenKind.COLON)
  value_tok = s.pop_or_error(TokenKind.NUMBER)
  constructor = Value.make_sbits if signed else Value.make_ubits
  return constructor(
      bit_count=ast_helpers.get_token_value_as_int(bit_count_tok),
      value=ast_helpers.get_token_value_as_int(value_tok))
예제 #3
0
def _bit_value_from_scanner(s: Scanner, signed: bool) -> Value:
    s.pop_or_error(TokenKind.OBRACK)
    bit_count_tok = s.pop_or_error(TokenKind.NUMBER)
    s.pop_or_error(TokenKind.CBRACK)
    s.pop_or_error(TokenKind.COLON)
    value_tok = s.pop_or_error(TokenKind.NUMBER)
    tag = Tag.SBITS if signed else Tag.UBITS
    return Value.make_bits(
        tag,
        ir_bits.from_long(
            bit_count=ast_helpers.get_token_value_as_int(bit_count_tok),
            value=ast_helpers.get_token_value_as_int(value_tok)))
예제 #4
0
def main(argv):
  if len(argv) > 2:
    raise app.UsageError('Too many command-line arguments.')

  path = argv[1]

  with open(path, 'r') as f:
    text = f.read()

  pprint.pprint(Scanner(path, text).pop_all())
예제 #5
0
def parse_and_test(program: Text,
                   name: Text,
                   *,
                   filename: Text,
                   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.
    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
    import_cache = import_routines.ImportCache()
    f_import = functools.partial(import_routines.do_import, cache=import_cache)
    type_info = None

    try:
        module = Parser(Scanner(filename, program), name).parse_module()
        type_info = typecheck.check_module(module, f_import)

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

        interpreter = Interpreter(module,
                                  type_info,
                                  f_import,
                                  trace_all=trace_all,
                                  ir_package=ir_package)
        for test_name in module.get_test_names():
            if not _matches(test_name, test_filter):
                continue
            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)
                interpreter.run_quickcheck(quickcheck, seed=seed)
                print('[               OK ]', test_name, file=sys.stderr)

    except PositionalError as e:
        did_fail = True
        parser_helpers.pprint_positional_error(e)
        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()

    return did_fail
예제 #6
0
def value_from_scanner(s: Scanner) -> Value:
    """Recursive call for converting a stream of tokens into a value."""
    s = _LookaheadWrapper(s)
    if s.try_pop(TokenKind.OPAREN):
        elements = []
        must_end = False
        while True:
            if s.try_pop(TokenKind.CPAREN):
                break
            if must_end:
                s.pop_or_error(TokenKind.CPAREN)
                break
            elements.append(value_from_scanner(s))
            must_end = not s.try_pop(TokenKind.COMMA)
        return Value.make_tuple(tuple(elements))

    if s.try_pop(TokenKind.OBRACK):
        elements = []
        must_end = False
        while True:
            if s.try_pop(TokenKind.CBRACK):
                break
            if must_end:
                s.pop_or_error(TokenKind.CBRACK)
                break
            elements.append(value_from_scanner(s))
            must_end = not s.try_pop(TokenKind.COMMA)
        return Value.make_array(tuple(elements))

    if s.try_pop_keyword(Keyword.BITS) or s.try_pop_keyword(Keyword.UN):
        return _bit_value_from_scanner(s, signed=False)
    if s.try_pop_keyword(Keyword.BITS) or s.try_pop_keyword(Keyword.SN):
        return _bit_value_from_scanner(s, signed=True)

    tok = s.pop()
    if tok.is_type_keyword():
        type_ = tok
        s.pop_or_error(TokenKind.COLON)
        value_tok = s.pop_or_error(TokenKind.NUMBER)
        signedness, bit_count = scanner_mod.TYPE_KEYWORDS_TO_SIGNEDNESS_AND_BITS[
            type_.value]
        constructor = Value.make_sbits if signedness else Value.make_ubits
        return constructor(bit_count=bit_count,
                           value=ast_helpers.get_token_value_as_int(value_tok))

    raise ScanError(tok.span.start,
                    'Unexpected token in value; found {}'.format(tok.kind))