Skip to content

M6f: ordered stages on root/sort tuple steps (joins/index 6 & 12)#23

Merged
flearc merged 3 commits into
mainfrom
feature/m6f-stages
Jun 25, 2026
Merged

M6f: ordered stages on root/sort tuple steps (joins/index 6 & 12)#23
flearc merged 3 commits into
mainfrom
feature/m6f-stages

Conversation

@flearc

@flearc flearc commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Summary

Ports JSONata v2.2.1's ordered stages model for path steps so a #$v index that follows a filter or sort renumbers the post-filter/post-sort survivors — closing the two cleanly-fixable remaining joins cases.

  • Parser (cbb48f9): mark_binding's # branch now applies jsonata's move-on-# rule — a filter preceding the # moves into an ordered .stages list ({filter}/{index}), then the index is pushed as a stage; the @-focus S0215 guard also rejects pre-existing stages.
  • Evaluator (cbb48f9): new apply_stages (filter → predicate; index → renumber tuples 0-based), applied in eval_path_tuple's seeding and main loop; the sort branch binds its #-index. All gated on .stages/sort-.index, so non-tuple eval_path and the existing M6c–M6e joins are untouched.
  • Baseline (51a32ca): regen, additions-only.
  • Fidelity (0183939): adversarial review caught $#$a^($)#$b[$b<2][1,1] vs jsonata undefined (a contrived double-index around a sort). Fixed to jsonata's exact rule: a sort binds its index only on a raw, not-yet-tuple-bound stream.

Results

  • Official suite 1249 → 1251 (+2); joins 38 → 40/43 (joins/index/6, /12).
  • 498 unit tests green; zero-regression guard green (baseline additions-only; non-tuple predicates / sorting / %-parent / M6c–M6e joins unchanged).
  • Adversarial review vs genuine jsonata-js v2.2.1: target cases, ordering variants, multi-filter move, sort-index, no-perturbation — all oracle-faithful after the fidelity fix.

Deferred (the last 3 joins cases)

library-joins/7,8,10 (books@$b[…][1], …#$ib2, …[1][]) require stages applied to the whole post-cross-product stream, but our parser nests predicated tuple-steps into sub-paths evaluated per outer tuple (so a positional [1] applies per-loan, not globally). Faithfully closing them means jsonata's flat-steps + global-stages rework — flattening predicated tuple steps, which touches the machinery M6b (keepArray nesting) and M6c–M6e (all joins) rely on. Deferred as a separate, higher-risk architectural item.

Test plan

  • busted spec/ — 498/0
  • busted spec/jsonata_suite_spec.lua — zero-regression guard green
  • bash scripts/run-suite.sh — 1251/1682, joins 40/43
  • Adversarial oracle fidelity review (jsonata@2.2.1) incl. ordering/move/sort-index variants

🤖 Generated with Claude Code

flearc and others added 3 commits June 25, 2026 10:51
mark_binding's # branch now moves a preceding filter into an ordered .stages
list before pushing the index stage (jsonata move-on-#), so an index numbers
the post-filter/post-sort survivors. The evaluator's apply_stages runs the
stages in order in eval_path_tuple's seeding and main loop, and the sort branch
binds its #-index. Gated on .stages/sort-.index — non-tuple paths and existing
joins are untouched.

Defers library-joins 7,8,10 (flat-stages cross-product rework).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…egressions

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adversarial review found $#$a^($)#$b[$b<2] returned [1,1] vs jsonata undefined:
jsonata's evaluateTupleStep binds a sort step's index ONLY when sorting a
non-tuple-bound stream (the `tupleBindings === undefined` branch). Gate the
sort-index binding on the incoming tuples carrying no key beyond "@"; index/6
($^($)#$pos, a raw stream) still binds, the double-index case now yields
undefined.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@flearc flearc merged commit b00c703 into main Jun 25, 2026
1 check passed
@flearc flearc deleted the feature/m6f-stages branch June 25, 2026 03:09
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