Castle: The best Real-Time/Embedded/HighTech language EVER. Attempt 2
修订版 | 1403faaa44fb4319baa0ac784a3d017a71cdefc5 (tree) |
---|---|
时间 | 2023-10-19 00:05:00 |
作者 | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
ASIS (busy with NameSpace)
@@ -21,10 +21,12 @@ | ||
21 | 21 | pytst/aigr/test_0_aid.py \ |
22 | 22 | # |
23 | 23 | rPY_CURRENT = \ |
24 | + pytst/aigr/test_3_namespaces.py \ | |
25 | +# | |
26 | +CC2CPy_TODO = \ | |
27 | + pytst/aigr/test_0_AIGR.py \ | |
24 | 28 | pytst/writers/RPy/test_3_SieveProtocols.py \ |
25 | 29 | pytst/writers/RPy/test_4_NameSpaces.py \ |
26 | -# | |
27 | -CC2CPy_TODO = \ | |
28 | 30 | pytst/writers/RPy/test_99_SieveMoats.py \ |
29 | 31 | pytst/writers/RPy/test_999.py \ |
30 | 32 | # |
@@ -0,0 +1,5 @@ | ||
1 | +# (C) Albert Mietus, 2023. Part of Castle/CCastle project | |
2 | + | |
3 | +from castle.aigr.protocols import baseProtocol | |
4 | + | |
5 | +Protocol = baseProtocol |
@@ -1,4 +1,5 @@ | ||
1 | 1 | # (C) Albert Mietus, 2023. Part of Castle/CCastle project |
2 | 2 | |
3 | 3 | from .protocols import * |
4 | -from .moats import * | |
4 | +from .namespaces import * | |
5 | +#XXXfrom .moats import * |
@@ -10,6 +10,7 @@ | ||
10 | 10 | Event(name='runTo', return_type=None, typedParameters=(TypedParameter(name='max', type=int),)), |
11 | 11 | Event(name='newMax', return_type=None, typedParameters=(TypedParameter(name='max', type=int),)))) |
12 | 12 | |
13 | + | |
13 | 14 | SlowStart = EventProtocol('SlowStart', |
14 | 15 | typedParameters=(TypedParameter(name='queue_max', type=int),), |
15 | 16 | events=( |
@@ -17,7 +18,7 @@ | ||
17 | 18 | |
18 | 19 | SlowStart_1 = ProtocolWrapper("SlowStart_1", |
19 | 20 | based_on=SlowStart, |
20 | - #arguments=(Argument(name=queue_max, value=1),)) | |
21 | + #OR: arguments=(Argument(name=queue_max, value=1),)) | |
21 | 22 | arguments=(Argument(value=1),)) |
22 | 23 | |
23 | 24 | SimpleSieve = EventProtocol('SimpleSieve', |
@@ -6,8 +6,7 @@ | ||
6 | 6 | from CC import buildin |
7 | 7 | from CC import base |
8 | 8 | |
9 | -#Put the Castle/generated imports here | |
10 | - | |
9 | +import SlowStart_1 | |
11 | 10 | |
12 | 11 | |
13 | 12 | ## |
@@ -19,7 +18,7 @@ | ||
19 | 18 | |
20 | 19 | cc_P_SimpleSieve = buildin.CC_B_Protocol(name="SimpleSieve", |
21 | 20 | kind=buildin.ProtocolKind.Event, |
22 | - inherit_from=cc_P_SlowStart_1, | |
21 | + inherit_from=SlowStart_1.cc_P_SlowStart_1, | |
23 | 22 | events=[]) |
24 | 23 | |
25 | 24 | cc_P_SimpleSieve.events.append(buildin.CC_B_P_EventID(name="input", |
@@ -22,7 +22,7 @@ | ||
22 | 22 | ('queue_max', int), |
23 | 23 | ), |
24 | 24 | kind=buildin.ProtocolKind.Event, |
25 | - inherit_from=cc_P_Protocol, | |
25 | + inherit_from=base.cc_P_Protocol, | |
26 | 26 | events=[]) |
27 | 27 | |
28 | 28 | cc_P_SlowStart.events.append(buildin.CC_B_P_EventID(name="setMax", |
@@ -6,8 +6,7 @@ | ||
6 | 6 | from CC import buildin |
7 | 7 | from CC import base |
8 | 8 | |
9 | -#Put the Castle/generated imports here | |
10 | - | |
9 | +import SlowStart | |
11 | 10 | |
12 | 11 | |
13 | 12 | ## |
@@ -19,7 +18,7 @@ | ||
19 | 18 | |
20 | 19 | cc_P_SlowStart_1 = buildin.CC_B_Protocol(name="SlowStart_1", |
21 | 20 | kind=buildin.ProtocolKind.Event, |
22 | - inherit_from=cc_P_SlowStart, | |
21 | + inherit_from=SlowStart.cc_P_SlowStart, | |
23 | 22 | events=[]) |
24 | 23 | |
25 | 24 | cc_P_SlowStart_1.events.append(buildin.CC_B_P_EventID(name="setMax", |
@@ -20,7 +20,7 @@ | ||
20 | 20 | |
21 | 21 | cc_P_StartSieve = buildin.CC_B_Protocol(name="StartSieve", |
22 | 22 | kind=buildin.ProtocolKind.Event, |
23 | - inherit_from=cc_P_Protocol, | |
23 | + inherit_from=base.cc_P_Protocol, | |
24 | 24 | events=[]) |
25 | 25 | |
26 | 26 | cc_P_StartSieve.events.append(buildin.CC_B_P_EventID(name="runTo", |
@@ -13,3 +13,4 @@ | ||
13 | 13 | from .events import * |
14 | 14 | from .protocols import * |
15 | 15 | from .interfaces import * |
16 | +from .namespaces import * |
@@ -4,14 +4,75 @@ | ||
4 | 4 | |
5 | 5 | There are several NameSpaces: the most prominent one is the ``Source_NS``, roughly the file that contains the (Castle) code. |
6 | 6 | """ |
7 | +from __future__ import annotations | |
7 | 8 | |
8 | -from __future__ import annotations | |
9 | +__all__ = ['NameSpace', 'Source_NS', 'GENERATED'] | |
10 | + | |
11 | +import logging; logger = logging.getLogger(__name__) | |
9 | 12 | import typing as PTH # Python TypeHints |
10 | 13 | from enum import Enum |
11 | 14 | from dataclasses import dataclass, KW_ONLY |
12 | 15 | from dataclasses import field as dc_field |
13 | 16 | |
14 | -from . import AIGR | |
15 | 17 | |
16 | -class NameSpace(AIGR): pass | |
17 | -class Source_NS(NameSpace): pass | |
18 | +from . import AIGR, _Marker | |
19 | + | |
20 | +class GENERATED(_Marker):pass | |
21 | + | |
22 | + | |
23 | +class NamedNode(AIGR): pass # Move up, name:str is part of it | |
24 | +class NameError(AttributeError):pass | |
25 | + | |
26 | +@dataclass | |
27 | +class NameSpace(AIGR): | |
28 | + """This models a namespace (like a file, see ``Source_NS``). | |
29 | + | |
30 | + It contained *"named nodes"* that should be :method:`register()`ed and can be found by :method:`getID()` and/or :method:`findNode()`. | |
31 | + | |
32 | + XXX More""" | |
33 | + | |
34 | + name :str | |
35 | + _: KW_ONLY | |
36 | + _dict :dict=dc_field(init=None, default_factory=lambda: dict()) | |
37 | + | |
38 | + def register(self, named_node :NamedNode): | |
39 | + name = named_node.name | |
40 | + if name in self._dict: | |
41 | + old=self._dict[name] | |
42 | + logger.warning(f"The '{name}'-node is already in this namespace; -- it will be lost." + | |
43 | + f"Removed: {old}. New: {named_node}") | |
44 | + | |
45 | + self._dict[name] = named_node | |
46 | + named_node.ns = self | |
47 | + | |
48 | + | |
49 | + def findNode(self, name :str) ->PTH.Optional(NamedNode): | |
50 | + """Return the NamedNode with the specified name (aka ID), or None. | |
51 | + See :method:`getID` for an alternative""" | |
52 | + return self._dict.get(name, None) | |
53 | + | |
54 | + | |
55 | + def getID(self, name :str) ->NamedNode: #Or raise NameError | |
56 | + """Return the NamedNode with the specified name (aka ID), or raised an NameError:AttributeError. | |
57 | + See :method:`findNode` for an alternative""" | |
58 | + node = self.findNode(name) | |
59 | + if node is None: | |
60 | + raise NameError(f"No node named {name} in NS:{self.name}") | |
61 | + return node | |
62 | + | |
63 | + def search(self, dottedName :str) ->PTH.Optional(NamedNode): | |
64 | + """Search the namespace for the 1st part of `dottedName`, then that NS for the next part, etc. And return the "deepest" node, or None""" | |
65 | + | |
66 | + parts = dottedName.split('.',maxsplit=1) # parts is [<name>, (<name>.)*] parts[1] can be absent, parts[0] always exist | |
67 | + node = self.findNode(parts[0]) | |
68 | + if len(parts) == 1: | |
69 | + return node | |
70 | + try: | |
71 | + return node.search(parts[1]) | |
72 | + except AttributeError: #node isn't a search'able/NameSpace --> Not found --> return None | |
73 | + return none | |
74 | + | |
75 | +@dataclass | |
76 | +class Source_NS(NameSpace): | |
77 | + _: KW_ONLY | |
78 | + source :str |
@@ -10,6 +10,7 @@ | ||
10 | 10 | from . import AIGR, _Marker |
11 | 11 | from .events import Event |
12 | 12 | from .aid import TypedParameter, Argument # Castle/AIGR types |
13 | +from .namespaces import NameSpace | |
13 | 14 | |
14 | 15 | __all__ = ['ProtocolKind', 'Protocol', 'EventProtocol'] |
15 | 16 | # DataProtocol, StreamProtocol are added/implemented later |
@@ -35,11 +36,12 @@ | ||
35 | 36 | """ |
36 | 37 | _BASE: PTH.ClassVar=None # pragma: no mutate |
37 | 38 | |
38 | - name: str | |
39 | + name :str | |
39 | 40 | _: KW_ONLY |
40 | - kind: ProtocolKind | |
41 | - based_on: PTH.Optional[Protocol]=dc_field(default_factory= lambda :Protocol._BASE) # pragma: no mutate | |
42 | - typedParameters: PTH.Optional[PTH.Sequence[TypedParameter]]=() | |
41 | + kind :ProtocolKind | |
42 | + based_on :PTH.Optional[Protocol]=dc_field(default_factory= lambda :Protocol._BASE) # pragma: no mutate | |
43 | + typedParameters :PTH.Optional[PTH.Sequence[TypedParameter]]=() | |
44 | + _ns :PTH.Optional[NameSpace]=dc_field(init=None, default=None) | |
43 | 45 | |
44 | 46 | |
45 | 47 | @dataclass # pragma: no mutate |
@@ -14,7 +14,7 @@ | ||
14 | 14 | {% for p in interface.ports %} |
15 | 15 | {{- m.comp_interface_Name(interface.name) }}.ports.append(buildin.CC_B_C_PortID(name="{{ p.name }}", |
16 | 16 | protocol={{m.ProtocolName(p.type.name)}}, |
17 | - direction=XXX_NS_XXX. {{p.direction}}, | |
17 | + direction={{p.direction}}, | |
18 | 18 | part_of={{ m.comp_interface_Name(interface.name) }})) |
19 | 19 | {% endfor %} {#- ports #} |
20 | 20 |
@@ -24,7 +24,7 @@ | ||
24 | 24 | |
25 | 25 | {% endif %} |
26 | 26 | kind=buildin.{{proto.kind}}, |
27 | - inherit_from={{m.ProtocolName(proto.based_on.name)}}, | |
27 | + inherit_from={{proto.based_on.ns}}.{{m.ProtocolName(proto.based_on.name)}}, # XXX NS not ready | |
28 | 28 | events=[]) |
29 | 29 | |
30 | 30 | {% for e in proto.events %} |
@@ -0,0 +1,1 @@ | ||
1 | +XXX protocol_imports.jinja2 |
@@ -15,8 +15,10 @@ | ||
15 | 15 | |
16 | 16 | {% block imports %} |
17 | 17 | #Put the Castle/generated imports here |
18 | +{% include 'parts/protocol_imports.jinja2' %} | |
18 | 19 | {% endblock %} |
19 | 20 | |
21 | + | |
20 | 22 | {% block EventIndexes %} |
21 | 23 | {% for protocol in protocols %} |
22 | 24 | {% set events = protocol.events %} |
@@ -8,16 +8,23 @@ | ||
8 | 8 | from . import T_Protocol |
9 | 9 | |
10 | 10 | |
11 | - | |
11 | +@pytest.mark.xfail(reason="NS support in ``TestDoubles/reference/protocols/*``, not in code") | |
12 | 12 | def test_01_StartSieve(generatedProtocol_verifier): |
13 | 13 | generatedProtocol_verifier(aigr_mock=sieve.StartSieve, td=TstDoubles('protocols/StartSieve')) |
14 | 14 | |
15 | + | |
16 | +@pytest.mark.skip("Top one first") | |
17 | +@pytest.mark.xfail(reason="NS support in ``TestDoubles/reference/protocols/*``, not in code") | |
15 | 18 | def test_02_SlowStart(generatedProtocol_verifier): |
16 | 19 | generatedProtocol_verifier(aigr_mock=sieve.SlowStart, td=TstDoubles('protocols/SlowStart')) |
17 | 20 | |
21 | +@pytest.mark.skip("Top one first") | |
22 | +@pytest.mark.xfail(reason="NS support in ``TestDoubles/reference/protocols/*``, not in code") | |
18 | 23 | def test_03a_SlowStart1(generatedProtocol_verifier): |
19 | 24 | generatedProtocol_verifier(aigr_mock=sieve.SlowStart_1, td=TstDoubles('protocols/SlowStart_1')) |
20 | 25 | |
26 | +@pytest.mark.skip("Top one first") | |
27 | +@pytest.mark.xfail(reason="NS support in ``TestDoubles/reference/protocols/*``, not in code") | |
21 | 28 | def test_03b_SimpleSieve(generatedProtocol_verifier): |
22 | 29 | generatedProtocol_verifier(aigr_mock=sieve.SimpleSieve, td=TstDoubles('protocols/SimpleSieve')) |
23 | 30 |