From: Ken A. <kan...@bb...> - 2004-03-15 22:12:27
|
At 08:20 AM 3/15/2004 +1300, Toby Allsopp wrote: >On Thu, Mar 11, 2004 at 05:10:20PM -0500, Ken Anderson wrote: >> OK, since you've got 3 or 4 votes for your proposal, and none against, >> give it a shot. >> >> Why don't you email Tim and i as you do it, for guidence. >> >> What i'd do is copy jsint.Scheme into either jsint.REPL or >> jsint.Evaluator. make most of the static fields non static ... Then >> get jscheme.REPL to use it rather than jsint.Scheme in main(). Maybe >> we'll just get rid of Scheme eventually. In fact, remove it and let >> the compiler tell you where you need to change the code. > >My first cut (which seems to work for my purposes) is basically exactly >that. There are a ton of calls to static Scheme methods all through >everything, so I think I'll leave those alone as much as possible and >just redirect them to the appropriate Evaluator instance. References to >static fields in Scheme need to be changed anyway though. right. >In order to determine the appropriate Evaluator instance, I've set up a >thread-local stack of them, the interface to which is four methods in >JS: > >Evalutor enter() >Evalutor enterNew() >void enter(Evaluator) >void exit() > >The expected usage is that any Java code that wants to make calls to >JScheme needs to wrap them in: > > JS.enter(); > try { > ... > } finally { > JS.exit(); > } > >The parameterless enter() method will use an existing Evaluator if there >is one for the current thread, or will create a new one. The enterNew() >method will always create a fresh, new Evaluator instance. > >New threads get a copy of their parent's Evaluator stack (but the actual >Evaluator instances are shared). At first look, i don't like this. I don't like having to do a try/finally in Java to get something done for me by Scheme. My first suggestion of leaving the JS interface alone is probably wrong. The way JS is typically used is you define a Java class that loads some Scheme code as a static init and then defines some Java methods that do JS.call() to get the behavior done for it. So putting a try/finally around one line is too costly. You may also want to turn an s-expression as a string into an Object. Maybe, JS should just be a wrapper around an Evaluator and a class or a Thread that wanted Scheme evaluated would just set up the Scheme environment it want the Evaluator to have and call the appropriate JS functions. >> Scheme.ARGS only makes sense for the first Evaluator. So it should >> just become a global variable on the Scheme side. > >I don't think ARGS is referred to outside of jsint.Scheme, so it doesn't >really make much difference either way. I'd probably prefer it to be an >instance field in Evaluator so that you can run multiple scripts that >use the args and don't know about each other. ARGS is there to allow Scheme code to see what arguments were passed in. Any piece of code might want that, but it certainly doesn't make much sense in a "container environment". So maybe ARGS should just be a global variable in the initial environment so it can be used by any Evaluator down stream, was my initial thought. However, Looking at all the arguments doesn't make much sense because the arguments are processed by Scheme in a particular way and you can use the -main option to take over interpreting the rest of the arguments, as in src/using/command.scm for example. So, my proposal now is to get rid of ARGS. In Common Lisp, proposals were named like this: get-rid-of-args. >> What arguments should the constructor take? Probably a >> DynamicEnvironment at least optionally, but probably also the input, >> output, and error. Try to avoid setter methods, we want to think >> functionally when we can. > >Do you intend the DynamicEnvironment argument to intialise >INTERACTION_ENVIRONMENT? The idea was that evaluators could somehow share environments so either an evaluator could load specific code, as you might want in scheme-server-pages or could share code that was only loaded once, which you might want if you're a server spawing a new evalutor for each thread, but they all have the same behavior. >A fair amount of existing code assigns to the input and output fields. >Do you mean to replace that with code that instead creates a new >Evaluator? No, this code must bechanged into nonstatic calls. >> The jscheme.JS class that interfaces from Java to Scheme will need to >> be changed. For now, have that class create a static final instance >> to use to keep the code simple. > >I think I've covered this with the methods I propose adding to JS above. > >> This may be a good tern of events because it may guide us into some >> good refactorings. For example, i've thought that the REPL (Read Eval >> Print Loop) could be split up. The E would be an object that too >> s-expressions and returned their value. It could be attached in the >> usual REPL way or it could be controled by a GUI that passed commands >> to it as the user clicked on things and updated the screen accordinly. > >Sounds like a good idea. My changes will get you everything rolled into >the E and you can split out the R and the P later if it looks like a >good idea. > >> Also, i once made eval and load replaceable procedures, so for example >> you could get R5RS macros. But that disappeared when Tim put in >> DynamicEnvironments. >Sounds cool :-) I don't know what it means though :-( (load) and (eval) are Scheme procedures that have fixed semantics written in Java. By redefining them, you can change the semantics for example by adding a more powerful macro system than Scheme has by default. Or you could play with new evaluation models as in Paul Graham's ARC language http://www.paulgraham.com/arc.html so you could do things like (define v #(0 1 2 3)) (v 1) -> 1; apply a vector. or even (1 v) -> 1; apply a number to a vector. |