groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Keith Suderman <suder...@cs.vassar.edu>
Subject Re: Remembering imports between script invocations
Date Thu, 01 Nov 2018 15:19:48 GMT
Hi David,

I am not a Groovy committer and I am not that familiar with the Groovy code base so _I_ can't
revise the JSR-223 implementation.  I did take a quick look at the code, and other than having
"GroovyScriptEngine" in their names the two classes (GroovyScriptEngine and GroovyScriptEngineImpl)
have nothing in common and parse/load Groovy code in completely different ways.  I suspect
adding a feature like you want would be a non-trivial undertaking.  Maybe one of the active
committers (Paul, Daniel, et al)  can comment.

However, I suspect that the GroovyScriptEngineImpl class is "crippled" by JSR-223 itself as
it caters to the lowest common denominator

- Keith

> On Oct 31, 2018, at 12:12 PM, David Ekholm <david@jalbum.net> wrote:
> 
> Hi Keith,
> 
> I'm "resurrecting" this old thread in an attept to see if we can use Groovy as the next
scritpting language in jAlbum. What I'd really want to achive is to supply a number of default
star imports. This is expecially important as Groovy sadly doesn't remember imports between
script invocations.
> 
> I looked at your code suggetion below and tried to fit it to JSR-223 (javax.script API)
but it fails as the GroovyScriptEngineImpl class I get from that API doesn't extend the GroovyScriptEngine
class. It's only the GroovyScriptEngine class that supplies the important setConfig method.
> 
> Could you revise the JSR-223 implementation so it isn't unnecessary crippled compared
to the GroovyShell API, at very least add the setConfig method to the GroovyScriptEngineImpl
class? If we're to use the GroovyShell API, then we need to introduce our own abstraction
layer in order to continue supporting multiple scripting languages in jAlbum.
> 
> Regards
> /David, jAlbum founder
> 
>> On 10 Feb 2018, at 21:25, Keith Suderman <suderman@anc.org <mailto:suderman@anc.org>>
wrote:
>> 
>> Import statements are really just shortcuts to tell the compiler how to resolve class
names so there is nothing to "remember" between invocations, that is, nothing gets added to
the Binding.
>> 
>> I am not familiar with the javax.script API, but I suspect that you will have to
provide your own ScriptEngine implementation as you will need to modify the CompilerConfiguration
object the GroovyShell is using to compile the Groovy code.  For example:
>> 
>>         CompilerConfiguration configuration = new CompilerConfiguration()
>>         GroovyShell compiler = new GroovyShell(configuration)
>>         println compiler.evaluate('json=\'{"foo":"bar"}\'')
>>         println compiler.evaluate("groovy.json.JsonOutput.prettyPrint(json)")
>> 
>>         /* Fails: MissingPropertyException */
>>         /* println compiler.evaluate("JsonOutput.prettyPrint(json)") */
>> 
>>         ImportCustomizer imports = new ImportCustomizer()
>>         imports.addStarImports("groovy.json")
>>         configuration.addCompilationCustomizers(imports)
>> 	// Works, the compiler can now resolve groovy.json.JsonOutput
>>         println compiler.evaluate("JsonOutput.prettyPrint(json)")
>> 
>> The difficult part will be "hooking" into the compiler to know when an import statement
is used so you can update your CompilerConfiguration object.  I am sure the really clever
programmers here could come up with some sort of AST transform that would do this.  However,
depending on what you are allowed to do one option would be to tell your users that you have
a "Groovy DSL" and then implement an "include" method that users would use to "import" Java
packages.
>> 
>>         println eval('json=\'{"foo":"bar"}\'')
>>         println eval('include "groovy.json"')
>>         println eval('JsonOutput.prettyPrint(json)')
>> 	
>>     Object eval(String code) {
>>         Script script = compiler.parse(code)
>>         ExpandoMetaClass metaClass = new ExpandoMetaClass(script.class, false)
>>         metaClass.include = { String name ->
>>             ImportCustomizer includes = new ImportCustomizer()
>>             includes.addStarImports(name)
>>             configuration.addCompilationCustomizers(includes)
>>             "Imported $name"
>>         }
>>         metaClass.initialize()
>>         script.metaClass = metaClass
>>         script.run()
>>     }
>> 
>> Hopefully that gives you some ideas.
>> 
>> Cheers,
>> Keith
>> 
>>> On Feb 8, 2018, at 3:47 PM, David Ekholm <david@jalbum.net <mailto:david@jalbum.net>>
wrote:
>>> 
>>> How do I do that via the javax.script API?
>>> 
>>> Even if this is possible via the javax.script API, chances are that a user wishes
to ad-hoc add another import, but as they are forgotten between script invocations, it makes
it hard to use Groovy to interactively create, say a Swing or JavaFX UI one line at a time.
With BeanShell, the user can add the needed imports, execute that "script" and then continue
to refer to the imported classes in the following script invocations. Making Groovy remember
imports would make it behave in as nice fashion as the new JShell tool in Java 9. JShell unfortunately
cannot run embedded via the javax.script API :-(
>>> 
>>> Regards
>>> /David
>>> 
>>>> On 8 Feb 2018, at 21:34, eric.milles@thomsonreuters.com <mailto:eric.milles@thomsonreuters.com>
wrote:
>>>> 
>>>> You can add all the imports you want to your compiler configuration and they
will be consistently available for all scripts.
>>>>  
>>>> From: David Ekholm [mailto:david@jalbum.net <mailto:david@jalbum.net>]

>>>> Sent: Thursday, February 08, 2018 2:12 PM
>>>> To: dev@groovy.apache.org <mailto:dev@groovy.apache.org>
>>>> Subject: Remembering imports between script invocations 
>>>>  
>>>> We're considering supporting Groovy as an additional scripting language to
our web gallery software jAlbum (http://jalbum.net <https://urldefense.proofpoint.com/v2/url?u=http-3A__jalbum.net&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=39n_uU4e7-n_s_WwrNC_8tQYLfhWKgmT_dDWwJw8ctA&s=jGwsu2zf5Pm3kG3GKLFFxalyi30aoXq_-izsMrEy_iQ&e=>),
but one aspect bugs me: It doesn't seem like import statements are remembered between script
invocations. This makes it far harder to use Groovy to prototype UIs within jAlbum's scripting
console than for instance BeanShell (using the javax.script API). We currently support the
slow BeanShell scripting language and JavaScript. BeanShell behaves well in this regard, remembering
earlier imported packages between script invocations. Can this be added to Groovy or is there
some API flag we can set?
>>>>  
>>>> Regards
>>>> /David, jAlbum founder and client lead developer.
>>> 
>> 
>> ----------------------
>> Keith Suderman
>> Research Associate
>> Department of Computer Science
>> Vassar College, Poughkeepsie NY
>> suderman@cs.vassar.edu <mailto:suderman@cs.vassar.edu>
>> 
>> 
>> 
>> 
> 



----------------------
Keith Suderman
Research Associate
Department of Computer Science
Vassar College, Poughkeepsie NY
suderman@cs.vassar.edu





Mime
View raw message