regex: fold 5a — add_thread dups parent captures/rep_counters (ha:568-573)

The loud bound (capture dup not yet portable, #35/#34/#7) flips to the
real dup now that #35's spread place-chain sources landed: fresh slice
header + spread-append, the D3 spelling of Hare's alloc-dup. The
ok/defer-if frees drop (free() is the documented no-op, #27).
Dup-independence rows drive add_thread directly: values carried,
backing independent both directions, empty parent → empty dup.
This commit is contained in:
2026-06-05 00:36:33 +09:00
parent 06b0fea98b
commit 0e61db1857
2 changed files with 64 additions and 18 deletions

View File

@@ -626,23 +626,15 @@ fn add_thread(threads: *[]thread, parent_idx: size, new_pc: size) (void | nomem)
};
};
// Hare dups the parent's captures/rep_counters here
// (`alloc(threads[parent_idx].captures...)?`, ha:569/572). Every
// ww route into that dup is blocked today (re-probed post-C3,
// PB7): the deref-spine spread SOURCE is loud-rejected (#35),
// the per-element append is loud-rejected (#34 struct element
// source), and the whole-element let-copy drops bytes (#7/F5).
// The abort is sound, not a semantic hole: fold-2a's compile()
// cannot emit inst_groupstart/inst_repeat, so both slices are
// provably empty in every program this fold can run; the empty
// case appends honest zeroed headers below. The verbatim dup
// lands with the group/repeat fold (ww-core #3).
if ((*threads)[parent_idx].captures.len != 0
|| (*threads)[parent_idx].rep_counters.len != 0) {
abort("regex: capture dup not yet portable (#35/#34/#7)");
};
// Hare dups via `alloc(threads[parent_idx].captures...)?`
// (ha:568-573); the alloc-dup form has no ww spelling (D3) —
// fresh slice header + spread-append, the #35-landed deref-spine
// source. The ok/defer-if frees (ha:570/573) drop: free() is the
// documented no-op (#27; see finish()).
let captures: []capture;
append(captures, (*threads)[parent_idx].captures...);
let rep_counters: []size;
append(rep_counters, (*threads)[parent_idx].rep_counters...);
append(*threads, thread {
pc = new_pc,