These libraries are experimental. APIs may change without notice. Generated from source with koruc 0.1.7 on 8/19/2026.

PCRE2

@korulang/pcre2@0.0.1

PCRE2 (Perl-compatible regular expressions) for Koru with phantom obligation types

pcre2/index.kz · 7 tors

@korulang/pcre2 — the definitive Koru PCRE2 edition · 31 more lines
@korulang/pcre2 — the definitive Koru PCRE2 edition Lifts PCRE2 (the Perl-Compatible Regular Expressions library that git, PHP, nginx, and Apache all rely on) into a phantom-obligation-typed Koru edition. The raw C API has two hand-managed heap resources — the compiled pattern (`pcre2_code`) and the per-search match data (`pcre2_match_data`) — and the classic footgun of iterating matches with a manual offset cursor. This edition compiles those footguns away: • The compiled pattern is a phantom obligation: the build FAILS if you forget to free it, and fails if you use it after freeing it. • The match-data buffer never touches your hands at all — the `find.all` loop owns it, iterates every match for you, and frees it exactly once. You cannot leak it because you never hold it. • Each match is a per-iteration BORROW, valid only inside its `! match` body — capture that borrow past the body and the phantom checker rejects the build (KORU030), the same wall sqlite3's `! row` uses. USAGE: ~import libs/pcre2 ~libs/pcre2:compile(pattern: "(\\w+)@(\\w+)") | ok re |> libs/pcre2:find.all(re: re, subject: "a@b and c@d") ! match m |> libs/pcre2:group.text(m: m, index: 1): user |> libs/pcre2:group.text(m: m, index: 2): host |> std/io:print.ln("{{ user:s }} at {{ host:s }}") | done |> libs/pcre2:free(re) | err e |> libs/pcre2:free(re) | err e |> std/io:print.ln("bad pattern: {{ e.msg:s }}")

Phantom lifecycles

Derived from the phantom labels in the declarations below — state! issues an obligation the compiler will chase, !state discharges it, a bare state holds it without moving it. Nothing here is hand-drawn.

Regex 1 state compiled!
Match 1 state match!

compile

<compiled!> index.kz:87

free

<!compiled> index.kz:110

find.all

<compiled><match!> index.kz:131

unmatch

<!match> index.kz:190

group.count

<match> index.kz:199

group.text

<match> index.kz:207

match.start

<match> index.kz:219