Towards Minimal L World
john.r.rose at oracle.com
Fri May 18 19:28:59 UTC 2018
On May 17, 2018, at 4:40 PM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
> On 17/05/18 23:22, John Rose wrote:
>> A Java constructor in a value class will internally use withfield
>> to translate any assignment of the form "this.x = y", and instead
>> of the blank instance being an incoming reference in L, the
>> constructor builds a blank value instances out of thin air using
> So, if I understand correctly, a classic Java constructor is a void-returning instance method; in the model you propose a value class constructor would be more similar to a V-returning static method (where V is the value to be constructed).
I think I failed to say clearly that, while I'm talking about JVM-level translation
strategy, I'm mainly concerned with JLS-level notation, semantics, and user
model. Usually I have my JVM hat on and JLS on the shelf, but this note
Thesis: Value constructors are the same notation as VBC constructors.
I was speaking of the JLS-level semantics, in which there is no connection
at all between constructors and methods (whether void returning or not,
static or not). There's a good reason for this, becauseJLS-level
constructors for objects translate to a bizarre <init> thingy with properties
like you describe, but with more properties which don't fit at all into the JLS,
like the requirement that the JVM-level caller create a blank object instance
and pass it as the receiver of an invokespecial instruction to the <init>
quasi-method (method at JVM level, constructor at JLS level).
So I'd like to restate that it is my conviction that the JLS level semantics
of constructors (please pretend for a moment that you never read bytecodes)
can be carried over 100% wholesale from objects to values, by inspecting
the JLS-level semantics of constructors on objects (*especially* in value-based
classes) and observing that they apply in detail, without significant change,
to a perfectly reasonable (and familiar!) semantics of constructors on values.
All the stuff like "this is a factory and that is a void function" is an artifact
of translation strategy. The semantics come first, and the translation strategy
is a distant second.
Then, if you work the details of translation strategy for values, you will find
that the user model is the same but the detailed instructions are very different.
Kind of like putfield vs. withfield, but deeper in the case of constructors.
It is not a red flag, nor is it confusing to users, that the translation strategy
must differ between objects and values, even though the constructor
semantics are 99% identical. (The 1% comes in if object identity plays
Brian's reply is more on-point to what I am trying to say (sorry I was not clear!),
in that he proposes a translation strategy that "saves the appearances" of
classic Java constructors (our promise is "codes like a class"), while taking
care of the necessary changes to bytecode mechanics behind the scenes.
(I would like to be slightly more aggressive than Brian about saving the
appearance of 'this'; his solution is 99% but I think we can go safely to
99.9% of VBC operations. But that's a sub-discussion.)
> This is all and well, but I feel that this pushes the problem under the (assignment) rug. E.g. I believe that reinterpreting the meaning of 'this.x = y' inside a value constructor to mean "get a brand new value and stick y into x" would be very confusing, as semantically, there's no assignment taking place. And, semantically, it doesn't even make sense to think about a 'this' (after all this is more like a static factory?).
I don't know how to respond to this. The semantics *I* am proposing preserve
all the appearances of classic Java constructors, which *do* appear semantically
to initialize an instance (object or value) by assigning to fields. Even when
such assignment is illegal (even meaningless!) in other contexts.
Note that constructors are allowed to assign to fields when all other class coce
are not, and that (at the JLS level) the assignments to fields in constructor are
carefully choreographed by DA/DU rules. I am, of course, talking about final
fields here. That's the common ground between VTs and VBCs.
> Of course you can spin this as reinterpreting the meaning of the word 'this' inside a value constructor - e.g. the new meaning being "the opaque value being constructed"; but that is likely to clash with other utterances of 'this' in the same value class (e.g. in other instance methods - where 'this' would simply mean 'this value').
The only spin I want to spin is to preserve the classic constructor semantics,
of field-wise initialization by assignment (static single assignment!). I think that
is the least surprising model.
> Language-wise (and I repeat, it might well be too soon to dive into this), it feels like we're missing a way to express a new kind of a primitive operation (the wither). Without that, I'm a bit skeptical on our ability to be able to express value type constructors in a good way.
It sounds like you fear that migrating a VBC to a VT must require rewriting its
constructor into a completely new notation, not yet invented. I am saying that's
not required, as the VBC notation is perfectly reasonable.
Yes, withers require an *extension* to constructors, which (in a not yet specified
way) allows field-wise single assignment to produce a new instance of a value
given the field bindings of an old value, plus a constructor-like body of code.
Working title for that is "reconstructor".
For me, one sign that such extensions are done right *at the JLS level* is that
they will be immediately applicable to VBCs as well as VTs.
If we do withers right (at JLS level!), they will apply to VBCs as well as VTs.
Their translation strategy will differ, just as values and objects differ, but
the notation will apply to both indiscriminately. If we do it right.
If we fumble the ball we'll split "codes like a class" into "codes like a value
class when it's a value". But I don't think we will.
More information about the valhalla-spec-observers