Skip to content

[pull] master from GaijinEntertainment:master#1009

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

[pull] master from GaijinEntertainment:master#1009
pull[bot] merged 14 commits into
forksnd:masterfrom
GaijinEntertainment:master

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented May 18, 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 : )

aleksisch and others added 14 commits May 18, 2026 18:41
unsafe should mark only parts of code that require unsafe.
Three issues in include/das_hash_map/das_hash_map.h:

(1) 10 redundant #includes. The header is only ever pulled via
das_config.h, which already includes <vector>, <utility>, <functional>,
<string>, <type_traits>, <initializer_list> etc. before reaching us, so
the local includes were dead weight in every TU. Dropped.

(2) `using std::vector;` / `pair;` / `hash;` / `equal_to;` / `move;` /
`forward;` / `forward_iterator_tag;` block. Harmless in the default
build, but actively wrong in the EASTL config (das_config_eastl does
`using namespace eastl;`): those using-declarations would shadow
eastl::* with std::* and defeat the abstraction. Switched all
references to das:: prefix, which routes to std:: or eastl:: depending
on the active using-directive in the config.

(3) `throw std::out_of_range(...)` in at(). EASTL doesn't define
eastl::out_of_range (it uses std::out_of_range directly throughout its
own headers), and on libstdc++ <stdexcept> isn't transitively pulled by
das_config.h's includes — CI was failing on this on both Linux jobs and
the EASTL job. More importantly, games embedding daslang frequently
disable C++ exceptions entirely, so a raw `throw` in a low-level header
is the wrong primitive regardless. Switched to das::das_throw, which is
daslang's own setjmp/longjmp panic mechanism. Required widening
das_throw to be declared/defined unconditionally (it was previously
gated on DAS_ENABLE_EXCEPTIONS=0):

  - das_config.h, das_config_eastl/das_config.h, include_fmt.h: move
    the `void das_throw(const char *)` declaration out of the
    DAS_ENABLE_EXCEPTIONS=0 #if. FMT_THROW macro stays conditional.
  - runtime_string.cpp: add an implementation for the
    DAS_ENABLE_EXCEPTIONS=1 case that routes through dasException, so
    catch(dasException&) handlers in simulate_exceptions.cpp pick up
    C++-side panics from low-level headers too.

Verified:
- Default libc++/std: full Release build clean, ctest 34/34 pass
- EASTL (das_config_eastl + cloned EASTL/EABase): daslang target builds
  clean, binary runs and reports version

.gitignore: hide the local-verify checkout dirs (eastl/, eabase/,
build_eastl/).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…p-prune-includes

das_hash_map: drop redundant includes, fix EASTL/no-exception support
Eight blind-mouse cache cards accumulated across PRs #2712/#2714 (linq_fold
work) and #2716 (das_hash_map cleanup):

- das-namespace-abstraction-std-vs-eastl-swap — how das:: routes to std::
  or eastl:: via `namespace das { using namespace ...; }` in the two
  configs; why explicit `using std::vector` blocks inside `namespace das`
  are harmful for EASTL builds.
- das-throw-universal-panic-primitive-low-level-headers — das_throw is
  daslang's setjmp/longjmp panic primitive; embedded games disable C++
  exceptions, so raw `throw` is the wrong primitive in low-level headers.
  Captures the unconditional-declaration change from #2716.
- daslang-eastl-config-local-build-setup — clone EASTL + EABase
  separately (no longer submoduled), cmake invocation, what to test, the
  common `error: no member named 'X' in namespace 'das'` failure mode.
- libstdcpp-vs-libcpp-transitive-stdexcept-asymmetry — why CI failed on
  Linux only on the first push of #2716; libstdc++ doesn't pull
  <stdexcept> transitively via <vector>/<string>, libc++ does.
- github-pr-body-angle-brackets-stripped-in-backticks — GitHub strips
  <vector> inside backticks in PR body markdown; use `&lt;X&gt;`
  entities and re-read after every update.
- how-do-i-dedupe-a-select-projection-... — Phase 3d projection
  double-eval root cause and PR #2714 fix.
- inlining-a-sort-comparator-key-body-... — both forms evaluate the key
  body twice per comparison; sort-cmp inlining saves dispatch only.
- qmacro-multi-arg-block-declaration-... — parser dup-check fires on
  `MACRO TAG` placeholder name before macro substitution can rename;
  PR #2714 parser fix details.

skills/das_macros.md: add a section about pre-setting `_type` on emitted
ExprVar (and similar nodes) before they flow into typed positions —
captures the 30165 trap from PR #2714's try_make_inline_cmp work, since
Expression::clone deep-copies _type faithfully and the typer's
generic-instantiation pass runs before local-variable-resolution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-and-macros-skill

docs: mouse cards from PRs #2712/#2714/#2716 + ExprVar._type pre-set guidance
Forbid broad unsafe. If unsafe used it should be minimal possible.
unsafe { ... unsafe { ...} ... } should be forbidden.
Modified files should pass linter checks.
…6 in-process tools to subprocess

Adds a parallel `project_root` argument to every MCP tool that currently takes
`project` (a .das_project file path). `project_root` mirrors daslang's
`-project_root <dir>` CLI flag, which scans `<dir>/modules/*/.das_module` for
daspkg-style discovery (require_dynamic_modules in src/ast/dyn_modules.cpp).

Motivation

External daslang modules like dasImgui at D:/DASPKG/dasImgui can now be
linted/compiled/searched from the MCP using a dummy-root junction
(D:/IMGUI_DEMO/modules/dasImgui -> D:/DASPKG/dasImgui) without
`daspkg install`. Before this PR, every MCP call against a dasImgui consumer
file errored with `missing prerequisite 'imgui'` and the workaround was
falling back to a shell `daslang.exe -project_root D:/IMGUI_DEMO ...` invocation.

Architecture

The plumbing has two halves:

1. Subprocess argv injection (utils/mcp/tools/common.das `run_mcp_subtool`):
   when a caller passes `project_root`, the spawned argv becomes
   `daslang.exe -project_root <P> <subtool.das> -- <args>` so the subprocess
   fires `require_dynamic_modules` at startup. The subtool itself doesn't
   change -- its `compile_file()` picks up registrations from the now-populated
   process-global registry. Same approach for `tools/live.das` `do_live_launch`
   (append `-project_root` to daslang-live's script_args) and the direct
   daslang.exe spawns in `run_test.das`, `run_script.das`, `eval_expression.das`.

2. Refactor 6 in-process tools to subprocess: `program_log`, `list_requires`,
   `find_references`, `ast_dump`, `type_of`, `goto_definition` used to call
   `compile_program()` / `compile_only()` directly in the MCP server's own
   daslang context. The bodies move to new `utils/mcp/subtools/<name>.das`
   files; the `tools/<name>.das` wrappers collapse to thin
   `run_mcp_subtool(...)` calls. Two payoffs:
   - The `-project_root` flag injected by run_mcp_subtool now reaches these
     6 tools' compile_file via the daslang.exe startup path.
   - The MCP server's own daslang context never loads shared modules from
     user code (dasModuleImgui, dasModulePugixml, etc.). Once a shared
     module loads, daslang cannot unload it -- so the previous architecture
     held DLLs open for the lifetime of the MCP server. Iterating on a
     binding's C++ side now needs no MCP restart; the next subtool spawn
     loads + drops the rebuilt DLL on its own process lifecycle.

Schema changes (utils/mcp/protocol.das)

- New `PROJECT_ROOT_PROP` constant + `project_root` field added to
  `make_file_tool()` and to every `make_tool(...)` call that already had
  `project`. 17 tools updated.
- `handle_tools_call()` extracts `project_root = get_string_arg(args, "project_root")`.
- `run_tool()` and `dispatch_tool()` take `project_root` as a top-level param
  (parallel to existing `project`), forwarded to every `do_*` that needs it.

Files

- utils/mcp/protocol.das -- schema + dispatch
- utils/mcp/tools/common.das -- `run_mcp_subtool` argv injection
- utils/mcp/tools/{compile_check,list_functions,list_types,run_test,run_script,
  eval_expression,describe_type,find_symbol,list_module_api,aot,lint_tool,
  live}.das -- `project_root` param threaded through
- utils/mcp/tools/{program_log,list_requires,find_references,ast_dump,
  type_of,goto_definition}.das -- refactored from in-process to subprocess
- utils/mcp/subtools/{program_log,list_requires,find_references,ast_dump,
  type_of,goto_definition}.das -- NEW, lifted in-process bodies
- skills/external_module_debugging.md -- NEW, workflow recipe for the
  `<DummyRoot>/modules/<your-module>` junction pattern
- CLAUDE.md -- skill table entry

Validated locally

- `daslang.exe -dry-run utils/mcp/main.das` compiles clean.
- Each new subtool compiles individually.
- Subtool smoke tests via daslang.exe -project_root D:/IMGUI_DEMO against
  dasImgui files:
  - subtools/list_requires.das returns full 40-entry require chain with
    every imgui/* resolving through D:/IMGUI_DEMO/modules/dasImgui/...
  - subtools/program_log.das returns the post-compile program text
  - subtools/type_of.das returns the type at cursor position
- MCP server schema and dispatch verified by full main.das compile.

Tool-registration changes (new arg in schema) require a Claude Code restart
to pick up the new `tools/list` response -- a plain MCP server bounce isn't
enough.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Follow-up to 26e1407 (project_root refactor). utils/mcp/test_tools.das
had no coverage for the new project_root arg path -- 17 tool signatures
gained the arg, 0 tests exercised it. This commit adds ~26 tests across
four tiers + a Linux CI step + one real bug fix surfaced during the
testing process.

Tier 1 -- project_root end-to-end against a checked-in daspkg-style fixture

  utils/mcp/tests/_pretend_root/
    consumer.das                 -- require pretend_mod/greet; calls hello()
    modules/pretend_mod/
      .das_module                -- register_native_path("pretend_mod",
                                                        "greet",
                                                        "{project_path}/greet.das")
      greet.das                  -- module greet shared public

18 [test] blocks: 17 paired sub-asserts (each tool fails without
project_root with "missing prerequisite 'pretend_mod'", succeeds with it),
plus 1 negative that pins current daslang behavior on nonexistent
project_root (silently no-ops dyn-modules scan, consumer compile still
fails with missing-prereq). Tools covered: compile_check, lint, aot,
list_functions, list_types, list_requires, program_log, ast_dump,
find_references, goto_definition, type_of, find_symbol, list_module_api,
describe_type, eval_expression, run_script, run_test.

The fixture lives under utils/**/modules/ which is gitignored for daspkg
install dirs -- added a .gitignore !exception for this one fixture path.

Tier 2 -- do_program_log smoke (2 tests)

Pre-existing gap (no program_log tests existed). Locks behavior after the
in-process to subprocess refactor.

Tier 3 -- build_subtool_argv unit tests (3 tests)

Extracted from run_mcp_subtool's inline argv builder into a testable
helper. Pins the load-bearing invariant: -project_root <P> MUST be
inserted BEFORE the subtool script path. Otherwise daslang treats it as
a positional .das file to load, silently breaking dyn-module discovery.

Tier 4a -- build_live_script_args unit tests (5 tests)

Extracted from do_live_launch's inline script_args composition. Locks the
flag ordering (project_root prepended LAST = leftmost in output) and the
Windows slash-replace path.

Real bug fix in do_live_launch surfaced during the Tier 4b attempt:
relative paths for file, project, project_root weren't surviving
daslang-live's -cwd chdir (utils/daslang-live/main.cpp:696-707 chdir's
to script's folder BEFORE require_dynamic_modules at line 730). Fix:
resolve_path() on all three before composing args.

Tier 4b deferred -- daslang-live has no -port flag (port is hardcoded) and
acquire_single_instance blocks parallel spawns, so reliable in-suite
e2e spawn testing isn't viable without an upstream daslang-live change.

Tier 5 -- CI wiring

extended_checks.yml gets a new "Test MCP tools" step after "Test ser/deser",
Linux-only (mirrors the gating pattern used by other extended steps).
~30s wall-clock add to a job that already runs ~8-10 min.

Pre-existing test breakage fixed (silently broken by the 26e1407
signature changes, no CI to catch it):

  - do_list_requires / do_compile_check / do_run_test: added "" for
    project_root in the positional slot
  - do_find_references x 10: added missing no_opt_str arg
  - do_find_symbol, do_goto_definition: added project_root insertion
  - run_mcp_subtool timeout: switched 0.5 positional to [timeout_sec=0.5]
    since project_root now occupies the third positional slot

Verified: 346 tests pass locally, all changed .das files lint-clean and
formatted.

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

MCP: project_root threading + 26-test coverage + do_live_launch path fix
…inx/CI

16 cards from dasImgui imgui_demo port work (PR #47, #48) and the MCP
project_root refactor (PR #2718):

MCP project_root (new this session):
- daslang-live-cwd-flag-chdir-before-require-dynamic-modules-relative-paths-break
- daslang-live-no-port-flag-single-instance-lock-e2e-spawn-tests-infeasible
- daslang-deduce-project-root-auto-fallback-from-script-dir-affects-test-design
- my-daspkg-package-s-register-native-path-module-isn-t-found... (updated:
  MCP project_root now supported as of 2026-05-18, replaces stale "MCP can't
  resolve dynamic modules" paragraph)

dasImgui drawlist + widgets (PR #47 / #48):
- dasimgui-drawlist-prim-macro-path-key-only-no-state-global-render-only-rail
- dasimgui-hover-target-widget-variant-pattern-color-button-hover-selectable-hover
- dasimgui-imguisizeconstraints-lambda-needs-module-scope-lifetime-not-stack-local
- dasimgui-integration-tests-use-examples-features-recordings-use-examples-tutorial
- how-do-i-draw-on-the-imgui-foreground-or-window-drawlist-from-dasimgui-code
  (updated: now uses with_window_drawlist rail; raw GetWindowDrawList is
  IMGUI002 as of PR #48)

dasImgui sphinx / CI:
- dasimgui-sphinx-w-cross-ref-add-labels-to-external-types-rst-when-wrappers-reference-new-imgui-types
- github-actions-pr-merge-ref-sphinx-duplicate-target-local-passes-ci-fails
- wsl-ubuntu-repro-dasimgui-docs-ci-build-job-step-by-step

daslang-live recording infra:
- how-do-i-disable-hdpi-framebuffer-scaling-in-daslang-live-for-recording
- how-do-i-make-with-recording-app-attach-to-an-already-running-daslang-live

Daslang / daspkg misc:
- how-do-i-read-a-pre-dash-dash-daslang-exe-flag-from-inside-a-script
- daspkg-standalone-marker-skips-in-tree-daslang-cmake-include-for-installed-modules

2 cards moved from D:/DASPKG/dasImgui/docs/ (they were created in the wrong
folder during dasImgui dev work):
- dasimgui-hover-target-widget-variant-pattern-color-button-hover-selectable-hover
- dasimgui-integration-tests-use-examples-features-recordings-use-examples-tutorial

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-2026-05-18-v2

mouse-cards: 16 cards (MCP project_root, dasImgui drawlist rail, recording, sphinx/CI)
@pull pull Bot locked and limited conversation to collaborators May 18, 2026
@pull pull Bot added the ⤵️ pull label May 18, 2026
@pull pull Bot merged commit adafc7d into forksnd:master May 18, 2026
@pull pull Bot had a problem deploying to github-pages May 18, 2026 20: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.

2 participants