nano: libDaScriptNano - the daslang runtime with no compiler in it - #3869
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes an installed-SDK build regression in vecmath headers and introduces libDaScriptNano, a “runtime-only” daslang library intended for embedding precompiled standalone-AOT contexts without pulling in the compiler (AST/module system, fmt-heavy paths, etc.). To support nano’s “shadow include root” design, several runtime-only implementations are carved out of mixed compiler/runtime translation units, and a set of standalone examples + a C++ big test are added to keep the nano tiers link-tested.
Changes:
- Fix SDK install list for vecmath by adding missing headers that
dag_vecMath.hincludes unconditionally. - Add
nano/(headers + sources + docs) and wire it into the build/install, plus standalone-AOT example targets and anano_ctxC++ big test. - Refactor (“carve”) runtime-only code into new
src/simulate/*translation units to decouple runtime code from compiler dependencies.
Reviewed changes
Copilot reviewed 41 out of 41 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests-cpp/big/nano_ctx/test_nano_ctx.cpp | New big C++ test linking four standalone-AOT tiers into one nano-linked binary. |
| tests-cpp/big/nano_ctx/CMakeLists.txt | Build rules for generating AOT contexts and linking them against libDaScriptNano. |
| src/simulate/runtime_string.cpp | Removes escapeString implementation from this TU as part of runtime/compiler decoupling. |
| src/simulate/escape_string.cpp | New TU containing escapeString implementation for reuse by both full runtime and nano. |
| src/simulate/builtin_runtime_ops.cpp | New TU containing runtime-only builtin implementations used by AOT output. |
| src/simulate/builtin_array_ops.cpp | New TU containing runtime-only array builtin implementations used by AOT output. |
| src/simulate/annotation_arguments.cpp | New TU moving AnnotationArgumentList option helpers out of AST module code. |
| src/builtin/module_builtin_runtime.cpp | Removes runtime-only builtin bodies now moved to src/simulate/builtin_runtime_ops.cpp. |
| src/builtin/module_builtin_array.cpp | Removes runtime-only array builtin bodies now moved to src/simulate/builtin_array_ops.cpp. |
| src/ast/ast_module.cpp | Removes AnnotationArgumentList helper implementations now moved to simulate/. |
| skills/cpp_integration.md | Documents embedding via libDaScriptNano and include-order requirements. |
| nano/src/nano_stubs.cpp | New nano “seams” TU: print sink plumbing and fail-closed stubs for unsupported features. |
| nano/src/nano_string_writer.cpp | New nano StringWriter/TextPrinter implementation using snprintf instead of fmt. |
| nano/src/nano_context.cpp | New nano Context implementation for standalone-AOT execution (no compiler). |
| nano/REVIEW.md | New nano-specific code review checklist. |
| nano/REVIEW.das | New mechanical review gate for nano invariants (install list, include-order guard, etc.). |
| nano/README.md | New user-facing overview and build instructions for nano. |
| nano/include/daScript/simulate/simulate.h | New nano shadow header providing a minimal Context/runtime surface for standalone AOT. |
| nano/include/daScript/simulate/runtime_profile.h | Empty nano shadow header to satisfy require $ includes without pulling profiler. |
| nano/include/daScript/simulate/bin_serializer.h | Empty nano shadow header to satisfy require $ includes without pulling serializer. |
| nano/include/daScript/nano_print.h | Public nano embedder hook for routing all runtime output to one sink. |
| nano/include/daScript/misc/performance_time.h | Empty nano shadow header to satisfy require $ includes without pulling timing APIs. |
| nano/include/daScript/das_config.h | Nano shadow config header redirecting runtime output and disabling compiler-adjacent features. |
| nano/include/daScript/ast/ast.h | Nano shadow header providing a minimal subset of AST-facing types needed by reused runtime code. |
| nano/CMakeLists.txt | Defines libDaScriptNano as a static lib built from nano-owned + shared runtime sources. |
| nano/ARCHITECTURE.md | Documents the shadow-include-root mechanism, tiers, and fail-closed seams. |
| install/CLAUDE.md | Updates skill index entry to include nano in skills/cpp_integration.md. |
| include/daScript/simulate/annotation_arguments.h | Fixes default values for numeric option getters to be 0 instead of false. |
| examples/standalone/CMakeLists.txt | Adds in-tree build targets for nano standalone-AOT examples (generated via daslang). |
| examples/standalone/CMakeLists.standalone.cmake | Adds SDK-consumer build entrypoint using find_package(DAS) + building nano from sources. |
| examples/standalone/04_c_binding/main.cpp | New standalone example: C-owned loop + das decision + nano print sink. |
| examples/standalone/04_c_binding/blinker.das | New .das example for tier “output” via print. |
| examples/standalone/03_closures/main.cpp | New standalone example exercising lambdas/function pointers/generators. |
| examples/standalone/03_closures/closures.das | New .das example for tier C behaviors (closures/generators). |
| examples/standalone/02_heap/main.cpp | New standalone example exercising heap usage and delete path. |
| examples/standalone/02_heap/heap_demo.das | New .das example for tier B behaviors (arrays/tables/new/delete). |
| examples/standalone/01_pure/pure_math.das | New .das example for tier A (pure POD compute, no heap). |
| examples/standalone/01_pure/main.cpp | New standalone example driver for tier A. |
| CMakeLists.txt | Fixes vecmath install list; wires nano + standalone examples into build; installs nano and shared sources. |
| CLAUDE.md | Updates skill index and directory overview to mention nano. |
| ci/nano_arm_build.sh | Adds a (currently red) acceptance script for future freestanding cross-compile work. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
b3ba168 to
30787f6
Compare
30787f6 to
fa4074e
Compare
fa4074e to
014ff94
Compare
014ff94 to
d735b9d
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 42 out of 42 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
src/simulate/builtin_array_ops.cpp:29
- Same issue as builtin_array_size(): the capacity guard is against INT32_MAX but the message says INT_MAX. Align the message with the enforced limit so a panic is actionable and not confusing.
A shadow include root (nano/include ahead of include/) replaces four headers - das_config.h, simulate.h, a minimal ast.h, and the three empty `require $` stubs - so thirteen sources compile straight out of src/ against a minimal Context with no #ifdef in the shared tree. nano owns three sources: the Context, the seams where it ends, and a snprintf-backed string writer. Five carves split the runtime half of a file away from its compiler half, each a universal improvement: annotation_arguments.cpp, escape_string.cpp, builtin_array_ops.cpp and builtin_runtime_ops.cpp join simulate_gc_pod.cpp. Four examples under examples/standalone/, one per tier - POD compute, heap, closures, output - build in-tree and from an installed SDK; tests-cpp/big/ nano_ctx links all four into one program. Also fixes a shipped-SDK regression: VECMATH_SRC never picked up dag_vecMath_double.h or dag_vecMath_scalar.h, and dag_vecMath.h includes the first unconditionally, so any SDK consumer compiling against vecmath failed. nano is not freestanding yet; ci/nano_arm_build.sh is the acceptance test for that port and is not wired into CI. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ELhvojnmb6xx5p6ty3PyNk
d735b9d to
958f28a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 44 out of 44 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
src/simulate/builtin_array_ops.cpp:104
builtin_array_erase_i64uses(index+1)whereindexisint64_t. IfpArray.size > INT64_MAX, a validindex == INT64_MAXpasses the bounds check, butindex+1overflows signed int64 (UB) in the pointer arithmetic. Mirror the range-erase implementation: convert touint64_tafter theindex<0check and do all arithmetic in unsigned.
Fixes a shipped-SDK regression:
VECMATH_SRCnever listeddag_vecMath_double.hordag_vecMath_scalar.h, anddag_vecMath.hincludes the first unconditionally - so any SDK consumer that compiled a file reaching vecmath failed to build. Nothing in the bundle smoke test compiles C++ against vecmath, which is why it went unseen.libDaScriptNanois the daslang runtime with no compiler in it. A program that only ever runs already-compiled daslang still links the AST, the module registry, the debugger, the serializer and fmt today, because the compiler and the runtime share headers. nano breaks that sharing without forking anything:nano/includegoes ahead ofinclude/in the search order, four headers resolve to nano's, and thirteen sources compile straight out ofsrc/against a minimalContextwith no#ifdefanywhere in the shared tree. nano owns three sources - theContext, the seams where it ends, and asnprintf-backed string writer that replaces the one template that reached fmt.Making those thirteen compile unmodified needed five carves, each splitting the runtime half of a file away from its compiler half.
annotation_arguments.cpp,escape_string.cpp,builtin_array_ops.cppandbuiltin_runtime_ops.cppjoinsimulate_gc_pod.cpp. Every one of them leaves the full runtime better factored: the array builtins no longer sit in the same file as their AST registration, andescapeStringno longer drags fmt into the heap's diagnostics.Four examples under
examples/standalone/cover one tier each - POD compute, the das heap, closures and generators, and output through the embedder's print sink. They build in-tree and from a bare installed SDK, andtests-cpp/big/nano_ctxlinks all four into a single program. A script that reaches past what nano carries fails to link rather than silently growing.nano is NOT freestanding yet. It builds where the full runtime builds, minus the compiler. Cross-compiling for bare metal needs portability work in
platform.h,smart_ptr.h,arraytype.h,vectypes.handinterop.h;ci/nano_arm_build.shis the acceptance test for that port and is deliberately not wired into CI, because it is red today.Where to look: the include-order trap in
nano/ARCHITECTURE.md- a target that links nano from a directory holding the repo'sinclude_directories()compiles against the fullContextwhile linking nano's, with no diagnostic. Every such directory clears the property, andnano/REVIEW.daschecks it.Validation, claims, ledger
Validation
ctest -L big(nano_ctxandstandalone_ctxamong them): 7/7 pass locally - CI runs-L smallonly, so nothing else proves them.cmake --installto a clean prefix, then configureexamples/standaloneagainst it withfind_package(DAS)and build - all four examples build and run. This is what surfaced the vecmath install gap.nano/REVIEW.das: each of its four checks was negative-controlled (bogus shared source, a header shadowing nothing, the include-order guard removed from both the in-tree and the SDK CMake, a source dropped from the install list).ctest -L small109/109.ctest -L bigalso carriesstyle_lint_style014_long_commentandstyle_lint_style015_long_comment_private.utils/lint/main.dasgained an unconditional skip forutils/lint/tests/on 2026-07-11, six weeks after those tests were added, so both have been dead since. They fail on master too. Excluded with-E style_lintfor the run above.Claims - stated, not tested
require $includes in generated output are dead weight: nothing emitted names a symbol frombin_serializer.h,runtime_profile.horperformance_time.h. Verified by compiling the generated TUs with all three shadowed by empty headers. A break would look like an undeclared identifier in a generated TU on nano only.src/builtin/REVIEW.das's bind-flavor scan. A break would look like a builtin resolving to a different node kind.Not done
nano/ARCHITECTURE.mdunder "Ledgered cases", measured against arm-none-eabi with newlib.require $includes. Shadowing them is compensation; the emitter fix rides the next nano change, andnano/ARCHITECTURE.mdsays so at the include contract.delete. Both ledgered.🤖 Generated with Claude Code