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)
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)
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)
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])
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)
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])
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
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)
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])
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)