← board

nilpy: re module

Motivation

import re is the first thing that stops songformatter's smallest module (key_analysis.py) from compiling, and it will stop most real Python. Backed by [[feature-lib-regex-engine]] — this ticket is only the frontend surface, the same shape as the existing os.* dotted-call mapping in pyparser.inc (os.path.join -> pyos_path_join).

Surface

Module-level: re.match, re.search, re.fullmatch, re.sub, re.findall, re.compile, and the flags (re.X/re.VERBOSE, re.I).

Match objects: truthiness (songformatter does bool(re.match(...)) and is not None), .group(n), .groups().

Compiled patterns: the same methods as the module functions.

Gate

make test-nilpy green with a .npy case diffed against CPython over the surveyed songformatter patterns, + --tier quick + self-host byte-identical.

Log

Update (2026-07-26) — landed, commit ca4dac8d

lib/rtl/re.pas, named re so NO frontend change was needed: import X becomes uses X, so the unit name IS the Python module name, and re.match(p, s) resolves by ordinary unit qualification (the flat match(p, s) works too). No entry in pyparser.inc's dotted-call table, no pylexer special case, and no -Fu flag — lib/rtl is already on the default search path when the compiler runs from the repo root.

Semantics were PROBED, not assumed, before the design was fixed: a class instance is truthy, nil is falsy, is None works on nil, and methods dispatch on a returned instance. Hence a match is a TMatch or nil, which gives Python's if m: for free.

Surface: match/search/fullmatch/sub/findall/compile/escape, flags under both spellings, m.group(n)/m.start(n)/m.stop(n), and a compiled TPattern accepted as the first argument to the module functions (CPython allows this too).

Deliberate differences, both documented in the unit header: findall with 2+ groups yields a list per match (no tuple type in NilPy; indexing identical), and m.end() is m.stop() because end is a Pascal keyword. Offsets are 0-based with -1 for a non-participating group, as CPython.

Gate: test/test_nilpy_re.npy wired into both test-nilpy variants, expectation = CPython's own output for the same script (diffed identical). make test-nilpy green, 135 compiles, run against the pinned stable — its default $(COMPILER) rule currently dies earlier on the self-host fixedpoint cmp, which reproduces on a clean tree and is [[chore-makefile-selfhost-iterate-to-convergence]].