[ 
https://issues.apache.org/jira/browse/GROOVY-12749?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Paul King reassigned GROOVY-12749:
----------------------------------

    Assignee: Paul King

> GEP-27: pack closures that use free names, with a pluggable resolver in place 
> of a generated class per closure
> --------------------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12749
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12749
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>
> Closure packing (GROOVY-12151) compiles a closure's body to a method of the 
> enclosing class instead of generating a class for each closure, but only when 
> the closure has no free names: a name in the body that is not a parameter or 
> local variable is resolved at run time through the owner, the delegate and 
> {{resolveStrategy}}, which a hoisted body bound to the owner cannot honour. 
> Such closures still get a class of their own.
> This issue extends packing to those closures, as the next step of GEP-27. 
> Such a closure is packed "open":
> * each use of a free name in the body is rewritten into a call on a leading 
> {{OpenClosure.Resolver}} parameter of the hoisted method;
> * the closure is created with a {{ClassicResolver}}, which implements today's 
> resolution through the owner, the delegate and {{resolveStrategy}}, so 
> {{setDelegate}} and {{setResolveStrategy}} keep working after creation;
> * the closure is an ordinary fixed-arity {{PackedClosure}}, sharing the 
> dispatch tables of other packed closures, with no class generated for it.
> Behaviour is meant to be identical to today's generated closure classes.
> h3. Shape
> * Open closures are created through {{ScriptBytecodeAdapter.openClosure}} 
> ({{@GroovyABI(since = "7.0.0")}}), which builds the resolver from the owner, 
> so only the {{Resolver}} interface appears in generated class files.
> * {{PackedClosure}} forwards {{setDelegate}} and {{setResolveStrategy}} to 
> the attached resolver. An open closure never has the strict guard of an 
> ordinary packed closure: the resolver replaces it.
> * The open path has its own trigger, {{isOpenPackTriggered}}, which the 
> static closure writer turns off, so {{@CompileStatic}} code is unchanged.
> * The feature is off by default and enabled by {{<switch to be named>}}.
> h3. Parity with generated closure classes
> Tests compile the same source both ways and compare the results for:
> * each resolve strategy ({{OWNER_FIRST}}, {{DELEGATE_FIRST}}, 
> {{DELEGATE_ONLY}}, {{OWNER_ONLY}}, {{TO_SELF}}), including the exceptions for 
> a name that cannot be resolved;
> * a delegate and a resolve strategy set after the closure is created;
> * a name that both the owner and the delegate define;
> * {{methodMissing}} and {{propertyMissing}} on the owner and on the delegate;
> * a script as the owner;
> * assignment to a free name.
> h3. Not packed open (the closure keeps its generated class)
> * nested closures;
> * {{++}} or {{--}} applied to a free name;
> * closures compiled by the static compiler.
> h3. Still to address
> * what happens when an open closure is passed to statically compiled code, 
> stored in a field of type {{Closure}}, or serialized; it needs either tests 
> or a statement that it is unsupported or falls back;
> * the GEP-27 text, to describe open closures and the resolver.
> h3. Related
> * GROOVY-12151 (closure packing), GROOVY-12143 (lambda hoisting)
> * PR: https://github.com/apache/groovy/pull/2714



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to