diff --git a/lib/regex/regex.ww b/lib/regex/regex.ww index 247e8625..d07dcadd 100644 --- a/lib/regex/regex.ww +++ b/lib/regex/regex.ww @@ -4,13 +4,12 @@ // other metacharacter arm, exec / find / replace are DEFERRED to // later folds. // -// Two fold-1 constructs are held back behind filed compiler/fidelity -// gaps (see the charclass_map and finish() sites below): +// One fold-1 construct is held back behind a filed compiler/fidelity +// gap (see the charclass_map site below): // - charclass_map (regex.ha:74-87) — a module-level const slice of // (str, *fn(rune) bool) tuples. Blocked on the array-literal→slice // element-coercion checker gap (#25; type.c:402-404 #258 borrow // uses exact type_eq, no element decay). -// - finish() (regex.ha:96-102) — frees; ww is a no-free runtime (#27). package regex; import strings; @@ -92,15 +91,18 @@ export type regex = struct { // Frees resources associated with a [[regex]]. // -// ref/hare/regex/regex.ha:96-102 frees re.insts / each charset / -// re.charsets. ww is a no-free runtime (rt/alloc.s:30 — rt_free is a -// no-op; the bump allocator can't reclaim, process-exit does), so the -// faithful ww body drops the frees, matching how the port drops every -// Hare free(). Kept for API parity with the Hare surface. Temporary -// empty body: #27 makes the free() builtin compile to a documented -// no-op, after which this ports the Hare frees VERBATIM (the no-op -// builtin reclaims nothing, same end state). -export fn finish(re: *regex) void = { }; +// ref/hare/regex/regex.ha:96-102, verbatim. The free() builtin is a +// documented no-op (#27 landed): ww is a no-free runtime (rt/alloc.s:30 +// — the bump allocator can't reclaim, process-exit does), so each free +// below evaluates its operand and reclaims nothing. Kept verbatim for +// API + source parity with the Hare surface. +export fn finish(re: *regex) void = { + free(re.insts); + for (let charset .. re.charsets) { + free(charset); + }; + free(re.charsets); +}; // Compiles a regular expression string into a [[regex]]. // @@ -114,8 +116,9 @@ export fn finish(re: *regex) void = { }; // was_prev_rune_pipe / group_level / capture_idx (ha:253-256). // // Hare's `defer if (!ok) free(...)` cleanup (ha:231-237) is omitted: -// ww has no `defer if` (cf lib/strings/strings.ww:85) and is a no-free -// runtime (#27) — the port drops every Hare free(). +// ww has no `defer if` (cf lib/strings/strings.ww:85), and the free() +// builtin is a no-op anyway (#27 — ww is a no-free runtime), so the +// cleanup would reclaim nothing. export fn compile(expr: str) (regex | error | nomem) = { // Hare `let insts: []inst = [];` — a bare ww slice declaration // zeroes the header (cgen.c:9836 no-rhs multi-word composite