[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