[pull] master from GaijinEntertainment:master#1029
Merged
Conversation
Widen MSVC-only gates to Windows-wide where the code is actually
general Windows API, not MSVC-specific. clang-mingw64 (clang 22.1.4 +
lld + libc++) now builds a working daslang.exe end-to-end.
Most changes are mechanical `_MSC_VER` -> `_WIN32` for code that uses
plain `<windows.h>` API. The structural ones:
- CMakeLists.txt: `/wd4251 /wd4661 /wd4275` were gated on `if(WIN32)`
(MSVC-only flags; clang reads them as filenames). Narrowed to
`if(MSVC)`. Else-branch already does the right thing on non-MSVC
Windows (PIC is a no-op there per CMakeLists.txt:106-109).
- CMakeLists.txt: source files reference `ws2_32`, `mswsock`,
`advapi32`, `rpcrt4` via `#pragma comment(lib,...)`. MSVC honors
those; ld.lld in mingw mode does not always pick up .drectve
defaultlib directives. List them explicitly. Harmless on MSVC.
- platform.h DAS_API family: the MSVC-only gate left clang-mingw with
`__attribute__((visibility("default")))` -- ELF visibility, no-op
on PE/COFF. lld then defaulted to "export every global" and
overflowed the PE 16-bit ordinal table (108277 > 65535). Widening
the `__declspec(dllexport)` gate to `_WIN32` makes lld switch to
"export only tagged symbols", as intended on every Windows toolchain.
- platform.h `_aligned_*` allocator: widened gate so clang-mingw uses
`_aligned_malloc`/`_aligned_free`/`_aligned_msize` (the MS CRT
family mingw-w64 also ships) instead of POSIX `posix_memalign` /
`malloc_usable_size`. Also includes `<malloc.h>` on Windows.
- aot_builtin_fio.h: tripartite include split. `<io.h>`/`<direct.h>`
on every Windows toolchain; `<dirent.h>`/`<unistd.h>` on non-MSVC
(POSIX shims mingw-w64 ships); `<libgen.h>`/`<sys/mman.h>` on
non-Windows only.
- project_specific_crash_handler.cpp: kept `__try`/`__except` SEH
path under `_MSC_VER` (covers MSVC + clang-cl, which defines
`_MSC_VER`). Added a `_WIN32` branch for clang-mingw / gcc-mingw
using `VirtualQuery` to probe page protection -- safe to call from
a signal handler, no SEH needed.
- daScriptModule.h: `register_builtin_modules` is defined in
`src/builtin/modules.cpp` which ships in the compiler lib
(`DAS_CC_EXPORTS`), not the runtime lib (`DAS_EXPORTS`). Declaration
was tagged `DAS_API` instead of `DAS_CC_API`. MSVC tolerates the
mismatch; clang-mingw drops the dllimport tag and the symbol stays
unexported.
- sysos.cpp, performance_time.cpp, debug_break.cpp,
module_builtin_fio.cpp: ~20 individual `_MSC_VER` -> `_WIN32`
widenings for code calling plain Win32 API. The two
`#pragma warning(push/pop)` blocks in module_builtin_fio.cpp stay
under `_MSC_VER` (genuinely MSVC-only directive).
No CI coverage for mingw, so this is best-effort tested via:
bin/daslang.exe _smoke.das
which loads, parses gen2, compiles, executes hello + arithmetic +
for-loop -- all clean.
Two fixes:
- dasGLFW.main.cpp: `_MSC_VER` -> `_WIN32` so clang-mingw / gcc-mingw
reach the Win32-native-handle path (`glfwGetWin32Window`) instead of
the `#else` fallback. Also added the missing
`DAS_glfwGetNativeDisplay` stub to the fallback branch -- existing
latent bug that would link-fail on any platform that hits `#else`
(Haiku, future targets).
- CMakeLists.txt: GLFW v3.4 produces different import-lib filenames
on mingw than on MSVC. Split the Windows branch:
MSVC : lib/glfw3.lib (static), lib/glfw3dll.lib (import lib)
mingw: lib/libglfw3.a (static), lib/libglfw3dll.a (import lib)
The runtime .dll itself is named glfw3.dll on both, so the install
line stays unchanged.
Runtime caveat (NOT fixed in this commit): the mingw build places
glfw3.dll under bin/Release/ rather than directly in bin/. Loading
dasModuleGlfw.shared_module via LoadLibraryEx then fails because
glfw3.dll is not in any of the searched directories
(SEARCH_DLL_LOAD_DIR / SEARCH_APPLICATION_DIR / SEARCH_DEFAULT_DIRS).
Workaround: manually copy glfw3.dll into bin/ alongside daslang.exe,
or next to modules/dasGlfw/dasModuleGlfw.shared_module. A POST_BUILD
copy step is the right long-term fix.
Three Windows-branch fixes: - Split WIN32 into MSVC vs mingw. The MSVC path stays as-is (builds OpenSSL from source via `perl Configure VC-WIN64A` + nmake, which only work with MSVC). The new mingw path uses the system OpenSSL shipped by mingw-w64-clang-x86_64-openssl (or the gcc-mingw64 equivalent). - Auto-derive OPENSSL_ROOT_DIR from the C compiler path on mingw. FindOpenSSL.cmake on Windows doesn't look in the mingw sysroot by default, so even though clang64 ships libcrypto.dll.a + libssl.dll.a, find_package would find the headers (sees the version) but fail to locate the libraries. Setting OPENSSL_ROOT_DIR to <SYSROOT> (derived from <SYSROOT>/bin/clang.exe) makes it find both. - Use libhv_static.a (not libhv.a) on mingw and link winmm explicitly. On POSIX libhv renames hv_static's OUTPUT_NAME to "hv" (-> libhv.a); on mingw it keeps the original (-> libhv_static.a). libhv calls timeSetEvent/timeKillEvent from winmm.dll, which MSVC auto-pulls via #pragma comment(lib, "winmm") but ld.lld in mingw mode does not honor reliably. Verified by: bin/daslang.exe _smoke_hv.das -> "dashv + dashv_boost loaded" / exit 0 loading dashv (the native module) + dashv_boost.das (the daslib wrapper) confirms the libhv static lib + OpenSSL dynamic libs both link and load at runtime under clang-mingw64. Runtime caveat: dasModuleHV.shared_module depends on libssl-3-x64.dll + libcrypto-3-x64.dll from clang64. PATH=C:\msys64\clang64\bin during invocation suffices today; a POST_BUILD copy step (matching glfw3.dll TODO) would be cleaner.
Two cosmetic / ergonomic cleanups for the clang-mingw64 build, both
of which only fire on Windows-non-MSVC and leave MSVC + POSIX
behavior unchanged.
1. Double-lib prefix on shared and static library outputs.
Mingw's ADD_LIBRARY auto-prepends "lib" to the output filename.
When the target name already starts with "lib" -- which is the
case for every daslang SHARED lib (libDaScript / libDaScriptDyn /
libDaScript_runtime / libDaScriptDyn_runtime) and every static
module lib (libDasModuleAudio / libDasModuleGlfw / ...) -- this
produced ugly disk names like liblibDaScriptDyn.dll and
liblibDasModuleAudio.a.
Added STRIP_DOUBLE_LIB_PREFIX_ON_MINGW(${lib}) macro that sets
PREFIX "" + IMPORT_PREFIX "" when WIN32 AND NOT MSVC AND the
target name starts with "lib". Wired into both
SETUP_DAS_SHARED_LIBRARY and ADD_DAS_STATIC_LIBRARY so every
affected target gets the fix automatically.
Linux/macOS keep their conventional `lib` prefix (which they
need to be linkable as -lname).
2. glfw3.dll lands in the wrong directory on mingw.
The existing Windows POST_BUILD copy used "${EXECUTABLE_OUTPUT_PATH}/$<CONFIG>/glfw3.dll"
as the destination. That's correct for MSVC multi-config
(.exe sits in bin/Release/ too), but wrong for mingw single-config
where daslang.exe sits in bin/ directly -- the .dll was being
stranded in bin/Release/ and LoadLibraryEx couldn't find it.
Switched to a configure-time choice keyed off
CMAKE_CONFIGURATION_TYPES: multi-config keeps the per-config
subdir; single-config drops it. Avoided $<TARGET_FILE_DIR:daslang>
even though it would have been cleaner -- that creates a
dependency cycle because daslang already depends on
dasModuleGlfw transitively.
Verified end-to-end: after a clean rebuild, bin/ contains
daslang.exe + glfw3.dll + libDaScriptDyn.dll (no double-lib) side
by side, and a script that does `require glfw` loads cleanly with
no manual dll-copy step.
build-mingw/ is the clang-mingw64 out-of-tree build dir established earlier in this branch; _smoke*.das / _smoke*.cpp / _smoke*.o are ad-hoc repro scripts kept locally to verify each module. None of them belong in source control - gitignore them so the working tree stays clean while iterating on dasLLVM / dasClangBind.
The JIT-to-native-DLL path (daslang -jit, llvm_macro::write_dll) was
gated to MSVC + linux + macOS only. On clang-mingw64 daslang.exe, three
things had to change before the link succeeded:
1. The platform gate around create_shared_library / link_wasm widened
from `_MSC_VER` to `_WIN32`. Game consoles (xbox/durango) still get
the stub-return-true; mingw daslang now reaches the real link path.
2. Inside the Windows branch of get_real_lib_linker_paths and
create_shared_library, split MSVC from mingw:
MSVC (incl. clang-cl) keeps the existing flow — clang-cl.exe with
`-DLL`/-link/`-OUT:` syntax, .lib import libs, msvcrt.lib.
mingw uses clang.exe (mingw-flavored Unix driver) with
`-shared`/`-o` syntax, .dll.a import libs, no msvcrt.lib reference,
`-Wl,--no-as-needed` only for the linkWholeLib path. Outer
`\"...2>&1\"` quote wrap mirrors the MSVC branch — popen
-> cmd.exe strips one quote pair, inner per-arg quotes survive.
No rpath: Windows resolves DLLs via PATH + LoadLibrary search order
so the Linux branch's `-Wl,-rpath,$ORIGIN` escape is dropped.
3. New `host_jit_triple()` C builtin returns the daslang-host toolchain's
LLVM triple (x86_64-w64-windows-gnu on clang-mingw64; empty elsewhere
meaning "use LLVMGetDefaultTargetTriple"). daslib/llvm_jit_common.das
with_default_target_machine now prefers it when non-empty.
The motivation for #3: the prebuilt LLVM.dll shipped via dasLLVM's
FetchContent is built with MSVC clang-cl, so LLVMGetDefaultTargetTriple()
always returns `x86_64-pc-windows-msvc` regardless of what compiled
daslang.exe. On mingw, that triple emits MSVC-ABI .o files referencing
msvcrt marker symbols like `_fltused` that mingw's ld.lld + CRT cannot
satisfy. Forcing `x86_64-w64-windows-gnu` makes LLVM emit a
mingw-flavored .o with no MSVC-ism residue; the link against
libDaScriptDyn_runtime.dll.a then succeeds and the resulting DLL calls
into mingw daslang.exe via the same Win64 C ABI without CRT-mismatch
hazards.
Verified on clang-mingw64 (MSYS2 clang64, Clang 22.1.4):
- modules/dasLLVM/examples/{hello_jit,hello_llvm_jit,hello_llvm_jit_function}.das
all run with -jit and exit 0.
- dastest -jit on tests/jit: 19/19 passed.
- dastest -jit on tests/algorithm: 162/162 passed.
- DLL cache hit path (second run skips codegen) also works.
MSVC / linux / macOS paths unchanged in behavior; only the previously
empty mingw branch is filled in.
llvm_jit_common.das has carried a `LLVM_ENABLE_DIAGNOSTIC = false` flag and a 3-line dead branch since the 2023 LLVM-debug-info-wip commit (d68fdbb) — the flag is always false, and the function it would call, `set_context_diagnostics_to_log`, was never actually defined anywhere in the tree (`Grep` returns only the call site itself). The lint pass surfaces this as a 30341 unresolved-function error whenever a PR touches this file (lint compiles each changed .das standalone). Because no recent PR has edited llvm_jit_common.das, master CI has not surfaced it — but the clang-mingw64 JIT work in this branch touches the file and unmasks it. Removing the dead branch is the minimal fix: no behaviour change (branch never executed), no debug toggle preserved (the unimplemented hook was a half-formed feature, not a functional path). If the diagnostic-logging idea is wanted in the future, it should land alongside its actual implementation rather than as a stranded call.
Four fixes, one commit:
1. project_specific_crash_handler.cpp safe_read (mingw):
- reject PAGE_GUARD / PAGE_NOACCESS — the old `mbi.Protect & 0xFF`
mask dropped the high-byte PAGE_GUARD flag, so guard pages were
classified readable and reading them would raise
EXCEPTION_GUARD_PAGE — defeating the entire point of safe_read.
- validate that [addr, addr+size) is fully covered by readable
committed memory, requerying for the next region when the read
spans a boundary. The old code ignored `size` and could fault on
a 4/8-byte read near end-of-region by crossing into an unmapped
or PAGE_GUARD page.
2. module_jit.cpp host_jit_triple — derive arch from preprocessor
macros instead of hardcoding x86_64. clang32 (i686), clang64
(x86_64), clangarm64 (aarch64), clangarm32 (armv7) all share the
`-w64-windows-gnu` vendor/os/env tail but differ on arch.
Hardcoding x86_64 would have made LLVM emit wrong-arch .o files
on non-x86_64 mingw hosts. Unknown arch falls back to LLVM
default and the user can still override via customLinker.
3. debug_break.cpp — use WinAPI DebugBreak() on mingw, keep the
__debugbreak() intrinsic only for MSVC (incl. clang-cl).
__debugbreak isn't reliably exposed on gcc-mingw without
<intrin.h> and the right configuration; DebugBreak from kernel32
is the portable Windows API that works on every Windows compiler
at the cost of one extra call frame (negligible vs the win of
mingw-safe builds).
4. module_jit.cpp create_shared_library — drop the fixed
`char cmd[1024]` stack buffer in favor of fmt::format → string.
Long paths (deep build roots, spaces, long extraLinkerArgs) can
plausibly exceed 1024 bytes when combined with the format-string
constants and the runtime/compiler library paths — the old code
would silently corrupt the stack. fmt::format allocates on the
heap so growth is unbounded; matches the pattern link_wasm
already uses in the same file.
Verified on clang-mingw64 (Clang 22.1.4):
- daslang rebuilds clean
- hello_jit.das exit=0, JIT'd add(11,12) returns 23
build_decs_inner_for_pruned previously bailed to the unpruned bind path
whenever the body had a whole-var ref to decs_tup (`decs_lst := decs_tup`,
`push_clone(buf, decs_tup)`, `pred(decs_tup)`, etc) — forcing a per-iter
`var decs_tup = (n1=iter1, ...)` wrap even when slot pruning was infeasible
anyway.
DecsTupWholeRewriter rewrites each whole-var ref into a freshly synthesized
`(userName1=iter1, ...)` literal — exactly what build_decs_tup_bind would
produce, but inlined at each use site. After rewrite the body contains only
`decs_tup.field` refs (flattenable) plus iter-var refs in the synthesized
literals (picked up by the usage scanner). The existing flatten + bind-elision
path then unlocks for the bare-to-array / whole-element-terminator shapes,
saving the per-iteration named-tuple construction.
Per-element body before:
{
var decs_tup = (id=car_id, name=car_name, ...);
if (decs_tup.price > 500) {
decs_lst = decs_tup
}
}
After:
if (car_price > 500) {
decs_lst = (id=car_id, name=car_name, price=car_price, ...)
}
100K-row m4 INTERP bench wins (vs master after PR #2837):
sort_first 23.9 → 13.4 (Δ-10.5, BEATS m3f 41.3)
sort_take 31.0 → 20.1 (Δ-10.9, +2 vs m3f 22.7)
order_take_desc 30.9 → 20.0 (Δ-10.9, +2 vs m3f 22.3)
select_where_order_take 24.7 → 14.9 (Δ-9.8, BEATS m3f 21.4)
groupby_first 29.9 → 19.2 (Δ-10.7, +0.6 vs m3f 18.6)
single_match 14.8 → 5.4 (Δ-9.4, +2.5 vs m3f 2.9)
last_match 17.2 → 14.0 (Δ-3.2, +8.2 residual)
select_where 23.2 → 18.4 (Δ-4.8, +7.3 residual)
bare_order_where 135.6 → 130.8 (Δ-4.8)
10 lanes improved, 0 regressions.
Verification:
- 1390/1390 linq + 245/245 decs + 782/782 dasSQLITE INTERP + AOT green
- 1390/1390 linq JIT green
- test_wave4_unpruned_bare_to_array_splice_shape extended: now asserts
describe_count(body_expr, "decs_tup") == 0 (bind elided despite the
push_clone(decs_tup) whole-ref that originally forced unpruned bind)
Closes Session 2 of the m4 close-out roadmap and carries over wins to the
Session 1 (sort/order family) and Session 3 (groupby_first) targets.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…arly-exit-terminator-investigation linq_fold: elide decs_tup bind via whole-ref → make-tuple rewriter
…64-support Support clang-mingw64 toolchain (core + 7 modules + JIT)
PR #2838 enabled the clang-mingw64 toolchain on Windows but added no CI coverage; the mingw path in src/hal/debug_break.cpp, src/hal/project_specific_crash_handler.cpp, and src/builtin/module_jit.cpp would silently rot on the next Windows-touching change. Adds a separate top-level build_windows_mingw job sharing the windows-latest-fat runner pool with the MSVC matrix. Steps mirror the MSVC Windows test sequence: build (Ninja Release), interpreter sweep, JIT sweep, ctest small, test_aot. dasClangBind stays disabled here (libclang 16.0.6 strict-version pin unavailable in the msys2 clang64 sysroot); regen against Clang 22 is tracked separately. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Symmetric mirror of PR #2837's plan_decs_order_family fix, applied to the array-side splice. When the key is inline-able, `_order_by + first` splices to a per-walk streaming-min state (single `best` + `seen` flag) instead of dispatching through `min_by(arr, keyLambda)`. `_order_by + take(N)` splices to a bounded-heap walk instead of materializing then `top_n_by`. Two new emit branches in plan_order_family: **Streaming-min** (`firstName != "" && inlineCmp != null`): invoke($(source : srcParamType) : elemType { var order_best = default<elemType> var order_seen = false for (it in source) { if (!order_seen) { order_best := it; order_seen = true } elif (LESS(it, order_best)) { order_best := it } } panic-if-not-seen (first) OR return-default-if-not-seen (first_or_default) return order_best }, top) Avoids the per-element `invoke(keyLambda, x)` cost in min_by_impl's `key(x)` calls. **Bounded-heap** (`takeExpr != null && inlineCmp != null && firstName == ""`): invoke($(source : srcParamType) : array<elemType> { let n = takeExpr var order_buf : array<elemType> return <- order_buf if (n <= 0) for (it in source) { if (length(order_buf) < n) { order_buf |> push_clone(it) spliced_push_heap(order_buf, cmp) } elif (LESS(it, order_buf[0])) { spliced_pop_heap(order_buf, cmp) order_buf[len-1] := it spliced_push_heap(order_buf, cmp) } } order_inplace(order_buf, cmp) return <- order_buf }, top) Avoids materializing the full filtered set in a prefilter buffer before top_n_by. Both branches handle where_/no-where uniformly via optional `if (whereCond)` wrap around perElement, like the decs equivalent. ## Latent bug fix in make_inline_less_call PR #2837's make_inline_less_call had a latent bug: when the key body is ExprVar at the root (e.g. `_order_by(_)` — identity key body == lambda arg), `apply_template`'s visitor would substitute the root via visitExprVar's return value, but the helper ignored the return value of apply_template — leaving the caller's `b1`/`b2` pointing at the un-substituted clone. The bug never surfaced in #2837 because every decs test had a field-access key (`_.price`), where substitution happens on the ExprField's child, not the root. Surfaced here when the array-side fix exposed it via the broad set of `_order_by(_)` tests in test_linq_fold.das. Fix: capture and reassign `b1 = apply_template(r1, b1.at, b1)`. ## Bench (100K rows, INTERP, m3f deltas) sort_first_m3f 41.1 → 11.0 (-30.1, was 27.8 SLOWER than m4) select_where_order_take_m3f 21.4 → 12.1 (-9.3, now BEATS m4 by 2.8) sort_take_m3f 22.4 → 15.9 (-6.5) order_take_desc_m3f 22.4 → 16.0 (-6.4) All four m3f order-family lanes were slower than m4 by 2-28 ns/op before this PR; now m3f and m4 are within ±5 ns/op across the board (m4 still slightly faster on take by the archetype/streaming-walk advantage, m3f slightly faster on first thanks to direct array indexing). ## Verification - 1390/1390 linq + 245/245 decs + 782/782 dasSQLITE INTERP + AOT + JIT green - 7 AST shape tests updated: top_n_by_with_cmp / min_by / max_by → streaming-min (less-call) / bounded-heap (spliced_push_heap + spliced_pop_heap + order_inplace) - CI-style lint clean on both touched files Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…rder-family-streaming-min-port linq_fold: port streaming-min / bounded-heap to plan_order_family
dasModuleHV.shared_module on mingw transitively depends on libssl-3-x64.dll + libcrypto-3-x64.dll from msys2's clang64 sysroot. When daslang.exe runs from a cmd.exe context whose %PATH% does not include <msys64>/clang64/bin (e.g. ninja-spawned cmd.exe during build-time AOT codegen), LoadLibrary cannot resolve these DLLs and the .das_module initializer's register_dynamic_module call silently fails — "require dashv" then surfaces as 20605 missing-prerequisite. Mirrors the glfw3.dll POST_BUILD pattern from #2838 task #15: glob the openssl DLLs and copy them next to daslang.exe (under EXECUTABLE_OUTPUT_PATH). The glob handles version suffix bumps without CMake churn (libssl-3-x64.dll today, libssl-4-x64.dll in a future openssl major). MSVC has its own openssl build path (no-shared above) so the copy is gated on NOT MSVC. Also: fix CI workflow flag name DAS_CLANGBIND_DISABLED -> DAS_CLANG_BIND_DISABLED. The typo'd flag was a no-op since dasClangBind defaults to ON in the option declaration; functional impact zero but the flag now actually drives the option. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DAS_LLVM_DISABLED defaults to ON in the CMakeLists.txt option. Without
an explicit -DDAS_LLVM_DISABLED=OFF, dasLLVM was being skipped, LLVM.dll
never got fetched via FetchContent, and the JIT sweep then failed with
'can't load library LLVM.dll' for every dasLLVM/bindings/llvm_func.das
[extern] declaration. Mirror the MSVC matrix entries that pass
-DDAS_LLVM_DISABLED=${{ env.das_llvm_disabled }} (where env value is OFF).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The flag was carried over from the linux branch's create_shared_library in PR #2838 but has no effect on PE/COFF: Windows linkers always record every listed library in the import table — there is no lazy-bind / DT_NEEDED concept to suppress. Worse, ld.lld on newer mingw sysroots (msys2 clang64 with clang 22.1.4 as of CI provisioning) rejects --no-as-needed as an unknown argument, breaking every daslang.exe -exe invocation that links a compilerLibrary (dascov, dastest, daspkg, mcp, aot, detect-dupe). Older clangs / GNU ld silently ignored the flag, which is why this only surfaced when the Windows mingw CI worker came online (PR #2840) and not during PR #2838's local validation. Behavior on Boris's local mingw is unchanged: the linker was already linking the compilerLibrary unconditionally; --no-as-needed was a no-op. Verified by rebuilding daslang.exe and running `daslang.exe -exe -output ... utils/dascov/main.das` — exe links successfully. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The WASM build step has been silently failing when emscripten / clang
hiccups: continue-on-error: true paints the step green, the staging
step's file-exists guard skips the real /playground/ copy, and we ship
site/playground/placeholder.html ("Runtime rebuild in progress.").
Master shows green; the live playground is the fallback page.
Most recent example: pages run 26345453541 (commit 1c8ff91, 2026-05-23
22:40) — em++ bus-errored in clang::Lexer::SkipBlockComment while
compiling utils/dasFormatter/ds_parser.cpp:6484. Four prior runs today
on the same emsdk pin (5.0.3, resolved to LLVM commit e5927fec from
2026-03-13) built ds_parser.cpp fine, so this is an intermittent
preprocessor flake in clang 23.0.0git rather than a deterministic bug.
We want the deploy to fail red so the next flake is visible immediately
rather than re-running quietly with the placeholder for hours.
Also retire the misleading "5.0.7 crashes, 5.0.3 known-good" pin
comment — 5.0.3 itself just crashed, and the pin is really about staying
close enough to the LLVM main snapshot family that the rest of the code
compiles. Note the family characteristic (clang 23.0.0git preview) and
the next-downgrade target (4.0.23, pre-LLVM-22.1.0 main snapshot) for
future Claude / human triage.
The placeholder-staging else-branch survives as defense-in-depth: still
useful if a future workflow change re-introduces continue-on-error or
the artifacts go missing despite a green build, since
actions/deploy-pages publishes _site as a complete snapshot.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trims each bench to three lanes (SQL / Array / Decs == m1 / m3f / m4) by dropping the m3 eager-linq lane that the splice ladder rendered redundant; also drops sort_take's legacy m3_topn_array / m3_topn_iter algorithm-comparison wrappers. Back-fills the SQL lane for join_count (sqlite_linq's _join+_select accepts the chain when the projection is a named tuple — the existing "db handle wiring" comment was wrong about the real blocker, which was the positional-tuple shape). Refreshes the 5 keep-out comments (distinct_by_count, groupby_first, groupby_select_sum, take_count_filtered, take_sum_aggregate) with dated TODO markers quoting the actual sqlite_linq error each chain produces, and the 2 by-design absences (take_*_aggregate LIMIT-on-aggregate semantics, zip_dot_product no relational analog). The join_count decs (m4) lane stays absent with a TODO referencing plan_join in linq_fold.das. Adds benchmarks/sql/results.md with both INTERP and JIT tables (generated 2026-05-23 from master 1c8ff91) plus per-gap footnotes that quote each ".das" source comment verbatim so the file is the single source of truth for "why is this cell empty." Updates benchmarks/README.md sql/ section with a per-file table. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds tutorials/language/55_linq_decs.das (runnable, self-contained [export] def main) covering from_decs_template, the _fold splice over decs entities, and three canonical chain shapes (where+count, order_by+first streaming-min, group_by+select). Paired RST at doc/source/reference/tutorials/55_linq_decs.rst with the standard label / seealso / download blocks; added to the language toctree after 54_glob. Adds doc/source/reference/linq_fold_patterns.rst — a lookup-oriented catalog of every chain shape that _fold recognizes, with the splice arm (plan_*/emit_* in daslib/linq_fold.das) each one fires. Organized by source type (array vs decs vs zip) plus a "what falls back" tail listing the chains that drop to fold_linq_default. Linked from the reference toctree (doc/source/reference/index.rst). Links the new patterns page from the linq_fold module docs by adding a "See also" block to doc/source/stdlib/handmade/module-linq_fold.rst (the handmade source that feeds the generated linq_fold.rst). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
to_cpp_float was using "{:e}f" which defaults to 6 digits after the
decimal point — 7 significant figures total. IEEE 754 single requires
FLT_DECIMAL_DIG=9 significant digits to guarantee a text→float→text→float
roundtrip is bit-identical. With only 7 digits, AOT-emitted float
literals can parse back to a value 1 ULP off from the runtime-computed
constant, shifting boundary results in the AOT'd C++ relative to the
interpreter/JIT.
Surfaced during PR #2840 diagnosis: tracing a tests/language/
random_numbers.das AOT failure (which turned out to have a separate
root cause — see the -fwrapv commit) revealed that 1.0f/32767.0f was
being serialized as "3.051851e-05f" instead of "3.05185094e-05f".
The roundtrip happened to land on the same float here, but the
precision shortfall is real and worth fixing standalone.
to_cpp_double already uses "{:.17e}" (DBL_DECIMAL_DIG=17), so this
brings the float emitter in line with its double counterpart.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
daslang's signed integer arithmetic is defined to wrap on overflow, but AOT lowers it to plain C++ int*int / int+int which is UB at the C++ level. Modern clangs exploit this UB aggressively. CMakeCommon.txt already worked around it for AppleClang 21+; the same exploit now fires under mingw clang 22.1.4 -O2, surfaced by PR #2840's new Windows mingw CI worker: daslib/random.das random_int: seed.x = 214013 * seed.x + 2531011 // signed overflow return (seed.x >> 16) & LCG_RAND_MAX // mathematically <= 32767 With -O2 + UB exploitation, the optimizer drops the trailing `& 0x7FFF` mask reasoning and returns values up to 65535, so float(r) * (1.0/32767) exceeds 1.0 and tests/language/random_numbers.das's "f < 1.0" assertion flips. Confirmed locally: -fwrapv added → 13/13 pass, full AOT sweep (tests/) green at 8620/8626. Promotes the existing Apple-scoped ADD_COMPILE_OPTIONS(-fwrapv) to a unified gate near the top of SETUP_COMPILER, applied to GNU, Clang (non-MSVC frontend), and AppleClang. clang-cl and MSVC are excluded — clang-cl rejects the flag, MSVC defaults to wrap-around in practice and doesn't have the equivalent option. Tiny perf cost: x86 already wraps in hardware, the flag only prevents the optimizer from assuming no overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop `from_decs` (runtime-list form) from the 55_linq_decs tutorial header bullets and RST index — tutorial body only demonstrates `from_decs_template`; mention `from_decs` in the RST intro as explicitly out of scope. - Fix benchmarks/README.md sql/ lane table: the Decs lane uses `from_decs_template(type<DecsCar>)`, not `type<Car>` — `DecsCar` is the `[decs_template]` fixture in `_common.das`. - Rewrite linq_fold_patterns.rst dispatch-order section to match the actual `LinqFold.visit` sequence (12 steps, decs/array variants interleaved per source-type-first matching), instead of the abstract "Decs source → Zip → Array" grouping that didn't match the code. - linq_fold_patterns.rst Array-source `count` row: replace "Per-archetype counter" (decs terminology) with "Single counter, no allocation; one pass over the array." - benchmarks/sql/results.md: switch the embedded `_sql` error messages from single-backtick inline code (which can't contain backticks) to fenced code blocks. GitHub markdown rendering now shows the error text verbatim. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…-pin-and-fail-loud pages.yml: drop continue-on-error on WASM build step
…gw-ci-job ci: add Windows clang-mingw64 worker
…leanup-tutorials-patterns-doc benchmarks/sql cleanup + linq_decs tutorial + linq-fold patterns reference
5.0.3 ships clang 23.0.0git (LLVM main snapshot from 2026-03-13), and that preview compiler has now failed on utils/dasFormatter/ds_parser.cpp two separate ways on the same runner SHA: • Pages run 26345453541 (2026-05-23 22:40, master 1c8ff91): em++ bus-errored in clang::Lexer::SkipBlockComment at line 6484, code=135 / SIGBUS. • Pages run 26348244284 (2026-05-24 01:11, master bfb04c7): em++ rejected ds_parser.hpp with "unterminated conditional directive" at line 38 (YY_DAS_YY_DS_PARSER_HPP_INCLUDED guard) and line 102 (DAS_YYTOKENTYPE) — both have matching #endif on disk. Native clang in step 1 of the SAME run compiled the same file fine 10 minutes earlier, so the file isn't corrupt — clang-23's preprocessor is. Since #2842 dropped continue-on-error: true on the WASM step, master's pages deploy is now red. The live playground is whatever the last green deploy staged (the placeholder page) and will stay that way until the WASM build succeeds again. 4.0.23 is the last 4.x release before the 5.0.x family cutover (2026-01-10), pinning LLVM main from 2026-01-09 — pre-LLVM-22.1.0- release, roughly clang 22.0.0git. That's months older than the preview clang 23 snapshot 5.0.3 was on, so it doesn't carry the preprocessor regression, and it's the closest emsdk we have to dasLLVM's 22.1.5 pin. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two new chain shapes lower in `_sql(...)`: - `|> long_count()` → `SELECT COUNT(*)` with an int64 column binding, symmetric with `|> count()` (int). Also recognised in the grouped projection arm so `_select((..., N = _._1 |> long_count()))` widens the per-group counter to int64. - `|> _distinct_by(_.col) |> count()` (and the long_count variant) → `SELECT COUNT(DISTINCT "col")`. Receiver-pinned to ExprVar so `u.opt.X` keys reject loudly instead of silently emitting the wrong COUNT. `peel_count_terminal` factors the shared count/long_count peel so both share the distinct-by recognition path. Test surface: - `tests/dasSQLITE/test_31_long_count_distinct_by_canary.das` — 8 new tests covering SQL text emission + runtime values for both terminals, plus the int64-grouped projection. - `failed_sql_macro.das` case 23 — computed `_distinct_by` key (e.g. `_.Price % 100`) rejects with a precise diagnostic. Bench corpus: - `benchmarks/sql/distinct_by_count.das` — m1 lane backfilled (`_sql(... |> _distinct_by(_.brand) |> count())`); the dated TODO comment is removed. - `benchmarks/sql/long_count_aggregate.das` — m1 lane now actually calls `long_count()` instead of `count()`; the int64 accept matches m3f/m4. Latent bench-bug fixed. - `benchmarks/sql/results.md` — refreshed INTERP + JIT tables; commit header bumped; the `distinct_by_count SQL` bullet in "Notes on missing lanes" is removed now that the lane has a number. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…-downgrade-4-0-23 pages.yml: downgrade emsdk pin 5.0.3 → 4.0.23
…-distinct-by-count-and-long-count sqlite_linq: add long_count + _distinct_by dispatch arms
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 : )