Skip to content

[pull] master from GaijinEntertainment:master#1015

Merged
pull[bot] merged 13 commits into
forksnd:masterfrom
GaijinEntertainment:master
May 20, 2026
Merged

[pull] master from GaijinEntertainment:master#1015
pull[bot] merged 13 commits into
forksnd:masterfrom
GaijinEntertainment:master

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented May 20, 2026

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 : )

borisbat and others added 13 commits May 19, 2026 19:24
New [call_macro] from_decs_template(type<Foo>) that converts a struct
annotated with [decs_template] into an iterator<tuple<...>> over the
matched archetype set. Field names + types are derived from the struct
definition; component names are the [decs_template(prefix=...)] prefix
joined with each field name (same prefix-resolution as DecsTemplate.apply
and is_decs_template).

Eager bridge: emits invoke($() { var res : array<tuple<...>>; query(...)
{ res |> push((...)) }; return res.to_sequence() }) — same shape as the
existing from_decs($(field:T;...){}) macro, just with the field list
sourced from the struct instead of a block. Tuple elements are by-value
since archetype refs don't outlive the invoke block (Phase 4 splice form
will keep refs alive inside for_each_archetype directly).

Default field values (fld.init) propagate to the query block so the
query macro infers get_default_ro for optional components.

Tests: 6 new in test_linq_from_decs.das covering custom-prefix /
default-prefix (StructName_) / empty-prefix variants plus a projection
case (.select(_.field).sum()). Parity assertions verify that the
from_decs_template chain produces identical results to the equivalent
hand-written from_decs($(prefix_field:T;...){}) chain.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two test-isolation fixes for test_from_decs_template, per Copilot review
on PR #2745 (#2745 (comment)):

(1) Add restart() at the top of test_from_decs_template to clear any ECS
state from earlier [test] functions in the same file. Tests in
test_linq_from_decs.das share a single dastest context, so without an
explicit reset the entities created by test_from_decs would persist into
test_from_decs_template's archetype set.

(2) "default-prefix parity (struct name)" sub-test: change via_explicit
from $(FromTemplateImplicit_iv : int) to
$(FromTemplateImplicit_iv : int; FromTemplateImplicit_sv : string). The
template-form via_template requires BOTH components (the FromTemplateImplicit
struct has 2 fields). The previous explicit form only required _iv, so
any future test creating an entity with _iv but not _sv would have flaked
the parity assertion. The new explicit form has the same component
requirements as the template form, making the parity comparison
semantically equivalent.

The other 3 parity sub-tests (custom prefix, empty prefix, projection)
were already symmetric and need no change.

Verification: lint clean; 7/7 file tests green; interpret sweep
tests/linq 1138/1138 green; AOT sweep (after --aot-regen + test_aot
rebuild) 1138/1138 green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ecs-template

decs_boost: from_decs_template macro (eager bridge to from_decs)
Reflection on switching das to 64-bit arrays/tables — Borland-to-32-bit
nostalgia, why uint32_t (not size_t) was the right call, and the cost
of not breaking 8.5k tests (hence long_length / long_reserve shadow
names instead of a hard widen).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-all-over-again

