[pull] master from GaijinEntertainment:master#1012
Merged
Conversation
Closes the deferred follow-up from PR-D: a having predicate may now reference a reducer absent from the select. plan_group_by scans the predicate first, appends a hidden ReducerSpec for each unmatched reducer (bare or inner-select), and extends the named-tuple table value type with the new slot's acc type. The existing PR-D rewrite_having_pred runs unchanged once specs cover every reducer reference; result-build re-synthesizes the user's tuple slot-by-slot, naturally omitting hidden slots by iterating only the user-visible argTypes. Bare-form select with hidden slot cascades to tier 2 — the bare table type uses `tuple<KeyT; AccT>` synthesized inside a qmacro with embedded `typedecl(invoke(...))` for the key, which can't be dynamically grown with extra acc slots. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…g (PR-E) New benchmark groupby_having_hidden_sum mirrors the m1/m3/m3f tri-form pattern with an inner-select-sum reducer present only in the having clause (no matching select slot). Headline: 40 ns/op (m3f) — 2.7x over m3 plain LINQ (109), 4.4x over m1 SQL (175). groupby_having_count (regression check) stays at 36 ns/op, so the scan-then-rewrite refactor preserves the matching-slot splice. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
C1 (correctness): scanner bail for second same-named hidden inner-select. A having clause with two same-named inner-select reducers over different lambdas (e.g., sum(select(λ1)) + sum(select(λ2))) previously routed both predicate terms to the first hidden slot — silently wrong. Now bails to tier 2, which evaluates each select() separately and stays correct. Match against a select-side spec (visible slot ≤ userVisibleSlotCount) still reuses, preserving PR-D's matching-slot optimization. Pinned by new parity test `test_group_by_having_two_same_named_inner_select_diff_lambdas` and AST cascade test `test_group_by_having_two_same_named_inner_select_cascades_to_tier2`. C2 (cosmetic): align groupby_having_count m3 in the PR-E regression-check row to PR-D's published 78 (was 92 from a fresh run; ~17% variance on the ~80 ns/op baseline). The row's purpose is to show m3f stayed at 36. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…roupby-having-hidden-slot linq_fold group_by: hidden-slot reducer-in-having (PR-E)
…ent type) `aggregate_impl_const` checked `is_workhorse(type<TT>)` where TT is the element type, but move-vs-return is decided by AGG (return/accumulator type). The two differ for aggregates that produce a workhorse acc from a non-workhorse element (e.g. summing prices off `array<Car>` with int seed) — the impl tried `return <- int_from_const` which fails to compile. Fixed by checking `is_workhorse(type<AGG>)` to match the public `aggregate(array, ...)` overload's own static_if at linq.das:1478. Surfaced by adding a benchmark with non-workhorse element + workhorse seed for the upcoming terminal-walk splice work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…R-F)
Closes the `test_linq_element.das` (last / last_or_default / single /
single_or_default / element_at / element_at_or_default) and the
`test_linq_aggregation.das` (aggregate(seed, fn)) `_fold` cascade gaps.
Builds on the existing EARLY_EXIT lane infrastructure. The function name
`emit_early_exit_lane` is now a misnomer (last/single/aggregate walk the full
source), but the structural shape — one for-loop + prelude/per-match/tail
stmts + optional skip/take wrap — fits all seven new operators perfectly.
Three pieces:
1. `classify_terminator` extension. Adds 7 new names to the EARLY_EXIT bucket
(the lane now covers any single-return terminator with that emission shape).
2. `fold_linq_cond2` helper. 2-arg sibling of `fold_linq_cond` that peels
`block<(acc, x):AGG>` bodies — single-return blocks get their formals
renamed via `Template.renameVariable` on both `acc` and `x`. Non-peelable
bodies return null so the caller falls back to runtime `invoke(fn, acc, val)`.
3. Per-op emission arms (in `emit_early_exit_lane`):
- last / last_or_default: prelude `var found; var lastBind`; per-match
`found = true; lastBind := val`; tail panic / return default.
- single / single_or_default: per-match panics or returns default on the
SECOND match; single keeps walking, single_or_default early-exits.
- element_at / element_at_or_default: counter early-exit at the N-th
surviving match; negative index pre-loop panics or returns default.
- aggregate: workhorse seed uses `=` / `return`; non-workhorse uses
`<-` / `return <-` (matches linq.das:1466 user-side static_if).
Tests:
- 36 new parity subtests across 7 [test] functions (test_linq_fold.das)
covering bare/where/select/empty/non-workhorse-string/skip-take/parity-vs-
plain-linq for each operator.
- 9 new AST-shape tests (test_linq_fold_ast.das) asserting splice fires:
invoke wrapper, single for-loop, panic-presence-or-absence, counter ++,
peeled aggregate body (zero per-element invoke nodes via new
`count_invoke_nodes` helper).
342 + 125 tests green in interpreter; same in AOT.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four new tri-form (m1 SQL / m3 plain LINQ / m3f _fold splice) benchmarks at 100K rows: - last_match: m3 29 → m3f 5 ns/op (5.8× over m3) - single_match: m3 19 → m3f 2 ns/op (9.5× over m3) - element_at_match: m3 29 → m3f 0 ns/op (early-exit at ~100 source elements; splice exits after INDEX+matching_density elements, so total time / N bottoms out below dastest's timer granularity) - aggregate_match: m3 51 → m3f 5 ns/op (10.2× over m3, 6.8× over m1 SQL — peeling the block body inline + fusing the upstream where filter eliminates BOTH the per-element block invoke AND the where-iterator allocation; m3 pays for both, m3f for neither) LINQ.md gets a "Phase 3+ terminal-walk lane" section documenting design, bail cases, edge cases, headline numbers, and a deferred-follow-up note (aggregate with non-peelable multi-statement block bodies cascade to tier 2 — correct but slower; future `return $b(stmts)` recognizer would fix that). Coverage checklist rows for test_linq_element.das and test_linq_aggregation.das flip from ⏳ to ✅ for the relevant operators. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…erminal-walk-last-single-element-aggregate linq_fold: terminal-walk lane for last/single/element_at/aggregate (PR-F)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )