Skip to content

state_exec: parser.max_depth 100000; the last recursive walks over parsed data - #678

Merged
transfix merged 3 commits into
masterfrom
feat/state-exec-deep-finish
Oct 18, 2026
Merged

transfix merged 3 commits into
masterfrom
feat/state-exec-deep-finish

Conversation

@transfix

Copy link
Copy Markdown
Owner

Finishes what #657 and #658 left over parsed data. Nothing in libcvc walks parsed data on the native stack any more, so parser.max_depth stops being a stack guard and its default rises from 256 to 100000 (the user's choice). 100000 is the depth every walker is tested at on a 64 KiB stack.

What changes

  • Ariadne channel lint. collect_channel_refs (loader.cpp) keeps its open lists on a heap stack. The old cutoff at 256 levels is gone, so a msg-* reference at any depth is checked.
  • stream-capture-audio graphs. A built tone/gain/mix graph pulls each chunk through one native call per level on the producer thread, and frees itself the same way. A builder loop would not help, so depth is capped instead: a SPEC nesting mix/gain more than 64 levels deep is refused with an error ("... more than 64 levels deep") instead of built.
  • state-set of a list or dict prints it as a data job (run_data_job(make_print_job(...))). With data.step_nodes > 0 the printing runs a slice per step like str, and the node is written once the whole string is ready. Scalars are unchanged.
  • Test-only tree-walking evaluators (evaluator, async_evaluator). Their macro substitute runs the stackless evaluator's walk whole instead of recursing per template level.
  • parser.max_depth defaults to 100000. The header comment, the grammar doc ("Nesting", "Parser settings", the P1b row) and the pycvc comment/README say why. Values crossing into Python go through pycvc's converter, which has its own depth limit (pycvc: state_exec parity part 1 (values, parsing, parse_error, value codec) #661).

Not in this PR

PR B, on top of #665's call_function:

  • a cap on native→native nesting (apply/send on a self-containing list, class constructor/init cycles);
  • class teardown without a native frame per superclass;
  • generators and defclass methods without nested evaluators;
  • the snapshot codec walking closures and environments iteratively.

The pycvc converter (value_to_py/py_to_value) is left to the parity stack (#661 and its follow-up), which replaces it.

Tests

  • StateExecDeepData.ParsedDataAtTheDefaultDepthLimit: on the small stack, a script at the default limit parses, compares, prints and frees, and one level more is a parse_error. It passes at 256 KiB and 64 KiB (CVC_DEEP_DATA_STACK_KIB=64).
  • DataStepsScheduler.StateSetOfADeepValueSlices: a 300-deep list takes data steps, the node is empty mid-walk, and it ends holding the printed list.
  • AriadneChannelLint.SeesChannelsNestedAnyDepth: an undeclared channel 1000 levels down fails a strict load.
  • cvcgl_media_audio: a 64-level gain chain is built, and a 65-level one is refused with the cap's error.
  • The default's asserts (parser, grammar P1b row, integration settings tests, pycvc) now say 100000. NestingLimitStopsRunawayInputBeforeTheStackDoes feeds a million ( and checks the error is at column 100001.

Local results (MSVC 14.38 Release, Windows)

…rsed data

Nothing in libcvc walks parsed data on the native stack any more, so the parser's nesting
limit no longer guards the stack. Its default rises from 256 to 100000, the depth every
walker is tested at on a 64 KiB stack (the user's choice).

- Ariadne channel lint: collect_channel_refs keeps its open lists on a heap stack. The
  256-level cutoff is gone, so a msg-* reference at any depth is checked.
- stream-capture-audio: a built tone/gain/mix graph pulls each chunk through one native
  call per level on the producer thread, and frees itself the same way. A graph nesting
  mix/gain more than 64 levels deep is refused with an error instead of built.
- state-set of a list or dict prints it as a data job, a slice per step when the process
  slices deep data. The node is written once the whole string is ready.
- The test-only tree-walking evaluators' macro substitute runs the stackless evaluator's
  walk whole, instead of recursing per template level.

Tests: ParsedDataAtTheDefaultDepthLimit (parse, compare, print and free a script at the
default limit on the small stack), StateSetOfADeepValueSlices, a channel lint test 1000
levels deep, the audio graph cap in cvcgl_media_audio, and the default's asserts.
…ec-deep-finish

One conflict: STATE_EXEC_GRAMMAR.md's paragraph on walks that still run whole. #665 made the stdlib's materializers jobs and this branch makes state-set's coercion one, so neither runs whole any more.
transfix added a commit that referenced this pull request Oct 18, 2026
…it is reported (#680)

PredicateMaterializerIsCutByTheEvalBudget (from #665) runs a one-node-a-step
collections.range 120000 in a predicate and expects it cut. On the Linux
Debug lane the time cap fired inside the job's own deadline poll, which
reports "collections.range: evaluation exceeded time budget" through the
job's error rather than the evaluator's "exceeded the eval budget"
(seen on #678, job 117587719214). Both are the predicate being cut;
the test now accepts either.
@transfix
transfix enabled auto-merge (squash) October 18, 2026 06:34
…p-finish

Conflicts: STATE_EXEC_GRAMMAR.md's native-calls list (state-json/state-from-json from #681, state-set here: both kept), and the tests #681/#682 and this branch each added to state_exec_data_steps_test.cpp and state_exec_deep_data_test.cpp (all kept). #675's pycvc tests asserted the old parser.max_depth default of 256; they now compare with pycvc.parse_options().max_depth, as agreed with the parity session.
@transfix
transfix merged commit 69aafc6 into master Oct 18, 2026
15 checks passed
transfix added a commit that referenced this pull request Oct 18, 2026
No conflicts: #678's tests and grammar-doc edits sit next to this branch's.
transfix added a commit that referenced this pull request Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant