Issue Details (XML | Word | Printable)

Key: GROOVY-2053
Type: Improvement Improvement
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Jason Dillon
Reporter: Jason Dillon
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
groovy

Re-write InteractiveShell (aka. groovysh) in Groovy

Created: 13/Aug/07 03:17 PM   Updated: 06/Oct/07 12:14 AM   Resolved: 06/Oct/07 12:14 AM
Return to search
Component/s: None
Affects Version/s: None
Fix Version/s: 1.1-rc-1

Time Tracking:
Not Specified


 Description  « Hide

Currently the InteractiveShell (aka. groovysh) class is written in Java... and well, AFAICT there is no good reason for that. So re-write it in Groovy



Guillaume Laforge added a comment - 13/Aug/07 03:45 PM

Requirements:

  • make sure we don't have to type 'go' anymore
  • allow class definitions not to be forgotten after execution of a valid script, so that we can further create instances of that class in the following valid scripts being executed
  • allow methods to be remembered as well and be available to the following valid scripts that will be executed (for instance, inspecting the script, finding new methods defined on it, and storing them as MethodClosures in the global binding, so that they are available for the next run)

Jason Dillon added a comment - 14/Aug/07 09:40 PM

Any hints on how to get the underlying GroovyShell instance to remember things? Seems like it doesn't do that at all right now. Perhaps the SourceUnit needs to be inspected and then use that information to pull out bits from the compiled script... er something?


Guillaume Laforge added a comment - 15/Aug/07 06:13 AM

As you'll evaluate new scripts with GroovyShell, you can pass a binding containing variables. So in this binding, you can put MethodClosures wrapping methods defined in previous scripts.


Jason Dillon added a comment - 15/Aug/07 02:34 PM

Okay, and I'm guessing that previously defined classes should already stick na?

What about things like:

def foo = "bar"

And more so... how does one figure out what methods (and or simple defs like above) were defined? Seems that the binding does not capture those (unfortunately IMO), so I'm probably going to have to use the SourceUnit to track those down?


Guillaume Laforge added a comment - 15/Aug/07 03:28 PM - edited
def foo = "bar"

is a local variable, so we won't be able to capture it and put into the binding, but:

foo = "bar"

will go in the binding of the script by default.

For methods, as if you evaluate this script:

def err(msg) { System.err.println(msg) }

you will have to introspect the Script class that is compiled to retrieve the methods that have been defined on it. Then, you wrap that in a MethodClosure that you keep inside the binding as 'err' (for the key), and the method closure for the value, so that later on, people can call err('hi') (in fact, the script will retrieve the err property in the binding, and as it's a closure, will call it)

The trickier thing is probably how to memorize the imports :-/
An idea could be to "catch" the imports as if they were shell commands, then you keep them somewhere in memory.
You could append them to the script evaluated, but you'd loose the right line number information.
So a better approach, ideally, would be to use the GroovyClassLoader and add imports transparentely when the script is compiled.
See blackdrag's blog for some ideas: http://blackdragsview.blogspot.com/2006/11/chitchat-with-groovy-compiler.html
This is also a technique that Alexandru Popescu used to add TestNG imports automatically in his Test'N'Groove project:
Look at the end of this file to see how to do that:
http://testngroove.googlecode.com/svn/trunk/src/main/org/codehaus/groovy/testng/GroovyTestNG.java

The last thing also that would be needed would be to remember class definitions, so that you can define a class in a first script:

class A {}

and then in another script execution being able to create new instances:

new A()

There might be some tricks with classloaders to make that possible though, and I'm not sure yet how to best do that.
Perhaps Jochen can give some perspective on this.


Jason Dillon added a comment - 06/Oct/07 12:14 AM

This is done, enable with NEWSHELL=t ./bin/groovysh atm.