Skip to content

[JULES] Refactor src/stdlib/pattern.rs with standard type helpers - #448

Closed
logbie wants to merge 1 commit into
mainfrom
jules/refactor-pattern-expect-2133405730978822157
Closed

[JULES] Refactor src/stdlib/pattern.rs with standard type helpers#448
logbie wants to merge 1 commit into
mainfrom
jules/refactor-pattern-expect-2133405730978822157

Conversation

@logbie

@logbie logbie commented Apr 11, 2026

Copy link
Copy Markdown
Collaborator

Summary of Changes

  • The Issue: The src/stdlib/pattern.rs file contained significant repetition in extracting values from arguments via manual match blocks. Functions like pattern_matches_native, pattern_find_native, pattern_find_all_native, native_pattern_replace, and native_pattern_split all repeated the exact same 10-line boilerplate to assert argument types. In addition, the split and replace functions suffered from performance debt by unnecessarily allocating new reference-counted string buffers using Arc::from on &str instead of cloning the underlying Arc<str>.
  • The Rational: Reduced binary size, improved code maintainability and readability, and eliminated minor performance bottlenecks (unnecessary heap allocations) in text manipulation.
  • The Solution: Implemented a unified macro generation block for expect_pattern in src/stdlib/helpers.rs and replaced all the manual matching blocks with standard helper calls. Reused the Arc<str> reference directly where applicable in pattern replacement and string splitting to avoid new string allocations. Updated tests to mirror the standardized error messages.

Verification Checklist

  • cargo fmt executed and passed.
  • cargo clippy returned no warnings or errors.
  • All cargo test suites passed (100% success rate).

PR created automatically by Jules for task 2133405730978822157 started by @logbie


Open with Devin

Summary by CodeRabbit

  • Bug Fixes

    • Improved error messages for pattern matching operations to provide more consistent and descriptive feedback when incorrect types are provided.
  • Tests

    • Updated test assertions to reflect improved error message formatting.

…helpers

Created an `expect_pattern` helper using the `generate_expect!` macro and refactored all native functions in `src/stdlib/pattern.rs` to use it along with `expect_text`. This eliminates repetitive manual matching of arguments. As a side effect, it optimizes string allocations in `native_pattern_split` and `native_pattern_replace` by reusing `Arc<str>` references instead of allocating new buffers. Updated integration tests to match standard error strings.

Co-authored-by: logbie <1138960+logbie@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings April 11, 2026 09:09
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR introduces a new expect_pattern helper function to consolidate pattern type-checking and refactors five native pattern functions to use both expect_pattern and existing expect_text helpers, reducing code duplication and improving error message consistency across the stdlib.

Changes

Cohort / File(s) Summary
Pattern Helper Addition
src/stdlib/helpers.rs
Added new expect_pattern function via generate_expect! macro to extract and validate Value::Pattern as Rc<CompiledPattern>, with standardized error messaging.
Pattern Functions Refactoring
src/stdlib/pattern.rs
Refactored pattern_matches_native, pattern_find_native, pattern_find_all_native, native_pattern_replace, and native_pattern_split to use expect_text and expect_pattern helpers instead of manual type-checking, reducing line count and improving consistency.
Test Assertion Update
src/stdlib/pattern_test.rs
Updated test expectation in test_pattern_matches_native_wrong_first_arg_type to assert "Expected text" error message from consolidated helper instead of "First argument".

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐰 A helper hops through pattern code,
Consolidating validation's load,
With expect_pattern shining bright,
Native functions take their flight,
Less duplication, code feels right! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: refactoring pattern.rs to use standard type helper functions, which is the core objective of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jules/refactor-pattern-expect-2133405730978822157

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment thread src/stdlib/pattern.rs
Comment on lines +144 to +146
let text = expect_text(&args[0])?;
let _pattern = expect_pattern(&args[1])?;
let _replacement = expect_text(&args[2])?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Type-error messages in native_pattern_replace and native_pattern_split lose source location (line/column)

The functions native_pattern_replace and native_pattern_split accept line and column parameters (passed from the AST by the interpreter at src/interpreter/mod.rs:6736 and src/interpreter/mod.rs:6749) specifically to provide accurate source positions in error messages. The old inline match arms forwarded these values into RuntimeError::new(…, line, column). The new expect_text / expect_pattern helpers always hardcode (0, 0) (src/stdlib/helpers.rs:201-204), so type-mismatch errors now report position (0, 0) instead of the real source location. This is a regression for these two functions only — the other three pattern functions (pattern_matches_native, pattern_find_native, pattern_find_all_native) already used (0, 0) before this change.

Prompt for agents
The functions native_pattern_replace (line 131) and native_pattern_split (line 153) in src/stdlib/pattern.rs accept line and column parameters that represent the source code location from the AST. Before this refactoring, type-validation errors used those values in RuntimeError::new(msg, line, column). Now the expect_text / expect_pattern helpers (generated by the generate_expect! macro in src/stdlib/helpers.rs:188-208) always hardcode 0, 0.

