<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<br>
<blockquote type="cite" cite="mid:CY4PR1001MB2150021DB903999A6991C51C8C949@CY4PR1001MB2150.namprd10.prod.outlook.com">
<div class="WordSection1"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">To be more specific about the actual classes:<o:p></o:p></span>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Mapping accepts only fragments, because it must
render as single line and for example in XML it renders as
single element with attributes.</span></p>
</div>
</blockquote>
<br>
OK, so this unearths a previously unstated requirement: that we be
able to turn certain maps into attributes, rather than embedded
elements, when converting to XML. Does this requirement correspond
to anything in other formats? Do we gain anything by dropping this,
and formatting always to elements, and/or using other heuristics to
determine when we can get away with this format optimization? <br>
<br>
In general, I'd like to unearth more of this sort of requirements.
Looking at the current hierarchy, I can't help but feel we've not
yet "hit bottom"; it doesn't feel factored into separate concerns
yet. But I'm optimistic we can get there. <br>
<br>
Here's a naive decomposition, which looks a lot like the JSON spec
if you squint: <br>
<br>
Value = SimpleValue(ConstantDesc) | ListValue(List<Value>)
| MapValue(Map<String, Value>)<br>
<br>
Converting to this form is useful separate from formatting -- it
provides a basis for query/traversal using simple string keys. But
it's not good enough for getting good formatting yet, because you
need formatting hints to determine how to lay out / indent, right?
So let's consider how we might add these in as hints, that are more
transparent. <br>
<br>
So far, I've seen that it's useful to:<br>
<br>
- Indent properly in multi-line formatting<br>
- Render simple maps in XML using attributes rather than elements<br>
- Render some lists on one line, rather than one line per element<br>
- Render some maps on one line, rather than one line per element<br>
<br>
The single-line / multi-line seems to be a hint based on the
"complexity" of the element, which the traverser knows and wants to
encode in the result. Here's an attempt at simplifying. <br>
<br>
Value = SimpleValue(ConstantDesc c) |
ListValue(List<Value> l) | MapValue(Map<String, Value>
m)<br>
| BlockValue(Value v)<br>
<br>
Here, BlockValue is a "hint wrapper", which takes some Value and
wraps it with a hint that "this thing is complex, don't try to do it
all in one line." Non-format code can just ignore the hint and
unwrap the BlockValue payload, and keep going. <br>
<br>
You currently distinguish the payload kind between Mapping and
BlockMapping; one has a List<Fragment>, whereas the other has
a List<Printable>. If we detune the payload type to
List<Printable> (Value in this simple example), we only need
one Mapping type. And the same thing goes with List vs BlockList.
<br>
<br>
This puts a small additional burden on the formatter -- dealing with
the case where we have an unwrapped List (therefore, non-block
formatting), but some of its elements are not simple values. I
think this is easy enough, and there are choices: either reject
these, or we fall back to block formatting when non-simple values
are present. This is a simple matter of checking: <br>
<br>
l.stream().allMatch(v -> v instanceof SimpleValue)<br>
<br>
and falling back to block formatting if this isn't true. <br>
<br>
Alternately, we can get rid of the block wrapper, and add a "block
hint" to the structured elements. Switching back to your notation
(but keeping my "keys are only for maps" modeling):<br>
<br>
Printable = Value(ConstantDesc value) <br>
| ValueList(FormatHint f, List<Printable> list)<br>
| ValueMap(FormatHint f, Map<String, Printable> map)<br>
| Comment()<br>
<br>
where FormatHint might be as simple as `enum FormatHint { BLOCK,
NOT_BLOCK }`, but could of course be fancier. <br>
<br>
When we lose the specificity of the List element type, we downgrade
the formatting metadata from "authoritative requirement" to "hint",
but that seems OK, since these are heuristics for optimizing the
human-readable output. <br>
<br>
If someone arrived at this ADT, I think they'd know immediately what
it means. That's a big plus. <br>
<br>
Would this work? <br>
<br>
<br>
<br>
<br>
<blockquote type="cite" cite="mid:CY4PR1001MB2150021DB903999A6991C51C8C949@CY4PR1001MB2150.namprd10.prod.outlook.com">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">It can hold single values or list of values,
where the list is rendered into a single attribute value.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">It cannot hold another Mapping because we
cannot embed XML element into an attribute (so that is we it
implements printable).<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Rendering multiple elements on a single line is
still valid XML document, however far from human
readability.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Mapping can represent a Fragment in JSON and in
YAML, however XML throws an axe into that possibility.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">BlockMapping is the most powerful (multi-line
indenting) joint, able to nest and render correctly another
BlockMapping as well as any other Printable or Fragment.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">ValueList is restricted to leaf values
(Strings, quoted String, numbers), because it is simple in
all three formats. Construction of generic List of Fragments
will require printers to render tons of other joint
combinations, which we simply do not need.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">BlockList makes sense only in combination with
BlockMappings. We would like to avoid BlockList of
BlockLists as multi-level unnamed lists do not make much
sense. Also rendering lists with any other joints is
useless. If you have list of classes, list of methods, or
list of fields – it does not make sense to put any other
Fragment, BlockList or Comment in between them.
Theoretically we can replace BlockList with
ListOfBlockMaps(String key, String mapsKey,
List<List<Printable>> printables), however that
does not make anything easier nor smaller.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"> <o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<div style="border:none;border-top:solid #B5C4DF
1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="mso-margin-top-alt:0cm;margin-right:0cm;margin-bottom:12.0pt;margin-left:36.0pt"><b><span style="font-size:12.0pt;color:black">From: </span></b><span style="font-size:12.0pt;color:black">Brian Goetz
<a class="moz-txt-link-rfc2396E" href="mailto:brian.goetz@oracle.com"><brian.goetz@oracle.com></a><br>
<b>Date: </b>Monday, 25 July 2022 19:59<br>
<b>To: </b>Adam Sotona <a class="moz-txt-link-rfc2396E" href="mailto:adam.sotona@oracle.com"><adam.sotona@oracle.com></a><br>
<b>Cc: </b><a class="moz-txt-link-abbreviated" href="mailto:classfile-api-dev@openjdk.org">classfile-api-dev@openjdk.org</a>
<a class="moz-txt-link-rfc2396E" href="mailto:classfile-api-dev@openjdk.org"><classfile-api-dev@openjdk.org></a><br>
<b>Subject: </b>Re: Classfile API proposal to integrate
basic print functionality directly to ClassModel and
MethodModel<o:p></o:p></span></p>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:0cm;margin-right:0cm;margin-bottom:12.0pt;margin-left:36.0pt"><span style="font-size:13.5pt;font-family:"Courier New"">If
"block" means multi-line, and non-block means single-line,
I'm confused as to why we have<br>
<br>
public record Mapping(String key, List<Fragment>
fragments) implements Printable {}<br>
but<br>
public record BlockMapping(String key,
List<Printable> printables) implements Printable {}<br>
<br>
where one has fragments and the other only has Printables.
Similarly, we have<br>
<br>
public record ValueList(String key,
List<ConstantDesc> values) implements Fragment {}<br>
public record BlockList(String key,
List<BlockMapping> blockMappings) implements Printable
{}<br>
</span><br>
where again the List element differs. Is there no way to
make the block/non-block orthogonal to the payload type? That
would allow us to replace the two BlockXxx(...) with different
payloads, with a Block<T> wrapper as a formatting hint.
<br>
<br>
<span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:36.0pt"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
</blockquote>
<br>
</body>
</html>