Skip to content

Commit f045958

Browse files
authored
Merge pull request #16 from nafasebra/stable
Add some string functions in built-in functions
2 parents 56148e7 + 3459890 commit f045958

6 files changed

Lines changed: 131 additions & 0 deletions

File tree

src/builtin_function/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ pub fn function_match(function_name: &str) -> Option<BuiltinFunction> {
8080
"length" | "len" => Some(strings::length::length),
8181
"contains" | "has" => Some(strings::contains::contains),
8282
"slice" | "substring" => Some(strings::slice::slice),
83+
"charat" => Some(strings::char_at::char_at),
84+
"toupper" | "uppercase" => Some(strings::to_upper::to_upper),
85+
"tolower" | "lowercase" => Some(strings::to_lower::to_lower),
86+
"trim" => Some(strings::trim::trim),
8387
"insert" | "push" => Some(list::insert::insert),
8488
"get" | "at" => Some(list::get::get),
8589
"pop" => Some(list::pop::pop),
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use crate::builtin_function::utils::{param_to_datatype, returns};
2+
use crate::common::data_type::DataType;
3+
use crate::common::errors::{ChapError, Result};
4+
use crate::{common::executable::ExecutableLine, runtime::Runtime};
5+
6+
pub fn char_at(runtime: &mut Runtime, executable: &ExecutableLine) -> Result<()> {
7+
let p1 = param_to_datatype(runtime, executable.params.first(), executable.line_number)?;
8+
let p2 = param_to_datatype(runtime, executable.params.get(1), executable.line_number)?;
9+
10+
let (string_value, index) = match (&p1, &p2) {
11+
(DataType::String(s), DataType::Int(i)) => (s, *i),
12+
_ => {
13+
return Err(ChapError::runtime_with_msg(
14+
executable.line_number,
15+
format!(
16+
"{} function requires a string as first parameter and an integer as second parameter",
17+
executable.function_name
18+
),
19+
));
20+
}
21+
};
22+
23+
// Chap uses 1-based indexing, so index must be >= 1
24+
if index < 1 {
25+
return Err(ChapError::runtime_with_msg(
26+
executable.line_number,
27+
format!(
28+
"Index {} is invalid. Index must be 1 or greater (1-based indexing)",
29+
index
30+
),
31+
));
32+
}
33+
34+
let index_usize = index as usize;
35+
36+
// Check if index is within bounds (convert to 0-based for length check)
37+
if index_usize > string_value.len() {
38+
return Err(ChapError::runtime_with_msg(
39+
executable.line_number,
40+
format!(
41+
"Index {} is out of bounds for string of length {}",
42+
index,
43+
string_value.len()
44+
),
45+
));
46+
}
47+
48+
// Get the character at the specified index (convert to 0-based indexing)
49+
let chars: Vec<char> = string_value.chars().collect();
50+
let result_char = chars[index_usize - 1];
51+
let result = DataType::String(result_char.to_string());
52+
53+
returns(runtime, executable, result)
54+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
pub mod char_at;
12
pub mod contact;
23
pub mod contains;
34
pub mod length;
45
pub mod repeat;
56
pub mod slice;
7+
pub mod to_lower;
8+
pub mod to_upper;
9+
pub mod trim;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use crate::builtin_function::utils::{param_to_datatype, returns};
2+
use crate::common::data_type::DataType;
3+
use crate::common::errors::{ChapError, Result};
4+
use crate::{common::executable::ExecutableLine, runtime::Runtime};
5+
6+
pub fn to_lower(runtime: &mut Runtime, executable: &ExecutableLine) -> Result<()> {
7+
let p1 = param_to_datatype(runtime, executable.params.first(), executable.line_number)?;
8+
9+
let result = match p1 {
10+
DataType::String(s) => DataType::String(s.to_lowercase()),
11+
_ => {
12+
return Err(ChapError::runtime_with_msg(
13+
executable.line_number,
14+
format!(
15+
"{} function input param should be string",
16+
executable.function_name
17+
),
18+
));
19+
}
20+
};
21+
22+
returns(runtime, executable, result)
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use crate::builtin_function::utils::{param_to_datatype, returns};
2+
use crate::common::data_type::DataType;
3+
use crate::common::errors::{ChapError, Result};
4+
use crate::{common::executable::ExecutableLine, runtime::Runtime};
5+
6+
pub fn to_upper(runtime: &mut Runtime, executable: &ExecutableLine) -> Result<()> {
7+
let p1 = param_to_datatype(runtime, executable.params.first(), executable.line_number)?;
8+
9+
let result = match p1 {
10+
DataType::String(s) => DataType::String(s.to_uppercase()),
11+
_ => {
12+
return Err(ChapError::runtime_with_msg(
13+
executable.line_number,
14+
format!(
15+
"{} function input param should be string",
16+
executable.function_name
17+
),
18+
));
19+
}
20+
};
21+
22+
returns(runtime, executable, result)
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use crate::builtin_function::utils::{param_to_datatype, returns};
2+
use crate::common::data_type::DataType;
3+
use crate::common::errors::{ChapError, Result};
4+
use crate::{common::executable::ExecutableLine, runtime::Runtime};
5+
6+
pub fn trim(runtime: &mut Runtime, executable: &ExecutableLine) -> Result<()> {
7+
let p1 = param_to_datatype(runtime, executable.params.first(), executable.line_number)?;
8+
9+
let result = match p1 {
10+
DataType::String(s) => DataType::String(s.trim().to_string()),
11+
_ => {
12+
return Err(ChapError::runtime_with_msg(
13+
executable.line_number,
14+
format!(
15+
"{} function input param should be string",
16+
executable.function_name
17+
),
18+
));
19+
}
20+
};
21+
22+
returns(runtime, executable, result)
23+
}

0 commit comments

Comments
 (0)