[pull] master from GaijinEntertainment:master#1034
Merged
Conversation
…audit C1 + C5)
The "top-K distinct" composition family now splices end-to-end across array
and decs sources. Two arm pairs in mirror order share a single emission:
C1: `_distinct_by(K1) |> _order_by(K2) |> take(N) |> to_array()`
C5: `_order_by(K1) |> distinct() |> take(N) |> to_array()`
Both `plan_order_family` and `plan_decs_order_family` gained a `distinct` /
`distinct_by` recognizer in the walk loop. The bounded-heap path declares
`var dset : table<typedecl(...)>` above the source loop and wraps per-element
push by `if (!key_exists(dset, dkey)) { dset |> insert(dkey); HEAP_UPDATE }`.
Today this composition cascades to tier-2 (`distinct_by_to_array` →
`order_by_inplace` → `take_inplace` — full distinct materialization before
sort). After: single source pass, no full distinct array, only the bounded-N
heap allocated.
Position of `distinct` in the chain (before vs after `_order_by`) has no
bearing on emission — the set just gates the same heap update. The
bounded-heap path treats source-walk order as opaque. C1 and C5 reduce to
identical splice output; only the recognizer position differs.
v1 constraints:
- Inline-able order key required (existing bounded-heap gate; mirrors
plan_order_family's pre-existing constraint).
- first / first_or_default + distinct deferred (streaming-min path not
extended in v1).
- Composes with WHERE (filter before distinct gate) and terminal `_select`
(project ≤N heap survivors at return).
Tests: +9 tests / 18 sub-runs in
`tests/linq/test_linq_fold_theme3_c1_c5_distinct_order_take.das`. Coverage:
C1 ascending + descending, C5 with distinct (whole-tuple key), WHERE +
distinct gate, terminal `_select`, parity vs handwritten cascade, decs lane
for both C1 and C5, anti-test for non-inline order key cascade.
1515/1515 linq tests pass (interp) — was 1497 baseline post-PR-#2862.
245/245 decs tests pass. Lint + format clean.
Living-doc refresh per [[feedback-living-linq-fold-patterns-rst]]: new row in
both Array and Decs tables of `doc/source/reference/linq_fold_patterns.rst`;
audit doc C1 + C5 rows flipped FALLS-OFF → SPLICE-FIRES, Status section
gained a "Theme 3 Phase 3 — landed 2026-05-24" block. "Still open" reframed
to Themes 6/7/8 (Theme 3 closed entirely).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…e + RST/test polish
Copilot review surfaced 3 categories of valid concerns. All folded in.
## Semantic bails (silent miscompile fixes)
The R0 recognizer accepted `distinct[_by]` unconditionally and only enforced
the set-gate in the bounded-heap path. Three shapes either silently dropped
distinct or produced wrong output:
1. `_order_by(K2).distinct_by(K1)`: cascade semantics = "min-K2 per K1" (sort
first, then keep FIRST K1 per group in sort order). The source-walk set-gate
would keep an ARBITRARY K1 representative (first seen during walk, not
first in sort order). Concrete counter-example: `[(A,5),(B,3),(A,1)] ->
order_by(ts).distinct_by(name)` cascade → [(A,1),(B,3)]; broken splice
would have kept (A,5). Plain `distinct()` after order_by is still safe —
whole-tuple equality is position-invariant.
2. `_distinct[_by]` without `take`: the set-gate lives only in the bounded-
heap path. Without take the splice would fall through to the bottom emit
that ignores `distinctName`, silently dropping dedup.
3. `take(N).distinct[_by]()`: cascade takes first N source elements then
dedups; splice would have dedup'd all source then taken N distinct — wrong.
Fixed in both `plan_order_family` and `plan_decs_order_family` by extending
the distinct branch's combined bail (`distinctName != "" || firstName != ""
|| selectLam != null || takeExpr != null || (name == "distinct_by" &&
hasOrder)`) and adding a post-loop guard (`!hasOrder || (distinctName != ""
&& takeExpr == null)`).
## var inscope on dset
The R0 dset declaration was a plain `var ... : table<...>`. Other table-
holding splices in linq_fold (notably `plan_distinct`) use `var inscope` so
finalize fires reliably on scope exit. Both lanes (array + decs) updated to
match the convention.
## Docs + test polish
- RST rows previously documented `._distinct()` (no such shorthand macro
exists in daslib/linq_boost — only `_distinct_by` has one). Updated to
plain `.distinct()` in both Array and Decs tables; rows also document the
3 new bail conditions explicitly.
- C5 tests (array + decs) previously tracked distinctness by `r.name` only,
which would not catch a buggy "name-only dedup" implementation. Switched
to combined-key tracking (`"{r.name}:{r.score}"`) + exact-key existence
assertions.
## New cascade-guard tests
Added 3 anti-tests verifying the bails: `order_by.distinct_by` (must cascade
to honor sort-aware dedup), `distinct_by` without take (must cascade so
dedup isn't dropped), `take.distinct_by` (must cascade so distinct isn't
applied pre-take). Each test asserts the correct output AS IF cascade fires
— the bail itself is invisible to user-visible behavior.
Tests: 18 → 24 sub-runs (1497 → 1521 total linq). 245/245 decs. Lint clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…heme3-c1-c5-distinct-order-take linq_fold: Theme 3 Phase 3 — distinct[_by] + order_by + take (audit C1 + C5)
Adds collapse_chained_selects pre-pass that mutates the linq call array
in place, folding consecutive _select(f) |> _select(g) into a single
_select(g(f(_))) before the per-arm pattern-match. Symmetric to how
chained _where already compose via &&.
Composition: clone the INNER lambda for its param TYPE, rename its bound
param to a fresh qn("cs", at) name to avoid apply_template recursive
substitution when both lambdas share the boost-side `_` desugar, then
overwrite its body with outer's body where outer's param is substituted
by the renamed-inner body. Chain backlink rewired so subsequent planner
passes see the shortened AST (without this, plan_decs_order_family
re-flattens the original chain and re-collapses, compounding ._N
accessors).
Gated on !has_sideeffects(innerBody) — collapsing shifts evaluation
count when outer references its param zero or many times (cascade
always evaluates inner once per element). Impure inner cascades; output
remains correct.
Wired into 8 planners: plan_order_family, plan_reverse, plan_distinct,
plan_decs_order_family, plan_decs_reverse, plan_decs_distinct,
plan_decs_join, plan_zip. The two order_family planners are defensive
no-ops today (they don't accept any leading _select) but inherit the
collapse if their grammar extends. plan_loop_or_count, plan_group_by_core,
and plan_decs_unroll already handle chained selects natively via their
intermediateBinds / chain-info machinery.
Tests: 9 [test] / 18 sub-runs in
tests/linq/test_linq_fold_theme7_chained_select.das.
1539/1539 linq + 245/245 decs interp green.
Closes audit benchmarks/sql/linq_fold_chain_audit.md row 7c (zip + N
chained _selects) and the equivalent chained-select-before-arm-op shape
on plan_distinct, plan_reverse, plan_decs_*, and plan_decs_join.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Walk through the 30s -> 7.5s compile-time descent for dasImgui macros: compiler-side wins (~20% across the board), lambda -> @@ where possible, JsonValue?/from_JV/JV -> json_sprint/json_sscan for fixed schemas. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lable shape, comment latent func variant
- C1: add design comment in collapse_chained_selects explaining why LinqCall.name=="select" matching is safe even though it covers both `select` and `select_to_array` (downstream planners build emission from scratch using cll._1.name + the lambda, never re-evaluating cll._0.func; fold_linq_default picks the variant at emission time from top._type.isIterator). No behavior change.
- C2: document in linq_fold_patterns.rst that collapse only applies to peelable single-arg single-return ExprMakeBlock lambdas — multi-statement, captured, or function-pointer projections skip.
- C3-C6: drop 4 expression-form `unsafe(_fold(...))` wraps + 2 block-form `unsafe { _fold(...) }` wraps in tests — verified the splice output is safe-typed (no unsafe required for any of the 9 test runs).
18/18 sub-runs still pass. Full linq 1539/1539 interp green. Lint + format clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…acro-hell blog: from macro hell
forge-logo.svg shipped with a homemade `>`-in-a-gradient-tile placeholder that didn't match the brand on daslang.io. Swap in the actual currentColor glyph path from site/files/daslang.svg, tinted amber (#e8a13a) to match the nav lockup. Wordmark text (daslang + .io) and colors are unchanged.
…eal-glyph doc: replace placeholder Sphinx logo with real daslang glyph
- "PerfVie" -> "PerfView" - "Now there is" -> link to https://borisbat.github.io/dasImgui/
…-perfview-fix blog: fix PerfView typo + link dasImgui docs in macros post
…heme7-chained-select-collapse linq_fold: Theme 7 — chained _select collapse (audit 7c)
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 : )