<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>