| from __future__ import annotations |
| |
| import unittest |
| |
| from mypyc.ir.rtypes import ( |
| RStruct, |
| bool_rprimitive, |
| int32_rprimitive, |
| int64_rprimitive, |
| int_rprimitive, |
| object_rprimitive, |
| ) |
| from mypyc.rt_subtype import is_runtime_subtype |
| |
| |
| class TestStruct(unittest.TestCase): |
| def test_struct_offsets(self) -> None: |
| # test per-member alignment |
| r = RStruct("", [], [bool_rprimitive, int32_rprimitive, int64_rprimitive]) |
| assert r.size == 16 |
| assert r.offsets == [0, 4, 8] |
| |
| # test final alignment |
| r1 = RStruct("", [], [bool_rprimitive, bool_rprimitive]) |
| assert r1.size == 2 |
| assert r1.offsets == [0, 1] |
| r2 = RStruct("", [], [int32_rprimitive, bool_rprimitive]) |
| r3 = RStruct("", [], [int64_rprimitive, bool_rprimitive]) |
| assert r2.offsets == [0, 4] |
| assert r3.offsets == [0, 8] |
| assert r2.size == 8 |
| assert r3.size == 16 |
| |
| r4 = RStruct("", [], [bool_rprimitive, bool_rprimitive, bool_rprimitive, int32_rprimitive]) |
| assert r4.size == 8 |
| assert r4.offsets == [0, 1, 2, 4] |
| |
| # test nested struct |
| r5 = RStruct("", [], [bool_rprimitive, r]) |
| assert r5.offsets == [0, 8] |
| assert r5.size == 24 |
| r6 = RStruct("", [], [int32_rprimitive, r5]) |
| assert r6.offsets == [0, 8] |
| assert r6.size == 32 |
| # test nested struct with alignment less than 8 |
| r7 = RStruct("", [], [bool_rprimitive, r4]) |
| assert r7.offsets == [0, 4] |
| assert r7.size == 12 |
| |
| def test_struct_str(self) -> None: |
| r = RStruct("Foo", ["a", "b"], [bool_rprimitive, object_rprimitive]) |
| assert str(r) == "Foo{a:bool, b:object}" |
| assert ( |
| repr(r) == "<RStruct Foo{a:<RPrimitive builtins.bool>, " |
| "b:<RPrimitive builtins.object>}>" |
| ) |
| r1 = RStruct("Bar", ["c"], [int32_rprimitive]) |
| assert str(r1) == "Bar{c:i32}" |
| assert repr(r1) == "<RStruct Bar{c:<RPrimitive i32>}>" |
| r2 = RStruct("Baz", [], []) |
| assert str(r2) == "Baz{}" |
| assert repr(r2) == "<RStruct Baz{}>" |
| |
| def test_runtime_subtype(self) -> None: |
| # right type to check with |
| r = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive]) |
| |
| # using the exact same fields |
| r1 = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive]) |
| |
| # names different |
| r2 = RStruct("Bar", ["c", "b"], [bool_rprimitive, int_rprimitive]) |
| |
| # name different |
| r3 = RStruct("Baz", ["a", "b"], [bool_rprimitive, int_rprimitive]) |
| |
| # type different |
| r4 = RStruct("FooBar", ["a", "b"], [bool_rprimitive, int32_rprimitive]) |
| |
| # number of types different |
| r5 = RStruct( |
| "FooBarBaz", ["a", "b", "c"], [bool_rprimitive, int_rprimitive, bool_rprimitive] |
| ) |
| |
| assert is_runtime_subtype(r1, r) is True |
| assert is_runtime_subtype(r2, r) is False |
| assert is_runtime_subtype(r3, r) is False |
| assert is_runtime_subtype(r4, r) is False |
| assert is_runtime_subtype(r5, r) is False |
| |
| def test_eq_and_hash(self) -> None: |
| r = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive]) |
| |
| # using the exact same fields |
| r1 = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive]) |
| assert hash(r) == hash(r1) |
| assert r == r1 |
| |
| # different name |
| r2 = RStruct("Foq", ["a", "b"], [bool_rprimitive, int_rprimitive]) |
| assert hash(r) != hash(r2) |
| assert r != r2 |
| |
| # different names |
| r3 = RStruct("Foo", ["a", "c"], [bool_rprimitive, int_rprimitive]) |
| assert hash(r) != hash(r3) |
| assert r != r3 |
| |
| # different type |
| r4 = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive, bool_rprimitive]) |
| assert hash(r) != hash(r4) |
| assert r != r4 |