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 (basic variant), 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