Embedding a REPL in a Java application

Jamison Hope jrh@theptrgroup.com
Sun Nov 15 15:48:00 GMT 2009


On Nov 14, 2009, at 12:22 PM, Per Bothner wrote:

> On 11/13/2009 04:10 PM, Jamison Hope wrote:
>> Is there a way to construct two instances of ReplDocument which share
>> an environment, without having access to package-visible fields?
>
> After a little bit of thought, I think adding a "copy constructor"
> for ReplDocument might make sense:
>
>  public ReplDocument (ReplDocument old)
>  {
>    this(new SwingContent(), old.language, old.environment, true);
>  }
>
> and add a GuiConsole method to take a ReplDocument:
>
>  public GuiConsole(ReplDocument rdoc)
>  {
>    super("Kawa");
>    repl.getLanguage(); // In case a new GuiConsole is created from  
> Java.
>    init(doc);
>  }
>
>  public GuiConsole(Language language, Environment penvironment,  
> boolean shared)
>  {
>    this(new ReplDocument(language, penvironment, shared));
>  }
>
> Then the shared action becomes:
>
>    else if (cmd.equals(NEW_SHARED))
>      new GuiConsole(new ReplDocument(document));
>
> Could you this approach, and see how it works, both for the
> existing GuiConsole, and your application?

It sounds like for this to work, I would need to create and hold onto  
a special initial ReplDocument (with shared=false) and then all  
subsequent ReplDocument instances I would create from it with the  
proposed copy constructor. That could work, but it seems a bit heavy.  
Let me step back for a moment and state my overall aims for this:

(1) I want to augment my application with a Scheme layer, accessible  
to the user through one or more REPL windows.
(2) I want all REPL windows to be on an equal footing: the user should  
be able to open and close them at will. In particular, the first one  
shown should not be any more special than any other.
(3) I want all REPL windows to share an environment, in the sense that  
define and set! statements evaluated in one produce bindings visible  
in any other. In other words, I want these windows to be (or at least  
to appear to be) stateless views into a common underlying Scheme  
environment.
(4) I want the shared Scheme environment to be lazily loaded the first  
time the user requests a REPL, to keep it an opt-in feature.
(5) I want Scheme to be initialized with a number of domain-specific  
bindings (references to objects, as well as procedures and macros)  
prior to the first REPL window being displayed. For generality, let's  
assume that these can come from plaintext scm files, compiled class  
files, as well as direct "define" method calls in Java.
(5) Once instantiated, this shared environment should persist until I  
quit the program, even if all REPL windows have already been closed.

Each ReplDocument has its own backing Thread (a Future), right? So if  
I use one -- one not associated with any visible Frame -- as the  
(container of the) persistent Environment, I'll have spawned an extra  
Thread which is doing absolutely nothing. Is that as wasteful as it  
seems, or is such a Thread unavoidable if I want to preserve the  
Environment beyond the lifespan of a particular REPL window?

It also occurs to me that I may run into trouble with ReplDocument due  
to it calling repl.exitIncrement/exitDecrement. Unlike in the pure  
GuiConsole case, I don't want my application shutting down just  
because the last REPL window was closed!

I do think that the copy constructor would be a worthwhile addition to  
the ReplDocument API, regardless of whether it's right for my problem.

Thanks,
Jamie

--
Jamison Hope
The PTR Group
www.theptrgroup.com





More information about the Kawa mailing list