Tip
QuickNotes are short, quick, informal notes. Often to order my thoughts and analyse the options before I write the
“real” design (or other docs).
They are unofficially published. You can read them but do not expect that they are well written. Or till actually, as
maintaining them is not a goal.
QuickNote: Jinja Templating for rPY
With a working RPython implementation of The Sieve demo (start/DRAFT), it’s time to find the patterns to automate: generating RPython code from Castle-Code.
Like in QuickNote: Jinja Events (templating), part of the CC2Cpy: CCastle to C compiler in Python backend, we focus on the essential Jinja templates.
Caution
The given templates are written in the analysis (research) phase to guide where we are heading.
They are not used (or even ‘compiled’)! So, there may be syntax and other mistakes in them.
Templating
We focus on a few concept:
data-structures
connecting two ports
Sending Events (using only 1 Machinery)
Fire an events to an sub-Component
Those parts depend on the ubiquitous names for RPython chunks (like clases, methods, etc): calling a method ‘foo’
implies that method implementation is also called ‘foo’ – even when those named are generated in very different
places.
Therefore, we start with macro to generate names …
Note
In the examples below, all modele(file) namespaces are ignored. This is possible when those python identifiers are
imported (from ... import *
style).
When using the (better) import ...
style is used, that namespaces (in dot notation) should be prepended
{namespace}}.{{...}}
Naming
EventHandler names
As we use (R)Python namespaces (modules, classes), the generated names for the EventHandlers becomes shorter (than in C).
{%macro event_handler_Name(compName, protocol, event, portName) -%}
{{protocol}}_{{event}}__{{portName}}
{%- endmacro %}
Hint
The compName
parameter is not used/needed in the RPY implementation. The (generated) name unique as it is in the
namespace of the compName class.
For similarity reasons it is passed however.
Warning
The powerOn__power
method does not fit in this pattern, for two reasons.
Firstly it not really a event, there is no protocol defined that holds it, not is there a port
that receives it. Non of them are defined (yet).
This part of Castle is designed fully. Possibly the base-Component (now called ‘Board’) will have a power-port, with
a startup/down protocol. Then it becomes an event, with an EventHandler – and the name of the EventHandler will be
updated.
Secondly, possibly we should models this “power up” as a function/method – like the init method(s). Again, the demands a bit more attention to tje language design. And can have effect on the name
Structure names
The name of some structures are quite simple, and given without explanations.
The tree basic classes
{%macro comp_interface_Name(compName) -%} cc_CI_{{CompName}} {%- endmacro %}
{%macro comp_component_Name(compName) -%} CC_{{CompName}} {%- endmacro %}
{%macro comp_compClass_Name(compName) -%} cc_C_{{CompName}} {%- endmacro %}
Notice, the case. A small case CC prefix denotes an instance, whereas Classes use the uppercase CC prefix.
DispatchTable(s), one per port
{%macro dispatchtable_handler_Name(compName, portName) -%}
cc_S_{{compName}}_{{portName}}
{%- endmacro %}
For pins, that are a kind of internal ports, the pinID is used instead of the portName:
{%macro dispatchtable_for_pins_Name(compName, pinID) -%}
{{dispatchtable_handler_Name(compName, pinID)}}
{%- endmacro %}
Event & Protocols
These ‘names’ are actually numbers to be used as index (into the Dispatchtable), or an enumeration when you like.
{%macro EventIndexName(ProtoName, EventName) -%}
CC_P_{{ProtoName}}_{{EventName}}
{%- endmacro %}
{# used as (for example): #}
{%macro SetEventIndex(ProtoName, EventName, indexNo) %} {{EventIndexName(ProtoName, EventName)}} = {{indexNo}} {% endmacro %}
Behaviour
Connecting ports
{%macro connect(outComp, outPort, inComp, inPort) -%}
self.{{outComp}}.{{outPort}}.connection = self.{{inComp}}
self.{{outComp}}.{{outPort}}.handlers = {{dispatchtable_handler_Name(inComp, inPort)}}
{%- endmacro %}
Sending Events
The typical case
self.outlet.input(i); // Sent event ‘input’ over the port ‘outlet’
In the code below, the parametes are more-or-less ignored. It works with withParms
is correctly formated: a comma
(‘,’) separated list of values; e.g in python: ", ".join(for p in parms)
{%macro send_event(overPort, event, ofProtocol, withParms) -%}
outport = self.{{overPort}}
index = {{EventIndexName(ofProtocol, event)}}
handler = outport.handlers[index]
handler(outport.connection, {{withParms}})
{%- endmacro %}
Trigger sub-elements
{%macro trigger_event(toComp, toPort, subElm, withParms) -%}
table = {{dispatchtable_handler_Name(toComp, toPort)}}
index = {{EventIndexName(ofProtocol, event)}}
{{table}}[{{index}}]({{subElm}}, {{withParms}})
{%- endmacro %}
Comments
comments powered by Disqus