def test_stringify_type(self): fake_span = self.fake_span m = self.m number_5 = ast.Number(m, fake_span, '5') number_2 = ast.Number(m, fake_span, '2') number_3 = ast.Number(m, fake_span, '3') bits_token = Token(TokenKind.KEYWORD, value=Keyword.BITS, span=fake_span) type_ = ast_helpers.make_builtin_type_annotation(m, fake_span, bits_token, (number_5,)) self.assertEqual('bits[5]', str(type_)) type_ = ast_helpers.make_builtin_type_annotation( m, fake_span, Token(TokenKind.KEYWORD, value=Keyword.U32, span=fake_span), (number_5,)) self.assertEqual('u32[5]', str(type_)) # "no-volume" bits array. # TODO(leary): 2020-08-24 delete bits in favor of uN type_ = ast_helpers.make_builtin_type_annotation(m, fake_span, bits_token, ()) self.assertEqual('bits', str(type_)) # TypeRef with dims. my_type_tok = Token(TokenKind.IDENTIFIER, value='MyType', span=fake_span) name_def = ast.NameDef(m, fake_span, 'MyType') type_def = ast.TypeDef(m, False, name_def, type_) type_ref = ast.TypeRef(m, fake_span, my_type_tok.value, type_def=type_def) type_ = ast_helpers.make_type_ref_type_annotation(m, fake_span, type_ref, (number_2, number_3)) self.assertEqual('MyType[2][3]', str(type_))
def test_type_annotation_properties(self): m = self.m fake_span = self.fake_span number_5 = ast.Number(m, fake_span, '5') number_2 = ast.Number(m, fake_span, '2') number_3 = ast.Number(m, fake_span, '3') bits_token = Token(TokenKind.KEYWORD, value=Keyword.BITS, span=fake_span) un_token = Token(TokenKind.KEYWORD, value=Keyword.UN, span=fake_span) u32_token = Token(TokenKind.KEYWORD, value=Keyword.U32, span=fake_span) type_ = ast_helpers.make_builtin_type_annotation(m, fake_span, bits_token, (number_5,)) self.assertEqual('bits[5]', str(type_)) type_ = ast_helpers.make_builtin_type_annotation(m, fake_span, bits_token, (number_5, number_2)) self.assertIsInstance(type_, ast.ArrayTypeAnnotation) self.assertEqual('bits[5][2]', str(type_)) type_ = ast_helpers.make_builtin_type_annotation(m, fake_span, u32_token, ()) self.assertEqual('u32', str(type_)) type_ = ast_helpers.make_builtin_type_annotation(m, fake_span, u32_token, (number_3,)) self.assertIsInstance(type_, ast.ArrayTypeAnnotation) self.assertEqual('u32[3]', str(type_)) type_ = ast_helpers.make_builtin_type_annotation(m, fake_span, un_token, (number_2,)) self.assertEqual('uN[2]', str(type_)) type_ = ast_helpers.make_builtin_type_annotation(m, fake_span, un_token, (number_2, number_3)) self.assertIsInstance(type_, ast.ArrayTypeAnnotation) self.assertEqual('uN[2][3]', str(type_)) # TODO(leary): 2020-08-24 delete bits in favor of uN # "no-volume" bits array. type_ = ast_helpers.make_builtin_type_annotation(m, fake_span, bits_token, ()) self.assertEqual('bits', str(type_)) # TypeRef with dims. name_def = ast.NameDef(m, fake_span, 'MyType') type_def = ast.TypeDef(m, False, name_def, type_) type_ref = ast.TypeRef(m, fake_span, 'MyType', type_def=type_def) type_ = ast_helpers.make_type_ref_type_annotation(m, fake_span, type_ref, (number_2, number_3)) self.assertIsInstance(type_, ast.ArrayTypeAnnotation) self.assertEqual('MyType[2][3]', str(type_)) type_ = ast.TupleTypeAnnotation( m, fake_span, (ast_helpers.make_builtin_type_annotation(m, fake_span, bits_token, (number_5,)), ast_helpers.make_builtin_type_annotation(m, fake_span, bits_token, (number_2,)))) self.assertIsInstance(type_, ast.TupleTypeAnnotation) self.assertEqual('(bits[5], bits[2])', str(type_))
def _generate_cast_bits_to_array( self, env: Env) -> Tuple[ast.Cast, ast.TypeAnnotation]: """Generates a cast from bits to array type.""" # Get a random bits-typed element from the environment. make_arg, arg_type = self._choose_env_value(env, self._is_builtin_unsigned) # Next, find factors of the bit count and select one pair. bit_count = builtin_type_to_bits(arg_type) factors = [] for i in range(1, bit_count + 1): if bit_count % i == 0: factors.append((i, bit_count // i)) element_size, array_size = self.rng.choice(factors) element_type = ast_helpers.make_builtin_type_annotation( self.m, self.fake_span, scanner.Token(value=scanner.Keyword.UN, span=self.fake_span), (self._make_number(element_size, None), )) outer_array_type = self._make_array_type(element_type, array_size) return (ast.Cast(self.m, self.fake_span, outer_array_type, make_arg()), outer_array_type)
def _generate_primitive_type(self) -> ast.TypeAnnotation: """Generates a random primitive-based type (no extra dims or tuples).""" primitive_token = self._generate_type_primitive() return ast_helpers.make_builtin_type_annotation(self.m, self.fake_span, primitive_token, dims=())
def _create_element_invocation(owner: ast.AstNodeOwner, span_: span.Span, callee: Union[ast.NameRef, ast.ModRef], arg_array: ast.Expr) -> ast.Invocation: """Creates a function invocation on the first element of the given array. We need to create a fake invocation to deduce the type of a function in the case where map is called with a builtin as the map function. Normally, map functions (including parametric ones) have their types deduced when their ast.Function nodes are encountered (where a similar fake ast.Invocation node is created). Builtins don't have ast.Function nodes, so that inference can't occur, so we essentually perform that synthesis and deduction here. Args: owner: AST node owner. span_: The location in the code where analysis is occurring. callee: The function to be invoked. arg_array: The array of arguments (at least one) to the function. Returns: An invocation node for the given function when called with an element in the argument array. """ annotation = ast_helpers.make_builtin_type_annotation( owner, span_, scanner.Token(scanner.TokenKind.KEYWORD, span_, scanner.Keyword.U32), ()) index_number = ast.Number(owner, span_, '32', ast.NumberKind.OTHER, annotation) index = ast.Index(owner, span_, arg_array, index_number) return ast.Invocation(owner, span_, callee, (index, ))
def _make_type_annotation(self, signed: bool, width: int) -> ast.TypeAnnotation: assert width > 0, width if width <= 64: return ast.BuiltinTypeAnnotation( self.m, self.fake_span, ast_helpers.get_builtin_type(signed, width)) else: token = scanner.Token(self.fake_span, scanner.KeywordFromString('sN' if signed else 'uN')) return ast_helpers.make_builtin_type_annotation( self.m, self.fake_span, token, dims=(self._make_number(width, None),))
def test_visit_type(self): fake_span = self.fake_span five = self.five # Make a uN[5] type node. t = ast_helpers.make_builtin_type_annotation( self.m, fake_span, Token(TokenKind.KEYWORD, value=Keyword.BITS, span=fake_span), dims=(five,)) assert isinstance(t, ast.ArrayTypeAnnotation), t c = _Collector() t.accept(c) self.assertEqual(c.collected, [five, t])
def test_types(self): g = ast_generator.AstGenerator(random.Random(0), ast_generator.AstGeneratorOptions()) _, m = g.generate_function_in_module('main', 'test') u1 = g._make_type_annotation(signed=False, width=1) self.assertEqual(g._get_type_bit_count(u1), 1) self.assertTrue(g._is_bit_vector(u1)) self.assertTrue(g._is_unsigned_bit_vector(u1)) self.assertFalse(g._is_array(u1)) self.assertFalse(g._is_tuple(u1)) s1 = g._make_type_annotation(signed=True, width=1) self.assertTrue(g._is_bit_vector(s1)) self.assertFalse(g._is_unsigned_bit_vector(s1)) self.assertEqual(g._get_type_bit_count(s1), 1) self.assertFalse(g._is_array(s1)) self.assertFalse(g._is_tuple(s1)) u42 = g._make_type_annotation(signed=False, width=42) self.assertEqual(g._get_type_bit_count(u42), 42) self.assertTrue(g._is_bit_vector(u42)) self.assertTrue(g._is_unsigned_bit_vector(u42)) self.assertFalse(g._is_array(u42)) self.assertFalse(g._is_tuple(u42)) empty_tuple = g._make_tuple_type(()) self.assertEqual(g._get_type_bit_count(empty_tuple), 0) self.assertFalse(g._is_bit_vector(empty_tuple)) self.assertFalse(g._is_unsigned_bit_vector(empty_tuple)) self.assertFalse(g._is_array(empty_tuple)) self.assertTrue(g._is_tuple(empty_tuple)) tple = g._make_tuple_type((empty_tuple, s1, u1, u42, u42)) self.assertEqual(g._get_type_bit_count(tple), 86) self.assertFalse(g._is_bit_vector(tple)) self.assertFalse(g._is_unsigned_bit_vector(tple)) self.assertFalse(g._is_array(tple)) self.assertTrue(g._is_tuple(tple)) nested_tuple = g._make_tuple_type((tple, u42, tple)) self.assertEqual(g._get_type_bit_count(nested_tuple), 214) self.assertFalse(g._is_bit_vector(nested_tuple)) self.assertFalse(g._is_unsigned_bit_vector(nested_tuple)) self.assertFalse(g._is_array(nested_tuple)) self.assertTrue(g._is_tuple(nested_tuple)) array_of_u42 = g._make_array_type(u42, 100) self.assertEqual(g._get_type_bit_count(array_of_u42), 4200) self.assertFalse(g._is_bit_vector(array_of_u42)) self.assertFalse(g._is_unsigned_bit_vector(array_of_u42)) self.assertEqual(g._get_array_size(array_of_u42), 100) self.assertTrue(g._is_array(array_of_u42)) self.assertFalse(g._is_tuple(array_of_u42)) array_of_tuple = g._make_array_type(nested_tuple, 10) self.assertEqual(g._get_type_bit_count(array_of_tuple), 2140) self.assertFalse(g._is_bit_vector(array_of_tuple)) self.assertFalse(g._is_unsigned_bit_vector(array_of_tuple)) self.assertEqual(g._get_array_size(array_of_tuple), 10) self.assertTrue(g._is_array(array_of_tuple)) self.assertFalse(g._is_tuple(array_of_tuple)) u11_token = scanner.Token(g.fake_span, scanner.KeywordFromString('u11')) u11 = ast_helpers.make_builtin_type_annotation(m, g.fake_span, u11_token, dims=()) self.assertEqual(g._get_type_bit_count(u11), 11) self.assertTrue(g._is_bit_vector(u11)) self.assertTrue(g._is_unsigned_bit_vector(u11)) self.assertFalse(g._is_array(u11)) self.assertFalse(g._is_tuple(u11)) un_token = scanner.Token(g.fake_span, scanner.KeywordFromString('uN')) un1234 = ast_helpers.make_builtin_type_annotation(m, g.fake_span, un_token, dims=(g._make_number( 1234, None), )) self.assertEqual(g._get_type_bit_count(un1234), 1234) self.assertTrue(g._is_bit_vector(un1234)) self.assertTrue(g._is_unsigned_bit_vector(un1234)) self.assertFalse(g._is_array(un1234)) self.assertFalse(g._is_tuple(un1234)) sn_token = scanner.Token(g.fake_span, scanner.KeywordFromString('sN')) sn1234 = ast_helpers.make_builtin_type_annotation(m, g.fake_span, sn_token, dims=(g._make_number( 1234, None), )) self.assertEqual(g._get_type_bit_count(sn1234), 1234) self.assertTrue(g._is_bit_vector(sn1234)) self.assertFalse(g._is_unsigned_bit_vector(sn1234)) self.assertFalse(g._is_array(sn1234)) self.assertFalse(g._is_tuple(sn1234)) bits_token = scanner.Token(g.fake_span, scanner.KeywordFromString('bits')) bits1234 = ast_helpers.make_builtin_type_annotation( m, g.fake_span, bits_token, dims=(g._make_number(1234, None), )) self.assertEqual(g._get_type_bit_count(bits1234), 1234) self.assertTrue(g._is_bit_vector(bits1234)) self.assertTrue(g._is_unsigned_bit_vector(bits1234)) self.assertFalse(g._is_array(bits1234)) self.assertFalse(g._is_tuple(bits1234)) un1234_10 = ast_helpers.make_builtin_type_annotation( m, g.fake_span, un_token, dims=(g._make_number(1234, None), g._make_number(10, None))) self.assertEqual(g._get_type_bit_count(un1234_10), 12340) self.assertFalse(g._is_bit_vector(un1234_10)) self.assertFalse(g._is_unsigned_bit_vector(un1234_10)) self.assertTrue(g._is_array(un1234_10)) self.assertFalse(g._is_tuple(un1234_10))