ruediger / Boost-Pretty-Printer

GDB Pretty Printers for Boost
197 stars 61 forks source link

question: creating printers for types nested in template types #41

Closed cleeland closed 5 years ago

cleeland commented 5 years ago

I am using some of the fantastic pretty-printer framework to write printers for some in-house types. I have a situation that I'm not sure is covered by the existing framework code here.

Specifically, I have a template like the following:

template<typename T>
struct HomegrownContainer {
   // ...blah blah...
  struct Iterator {
    // ... blah etc....
  };
  Iterator begin();
};

I've written a printer that matches on HomegrownContainer, and another for HomegrownContainer<int>::Iterator. However, when I try to print out an instance of HomegrownContainer<int>::Iterator it matches the printer for HomegrownContainer and not for the nested type.

Before I embark on an effort to develop code to accommodate this scenario, can you confirm that this situation isn't covered by the code currently in places like utils.py or maybe variant.py?

Thanks!

mbalabin commented 5 years ago

It seems that this scenario is not well-covered. Current template name handling (see GDB_Value_Wrapper and Printer_Gen) is rather primitive, I am afraid.

mbalabin commented 5 years ago

The solution is not trivial, though. Given an object type (as a declaration string), we must match it against some set of patterns. If type is not templated, the problem can be solved with a regular expression. But template declarations are syntactically recursive and can not be parsed with a regex (e.g. Container<B<C>::D, E>::Iterator). I am afraid some custom expression description format and a parser may be required.

cleeland commented 5 years ago

The solution is not trivial, though. Given an object type (as a declaration string)...template declarations are syntactically recursive and can not be parsed with a regex

The difficulty of solving the problem is exactly why I was hoping something already in place. :)

Perhaps playing around with the GDB_Value_Wrapper, subprinters, and typename --> printer object lookup matching can achieve a partial solution.

Thanks for the quick response and confirmation.

mbalabin commented 5 years ago

I believe a full-blown c++ type parser would be an overkill for this task. A simple expression grammar would suffice. It may look like something like A<*>::B<P, Q>::C<*>, where everything is matched literally, except for a <*>.

Asterisk is a comma-separated sequence of types and it is not required to actually parse these types. It would suffice to count opening and closing angular brackets to find a corresponding right angular bracket. A very similar task is already done in split_parameter_pack function (variant.py). Such a grammar might be parsed with a simple parser.

If you come up with a good idea, do not hesitate to share.

cleeland commented 5 years ago

I had seen the code in variant yesterday and considered that to be a good starting point if there wasn't a pre-existing alternate solution. I was thinking of combining that with a new type of Printer_Gen that would match using existing exact-match rules for HomegrownContainer and delegate to "nested" types, but I'm not quite sure how to realize that in code. I'm more of a python hack than a python wizard, so a lot of the really pythonic tricks can elude me.

As in most cases, this endeavor is motivated by the need to answer some questions in an actual system, and it turns out that today I was able to answer the ultimate question via other means. This will likely move to lower priority for me as a result.

cleeland commented 5 years ago

I just noticed this code in intrusive_1_55.py Tree_Printer and I wonder if that would provide sufficient framework to implement something similar to the strategy I outlined above

mbalabin commented 5 years ago

I can not see how this code fragment would help you.