-
Notifications
You must be signed in to change notification settings - Fork 0
[JULES] Refactor text stdlib to use generic helpers #354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -473,3 +473,46 @@ pub fn expect_datetime(value: &Value) -> Result<Rc<chrono::NaiveDateTime>, Runti | |
| )), | ||
| } | ||
| } | ||
|
|
||
| /// Helper for unary text operations (Text -> Text) | ||
| /// | ||
| /// Handles argument count checking, type extraction, operation execution, | ||
| /// and result wrapping. | ||
| /// | ||
| /// # Arguments | ||
| /// | ||
| /// * `func_name` - Name of the function for error messages | ||
| /// * `args` - Arguments passed to the function | ||
| /// * `op` - The text operation to perform | ||
| pub fn unary_text_op<F>(func_name: &str, args: Vec<Value>, op: F) -> Result<Value, RuntimeError> | ||
| where | ||
| F: Fn(&str) -> String, | ||
| { | ||
| check_arg_count(func_name, &args, 1)?; | ||
| let text = expect_text(&args[0])?; | ||
| Ok(Value::Text(Arc::from(op(&text)))) | ||
| } | ||
|
|
||
| /// Helper for binary text predicates ((Text, Text) -> Bool) | ||
| /// | ||
| /// Handles argument count checking, type extraction, operation execution, | ||
| /// and result wrapping. | ||
| /// | ||
| /// # Arguments | ||
| /// | ||
| /// * `func_name` - Name of the function for error messages | ||
| /// * `args` - Arguments passed to the function | ||
| /// * `op` - The predicate to perform | ||
| pub fn binary_text_predicate<F>( | ||
| func_name: &str, | ||
| args: Vec<Value>, | ||
| op: F, | ||
| ) -> Result<Value, RuntimeError> | ||
| where | ||
| F: Fn(&str, &str) -> bool, | ||
| { | ||
| check_arg_count(func_name, &args, 2)?; | ||
| let a = expect_text(&args[0])?; | ||
| let b = expect_text(&args[1])?; | ||
| Ok(Value::Bool(op(&a, &b))) | ||
|
Comment on lines
+514
to
+517
|
||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,6 @@ | ||||||||||||
| use super::helpers::{check_arg_count, expect_number, expect_text}; | ||||||||||||
| use super::helpers::{ | ||||||||||||
| binary_text_predicate, check_arg_count, expect_number, expect_text, unary_text_op, | ||||||||||||
| }; | ||||||||||||
| use crate::interpreter::environment::Environment; | ||||||||||||
| use crate::interpreter::error::RuntimeError; | ||||||||||||
| use crate::interpreter::value::Value; | ||||||||||||
|
|
@@ -74,19 +76,11 @@ fn parse_key_value_pairs(input: &str, delimiter: char) -> std::collections::Hash | |||||||||||
| // which handles both text and lists | ||||||||||||
|
|
||||||||||||
| pub fn native_touppercase(args: Vec<Value>) -> Result<Value, RuntimeError> { | ||||||||||||
| check_arg_count("touppercase", &args, 1)?; | ||||||||||||
|
|
||||||||||||
| let text = expect_text(&args[0])?; | ||||||||||||
| let uppercase = text.to_uppercase(); | ||||||||||||
| Ok(Value::Text(Arc::from(uppercase))) | ||||||||||||
| unary_text_op("touppercase", args, |s| s.to_uppercase()) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| pub fn native_tolowercase(args: Vec<Value>) -> Result<Value, RuntimeError> { | ||||||||||||
| check_arg_count("tolowercase", &args, 1)?; | ||||||||||||
|
|
||||||||||||
| let text = expect_text(&args[0])?; | ||||||||||||
| let lowercase = text.to_lowercase(); | ||||||||||||
| Ok(Value::Text(Arc::from(lowercase))) | ||||||||||||
| unary_text_op("tolowercase", args, |s| s.to_lowercase()) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| pub fn native_substring(args: Vec<Value>) -> Result<Value, RuntimeError> { | ||||||||||||
|
|
@@ -135,29 +129,15 @@ pub fn native_string_split(args: Vec<Value>) -> Result<Value, RuntimeError> { | |||||||||||
| } | ||||||||||||
|
|
||||||||||||
| pub fn native_trim(args: Vec<Value>) -> Result<Value, RuntimeError> { | ||||||||||||
| check_arg_count("trim", &args, 1)?; | ||||||||||||
|
|
||||||||||||
| let text = expect_text(&args[0])?; | ||||||||||||
| let trimmed = text.trim(); | ||||||||||||
| Ok(Value::Text(Arc::from(trimmed))) | ||||||||||||
| unary_text_op("trim", args, |s| s.trim().to_string()) | ||||||||||||
|
||||||||||||
| unary_text_op("trim", args, |s| s.trim().to_string()) | |
| check_arg_count("trim", &args, 1)?; | |
| let text = expect_text(&args[0])?; | |
| let trimmed = text.trim(); | |
| Ok(Value::Text(Arc::from(trimmed))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These calls rely on deref coercions from
&Arc<str>to&str(op(&text)/op(&a, &b)), which is valid but a bit opaque. For readability and to make the intended types explicit, prefer passingtext.as_ref()(anda.as_ref(),b.as_ref()) into the closures.