Add Str::index and Str::to_list

Strings can be converted to a list of strings, split up by character.

Strings can also be indexed by character.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2024-09-30 16:49:48 -07:00
parent dab474a037
commit 32b11f1d86
2 changed files with 46 additions and 0 deletions

View File

@@ -101,6 +101,14 @@ impl Str {
}
}
pub(crate) fn to_list(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let this = vm.frame_stack()[0].clone();
let list_items = with_obj_downcast(this, |str: &Str| {
str.str_value().chars().map(|c| Str::create(c)).collect()
});
List::create(list_items).into()
}
pub(crate) fn len(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let len = with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &Str| {
str_inst.str_value().len() as i64
@@ -141,4 +149,38 @@ impl Str {
let new = format!("{}", lhs.borrow()).repeat(repeat_count);
Str::create(new).into()
}
pub(crate) fn index(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let this = vm.frame_stack()[0].clone();
let index_obj = vm.frame_stack()[1].clone();
let index = if let Some(index_obj) = index_obj.borrow().as_any().downcast_ref::<Int>() {
index_obj.int_value()
} else {
// TODO Str::index - throw an exception when the index object is not an integer
// BLOCKED-ON: exceptions
todo!("throw an exception when the index object is not an integer")
};
// TODO Str::index - maybe there is a way we can optimize this, because both getting the
// length in characters plus getting the nth character can be slow if we're doing UTF-8
// lookups. Maybe cache the length of the string in the Str struct?
let c = with_obj_downcast(this, |str: &Str| {
let len = str.str_value().chars().count();
let mut index = index;
if index < 0 {
index = len as i64 + index;
}
if index < 0 || index as usize >= len {
// TODO Str::index - throw an exception when the index is out of range
// BLOCKED-ON: exceptions
todo!("throw an exception when the str index is out of range")
} else {
str.str_value().chars().nth(index as usize).unwrap()
}
});
Str::create(c).into()
}
}

View File

@@ -157,6 +157,7 @@ pub fn init_types() {
to_bool => BuiltinFunction::create("to_bool", BaseObj::to_bool, 1),
to_int => BuiltinFunction::create("to_int", BaseObj::not_implemented_un, 1),
to_float => BuiltinFunction::create("to_float", BaseObj::not_implemented_un, 1),
to_list => BuiltinFunction::create("to_list", BaseObj::not_implemented_un, 1),
len => BuiltinFunction::create("len", BaseObj::not_implemented_un, 1),
// Constructor
@@ -204,6 +205,7 @@ pub fn init_types() {
to_str => BuiltinFunction::create("to_str", Str::to_str, 1),
to_int => BuiltinFunction::create("to_int", Str::to_int, 1),
to_float => BuiltinFunction::create("to_float", Str::to_float, 1),
to_list => BuiltinFunction::create("to_list", Str::to_list, 1),
len => BuiltinFunction::create("len", Str::len, 1),
// Constructor
@@ -214,6 +216,8 @@ pub fn init_types() {
__add__ => BuiltinFunction::create("__add__", Str::add, 2),
__mul__ => BuiltinFunction::create("__mul__", Str::mul, 2),
__index__ => BuiltinFunction::create("__index__", Str::index, 2),
// Methods
// TODO Str methods - .lower, .upper, .slice, etc
},