site/blog: add "Its like dejavu all over again" post
Shared URLs containing [test] functions (the example pinned at
https://daslang.io/playground/index.html#z=...) compile-failed because
dastest/ was not in the WASM. Embed dastest/ next to daslib/ via
--embed-file, and add a "test" button alongside "run" that invokes
/dastest/dastest.das --test /main.das. The button auto-toggles based
on whether any open buffer declares a [test] annotation, hooked into
the existing autosave pipeline (one signal covers edit / switch / add
/ rename / delete / hash load / autosave restore).

Two daslib modules transitively require peg/peg (dasPEG, not linked
in the WASM build): daslib/spoof and its only consumer
daslib/linked_list. Exclude both from the playground embed so the
require fails cleanly as "module not found" rather than a confusing
peg/peg compile error inside spoof.das.

Repeated --embed-file / --exclude-file flags use SHELL: prefix.
Without it, CMake folds multiple flags of the same name into one
token and the trailing paths become positional args, silently
dropping the second directive.

Adds a "Tests" dropdown sample + two Playwright specs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Approach Z splice for the from_decs* eager-bridge family. Recognizes the
post-expansion `invoke($() { var res; for_each_archetype(...); return
res.to_sequence() })` shape and, for the bare-count case (no chain ops),
emits `invoke($() { var acc=0; for_each_archetype(req, erq) $(arch) {
acc += arch.size }; return acc })` — skips the per-entity walk entirely.

Slot in the planner cascade between plan_group_by and plan_zip. On any
shape mismatch (different bridge layout, chain ops present, terminator
other than bare count) the planner returns null and tier-2 cascade runs
the eager bridge unchanged — safe degradation.

Benchmarks (interpreter, 100K entities):
- m1 hand-written for_each_archetype + arch.size:     0 ns/entity
- m2 from_decs_template.count() (eager bridge):       60 ns/entity
- m3 _fold(from_decs_template.count()) splice:        0 ns/entity  ← splice fires
- regression check: tests/linq 1138/1138, tests/decs 239/239

Subsequent slices: chain-aware terminators (sum/min/max/long_count) via
nested _fold leveraging plan_zip; buffer terminators (to_array); early-exit
(first/any/contains). Each slice incremental, each safe-degrading.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Address Copilot review: clicking Run or Test before Emscripten finishes
loading daslang_static.{js,wasm} hits FS.writeFile when FS is still
undefined and throws a ReferenceError. window.onerror surfaces a
"please reload" message, but it's a confusing UX during the ~3-5s
load window and the underlying code path is unsafe.

- Add isWasmReady() centralizing the FS + Module.callMain check.
- Both buttons ship disabled in index.html.
- Module.onRuntimeInitialized re-enables them once WASM streams in.
- updateButtonStates() (replaces updateTestButtonState, kept under
  the old name for the existing playground-tabs.js autosave hook)
  gates Run on isWasmReady() and Test on isWasmReady() + the
  [test] annotation scan.
- runCode + runTests print "daslang is still loading, please wait..."
  on early invocation rather than crashing — defensive guard since
  the button could still be clicked via a stale focus or scripted
  call before onRuntimeInitialized fires.
- Updated syncMemFsFromState's doc comment to accurately describe
  both reasons it returns false.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds chain-op handling for from_decs* eager-bridge splice: peels
_where + single _select between the bridge and the terminator, emits
the unrolled for_each_archetype with a named-tuple bind so the user's
`_.fieldname` chain access resolves naturally to the bridge's iter
vars without per-element lambda overhead.

Approach:
- DecsBridgeShape now carries the cloned inner ExprFor + bridge's
  iter var names + user-facing field names from the push tuple.
- emit_decs_accumulator clones the bridge's for-loop, replaces the
  push body with `var tup = (n=iter, ...); <wrapped chain body>`.
- fold_linq_cond peels user lambdas with bound name = tup, so
  `_.fieldname` becomes `tup.fieldname` (real named-tuple access,
  no rewriting required).
- Terminators: count/long_count (postfix ++), sum (+= projection;
  accumulator typed from projection._type).
- _where + _select canonical chain order (after-select where /
  chained selects bail to tier-2 — defer to follow-up).

Benchmarks (100K entities, interpreter):
- m1 hand-written query:                            4 ns/entity
- m4 _fold(from_decs_template..._where..._select..sum()) BEFORE: 63
- m4 _fold(from_decs_template..._where..._select..sum()) AFTER:   6  ← 10.5× faster
- regression check: tests/linq 1146/1146, tests/decs 239/239

Tests: 5 new functional parity + AST shape gate. Covers
select+sum, where+count, where+select+sum, long_count, single-field
+ multi-field bridges.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot noted hasTestAnnotation() ran on every keystroke. Move the
window.updateTestButtonState() call inside the AUTOSAVE_DEBOUNCE_MS
setTimeout so rapid typing coalesces into one scan per 250ms instead
of one per keystroke. Same UX (button enables ~250ms after typing
`[test]`); zero added complexity.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- extract_decs_bridge now verifies the inner push() writes into the
  same `res` variable declared in stmt 0 + that push has exactly 2
  arguments. Closes false-positive surface where a user-written
  invoke could return `res.to_sequence()` but push into an unrelated
  buffer — splice would have emitted count/sum over the wrong data.
- test_linq_from_decs.das: replace the brittle `describe(expr)`
  substring needle `"for ( "` (sensitive to formatter whitespace
  changes) with a structural count_expr_for(body_expr) AST walk.
  Other needles (`to_sequence`, `for_each_archetype`, `.size`) stay
  as describe-substring since those are stable call/field names that
  the formatter doesn't reshape.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…test-button

playground: add Test button, embed dastest, gate on [test]
…roll-pattern3

linq_fold: plan_decs_unroll — splice from_decs* eager bridge into for_each_archetype
@pull pull Bot locked and limited conversation to collaborators May 20, 2026
@pull pull Bot added the ⤵️ pull label May 20, 2026
@pull pull Bot merged commit 68fe61d into forksnd:master May 20, 2026
@pull pull Bot had a problem deploying to github-pages May 20, 2026 08:58 Error
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant