[Xcb] parametrized structs

Christian Linhart chris at DemoRecorder.com
Mon Aug 25 04:21:57 PDT 2014


Hi Ran,

Thank you for your comments and ideas.
Your ideas have inspired me for another solution ( described further below ).

On 08/24/14 10:47, Ran Benita wrote:
> A third option might be to add a sort of "dynamic scoping", e.g.
> 
>     <struct name="DeviceTimeCoord">
>         <field type="TIMESTAMP" name="time" />
>         <list type="DeviceTimeCoord" name="axisvalues">
>             <fieldref inherit>num_axes</fieldref>
>         </list>
>     </struct>
> 
> where "<fieldref inherit>" (or another better name) means: if you can't
> find the field in the immediate parent, look at its parent, etc.
> But this seems error-prone and probably not any easier to implement.

Your idea for dynamic scoping inspired my for another idea.
The dynamic scoping could be similar to a special case of
a highly simplified syntax of the paramref approach.

The first step of simplification could look like:
===============================================================================
01    <struct name="DeviceTimeCoord">
02        <field type="TIMESTAMP" name="time" />
03        <list type="INT32" name="valuators">
04            <paramref type="CARD8">num_axes</paramref>
05        </list>
06    </struct>
07
08    <request name="GetDeviceMotionEvents" opcode="10">
09        <field type="TIMESTAMP" name="start" />
10        <field type="TIMESTAMP" name="stop" altenum="Time" />
11        <field type="CARD8"     name="device_id" />
12        <pad bytes="3"/>
13        <reply>
14            <field type="CARD8"  name="xi_reply_type" />
15            <field type="CARD32" name="num_events" />
16            <field type="CARD8"  name="num_axes" />
17            <field type="CARD8"  name="device_mode" enum="ValuatorMode" />
18            <pad bytes="18" />
19            <list type="DeviceTimeCoord" name="events">
20                <typearg name="num_axes"><fieldref>num_axes</fieldref></typearg>
21                <fieldref>num_events</fieldref>
22            </list>
23        </reply>
24    </request>
===============================================================================

The changes to the previously more complicated approach are as follows:
* line 4: The <param>-tag is omitted and the <paramref>-tag implicitely declares the 
  parameter.
  The difference to <fieldref inherit> is that <paramref> contains a 
  type-attribute. 
  The type-attribute is necessary for the generator to determine
  the type of the parameter which is to be used on the param-list 
  of the generated "sizeof", "unpack", etc functions.

* line 19: "type" is an attribute of list again (instead of a <type> tag)
  so it is more similar to the scheme of non-parametrized structs.

* line 20: use a <typearg>-tag for defining the arglist of the type.
  ( instead of sub-tag <arg> of tag <type>

This can be further simplified by making the <typearg>-tag optional if 
the parameter has the same name as the field of the fieldref-expression
used as the arg, like it is the case here.
This will then look as follows:
===============================================================================
01    <struct name="DeviceTimeCoord">
02        <field type="TIMESTAMP" name="time" />
03        <list type="INT32" name="valuators">
04            <paramref type="CARD8">num_axes</paramref>
05        </list>
06    </struct>
07
08    <request name="GetDeviceMotionEvents" opcode="10">
09        <field type="TIMESTAMP" name="start" />
10        <field type="TIMESTAMP" name="stop" altenum="Time" />
11        <field type="CARD8"     name="device_id" />
12        <pad bytes="3"/>
13        <reply>
14            <field type="CARD8"  name="xi_reply_type" />
15            <field type="CARD32" name="num_events" />
16            <field type="CARD8"  name="num_axes" />
17            <field type="CARD8"  name="device_mode" enum="ValuatorMode" />
18            <pad bytes="18" />
19            <list type="DeviceTimeCoord" name="events">
20                <fieldref>num_events</fieldref>
21            </list>
22        </reply>
23    </request>
===============================================================================

So, the only difference to your idea of dynamic scoping (besides naming of the tag)
is that the <paramref>-tag gets a type-attribute. ( line 4 ).

With that scheme we have a simple xml-scheme and still the full flexibility
of the original paramref-approach.

What do you think about that new proposal?

> c_client.py in these parts is quite a mess, so it's hard to tell really.
Thank you for that warning. 
If there's too much mess, I will do a refactoring before in a separate patch.
We'll see.

>> What do you think?
> 
> I'm not sure. The "paramref" approach looks complicated, really
> stretching the format. On the other hand the inlining approach has its
> own set of problems: duplication in multiple places and namespacing in
> this case, how the API looks, etc.
Thank you for that feedback.
Made me think about the simpler approach described above.
> 
> Keep in mind that we don't really need to be flexible for future
> extensions. I really don't think we'll see any more extensions with
> complex encodings like xkb or xinput, and hopefully new extensions will
> be written with an XCB xml or at least with XCB in mind. So we can
> limit ourselves to the simplest solution which fits only the existing
> requirements.
Yes, "keep it simple" is generally a good approach.
Sometimes, the simple way is not obvious at first glance.
Its worth investing time and energy and discussions 
in designing a simple and elegant solution.

Preventative complexity is usually never needed.
The art is to make the simple approach in a way that
it does not prevent adding more flexibility in the
10% of the cases where the simple approach needs to 
be extended later.

> In order to make a wise decision then, I think you should consider if
> there are any other cases where such a construct is needed (in
> xinput/xkb)? If so, do any of them have a "parameterized" struct which
> appears in more than one place (unlike DeviceTimeCoord)?
As far as I remember from my XKB-review, XKB will not need 
parametrized structs, but I can be wrong on that.
( I will organize and post the XKB-patches sometime later, 
after we'll have finished the XInput stuff. )

Chris

>> P.S.: I can implement either of the two schemes in the generator
>> though I have a slight preference for 
>> explicit parametrization because it allows
>> code-reuse on the xml-side.
> 
> As I said, lets first see if such reuse is needed (but in the end of
> course you should implement what you think is best).
> 
>> Here's why I feel confident that I can implement that:
>> I have a lot of experience will parsing and code-generation,
>> especially from former projects and a job where I wrote
>> parsers for CASE-tools and IDEs. The most complex one was a parser
>> parsing C++-code, where I implemented to whole ISO C++-98 standard
>> including template instantiation...
> 
> A parser for C++, that's heroic :)
Yeah, it was a special kind of project, details omitted here. ;-)
But it was ultimately successful after stretching the deadlines as much as possible...



More information about the Xcb mailing list