This is an archive of the discontinued LLVM Phabricator instance.

[Format] Simplify some of the formatter template glue
Needs ReviewPublic

Authored by zturner on Jun 16 2017, 9:07 AM.

Details

Reviewers
dblaikie
labath
Summary

The original idea here was that we would take the parameter pack and store it as both a tuple and a vector. To put things in a vector the items had to share a common base, so I made this format_adapter_base. Then there were 2 implementations. One implementation that would be used for types where the format method would invoke a member function on the type itself, and another where a global formatter would be used.

But we can make this simpler though. The only thing we need to store is just the value itself, and we can defer the knowledge of what kind of formatter it uses until we actually go to format it, and we can have the final selection just delegate to a global template function that is properly specialized. This has the advantage of making the template glue much simpler, but also allowing us a convenient syntax to define new formatters via a macro. A few existing formatters are converted to this new syntax as an example. The rest can be done in a followup, for now I just want to see if the approach is ok.

Eventually I'd like to get the point where the adapters are composable, so you can say like align(pad(Value, 7), Left, 3) but part of that means simplifying the underlying glue so that there's fewer moving parts.

Diff Detail

Event Timeline

zturner created this revision.Jun 16 2017, 9:07 AM
dblaikie added inline comments.Jun 18 2017, 10:02 AM
llvm/include/llvm/Support/FormatProviders.h
28–33

Not sure this benefits much from being a macro, does it?

Calls to these functions look like they're ADL compatible, so there's no need to put them in the llvm namespace - they can go in whatever namespace the Type is in, probably? (doesn't matter too much in the LLVM project - we don't need to protect the llvm namespace, etc, but is perhaps a more generic extensibility mechanism than users having to write function definitions in the library's namespace)

394–396

Skip braces on one-line if?

395

Usually assert(false) should be llvm_unreachable, but branch-to-unreachable isn't ideal either, so perhaps:

if (!Style.empty()) {
  bool Success = Style.getAsInteger(10, N);
  (void)Success;
  assert(Success && "Style is not a valid integer");
}

Yeah, I know it's a couple of lines longer, which is awkward too :/

I guess if getAsInteger returned Expected<size_t> might be a bit tidier:

if (!Style.empty())
  N = cantFail(Style.getAsInteger<size_t>(10));
404

If you can avoid turning a Twine into a std::string it could save some memory allocation/copying/processing.

But, yeah, supporting the length limiting support of the string formatter above would be a bit of work interacting with Twine's print function. (maybe Twine could use a template that takes a functor and is called back on the various kinds of elements it has) - something for another day I guess.

llvm/include/llvm/Support/FormatVariadicDetails.h
79–83

Does this support (for format members) pull its weight? Compared to all format extensibility going through a single ADL signature? (the definition of a non-member format function where the member format is written would be almost identical, if defined as an inline friend definition inside the class definition (you have to mention the type name in the signature and name that variable rather than using 'this'))

labath resigned from this revision.Jun 19 2017, 2:14 AM

I am not sure I can bring much to this, so I'll take a back seat.

llvm/include/llvm/Support/FormatProviders.h
28–33

I don't know about the technical feasibility of this, but I did feel awkward every time I had to write "namespace llvm" to write a lldb pretty-printer.

labath added a subscriber: labath.Jun 19 2017, 2:15 AM