Title: RE: Java -> elisp communication (was RE: BanInfo wizard anyone?)

Hi Paul,
        I think that in the case of Transmogrify we didn't have much choice. We wanted to interface with an engine and an interface that was already defined, so we could not change the control flow to use queues and even handlers. Maybe an adaptation layer could do the trick, I don't know. I didn't have enough elisp knowledge to create and manipulate sockets from the lisp side, so gnuclient sounded like a good compromise.

        Do you think it would be possible to expose the mechanism you implemented for MATLAB as an open, documented, JDE extension API? It sounds like you have solved the communication portion of the problem already, while Nick's JUCI takes care of hiding the elisp learning curve from Java programmers. Combine both and you have an open plug-in interface for JDE!

        I had recently used the Java 1.4 Dynamic Proxy feature to implement proxies as well (to extend CORBA to support JAAS-based authorization). This could also be used I suppose to provide a elisp "encoding" plus dispatching for arbitrary Java interfaces.

        Regards,
                Nascif


> -----Original Message-----
> From: Paul Kinnucan [mailto:[EMAIL PROTECTED]]
> Sent: Monday, December 09, 2002 3:59 PM
> To: Nick Sieger
> Cc: Abousalh-Neto, Nascif [NCRTP:3X50:EXCH]; [EMAIL PROTECTED];
> Graham Bennett
> Subject: RE: Java -> elisp communication (was RE: BanInfo
> wizard anyone?)
>
>
> Nick Sieger writes:
>  > > From: Nascif Abousalh-Neto [mailto:[EMAIL PROTECTED]]
>  > > Sent: Monday, December 09, 2002 11:46 AM
>  > > To: Nick Sieger; Galen Boyer; [EMAIL PROTECTED]
>  > > Cc: Graham Bennett
>  > > Subject: Java -> elisp communication (was RE: BanInfo
> wizard anyone?)  > >

