def map_size(t: ConcreteType, m: ast.Module, f: Callable[[Dim], Dim]) -> ConcreteType: """Runs f on all dimensions within t (transively for contained types).""" assert isinstance(m, ast.Module), m rec = functools.partial(map_size, m=m, f=f) if isinstance(t, ArrayType): return ArrayType(rec(t.get_element_type()), f(t.size)) elif isinstance(t, BitsType): return BitsType(t.signed, f(t.size)) elif isinstance(t, TupleType): nominal = t.get_nominal_type() if t.named: return TupleType( tuple((name, rec(type_)) for name, type_ in t.members), nominal) assert nominal is None, nominal return TupleType(tuple(rec(e) for e in t.members)) elif isinstance(t, EnumType): return EnumType(t.get_nominal_type(), f(t.size)) elif isinstance(t, FunctionType): mapped_params = tuple(rec(p) for p in t.params) mapped_return_type = rec(t.return_type) return FunctionType(mapped_params, mapped_return_type) else: raise NotImplementedError(t.__class__)
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(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.value, 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 _check_function(f: ast.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 type_info, 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.type_info, f f_type = ctx.type_info[f] assert isinstance(f_type, FunctionType), f_type annotated_return_type = f_type.return_type param_types = list(ctx.type_info[f].params) 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.type_info[f.name] = ctx.type_info[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. logging.vlog( 3, 'resolved return type: %s => %s resolved body type: %s => %s', annotated_return_type, resolved_return_type, body_return_type, resolved_body_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.type_info[f.name] = ctx.type_info[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(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)