To fix this properly, either:
1. Keep the inline match arms for these two functions (since they need line/column), or
2. Extend the generate_expect! macro to produce a second variant that accepts line/column parameters (e.g. expect_text_at(value, line, column)), or
3. Map the error after calling the helper, e.g. expect_text(&args[0]).map_err(|e| RuntimeError::new(e.message().to_string(), line, column))?

Option 3 is the least invasive.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/stdlib/pattern.rs`:
- Around line 144-147: The helper extractors (expect_text/expect_pattern)
currently produce RuntimeError with 0,0 which strips source coordinates; update
native_pattern_replace and native_pattern_split to call the helpers but, on Err,
replace the error's line and column with the original Arg's source coordinates
(use args[0]/args[1]/args[2] as appropriate) before returning the error so
type-mismatch diagnostics keep the correct line/column context for text,
pattern, and replacement.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b5373d6d-50de-4094-966d-f16c215142e5

📥 Commits

Reviewing files that changed from the base of the PR and between 7d45082 and 2bebbf1.

📒 Files selected for processing (3)
  • src/stdlib/helpers.rs
  • src/stdlib/pattern.rs
  • src/stdlib/pattern_test.rs

Comment thread src/stdlib/pattern.rs
Comment on lines +144 to 147
let text = expect_text(&args[0])?;
let _pattern = expect_pattern(&args[1])?;
let _replacement = expect_text(&args[2])?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Preserve source coordinates for type errors in interpreter entrypoints.

Line 144 and Line 166 now call shared extractors that emit RuntimeError with 0,0, so native_pattern_replace/native_pattern_split lose their line/column context on type mismatch. That regresses runtime diagnostics.

Proposed fix (keep helper usage, restore line/column)
-    let text = expect_text(&args[0])?;
-    let _pattern = expect_pattern(&args[1])?;
-    let _replacement = expect_text(&args[2])?;
+    let text = expect_text(&args[0]).map_err(|_| {
+        RuntimeError::new(format!("Expected text, got {}", args[0].type_name()), line, column)
+    })?;
+    let _pattern = expect_pattern(&args[1]).map_err(|_| {
+        RuntimeError::new(
+            format!("Expected a Pattern, got {}", args[1].type_name()),
+            line,
+            column,
+        )
+    })?;
+    let _replacement = expect_text(&args[2]).map_err(|_| {
+        RuntimeError::new(format!("Expected text, got {}", args[2].type_name()), line, column)
+    })?;
-    let text = expect_text(&args[0])?;
-    let pattern = expect_pattern(&args[1])?;
+    let text = expect_text(&args[0]).map_err(|_| {
+        RuntimeError::new(format!("Expected text, got {}", args[0].type_name()), line, column)
+    })?;
+    let pattern = expect_pattern(&args[1]).map_err(|_| {
+        RuntimeError::new(
+            format!("Expected a Pattern, got {}", args[1].type_name()),
+            line,
+            column,
+        )
+    })?;

Also applies to: 166-167

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/stdlib/pattern.rs` around lines 144 - 147, The helper extractors
(expect_text/expect_pattern) currently produce RuntimeError with 0,0 which
strips source coordinates; update native_pattern_replace and
native_pattern_split to call the helpers but, on Err, replace the error's line
and column with the original Arg's source coordinates (use
args[0]/args[1]/args[2] as appropriate) before returning the error so
type-mismatch diagnostics keep the correct line/column context for text,
pattern, and replacement.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the pattern stdlib natives to use standardized type-extraction helpers (generated via generate_expect!) and reduces unnecessary Arc<str> allocations in some paths, aiming to improve maintainability and minor runtime performance.

Changes:

  • Replaced repeated manual match-based argument type extraction in src/stdlib/pattern.rs with expect_text / expect_pattern.
  • Added expect_pattern helper generated via generate_expect! in src/stdlib/helpers.rs.
  • Updated pattern unit test expectations to match the standardized error wording.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/stdlib/pattern.rs Uses helper extractors for args; adjusts text/pattern usage and avoids some redundant string allocations.
src/stdlib/pattern_test.rs Updates assertions to match new standardized error message text.
src/stdlib/helpers.rs Adds expect_pattern helper via generate_expect! for consistent type extraction/errors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/stdlib/pattern.rs
Comment on lines +144 to +146
let text = expect_text(&args[0])?;
let _pattern = expect_pattern(&args[1])?;
let _replacement = expect_text(&args[2])?;

Copilot AI Apr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

native_pattern_replace receives line/column from the interpreter, but expect_text / expect_pattern return RuntimeError with (0,0) locations (via generate_expect!). This regresses error spans for type errors in pattern_replace. Consider mapping these extractor errors to the provided line/column (preserving the message), or adding location-aware helpers (e.g., expect_text_at, expect_pattern_at) for interpreter-called natives.