>
> [snip]
>
>  > > 3) Both my implementation and Graham's use gnuclient to
>  > > implement the Java -> elisp side of the equation (elisp ->
>  > > Java using the BeanShell support in JDE). The reason being
>  > > that Java tools will need (and that is true for Transmogrify)
>  > > to make asynchronous calls to the elisp side.
>
> gnuclient is not necessary to do this. My interface between
> the MATLAB debugger and Emacs, implemented in Java (one of
> MATLAB's extension languages), uses threads and sockets to
> handle asynchronous communications (i.e., debugger events)
> between the debugger and Emacs. At startup, the MATLAB-Emacs
> interface creates an Emacs-Matlab communictions socket and
> starts a "transciever" thread to listen for input on the
> socket. The interface then starts Emacs, using a command-line
> switch that starts up the Emacs side of the MATLAB-Emacs
> interface. The Emacs side of the interface creates a process
> that listens for input from the socket created by the MATLAB
> side. The input is always in the form of a Lisp form that the
> Emacs "transceiver" evaluates.  The MATLAB side of the
> interface listens for debugger events (e.g., a breakpoint
> hit) and reformats them as Lisp function evaluations (e.g.,
> (matlab-eei-breakpoint-hit "matlab-function.m" 22)) that are
> evaluated by the Emacs side.
> In other words, the Emacs side of the interface has a whole
> bunch of functions that correspond to debugger events. The
> Java side of the interface invokes them to do things like
> move a debug cursor through code being displayed in an Emacs buffer.
>
> In general, I highly recommend that anyone trying to
> implement an interface between Emacs and an external
> application do so via an asynchronous interface, i.e., each
> side interacts with the other side purely via commands and
> event handlers, e.g., if Emacs needs a response to a command
> sent to the other side, it should register an event handler
> for the response, issue the external command, and return to
> the internal (Emacs user) command loop. It should not attempt
> to suspend Emacs until the response comes back. If Emacs
> needs to issue a sequence of commands to the other side, with
> each command completing before the next is issued, it can
> create a queue of commands and have the event handler for the
> previous command issue the next command in the sequence. This
> approach is far more robust in my experience than having each
> command suspend Emacs until the other side responds to the command.
>
> - Paul
>

>  > > I'm curious on how the JUCI would solve that problem, as I
>  > > assume the BeanShell call that starts the communication with
>  > > the Java portion would block until a response is received, so
>  > > how could the Java portion (in the same thread of execution)
>  > > submit a lisp form back for evaluation? Would you use
>  > > multiple BeanShell instances or multiple threads inside
>  > > Beanshell, one to submit the Java request and one to "listen"
>  > > to stdout for asynchronous evaluation requests?
>  >
>  > The latter approach is what I'm using.  Java invocations
> made through JUCI come through a proxy which queues the
> invocation for execution on a separate thread. When the java
> code needs to invoke elisp, it prints an elisp form and
> blocks while waiting for results to be returned (through the
> beanshell's foreground thread).  >
>  > > An "real world" example from my Transmogrify Hook
>  > > implementation should make it clear. Let's say you use the
>  > > elisp interface to call the ExtractMethod refactoring on
>  > > Transmogrify. The steps would be:
>  > > 1) User marks a region in the current buffer and calls
>  > > "jde-transmogrify-extract-method";
>  > > 2) This defun calls jde-eval, using the BeanShell to activate
>  > > the Transmogrify engine;
>  > > 3) Transmogrify gathers the necessary information by making
>  > > calls to the Hook interface:
>  > > Here I'm guessing a little, I don't remember exactly the
>  > > number and order of calls to the Hook interface.
>  > > For simplicity let's assume all the source code info can be
>  > > obtained in 3.2 call. It could actually require three to four
>  > > calls to obtain line number, caret position, etc.
>  > > 3.1) getUserInput (to obtain the new method name)
>  > > 3.2) getSelecteText (to obtain the body of the extracted method)
>  > > 3.3) displayMessage or displayException (for the result)
>  > > Each one of the 3.* calls will create an elisp form that will
>  > > be sent (via gnuclient) back to Emacs for evaluation.
>  > > The processing keeps going back and forth between the
>  > > Transmogrify engine and Emacs (through the hook
>  > > implementation and gnuclient) until Transmogrify has all the
>  > > info it needs, at which point:
>  > > 4) Transmogrify applies the refactoring to the source code;
>  > > 5) Transmogrify returns the control to the original
> jde-eval call.
>  > > 6) jde-transmogrify-extract-method completes
>  > > (this is really asking for an UML sequence diagram :-)
>  >
>  > I agree -- I'll try to put one together with some amount
> of detail that would show the above scenario in JUCI.  >
>  > > So even though the refactoring is "put in motion" by the
>  > > jde-eval call, the control of execution is pretty much in the
>  > > hands of Transmogrify. Emacs must be ready to act as an
>  > > "evaluation server", receiving forms on demand. This is the
>  > > behavior implemented by gnuserv/gnuclient. It would be great
>  > > if you can find a way to implement this behavior using
>  > > BeanShell only. You mentioned that the Java code would print
>  > > "lisp forms back to stdout and are evaluated by
>  > > `bsh-eval-r'". Doesn't that imply that you are limited to
>  > > control flows where Emacs is driving? How can the Java proxy
>  > > "trigger" the call to bsh-eval-r, get the result of the
>  > > evaluation and recover the control of the execution flow -
>  > > for example, to move from 3.1 to 3.2 in the scenario
> described above?  >
>  > I can't say that I've tested such a scenario like the
> above, but I'd expect to be able to get it working otherwise
> JUCI wouldn't be viable.  The only aspect which may be tricky
> is the fact that multiple lisp forms must be sent back and
> evalled (probably one each for getUserInput, getSelectedText
> and displayMessage).  But each lisp form evaluated would
> produce a result (even nil) which would have to be sent back
> to the beanshell.  As long as there is an alternating balance
> between beanshell script sent to the beanshell and elisp
> forms sent back to Emacs, I don't think this will be an issue.  >
>  > [snip]
>  >
>  > Thanks for the helpful feedback.
>  >
>  > /Nick
>
>

Reply via email to