Castle: The best Real-Time/Embedded/HighTech language EVER. Attempt 2
修訂 | dbe3865aa2cc19e33bbe2b94d97d7adca5ff6d10 (tree) |
---|---|
時間 | 2023-02-04 07:04:13 |
作者 | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
asis
@@ -5,14 +5,16 @@ | ||
5 | 5 | LAST = \ |
6 | 6 | pytst/writers/CC2Cpy/test_2a_groundwork.py \ |
7 | 7 | pytst/writers/CC2Cpy/test_2b_EventProtocol.py \ |
8 | + pytst/writers/CC2Cpy/test_3a_CompPort.py \ | |
9 | + | |
8 | 10 | # |
9 | 11 | CURRENT_TESTS = \ |
12 | + pytst/writers/CC2Cpy/test_3b_CompInterface.py \ | |
13 | +# | |
14 | +TODO_TESTS = \ | |
10 | 15 | pytst/writers/CC2Cpy/test_3a_CompPort.py \ |
11 | - pytst/writers/CC2Cpy/test_3b_CompInterface.py \ | |
12 | 16 | pytst/writers/CC2Cpy/test_3c_CompClass.py \ |
13 | 17 | pytst/writers/CC2Cpy/test_3d_CompStruct.py \ |
14 | -# | |
15 | -TODO_TESTS = \ | |
16 | 18 | pytst/writers/CC2Cpy/test_999_NoNameCollision.py \ |
17 | 19 | # |
18 | 20 |
@@ -1,11 +1,13 @@ | ||
1 | 1 | # (C) Albert Mietus, 2022, 2023. Part of Castle/CCastle project |
2 | 2 | |
3 | -__all__ = ['CC_B_ComponentInterface', ] | |
3 | +__all__ = ['CC_B_ComponentInterface', 'CC_Port', 'CC_PortDirection'] | |
4 | 4 | |
5 | 5 | from enum import Enum |
6 | 6 | |
7 | 7 | from .CCbase import * |
8 | -CC_Component: TypeAlias = 'CC_Component' # Forward ref | |
8 | +from castle.auxiliary.pack import mk_tuple | |
9 | + | |
10 | +CC_Component: TypeAlias = 'CC_Component' # Forward ref # pragma: no mutate | |
9 | 11 | |
10 | 12 | class CC_PortDirection(Enum): |
11 | 13 | Unknown = CC_B_PortDirectionIs_UNKNOWN = 0 |
@@ -28,57 +30,57 @@ | ||
28 | 30 | def render(self) ->str: ### <port name> |
29 | 31 | return f'cc_P_{self.type if isinstance(self.type, str) else self.type.name}' |
30 | 32 | |
31 | -class CC_B_ComponentInterface(CC_Base):pass | |
32 | -## @dataclass | |
33 | -## class CC_B_ComponentInterface(CC_Base): | |
34 | -## name: str | |
35 | -## based_on: Optional[CC_Component]=() | |
36 | -## _: KW_ONLY | |
37 | -## ports: Sequence[CC_Port] =() | |
38 | - | |
39 | -## def __post_init__(self): | |
40 | -## self.based_on = mk_tuple(self.based_on) | |
41 | -## self.ports = mk_tuple(self.ports) | |
42 | - | |
43 | -## def no_of_ports(self, inherired=False, mine=True) ->int: | |
44 | -## count = 0 | |
45 | -## if inherired: | |
46 | -## for b in self.based_on: | |
47 | -## count += b.no_of_ports(inherired=True) | |
48 | -## if mine: | |
49 | -## count += len(self.ports) | |
50 | -## return count | |
51 | - | |
52 | -## def render(self, prepend:str="", indent=" ") ->str: | |
53 | -## self.render_struct(prepend=prepend, indent=indent) | |
54 | 33 | |
55 | -## def render_struct(self, prepend:str="", indent=" ") ->str: ## struct CC_B_ComponentInterface cc_CI_${name} ... | |
56 | -## """ | |
57 | -## .. todo:: | |
58 | - | |
59 | -## - Move `CC_B_ComponentInterface.render()` into a Rendering subclass-delegate | |
60 | -## - refactor & test: spilt into parts | |
61 | -## - optional: Use Jinja ipv f-strings | |
62 | -## - make name/prefix (``f'cc_CI_{self.name}``) in a getter oid | |
63 | -## """ | |
64 | -## name = f'cc_CI_{self.name}' | |
65 | -## based_on_link = f'&cc_CI_{self.based_on[0].name}' if self.based_on[0] else "NULL" | |
34 | +@dataclass | |
35 | +class CC_B_ComponentInterface(CC_Base): | |
36 | + name: str | |
37 | + based_on: Sequence[CC_Component]=() # pragma: no mutate | |
38 | + _: KW_ONLY | |
39 | + ports: Sequence[CC_Port] =() # pragma: no mutate | |
66 | 40 | |
67 | -## retval = [] | |
68 | -## retval.append(f'{prepend}struct CC_B_ComponentInterface {name} = {{') | |
69 | -## retval.append(f'{prepend}{indent}.name = "{self.name}",') | |
70 | -## retval.append(f'{prepend}{indent}.inherit_from = {based_on_link},') | |
71 | -## retval.append(f'{prepend}{indent}.length = {len(self.ports)},') | |
72 | -## retval.append(f'{prepend}{indent}.ports = {{') | |
41 | + def __post_init__(self): | |
42 | + self.based_on = mk_tuple(self.based_on) | |
43 | + self.ports = mk_tuple(self.ports) | |
73 | 44 | |
74 | -## #loop over ports ... | |
75 | -## for n,p in enumerate(self.ports, self.no_of_ports(inherired=True, mine=False)): | |
76 | -## retval.append(f'{prepend}{(indent*3)[:-2]}{{ .portNo = {n}, ') | |
77 | -## retval.append(f'{prepend}{indent*3}.protocol = &{p.render()}, ') | |
78 | -## retval.append(f'{prepend}{indent*3}.direction = {p.direction.render()}, ') | |
79 | -## retval.append(f'{prepend}{indent*3}.name = "{p.name}", ') | |
80 | -## retval.append(f'{prepend}{indent*3}.part_of = &{name} }} ,') | |
81 | -## retval.append(f'{prepend}{indent}}}') # end of ports | |
82 | -## retval.append(f'{prepend}}} ;') # end of struct | |
45 | + def no_of_ports(self, inherited=False, mine=True) ->int: | |
46 | + count = 0 | |
47 | + if inherited: | |
48 | + for b in self.based_on: | |
49 | + count += b.no_of_ports(inherited=True) | |
50 | + if mine: | |
51 | + count += len(self.ports) | |
52 | + return count | |
83 | 53 | |
84 | -## return '\n'.join(retval)+"\n" | |
54 | + def render(self, prepend:str="", indent=" ") ->str: | |
55 | + self.render_struct(prepend=prepend, indent=indent) | |
56 | + | |
57 | + def render_struct(self, prepend:str="", indent=" ") ->str: ## struct CC_B_ComponentInterface cc_CI_${name} ... | |
58 | + """ | |
59 | + .. todo:: | |
60 | + | |
61 | + - Move `CC_B_ComponentInterface.render()` into a Rendering subclass-delegate | |
62 | + - refactor & test: spilt into parts | |
63 | + - optional: Use Jinja ipv f-strings | |
64 | + - make name/prefix (``f'cc_CI_{self.name}``) in a getter oid | |
65 | + """ | |
66 | + name = f'cc_CI_{self.name}' | |
67 | + based_on_link = f'&cc_CI_{self.based_on[0].name}' if self.based_on[0] else "NULL" | |
68 | + | |
69 | + retval = [] | |
70 | + retval.append(f'{prepend}struct CC_B_ComponentInterface {name} = {{') | |
71 | + retval.append(f'{prepend}{indent}.name = "{self.name}",') | |
72 | + retval.append(f'{prepend}{indent}.inherit_from = {based_on_link},') | |
73 | + retval.append(f'{prepend}{indent}.length = {len(self.ports)},') | |
74 | + retval.append(f'{prepend}{indent}.ports = {{') | |
75 | + | |
76 | + #loop over ports ... | |
77 | + for n,p in enumerate(self.ports, self.no_of_ports(inherited=True, mine=False)): | |
78 | + retval.append(f'{prepend}{(indent*3)[:-2]}{{ .portNo = {n}, ') | |
79 | + retval.append(f'{prepend}{indent*3}.protocol = &{p.render()}, ') | |
80 | + retval.append(f'{prepend}{indent*3}.direction = {p.direction.render()}, ') | |
81 | + retval.append(f'{prepend}{indent*3}.name = "{p.name}", ') | |
82 | + retval.append(f'{prepend}{indent*3}.part_of = &{name} }} ,') | |
83 | + retval.append(f'{prepend}{indent}}}') # end of ports | |
84 | + retval.append(f'{prepend}}} ;') # end of struct | |
85 | + | |
86 | + return '\n'.join(retval)+"\n" |
@@ -9,7 +9,6 @@ | ||
9 | 9 | from . import * # CCompare |
10 | 10 | |
11 | 11 | from castle.writers.CC2Cpy.Component import * |
12 | -from castle.writers.CC2Cpy.Component import CC_PortDirection # Not public XXX | |
13 | 12 | |
14 | 13 | def test_1a_CC_PortDirection(): |
15 | 14 | # Test the (int) value -- needed for the generated C code |
@@ -29,7 +28,27 @@ | ||
29 | 28 | assert CC_PortDirection.Slave == CC_PortDirection.CC_B_PortDirectionIs_slave |
30 | 29 | |
31 | 30 | @pytest.mark.skip(reason="Is rendering needed?") |
32 | -def test_1b_PortRender(): pass | |
31 | +def test_1b_render_PortDirection(): pass | |
32 | + | |
33 | +def test_2a1_Port_defaults(): | |
34 | + n, t = "defaults", int | |
35 | + p1 = CC_Port(name=n, type=t) # Only direction is optional | |
36 | + assert p1.name == n | |
37 | + assert p1.type is t | |
38 | + assert p1.direction == CC_PortDirection.Unknown | |
39 | + | |
40 | +def test_2a1_Port_full(): | |
41 | + n, t = "full", float | |
42 | + d=CC_PortDirection.In | |
43 | + inp = CC_Port(name=n, type=t, direction=d) | |
44 | + assert inp.name == n | |
45 | + assert inp.type is t | |
46 | + assert inp.direction == d | |
47 | + | |
48 | + | |
49 | +@pytest.mark.skip(reason="Is rendering needed?") | |
50 | +def test_2z_render_Port(): pass | |
51 | + | |
33 | 52 | |
34 | 53 | |
35 | 54 |
@@ -7,8 +7,41 @@ | ||
7 | 7 | from castle.writers.CC2Cpy.Component import * # CC_B_ComponentInterface |
8 | 8 | |
9 | 9 | |
10 | +@pytest.fixture | |
11 | +def emptyComp(): | |
12 | + return CC_B_ComponentInterface('empty') | |
10 | 13 | |
14 | +@pytest.fixture | |
15 | +def demo2Comp(): | |
16 | + return CC_B_ComponentInterface('demo2', ports =[ | |
17 | + CC_Port(name='no_1', type=None), | |
18 | + CC_Port(name='no_2', type=None)]) | |
11 | 19 | |
20 | +@pytest.fixture | |
21 | +def subComp(demo2Comp): | |
22 | + return CC_B_ComponentInterface('sub', based_on=demo2Comp) | |
23 | + | |
24 | +def test_0_name(emptyComp, demo2Comp): | |
25 | + assert emptyComp.name == 'empty' | |
26 | + assert demo2Comp.name == 'demo2' | |
27 | + | |
28 | +def test_0_based_on(subComp, demo2Comp): | |
29 | + assert demo2Comp.based_on == () | |
30 | + assert subComp.based_on[0] is demo2Comp | |
31 | + | |
32 | +def test_1_NoOfPorts(emptyComp, demo2Comp): | |
33 | + assert emptyComp.no_of_ports() == 0 | |
34 | + assert demo2Comp.no_of_ports() == 2 | |
35 | + | |
36 | +def test_1_NoOfPorts_variants(subComp): | |
37 | + assert subComp.no_of_ports() == 0 # inherited=False, mine=True | |
38 | + | |
39 | + assert subComp.no_of_ports(inherited=False, mine=False) == 0 | |
40 | + assert subComp.no_of_ports(inherited=False, mine=True) == 0 | |
41 | + assert subComp.no_of_ports(inherited=True, mine=False) == 2 | |
42 | + assert subComp.no_of_ports(inherited=True, mine=True) == 2 | |
12 | 43 | |
13 | 44 | @pytest.mark.skip(reason="More CompInterface-tests are needed") |
14 | 45 | def test_more(): pass |
46 | + | |
47 | + |