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