feat(eval): make regex support explicit - #656
Conversation
Greptile SummaryThis PR decouples dynamic
Confidence Score: 5/5Safe to merge — the change is additive, all new code paths are tested end-to-end, and the decoupling from direct PCRE2 linkage is mechanically correct. The provider ABI is registered exactly once via OnceLock, the codegen correctly gates symbol emission on runtime_features.regex, the pcre2_shim REG_STARTEND fix is validated by a new C-level test, and all four behavior combinations have dedicated test coverage. No regressions in existing eval behavior are expected. Files Needing Attention: No files require special attention.
|
| Filename | Overview |
|---|---|
| crates/elephc-magician/src/regex_provider.rs | New file: introduces the versioned provider ABI and OnceLock-backed registration; test builds return an always-available host-PCRE2 provider; production path returns None until the generated init code calls __elephc_eval_register_regex_provider. |
| src/codegen/lower_inst/builtins/eval.rs | Adds register_eval_regex_provider to the not-yet-initialized branch of ensure_eval_context; emits symbol addresses for the three shim callbacks only when runtime_features.regex is set. |
| src/codegen_support/runtime_features.rs | Decouples eval_bridge from the pcre2 link requirement; eval alone now requires only the magician bridge, while regex is an independent feature that adds the pcre2 native package. |
| src/pipeline.rs | Forces runtime_features.regex when --with-regex is present and emits a post-build reminder when eval is compiled without regex support via direct eprintln!. |
| src/cli.rs | Extends --with- to accept non-bridge runtime capabilities alongside bridge crate names; error message and help text updated. |
| src/native_deps/recipes/pcre2_shim.c | Fixes REG_STARTEND handling by saving caller-supplied start/end offsets before zeroing the output array; recipe revision bumped from 1 to 2. |
| crates/elephc-magician/build.rs | Switches from cargo:rustc-link-lib to cargo:rustc-link-arg so PCRE2 is not propagated to downstream users of the staticlib. |
| crates/elephc-magician/src/interpreter/builtins/registry/mod.rs | Adds builtin_is_available helper that gates regex-area builtins on provider registration. |
| tests/codegen/eval.rs | Adds four new tests covering all behavior combinations; existing preg_* tests migrated to compile_and_run_with_regex. |
| tests/codegen/support/compiler.rs | Extends fixture helpers with optional regex capability propagation; adds compile_and_run_with_regex and compile_and_run_capture_with_regex entry points. |
Sequence Diagram
sequenceDiagram
participant CLI as elephc CLI
participant Pipeline as pipeline.rs
participant Codegen as eval.rs codegen
participant Binary as Generated Binary
participant Magician as libelephc_magician
participant Shim as pcre2_shim
CLI->>Pipeline: --with-regex flag
Pipeline->>Pipeline: "runtime_features.regex = true"
Pipeline->>Pipeline: link pcre2 native package
Pipeline->>Codegen: generate eval call site
Codegen->>Codegen: ensure_eval_context (not yet initialized)
Codegen->>Codegen: register_eval_regex_provider emits compile/exec/free addrs
Codegen->>Codegen: call __elephc_eval_register_regex_provider
Codegen->>Codegen: call __elephc_eval_init
Note over Binary,Shim: At runtime
Binary->>Magician: __elephc_eval_register_regex_provider(compile, exec, free)
Magician->>Magician: REGEX_PROVIDER.set(RegexProvider)
Binary->>Magician: eval preg_match call
Magician->>Magician: "builtin_is_available -> regex_provider_available() = true"
Magician->>Shim: provider.compile(pattern, flags, slots)
Shim-->>Magician: opaque handle
Magician->>Shim: provider.exec(handle, subject, slots, pairs, REG_STARTEND)
Shim-->>Magician: match offsets
Magician->>Shim: provider.free(handle)
Reviews (3): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile
Summary
eval()support from PCRE2 so Magician-only binaries no longer require a managed native project or link regex code.--with-regexfor regex calls that exist only inside opaque evaluated source, while keeping normal automatic detection for statically visible regex usage.preg_*ormb_ereg_match()and fails only if one of those unavailable functions is executed.examples/eval/program into a dedicatedexamples/eval_regex/project with a managed PCRE2 manifest and lockfile.Behavior
pcre2native dependency and an explicit--with-regexbuild.Testing
cargo test --bin elephc with_regex_records_runtime_capabilitycargo test --lib runtime_features::tests::test_evalcargo test --test codegen_tests test_dynamic_eval_without_regex_needs_no_native_projectcargo test --test codegen_tests test_dynamic_eval_regex_without_capability_fails_at_runtimecargo test --test codegen_tests test_dynamic_eval_with_regex_uses_managed_providercargo test --test codegen_tests test_static_regex_detection_enables_dynamic_eval_regex