diff --git a/src/stdlib/helpers.rs b/src/stdlib/helpers.rs index 9dde4972..b2afcfd9 100644 --- a/src/stdlib/helpers.rs +++ b/src/stdlib/helpers.rs @@ -596,6 +596,31 @@ generate_expect!( |dt: &Rc| Rc::clone(dt) ); +generate_expect!( + /// Extracts a Pattern value from a WFL Value, returning it as a reference-counted CompiledPattern. + /// + /// Returns an `Rc` to enable efficient memory sharing. + /// + /// # Arguments + /// + /// * `value` - The WFL Value to extract from + /// + /// # Returns + /// + /// Returns an `Rc` clone (incrementing the reference count) if the value + /// is a Pattern variant. + /// + /// # 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, + "a pattern", + |p: &Rc| Rc::clone(p) +); + /// Helper for unary list operations (List -> Value) /// /// Handles argument count checking, type extraction, and operation execution. diff --git a/src/stdlib/pattern.rs b/src/stdlib/pattern.rs index 4b3012c9..4a12d604 100644 --- a/src/stdlib/pattern.rs +++ b/src/stdlib/pattern.rs @@ -27,27 +27,10 @@ pub fn pattern_matches_native(args: Vec) -> Result { )); } - let text_str = match &args[0] { - Value::Text(s) => s.as_ref(), - _ => { - return Err(RuntimeError::new( - "First argument to pattern_matches must be text".to_string(), - 0, - 0, - )); - } - }; - - let compiled_pattern = match &args[1] { - Value::Pattern(p) => p, - _ => { - return Err(RuntimeError::new( - "Second argument to pattern_matches must be a compiled pattern".to_string(), - 0, - 0, - )); - } - }; + let text_arc = super::helpers::expect_text(&args[0])?; + let text_str = text_arc.as_ref(); + + let compiled_pattern = super::helpers::expect_pattern(&args[1])?; let matches = compiled_pattern.matches(text_str); Ok(Value::Bool(matches)) @@ -64,27 +47,10 @@ pub fn pattern_find_native(args: Vec) -> Result { )); } - let text_str = match &args[0] { - Value::Text(s) => s.as_ref(), - _ => { - return Err(RuntimeError::new( - "First argument to pattern_find must be text".to_string(), - 0, - 0, - )); - } - }; - - let compiled_pattern = match &args[1] { - Value::Pattern(p) => p, - _ => { - return Err(RuntimeError::new( - "Second argument to pattern_find must be a compiled pattern".to_string(), - 0, - 0, - )); - } - }; + let text_arc = super::helpers::expect_text(&args[0])?; + let text_str = text_arc.as_ref(); + + let compiled_pattern = super::helpers::expect_pattern(&args[1])?; match compiled_pattern.find(text_str) { Some(match_result) => { @@ -128,27 +94,10 @@ pub fn pattern_find_all_native(args: Vec) -> Result )); } - let text_str = match &args[0] { - Value::Text(s) => s.as_ref(), - _ => { - return Err(RuntimeError::new( - "First argument to pattern_find_all must be text".to_string(), - 0, - 0, - )); - } - }; - - let compiled_pattern = match &args[1] { - Value::Pattern(p) => p, - _ => { - return Err(RuntimeError::new( - "Second argument to pattern_find_all must be a compiled pattern".to_string(), - 0, - 0, - )); - } - }; + let text_arc = super::helpers::expect_text(&args[0])?; + let text_str = text_arc.as_ref(); + + let compiled_pattern = super::helpers::expect_pattern(&args[1])?; let matches = compiled_pattern.find_all(text_str); let mut result_list = Vec::new(); @@ -197,38 +146,17 @@ pub fn native_pattern_replace( )); } - let text = match &args[0] { - Value::Text(t) => t.as_ref(), - _ => { - return Err(RuntimeError::new( - "First argument must be text".to_string(), - line, - column, - )); - } - }; - - let _pattern = match &args[1] { - Value::Pattern(p) => p.as_ref(), - _ => { - return Err(RuntimeError::new( - "Second argument must be a pattern".to_string(), - line, - column, - )); - } - }; - - let _replacement = match &args[2] { - Value::Text(t) => t.as_ref(), - _ => { - return Err(RuntimeError::new( - "Third argument must be text".to_string(), - line, - column, - )); - } - }; + let text_arc = super::helpers::expect_text(&args[0]) + .map_err(|e| RuntimeError::new(e.message, line, column))?; + let text = text_arc.as_ref(); + + let _pattern_rc = super::helpers::expect_pattern(&args[1]) + .map_err(|e| RuntimeError::new(e.message, line, column))?; + let _pattern = _pattern_rc.as_ref(); + + let _replacement_arc = super::helpers::expect_text(&args[2]) + .map_err(|e| RuntimeError::new(e.message, line, column))?; + let _replacement = _replacement_arc.as_ref(); // TODO: Update to use new pattern system for replacement Ok(Value::Text(Arc::from(text))) @@ -248,27 +176,12 @@ pub fn native_pattern_split( )); } - let text = match &args[0] { - Value::Text(t) => t.as_ref(), - _ => { - return Err(RuntimeError::new( - "First argument must be text".to_string(), - line, - column, - )); - } - }; - - let pattern = match &args[1] { - Value::Pattern(p) => p, - _ => { - return Err(RuntimeError::new( - "Second argument must be a pattern".to_string(), - line, - column, - )); - } - }; + let text_arc = super::helpers::expect_text(&args[0]) + .map_err(|e| RuntimeError::new(e.message, line, column))?; + let text = text_arc.as_ref(); + + let pattern = super::helpers::expect_pattern(&args[1]) + .map_err(|e| RuntimeError::new(e.message, line, column))?; // Find all matches of the pattern in the text let matches = pattern.find_all(text); diff --git a/src/stdlib/pattern_test.rs b/src/stdlib/pattern_test.rs index a7a4a9a2..e38c61ec 100644 --- a/src/stdlib/pattern_test.rs +++ b/src/stdlib/pattern_test.rs @@ -57,6 +57,11 @@ mod tests { ]; let result = pattern_matches_native(args); assert!(result.is_err()); - assert!(result.unwrap_err().to_string().contains("First argument")); + assert!( + result + .unwrap_err() + .to_string() + .contains("Expected text, got Number") + ); } }