From 32b11f1d8696b2e55fbdd1b51c80473fad8d045b Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Mon, 30 Sep 2024 16:49:48 -0700 Subject: [PATCH] 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 --- src/obj/str.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ src/obj/ty.rs | 4 ++++ 2 files changed, 46 insertions(+) diff --git a/src/obj/str.rs b/src/obj/str.rs index f4d71a0..79b160f 100644 --- a/src/obj/str.rs +++ b/src/obj/str.rs @@ -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::() { + 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() + } } diff --git a/src/obj/ty.rs b/src/obj/ty.rs index 4d12478..dc08b5e 100644 --- a/src/obj/ty.rs +++ b/src/obj/ty.rs @@ -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 },