Exemplo n.º 1
0
def _check_function(f: Function, ctx: deduce.DeduceCtx) -> None:
    """Validates type annotations on parameters/return type of f are consistent.

  Args:
    f: The function to type check.
    ctx: Wraps a node_to_type, a mapping of AST node to its deduced type;
      (free-variable) references are resolved via this dictionary.

  Raises:
    XlsTypeError: When the return type deduced is inconsistent with the return
      type annotation on "f".
  """
    fn_name, _ = ctx.fn_stack[-1]
    # First, get the types of the function's parametrics, args, and return type
    if f.is_parametric() and f.name.identifier == fn_name:
        # Parametric functions are evaluated per invocation. If we're currently
        # inside of this function, it must mean that we already have the type
        # signature and now we just need to evaluate the body.
        assert f in ctx.node_to_type, f
        annotated_return_type = ctx.node_to_type[f].return_type  # pytype: disable=attribute-error
        param_types = list(ctx.node_to_type[f].params)  # pytype: disable=attribute-error
    else:
        logging.vlog(1, 'Type-checking sig for function: %s', f)
        param_types = _check_function_params(f, ctx)
        if f.is_parametric():
            # We just needed the type signature so that we can instantiate this
            # invocation. Let's return this for now and typecheck the body once we
            # have symbolic bindings.
            annotated_return_type = (deduce.deduce(f.return_type, ctx)
                                     if f.return_type else ConcreteType.NIL)
            ctx.node_to_type[f.name] = ctx.node_to_type[f] = FunctionType(
                tuple(param_types), annotated_return_type)
            return

    logging.vlog(1, 'Type-checking body for function: %s', f)

    # Second, typecheck the return type of the function.
    # NOTE: if there is no annotated return type, we assume NIL.
    annotated_return_type = (deduce.deduce(f.return_type, ctx)
                             if f.return_type else ConcreteType.NIL)
    resolved_return_type = deduce.resolve(annotated_return_type, ctx)

    # Third, typecheck the body of the function
    body_return_type = deduce.deduce(f.body, ctx)
    resolved_body_type = deduce.resolve(body_return_type, ctx)

    # Finally, assert type consistency between body and annotated return type.
    if resolved_return_type != resolved_body_type:
        raise XlsTypeError(
            f.body.span,
            resolved_body_type,
            resolved_return_type,
            suffix='Return type of function body for "{}" did not match the '
            'annotated return type.'.format(f.name.identifier))

    ctx.node_to_type[f.name] = ctx.node_to_type[f] = FunctionType(
        tuple(param_types), body_return_type)
Exemplo n.º 2
0
def fsig(arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
         _: Optional[ParametricBindings]) -> ConcreteType:
    _Checker(arg_types, name, span).len(2).is_uN((0, 1))
    return_type = BitsType(signed=False,
                           size=arg_types[0].get_total_bit_count() +
                           arg_types[1].get_total_bit_count())
    return FunctionType(arg_types, return_type)
Exemplo n.º 3
0
def fsig(arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
         _: Optional[ParametricBindings]) -> ConcreteType:
    _Checker(arg_types, name, span).len(1).is_array(0)
    t = arg_types[0].get_element_type()  # pytype: disable=attribute-error
    e = TupleType((ConcreteType.U32, t))
    return_type = ArrayType(e, arg_types[0].size)  # pytype: disable=attribute-error
    return FunctionType(arg_types, return_type)
Exemplo n.º 4
0
def fsig(arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
         _: Optional[ParametricBindings]) -> ConcreteType:
  checker = _Checker(arg_types, name, span).len(3).is_array(0).is_uN(1)
  checker.check_is_same(
      arg_types[0].get_element_type(), arg_types[2],  # pytype: disable=attribute-error
      'Want argument 0 element type {0} to match argument 2 type {1}')
  return FunctionType(arg_types, arg_types[0])
Exemplo n.º 5
0
def fsig(arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
         _: Optional[ParametricBindings]) -> ConcreteType:
  checker = _Checker(arg_types, name, span).len(2).is_bits(0).is_array(1)
  return_type = arg_types[1].get_element_type()  # pytype: disable=attribute-error
  checker.check_is_bits(return_type,
                        'Want arg 1 element type to be bits; got {0}')
  return FunctionType(arg_types, return_type)
Exemplo n.º 6
0
def fsig(arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
         _: Optional[ParametricBindings]) -> ConcreteType:
  checker = _Checker(arg_types, name,
                     span).len(3).is_array(0).is_uN(1).is_array(2)
  checker.eq(
      arg_types[0].get_element_type(), arg_types[2].get_element_type(),  # pytype: disable=attribute-error
      'Element type of argument 0 {0} should match element type of argument 2 {1}'
  )
  return FunctionType(arg_types, arg_types[2])
Exemplo n.º 7
0
def fsig(
    arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
    parametric_bindings: Optional[ParametricBindings]
) -> Tuple[ConcreteType, parametric_instantiator.SymbolicBindings]:
    """Returns the inferred/checked return type for a map-style signature."""
    logging.vlog(5, 'Instantiating for builtin %r @ %s', name, span)
    _Checker(arg_types, name, span).len(2).is_array(0).is_fn(1, argc=1)
    t = arg_types[0].get_element_type()  # pytype: disable=attribute-error
    u, symbolic_bindings = parametric_instantiator.instantiate_function(
        span, arg_types[1], (t, ), ctx, parametric_bindings)
    return_type = ArrayType(u, arg_types[0].size)  # pytype: disable=attribute-error
    return FunctionType(arg_types, return_type), symbolic_bindings
Exemplo n.º 8
0
def fsig(arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
         _: Optional[ParametricBindings]) -> ConcreteType:
    """Checks the type signature shown above and returns deduced output type."""
    checker = _Checker(arg_types, name, span).len(2).is_bits(0).is_array(1)

    arg0 = arg_types[0]
    arg1 = arg_types[1]
    assert isinstance(arg1, ArrayType), arg1
    assert isinstance(arg1.size, int), arg1
    return_type = arg1.element_type
    checker.check_is_bits(return_type,
                          'Want arg 1 element type to be bits; got {0}')
    checker.check_is_len(
        arg1, arg0.size,
        'bit width {target} must match {t} array size {t.size}')
    return FunctionType(arg_types, return_type)
Exemplo n.º 9
0
def fsig(arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
         _: Optional[ParametricBindings]) -> ConcreteType:
    _Checker(arg_types, name, span).len(3).is_uN((0, 1, 2))
    return FunctionType(arg_types, arg_types[2])
Exemplo n.º 10
0
def fsig(arg_types: ArgTypes, name: Text, span: Span, ctx: DeduceCtx,
         _: Optional[ParametricBindings]) -> ConcreteType:
    _Checker(arg_types, name, span).len(2).is_bits(0).is_same(0, 1)
    return FunctionType(arg_types, ConcreteType.U1)