[ 
https://issues.apache.org/jira/browse/GROOVY-12724?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18142634#comment-18142634
 ] 

ASF GitHub Bot commented on GROOVY-12724:
-----------------------------------------

daniellansun commented on PR #3259:
URL: https://github.com/apache/groovy/pull/3259#issuecomment-6781911494

   (3) The example I answered last time really was two locals, and 
`VariableScopeVisitor` rejects that with or without the bridge. What you meant 
is a field or a property and a local of the same name. That does compile, and 
the bridge does not treat them as one name.
   
   The lowered query is spliced into the method, `VariableScopeVisitor` links 
each reference to the declaration in scope, and the original call is put back. 
A `FieldNode` or a `PropertyNode` is not copied. It is read when the closure 
runs. A local or a closure parameter declared inside the query is a different 
declaration, and that is the one the references in that scope use. A 
`DynamicVariable` is not copied either. At conversion that is what an import 
alias still is, including a lower-case alias such as `import 
java.util.concurrent.TimeUnit as threshold`, and the alias then resolves to the 
class.
   
   I ran that shape under `@CompileStatic`. A field `threshold` of 10 is set to 
4 after the `GQ` expression and before `toList()`. The `where` clause sees 4. A 
closure parameter `threshold` of 5 in the same query's `select` stays 5. A 
getter/setter property behaves the same way: the getter runs at the terminal, 
not when the expression is built. `@TypeChecked` does this too. `GQL` still 
materializes at the expression, so a later write of the field is not observed. 
A closure parameter of the same name as the field wins over the field. Two 
locals of the same name are still rejected. `STRATEGY.md` now says this 
explicitly. There is still no name walk in the bridge.
   
   (5) You are right that I answered a different question. The problem is not 
that the GINQ operators are dynamic. `DYNAMIC_RESOLUTION = Boolean.TRUE` is set 
on the lowered query closure, and `StaticTypesClosureWriter` compiles that 
whole closure with the dynamic writer. Every expression in it is dynamic, 
including a call written in `where` or `select`. A target another transform 
already chose for that call is not what is emitted. The call is dispatched at 
runtime.
   
   A concrete case: an extension's `onMethodSelection` forces 
`choose(CharSequence)` when the argument is a `String`. In the enclosing 
`@CompileStatic` method that is the method that runs. The same call inside 
`select` hits `choose(String)`, because the runtime type wins. The same is true 
of any other call in the clause whose static target differs from the runtime 
dispatch.
   
   I tried not to mark the closure. Clause parameters stayed dynamic, so a map 
row is not inferred as a bean. A call the checker could resolve kept its 
target, and only an operator whose target was a stand-in became a dynamic call. 
The read-only snapshot was passed into the result lambda as a parameter, 
because a static lambda still cannot capture a local of an enclosing closure: 
the bytecode loads the outer class and casts it to `GroovyObject`. `orderby n 
in desc` and the join tests in the static suite still passed, and the 
`choose(CharSequence)` target was honoured inside the query.
   
   The rest of the dynamic query did not. On the groovy-ginq suite, 71 tests 
failed. `where note(n)`, `note` being a method of the enclosing class, was 
emitted as `invokevirtual` of `Object.note()`, which does not exist. A join 
alias was resolved against `QueryableCollection`. A parallel join that returns 
rows dynamically returned an empty list. Group, window, aggregate, and 
hash-join scripts failed in the same way. Parallel `submit` also cannot take 
the snapshot as an extra parameter, because that lambda is a `Supplier`.
   
   So the closure stays dynamic. The enclosing method does not. I have written 
that limitation into `STRATEGY.md` and the CompileStatic section of the user 
guide, including the `choose(CharSequence)` example. I would rather the clause 
bodies stayed on the static writer. I do not have a way to do that which still 
runs the queries that pass today.
   




> GINQ: support static compilation and a fluent query API
> -------------------------------------------------------
>
>                 Key: GROOVY-12724
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12724
>             Project: Groovy
>          Issue Type: Improvement
>          Components: GINQ
>            Reporter: Daniel Sun
>            Assignee: Daniel Sun
>            Priority: Major
>
> Under @CompileStatic / @TypeChecked, GQ, GQL, and @GQ currently rely on 
> dynamic lowering. This improvement makes those entry points usable from a 
> statically checked scope while keeping the SQL-like syntax lowered to the 
> in-memory collection runtime.
> h3. Goals
> * Allow GQ / GQL / @GQ from @CompileStatic and @TypeChecked without forcing 
> the lowered tree through static checking at the expression site.
> * Defer pipeline construction with LazyQueryable until a terminal read 
> (toList, count, etc.), copying locals at the expression site (same binding as 
> dynamic GQ).
> * Add Ginq.from(...) as a deferred, generic fluent chain on the same runtime, 
> with @ClosureParams so where/select/join/aggregate closures can infer element 
> types where inference is sound.
> * Preserve default lazy/deferred evaluation and dynamic GQ behavior for map 
> rows and other intentionally dynamic cases.
> h3. Non-goals / known limits
> * Stored untyped Closure variables still need a SAM target type for parameter 
> inference (same as Java/C#).
> * Raw Query parameters/fields cannot recover a safe element type.
> * Names bound by from inside GQ / GQL / @GQ stay dynamic by design; callers 
> that need checked element types use Ginq.from.
> h3. Related work
> GitHub PR: https://github.com/apache/groovy/pull/3259
> Stacked on GEP-26 SQL window work (PR #3167 / gep26-sql-window).



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

Reply via email to