abstract layouts
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Aug 12 10:08:43 UTC 2021
As we're approaching finalization of the API, I've been thinking about
things that are suboptimal, or that can be pruned from the API. Layout
attributes, frankly, seems one of such things.
I think it would generally be more useful to allow for inheritance, so
that you can define your own e.g. ValueLayout with the extra info you
need stapled onto the side.
One problem in the way of that is the fact that the layout API features
some "wither" methods: for instance `MemoryLayout::withName(String
string)`. Let's imagine a client adds a custom subclass of ValueLayout:
```
class ColoredLayout extends ValueLayout {
enum Color {
RED, GREEN, BLUE;
}
final Color color;
ColoredLayout(Color color, ... ??) {
...
}
...
}
```
Here, what happens if the client doesn't override `withName`,
`withBitAlignment`, etc. ? Well, the `super` implementation will be
called - but that implementation will yield a `ValueLayout` not a
`ColoredLayout`!
Fixing this is difficult, as the Java language doesn't have the concept
to mark a method as "you need to re-override this, even if an impl is
available in the supertype".
One thing we could do to approach to this would be to insert an
intermediate class:
```
class AbstractValueLayout extends ValueLayout { // extension point!
abstract AbstractValueLayout withName(String name);
...
}
```
E.g. re-abstract all the wither methods, so that clients are forced to
override them. But this approach has limitations too. For one, the
hierarchy looks odd, as the abstract class is at the bottom - but maybe
that can be fixed if we were willing to change the entire API to take
AbstractValueLayout in place of ValueLayout - at which point ValueLayout
would just be a leaf.
But the more worrying issue is that this trick would have to be repeated
for every layout subclasses (e.g. group, sequence layouts) - so we end
up with 3 extra abstract classes, which are used as extension points.
That's a lot of API surface for something that's not very common to use
(which is the same problem layout attributes have).
For these reasons, in the short term I'm tempted to just remove layout
attributes, and either leave the hierarchy sealed (which would mean loss
of functionality, albeit corner case one), or just open up the hierarchy
and allow subclasses (maybe with some spelling in the javadoc which says
"make sure to override the withers or it won't work").
P.S.
As to your original question, I think all you did is achievable using
static methods on the side which take a layout and add the empty
attributes. Layout attributes are (see above) a corner use case, and
abstract attributes are even a more cornery one (although I don't doubt
they are useful in your case), and I think adding the API you propose
has very low return on complexity. The hope is that, if we do end up
opening up the layout hierarchy (with some javadoc caveats), we'll be
out of your hair, and you can add as many custom layouts as you want -
which I think is a solution you would prefer in the long run.
Cheers
Maurizio
On 12/08/2021 10:23, Ty Young wrote:
> Hi,
>
>
> When decorating a layout with attributes, there is no way to declare
> that some attributes need to be filled in by an API user. In order to
> fix this, I'd like to introduce some simple changes in order to
> support that[1]:
>
>
> 1. withAttribute no longer accepts a null value as an attribute value.
>
> 2. Addition of an asAbstract method[2], which takes in a var args of
> attributes that need to be filled in(indicated by a null value).
>
> 3. Addition of an isAbstract method[3], which returns true if any
> attribute has a value of null.
>
> 4. Addition of an unfilledAttributes method[4] which returns a list of
> all attributes that have a null attribute value and need filled in.
>
>
> There are some minor code style consistency mistakes with the
> asAbstract method and the docs could be improved, but this is more
> about just putting the idea out there.
>
>
> [1] https://github.com/BlueGoliath/panama-foreign/tree/abstract_layouts
>
>
> [2]
> https://github.com/BlueGoliath/panama-foreign/blob/a1c81e0b2b929cc3e1738c31acc97830294e0346/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java#L251
>
>
> [3]
> https://github.com/BlueGoliath/panama-foreign/blob/a1c81e0b2b929cc3e1738c31acc97830294e0346/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java#L610
>
>
> [4]
> https://github.com/BlueGoliath/panama-foreign/blob/a1c81e0b2b929cc3e1738c31acc97830294e0346/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java#L342
>
More information about the panama-dev
mailing list