ur5us has quit [Ping timeout: 246 seconds]
ur5us has joined #jruby
ur5us has quit [Ping timeout: 272 seconds]
<boc_tothefuture[> @headius. I pushed the example in that gist I referenced above. It must be something OpenHab is doing with the script engine that in some way impacts JRuby, but not Jython... Just not sure what that would be.
Antiarc has quit [Ping timeout: 264 seconds]
Antiarc has joined #jruby
nieve[m] has quit [Quit: Idle for 30+ days]
ur5us has joined #jruby
subbu is now known as subbu|away
subbu|away is now known as subbu
<headius[m]> Ok I'll give it a try
<byteit101[m]> headius: I hate to be a bother, but I await your comments on https://github.com/jruby/jruby/pull/6422#issuecomment-716337104
<headius[m]> Getting my new keyboard set up and then I'll see what I can do
<boc_tothefuture[> Is there any trace logging I could enable that would show when items are loaded (potentially into the global space?)
Caerus has quit [Ping timeout: 272 seconds]
Caerus has joined #jruby
<headius[m]> there is a property you can set to show all files as they load
<headius[m]> jruby.debug.loadService
Caerus has quit [Ping timeout: 256 seconds]
<byteit101[m]> headius: thanks! Is it better than a butterfly?
<headius[m]> yeah curved ergo mechanical keyn
<byteit101[m]> Nice!
<headius[m]> keyboard
Caerus has joined #jruby
<headius[m]> I'm still getting used to it obviously
<headius[m]> from X-Bows
<byteit101[m]> Ah yes, retraining muscle memory for new keyboards :-)
<headius[m]> unfortunately the config software is windows only so it will just be on RGB chase sequence for a while
<byteit101[m]> Fancy! a bendy one
<headius[m]> yeah hopefully it isn't too hard to get used to
<headius[m]> looking at your pr now
<byteit101[m]> I'm sorry in advance :-)
<headius[m]> do you have a description of the current init sequence?
<byteit101[m]> There's several options for my impl, but if you are referring tot the current 9.2.x, see 449 (linked at top)
<byteit101[m]> *to
<byteit101[m]> (it's the diagram in 449)
<headius[m]> first thing I wondered is whether running the ruby init after the java constructor is a change
<byteit101[m]> (sans the java side, as that was the proposal)
<byteit101[m]> Yes, it is
<headius[m]> ok that diagram right
<byteit101[m]> that was one of my major questions: should java init sequence == ruby init sequence
<headius[m]> I am not sure from your diagram whether the ruby init can manipulate args passed to the java constructor
<headius[m]> currently
<byteit101[m]> in 9.2.x, it can
<headius[m]> my concern then is that if someone is extending a class they probably want to control when and how the parent constructor is called and we lose that here
<headius[m]> trying now to think through how we can do both though and it is hard
<byteit101[m]> Yes, that is what the super splitter proposal and demo is for
<headius[m]> one has to come first
<headius[m]> yeah
<headius[m]> I will read the rest of this comment
<byteit101[m]> see https://github.com/jruby/jruby/pull/6422#issuecomment-720055420 for what the ctor would look like in that case. Java (the language) doesn't like compiling it, though JVM Bytecode works fine, to solve the uninitializedThis.
<headius[m]> a couple more answers
<headius[m]> yes super is a keyword and can't really be overridden
<headius[m]> so an IR xform is ppossible
<byteit101[m]> Good, I have a hacky AST transform right now, but excellent!
<byteit101[m]> Also had to check that this is illegal: def initialize(*args) 1.times{|i| super(i, *args)} end
<headius[m]> so the init splitting
<byteit101[m]> but IR would be better I think
<headius[m]> I will probab;y repeat some stuff from pr so bear with me
<byteit101[m]> go ahead, it is a lot of stuff :-)
<byteit101[m]> And many moving bits. Take your time
<headius[m]> currently ruby init happens before java construct which is logical for a subclass but not compatible with construction from the java side
<byteit101[m]> correct
<byteit101[m]> also leads to some surprises: #6140
<byteit101[m]> Actually, reading that again, I disagree with https://github.com/jruby/jruby/issues/6140#issuecomment-605295047 now, as I _think_ I implemented that (not hooked up yet)
<byteit101[m]> (due to it being a keyword)
<headius[m]> what changes with "new" in your pr?
<byteit101[m]> unless I'm missing something
<byteit101[m]> Beyond who is calling init when I think new is still the same. Note that concrete classes no longer have alloc/__jallocate
<headius[m]> it would be a reasonable limitation that if you want init from java you must not expect to manipulate arguments from ruby first
<byteit101[m]> I also had the proposal in issue 449 of java_compute_super or something like that
<headius[m]> the presence of super may be our way to indicate that this is not initable from java
<headius[m]> I am starting to come around to the idea of other methods that hook into this sequence explicitly
<byteit101[m]> I have a working super-splitter, but it fails if `super` is inside an if, case, rescue, etc
<headius[m]> what if the init for this was just some other method and not initialize
<headius[m]> initialize being too bound to the normal ruby sequence
<byteit101[m]> I like that, particularly as `initialize` is a method, not a ctor in javafx, but then again it might add cognitive complexity
<headius[m]> def MyClassName()
<byteit101[m]> 449 had some other suggestions in that style too
<headius[m]> ok
<byteit101[m]> hmm, can you def a Const?
<headius[m]> yes
<byteit101[m]> TIL
<headius[m]> Kernel has methods like Integer()
<headius[m]> so sequence on pr is that the java constructor generated into the reified class calls ruby init after java superconstructor
<byteit101[m]> right now: super-splittter demo, but 1 commit ago: yes
<headius[m]> right ok
<headius[m]> ok so I dont have to go back and forth...
<headius[m]> I think using a continuation may be more complexity than we want
<byteit101[m]> Implemented and decompiled as https://github.com/jruby/jruby/pull/6422#issuecomment-720055420 (super variants are (int, string), and (string, bool)
<byteit101[m]> yes, I was looking at project loom :-)
<byteit101[m]> I used a lambda in the demo
<headius[m]> better mabe to just make a set of explicit stages in construction that can be hooked
<byteit101[m]> yea, the only downside is if you compute something for super, how do you pass it on if you don't want to stuff it in an @ivar (as I mention in one of the samples on 449). That was what I was attempting to see
<byteit101[m]> and in the part you pasted, "continuation" is anything that does the rest of init, be that a new hook, an actual contionation, a lambea, etc. I'm not wed to true continuations
<byteit101[m]> *lambda
<headius[m]> I am coming around to the idea of the ruby init just being a standalone non-superable method if there's another mechanism to get in front of the java super constructor call
<headius[m]> ok i see
<headius[m]> so it is allowing a way to defer a part of init in this sequence
<byteit101[m]> yes, from the perspective of a traditional init sequence
<byteit101[m]> The pre+post seperation is because we can't pass an uninitializedThis object around in bytecode
<byteit101[m]> so the <init> method MUST be the one to call invokespecial <init>, ....
<byteit101[m]> on the superclass
<headius[m]> reify code does not regenerate on purpose because you are explicitly sayong at that moment in time to generate the java type
<byteit101[m]> ah!
<headius[m]> limiting regeneration is totally acceptable to me as long as redefined methods (e.g. monkey patched) still get invoked
<headius[m]> the type we create can be a one shot deal
<headius[m]> I doubt anyone has ever really taken advantage of that regen
<byteit101[m]> caveat: #new implicity reifies
<headius[m]> right, which is how interface extension works anyway... once you start making instances the type is set
<byteit101[m]> cool
<headius[m]> I think there is an error in the diagram
<headius[m]> java object is inited on the far left and later in that sequence shows as initing?
<byteit101[m]> Ah, yes, should both be initing
<headius[m]> because the java obj constructor calls the ruby init, ok
<byteit101[m]> added correction note above
<headius[m]> ok
<byteit101[m]> for future reference
<headius[m]> yeah so I come back to the "new api" idea and not using initialize in this sequence because maybe it will just be confusing
<headius[m]> looking at idea in 449 now
<headius[m]> java_init
<byteit101[m]> so you are fine with the idea that ruby classes that extends java classes will behave differently from pure ruby classes?
<headius[m]> in general yes because it seems unavoidable anyway
<headius[m]> looking at this more like scripting a new java subclass rather than trying to pretend there's no separation
<headius[m]> I mean in an extreme API it might b
<headius[m]> be like a DSL
<headius[m]> but that is probably not necessary
<byteit101[m]> Because aside from the caviats of nested blocks (avoidable if we go java-style and say super must be at top level?), it is doable to re-use initialize, I think.
<headius[m]> thinking of use cases here...
<byteit101[m]> Also, avoiding initialize would break the current API
<headius[m]> why do people extend... one is to override behavior and inherit the reset
<byteit101[m]> though if you are saying to break it, I'm not going to argue :-)
<headius[m]> well this is where I have a problem... wondering how much will break if the old stuff goes away completely
<headius[m]> then we end up adding rather than replacing and as you have seen there's too much of that
<headius[m]> wanting to
<headius[m]> be able to construct from java is a very specific use case
<byteit101[m]> jrubyfx already does the 2nd thing: https://github.com/jruby/jrubyfx/blob/master/samples/fxml/complex_control.rb#L10 but that's because initialize is a method name
<headius[m]> like people probably arent extending ArrayList and wanting it to
<headius[m]> have a java constructor
<headius[m]> the old logic is overcomplicated and needs to be replaced anyway though
<headius[m]> so current logic just has a special super initialize that calls java init yes?
<byteit101[m]> yes. seen being used by jrubyfx here: https://github.com/jruby/jrubyfx/blob/master/lib/jrubyfx/controller.rb#L245
<headius[m]> super from initialize will eagerly call java init, or if that doesn't happen it is called after init but before new returns
<headius[m]> It would be nice to know how many users are calling super
<byteit101[m]> that was one question I was going to ask: is there an easily downloadable corpus of jruby ruby code?
<headius[m]> ok so bottom line, yes I think it is fine for the sequence to differ on the two sides
<headius[m]> it is a limitation we can't really get around
<headius[m]> if you can't super from initialize, though, I am reluctant to call it initialize, but as you say that breaks current API
<headius[m]> but breaking super does too
<headius[m]> so that is a question of impact
<byteit101[m]> eww, ok, first project I checked of mine does this: class NBWrap < Java::JavaIo::InputStream
<byteit101[m]> def initialize(io)
<byteit101[m]> super(io.to_java.getInStream)
<headius[m]> yeah I fear it may be fairly common
<byteit101[m]> Initialized from PTY.open
<headius[m]> so I asked about new because maybe we change the sequence there to better match the java side
<headius[m]> really the only thing it would do is <init> the java object and the java constructor would call initialize
<byteit101[m]> > but breaking super does too
<byteit101[m]> wait, sorry, which proposal breaks super, and how?
<headius[m]> I mean making the initialize super now be a no-op
<byteit101[m]> Ah, right, ok!
<headius[m]> if we wanted to or needed to keep that intact then why not completely divorce the ruby new from the typical ruby sequence
<byteit101[m]> > really the only thing it would do is <init> the java object and the java constructor would call initialize
<byteit101[m]> The PR implements this right now for some configurations as it's essential for the super-splitting to work
<headius[m]> new would construct java object by calling java init, which would construct ruby proxy and call its initialize
<headius[m]> ok
<headius[m]> I am trying to avoid the splitting... if we conceptually treated initialize as though it were the body of the java constructor there is nothing to split, right?
<byteit101[m]> yes, I dislike super-splitting too, but I feel it's the best way from a not-breaking api sort of way
<headius[m]> and this is called during the java init
<byteit101[m]> yes
<byteit101[m]> > if we conceptually treated initialize as though it were the body of the java constructor there is nothing to split, right?
<byteit101[m]> No, we need to get the super args out, we can't call super except from the parent frame
<headius[m]> there are ways
<byteit101[m]> before java super() is called, this is of type unInitializedThis, and can't be used, passed, etc. It's the root of the problems
<byteit101[m]> You know how to move an uninitializedThis?
<headius[m]> well invokedynamic has a mechanism for making these calls but I have not tried it
<headius[m]> I see what you are saying about splitting then
<byteit101[m]> *another option is to JIT the method, but then you loose dynamism, so I haven't suggested that
<byteit101[m]> ooo! if indy can avoid the uT problem,that would be excellent!
<headius[m]> mechanically speaking the ruby initialize can't physically call a super init but might be possible with indy
<headius[m]> ok starting to fall together for me a bit
<byteit101[m]> yea, I procrastinated making a super-splittting demo as I was in denial for awhile too
<headius[m]> so the splitting is due to the fact that we need to fully super the java init in order to have an object ready
<byteit101[m]> inline, in the <init> bytecode, yes
<headius[m]> but what we want is to be able to call initialize that can itself super init the java object
<headius[m]> if we could do that it would make this simpler
<byteit101[m]> ideally
<headius[m]> hmmm
ur5us has quit [Ping timeout: 260 seconds]
<byteit101[m]> yes, I'd love to get rid of super-splitting if that was possible
<headius[m]> it may be possible
<headius[m]> a method handle yanked from the generate class pointing at the super <init> may be invokable outside that frame
<headius[m]> ok right, and your examples that just allow the ruby subtype to transform the args is a way around not being able to call super directly
<headius[m]> that isn't a bad pattern really but it is a change
<byteit101[m]> I have too many examples, which one? the Balloons?
<byteit101[m]> oh, java_compute_super?
<byteit101[m]> ah yes, ok
<byteit101[m]> that is, in fact, " a way around not being able to call super directly"
<headius[m]> so this case allows ruby to xform the args on the way but no super because we can't
<byteit101[m]> correct
ur5us has joined #jruby
<headius[m]> existing code avoids this by generating a special java init that does the java super init call and initialize calling super just triggers the java object construction along that path
<byteit101[m]> correct
<headius[m]> sorry if I am going around in circles a bit
<byteit101[m]> not at all!
<byteit101[m]> It's a tricky thing to get right, and I'd prefer to get it right
<headius[m]> so open question is whether we can invoke java super init from outside java init, like in response to a ruby initialize with super
<byteit101[m]> any good/easy indy playgrounds so I can verify if indy super is viable?
<headius[m]> in normal bytecode we cannot but indy handle might make it possible
<headius[m]> sure on MethodHandles.Lookup class there is a way to get handle to "special" calls
<headius[m]> bringing docs up to look
<headius[m]> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandles.Lookup.html#findSpecial-java.lang.Class-java.lang.String-java.lang.invoke.MethodType-java.lang.Class-
<headius[m]> ah ok this does not do init
<headius[m]> findConstructor does but I am remembering now this was an issue for e.g. Groovy
<headius[m]> they wanted to do what we want to do and had trouble
<byteit101[m]> ah, yes, I am seeing some errors suggesting this isn't possible from the stack traces in, eg. https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8129740
<headius[m]> well there is a nuclear option
<headius[m]> generate the Ruby initialize body directly into the Java init
<headius[m]> no dispatch
<byteit101[m]> > *another option is to JIT the method, but then you loose dynamism, so I haven't suggested that
<byteit101[m]> ^
<headius[m]> right
<headius[m]> it may be fine for initialize though
<headius[m]> it simplifies this sequence quite a bit
<byteit101[m]> quite!
<headius[m]> also in order to handle arg conversion it would translate ruby super to a java this() call that does the converting and eventual super()
<headius[m]> so initialize calls super, which does invokespecial of this.<init>(ruby arguments) and that eventually does java super with java args
<headius[m]> just spitballing here
<headius[m]> this is more work obviously but it would eliminate the split construction
<headius[m]> IR transform would change super in these initialize methods into something like JavaSuperInstr
<byteit101[m]> yes. I haven't investigated, as I didn't like the loss of dynamism (and the jit code looked scary :-P)
<headius[m]> yeah it is a challenge but I think it would basically unify the two sides of construction finally
<headius[m]> outside of that option I think the arg-massaging path might be simplest... explicitly show that it is not initialize but it participates in init sequence
<headius[m]> the java_init style or the continuation that happens later
<byteit101[m]> yes
<headius[m]> hmmm
<byteit101[m]> well, simplest to implement? It's not the simplest conceptually from a users point of view
<headius[m]> one tricky bit is that the jit currently generates static methods but that can be adjusted
<headius[m]> yeah simplest to implement
<headius[m]> because it makes the sequence explicit
<headius[m]> you just hook in at appropriate stages
<headius[m]> ok so lets call the jit version a stretch goal for now
<byteit101[m]> breaking change with that: see balloon example (scroll up) and `p self` will fail to compile
<byteit101[m]> 6:16pm
<byteit101[m]> as it's before super
<byteit101[m]> oh hmm, actually that is safe
<byteit101[m]> but if it was `p self.to_java` it might change
<byteit101[m]> no, still NPE as today, ok NVM
<headius[m]> how does the balloon example work on PR now?
<byteit101[m]> as you expect, works fine
<headius[m]> what happens at the super call I mean
<byteit101[m]> ast transform kicks in
<headius[m]> aha
<byteit101[m]> and it calls the correct super(int, string)
<byteit101[m]> (the other ctor in parent class throws an exception for debugigng)
<headius[m]> ok how does that fit into construction from java side?
<byteit101[m]> works same either from java construction or ruby new
<byteit101[m]> I think I might be missing your question?
<byteit101[m]> oops, I need to fix that nil (if we go down that method)
<byteit101[m]> must have misplaced a scope
<headius[m]> from Java side, init is called, and that calls this initialize, and this calls the super? that is where I am stuck
<byteit101[m]> ah, right
<headius[m]> how is super not already called by the time this initialize is invoked basically
<headius[m]> ahh that one
<byteit101[m]> (just above New Method names => new generated class) section
<byteit101[m]> which this impl: https://github.com/jruby/jruby/pull/6422#issuecomment-720055420 can then deal with
<headius[m]> so that isn't what a user writes, it is generated by transforming the super calls
<byteit101[m]> correct
<headius[m]> ok we will want to get enebo in this discussion after the election since it involves IR but this is feeling ok to me
<byteit101[m]> (warning: very hacky and needs cleanup if we go that route)
<headius[m]> so it is similar to what we have now without all the extra codegen and fragile sequence
<byteit101[m]> > this
<byteit101[m]> this = super splitter + ast transform?