Suggested change
let text = expect_text(&args[0])?;
let _pattern = expect_pattern(&args[1])?;
let _replacement = expect_text(&args[2])?;
let text = expect_text(&args[0])
.map_err(|err| RuntimeError::new(err.to_string(), line, column))?;
let _pattern = expect_pattern(&args[1])
.map_err(|err| RuntimeError::new(err.to_string(), line, column))?;
let _replacement = expect_text(&args[2])
.map_err(|err| RuntimeError::new(err.to_string(), line, column))?;

Copilot uses AI. Check for mistakes.
Comment thread src/stdlib/pattern.rs
Comment on lines +166 to +167
let text = expect_text(&args[0])?;
let pattern = expect_pattern(&args[1])?;

Copilot AI Apr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as native_pattern_replace: native_pattern_split uses expect_text / expect_pattern, which produce errors with (0,0) even though this function is called with source line/column. Please propagate the provided location into type errors so runtime diagnostics point at the correct source span.

Copilot uses AI. Check for mistakes.
Comment thread src/stdlib/helpers.rs
Comment on lines +643 to +666
generate_expect!(
/// Extracts a CompiledPattern value from a WFL Value, returning it as a reference-counted compiled pattern.
///
/// Returns an `Rc<CompiledPattern>` to enable efficient memory sharing.
///
/// # Arguments
///
/// * `value` - The WFL Value to extract from
///
/// # Returns
///
/// Returns an `Rc<CompiledPattern>` clone (incrementing the reference count) if the value
/// is a Pattern variant. Multiple references to the same pattern share the underlying data.
///
/// # Errors
///
/// Returns `RuntimeError` if the value is not a Pattern, with an error message
/// indicating the expected type and the actual type received.
expect_pattern,
Pattern,
Rc<crate::pattern::CompiledPattern>,
"a Pattern",
|p: &Rc<crate::pattern::CompiledPattern>| Rc::clone(p)
);

Copilot AI Apr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expect_pattern is generated by generate_expect!, which hard-codes RuntimeError positions to (0,0). That’s fine for most stdlib calls, but it becomes problematic in interpreter entry points that do have source locations (e.g., native_pattern_split/native_pattern_replace). Consider extending generate_expect! (or providing parallel *_at(value, line, column) helpers) so callers can preserve accurate error locations when available.

Suggested change
generate_expect!(
/// Extracts a CompiledPattern value from a WFL Value, returning it as a reference-counted compiled pattern.
///
/// Returns an `Rc<CompiledPattern>` to enable efficient memory sharing.
///
/// # Arguments
///
/// * `value` - The WFL Value to extract from
///
/// # Returns
///
/// Returns an `Rc<CompiledPattern>` clone (incrementing the reference count) if the value
/// is a Pattern variant. Multiple references to the same pattern share the underlying data.
///
/// # Errors
///
/// Returns `RuntimeError` if the value is not a Pattern, with an error message
/// indicating the expected type and the actual type received.
expect_pattern,
Pattern,
Rc<crate::pattern::CompiledPattern>,
"a Pattern",
|p: &Rc<crate::pattern::CompiledPattern>| Rc::clone(p)
);
/// Extracts a CompiledPattern value from a WFL Value, returning it as a reference-counted compiled pattern.
///
/// Returns an `Rc<CompiledPattern>` to enable efficient memory sharing.
///
/// # Arguments
///
/// * `value` - The WFL Value to extract from
///
/// # Returns
///
/// Returns an `Rc<CompiledPattern>` clone (incrementing the reference count) if the value
/// is a Pattern variant. Multiple references to the same pattern share the underlying data.
///
/// # Errors
///
/// Returns `RuntimeError` if the value is not a Pattern, with an error message
/// indicating the expected type and the actual type received.
pub fn expect_pattern(
value: &Value,
) -> Result<Rc<crate::pattern::CompiledPattern>, RuntimeError> {
expect_pattern_at(value, 0, 0)
}
/// Extracts a CompiledPattern value from a WFL Value, preserving source location
/// information for any resulting type error.
///
/// # Arguments
///
/// * `value` - The WFL Value to extract from
/// * `line` - The source line to attach to any `RuntimeError`
/// * `column` - The source column to attach to any `RuntimeError`
///
/// # Returns
///
/// Returns an `Rc<CompiledPattern>` clone if the value is a Pattern variant.
///
/// # Errors
///
/// Returns `RuntimeError` if the value is not a Pattern, using the provided
/// source location instead of the default `(0, 0)`.
pub fn expect_pattern_at(
value: &Value,
line: usize,
column: usize,
) -> Result<Rc<crate::pattern::CompiledPattern>, RuntimeError> {
match value {
Value::Pattern(p) => Ok(Rc::clone(p)),
_ => Err(RuntimeError::new(
format!("Expected {}, got {}", "a Pattern", value.type_name()),
line,
column,
)),
}
}

Copilot uses AI. Check for mistakes.
@logbie logbie closed this Jun 5, 2026
@logbie
logbie deleted the jules/refactor-pattern-expect-2133405730978822157 branch June 19, 2026 04:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants