// regex — POSIX extended regular expressions. Port of // ref/hare/regex/regex.ha. Fold 1 = the data model only; compile() / // 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): // - 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; // ref/hare/regex/regex.ha:14 — an error string describing a compilation // error. export type error = !str; // ref/hare/regex/regex.ha:16-30. export type inst_lit = rune; export type inst_charset = struct { idx: size, is_positive: bool }; export type inst_any = void; export type inst_split = size; export type inst_jump = size; export type inst_skip = void; export type inst_match = bool; export type inst_groupstart = size; export type inst_groupend = void; export type inst_repeat = struct { id: size, origin: size, min: (void | size), max: (void | size), }; // ref/hare/regex/regex.ha:32-35. export type inst = (inst_lit | inst_any | inst_split | inst_jump | inst_skip | inst_match | inst_charset | inst_groupstart | inst_groupend | inst_repeat); // The resulting match of a [[regex]] applied to a string. // // The first [[capture]] corresponds to the implicit zeroth capture // group, i.e. the whole expression. // // The rest of the [[capture]]s correspond to the rest of the capture // groups, i.e. the sub-expressions. // ref/hare/regex/regex.ha:44. export type result = []capture; // A (sub)match corresponding to a regular expression's capture group. // ref/hare/regex/regex.ha:47-53. export type capture = struct { content: str, start: size, start_bytesize: size, end: size, end_bytesize: size, }; // ref/hare/regex/regex.ha:68-72. export type charset = [](charset_lit_item | charset_range_item | charset_class_item); export type charset_lit_item = rune; export type charset_range_item = (u32, u32); export type charset_class_item = (str, *fn(c: rune) bool); // ref/hare/regex/regex.ha:74-87 — charclass_map: the const // [](str, *fn(rune) bool) table mapping POSIX class tokens to the // matching ascii predicate. DEFERRED: the array-literal→slice // assignability check (type.c:402-404, the #258 borrow) compares // element types with exact type_eq and applies NO element coercion, so // the literal `[(":alnum:]", &ascii.isalnum), ...]` (typed // `[N](untyped_str, *fn(rune) bool)`) is rejected against the declared // `[](str, *fn(rune) bool)`. Minimal repro: `let xs: [](size, size) = // [(1, 2)];`. Reshaping to a fixed `[12](...)` array would compile but // is an unfaithful workaround (CLAUDE.md rule-7), so the table — and // the `import ascii;` it needs — land with the consuming fold (compile) // once the checker gap is fixed. // ref/hare/regex/regex.ha:89-93. export type regex = struct { insts: []inst, charsets: []charset, n_reps: size, }; // 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 = { };