From 8748f46fe1c8b3f9e7b4483ea8111a938c07c0b8 Mon Sep 17 00:00:00 2001 From: Rowan Torbitzky-Lane Date: Tue, 15 Apr 2025 19:11:15 -0500 Subject: [PATCH] More vector instructions --- src/instructions/mod.rs | 56 +++++++- src/instructions/vector.rs | 265 ++++++++++++++++++++++++++++++++++++- 2 files changed, 314 insertions(+), 7 deletions(-) diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index 342296c..081d6a6 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -129,7 +129,7 @@ pub mod macros { for _ in 0..$fn_arity { state.$in_stack.pop(); } - state.$out_stack.extend(result.iter()); + state.$out_stack.extend(result.into_iter()); } } } @@ -204,6 +204,42 @@ pub mod macros { }; } + /// Same as make_instruction_mult but can handle one auxiliary variable. + #[macro_export] + macro_rules! make_instruction_mult_aux { + ($in_stack:ident, $out_stack:ident, $fn_name:ident, $fn_type:ty, $fn_arity:stmt, $aux_stack:ident, $aux_arity:stmt, $aux_type:ty) => { + paste::item! { + /// Runs the $fn_name function on the top $fn_arity items from + /// the $in_stack and places the calculated value on the $out_stack. + /// $aux_stack is also used and popped $aux_arity time(s). + pub fn [< $in_stack $fn_name >] (state: &mut PushState) { + let in_stack_len = state.$in_stack.len(); + let aux_stack_len = state.$aux_stack.len(); + if in_stack_len < $fn_arity || aux_stack_len < $aux_arity { + return; + } + let mut inputs: Vec<$fn_type> = Vec::with_capacity($fn_arity); + let mut aux_inputs: Vec<$aux_type> = Vec::with_capacity($aux_arity); + for n in 1..=$aux_arity { + aux_inputs.push(state.$aux_stack[aux_stack_len - n].clone()); + } + for n in 1..=$fn_arity { + inputs.push(state.$in_stack[in_stack_len - n].clone()); + } + if let Some(result) = $fn_name(inputs, aux_inputs) { + for _ in 0..$aux_arity { + state.$aux_stack.pop(); + } + for _ in 0..$fn_arity { + state.$in_stack.pop(); + } + state.$out_stack.extend(result.into_iter()); + } + } + } + }; + } + /// Same as `make_instruction!` but can work on three stacks. Is there a way /// to generalize even this? /// @@ -377,8 +413,11 @@ pub fn string_instructions() -> Vec { string_index_of_vector, string_occurrences_of, string_occurrences_of_vector, + string_parse_to_prim, string_set_nth, + string_split_on, string_replace, + string_remove, // common.rs string_pop, ] @@ -436,8 +475,11 @@ pub fn vector_int_instructions() -> Vec { vector_int_index_of_vector, vector_int_occurrences_of, vector_int_occurrences_of_vector, + vector_int_parse_to_prim, vector_int_set_nth, + vector_int_split_on, vector_int_replace, + vector_int_remove, // common.rs vector_int_pop, ] @@ -474,8 +516,11 @@ pub fn vector_float_instructions() -> Vec { vector_float_index_of_vector, vector_float_occurrences_of, vector_float_occurrences_of_vector, + vector_float_parse_to_prim, vector_float_set_nth, + vector_float_split_on, vector_float_replace, + vector_float_remove, // common.rs vector_float_pop, ] @@ -511,8 +556,11 @@ pub fn vector_string_instructions() -> Vec { vector_string_index_of_vector, vector_string_occurrences_of, vector_string_occurrences_of_vector, + vector_string_parse_to_prim, vector_string_set_nth, + vector_string_split_on, vector_string_replace, + vector_string_remove, // common.rs vector_string_pop, ] @@ -549,8 +597,11 @@ pub fn vector_boolean_instructions() -> Vec { vector_boolean_index_of_vector, vector_boolean_occurrences_of, vector_boolean_occurrences_of_vector, + vector_boolean_parse_to_prim, vector_boolean_set_nth, + vector_boolean_split_on, vector_boolean_replace, + vector_boolean_remove, // common.rs vector_boolean_pop, ] @@ -587,8 +638,11 @@ pub fn vector_char_instructions() -> Vec { vector_char_index_of_vector, vector_char_occurrences_of, vector_char_occurrences_of_vector, + vector_char_parse_to_prim, vector_char_set_nth, + vector_char_split_on, vector_char_replace, + vector_char_remove, // common.rs vector_char_pop, ] diff --git a/src/instructions/vector.rs b/src/instructions/vector.rs index a076245..80a8f40 100644 --- a/src/instructions/vector.rs +++ b/src/instructions/vector.rs @@ -980,9 +980,10 @@ make_instruction_aux!( ); make_instruction_aux!(string, int, _occurrences_of, Vec, 1, char, 1, char); +/// Counts the amount of continuous occurrences one vector appears in another. pub fn _occurrences_of_vector(vals: Vec>) -> Option where - T: Eq + Hash, + T: Eq, { if vals[0].is_empty() { return Some(0); @@ -1007,13 +1008,27 @@ make_instruction_clone!(vector_boolean, int, _occurrences_of_vector, Vec, make_instruction_clone!(vector_char, int, _occurrences_of_vector, Vec, 2); make_instruction_clone!(string, int, _occurrences_of_vector, Vec, 2); -/// Pushes the values inside a vector to a primitive stack. -pub fn _parse_to_prim(vals: Vec>) -> Option> +/// Pushes the values inside a vector separated into individual vectors back to +/// the stack. +pub fn _parse_to_prim(vals: Vec>) -> Option>> where T: Clone, + Vec: FromIterator, { - Some(vals[0].clone()) + Some(vals[0].clone().into_iter().map(|x| vec![x]).collect()) } +make_instruction_mult!(vector_int, vector_int, _parse_to_prim, Vec, 1); +make_instruction_mult!(vector_float, vector_float, _parse_to_prim, Vec, 1); +make_instruction_mult!( + vector_string, + vector_string, + _parse_to_prim, + Vec>, + 1 +); +make_instruction_mult!(vector_boolean, vector_boolean, _parse_to_prim, Vec, 1); +make_instruction_mult!(vector_char, vector_char, _parse_to_prim, Vec, 1); +make_instruction_mult!(string, string, _parse_to_prim, Vec, 1); /// Sets the nth index in a vector. N from the int stack. pub fn _set_nth(vals: Vec>, aux0: Vec, aux1: Vec) -> Option> @@ -1104,8 +1119,129 @@ make_instruction_aux2!( i128 ); -/// Replaces all values in a vector with respect to two ints. The first int is the search value -/// and the second value is the one to replace. +/// Splits a vector based the first occurence of a primitive +pub fn _split_on(vals: Vec>, auxs: Vec) -> Option>> +where + T: Clone + Eq, + Vec: FromIterator, +{ + let mut final_vec = vec![]; + let mut temp_vec = vec![]; + for val in vals[0].iter() { + if &auxs[0] == val { + final_vec.push(temp_vec.clone()); + temp_vec.clear(); + continue; + } + temp_vec.push(val.clone()); + } + if !temp_vec.is_empty() { + final_vec.push(temp_vec); + } + Some(final_vec) +} +make_instruction_mult_aux!( + vector_int, + vector_int, + _split_on, + Vec, + 1, + int, + 1, + i128 +); +make_instruction_mult_aux!( + vector_float, + vector_float, + _split_on, + Vec, + 1, + float, + 1, + Decimal +); +make_instruction_mult_aux!( + vector_string, + vector_string, + _split_on, + Vec>, + 1, + string, + 1, + Vec +); +make_instruction_mult_aux!( + vector_boolean, + vector_boolean, + _split_on, + Vec, + 1, + boolean, + 1, + bool +); +make_instruction_mult_aux!( + vector_char, + vector_char, + _split_on, + Vec, + 1, + char, + 1, + char +); +make_instruction_mult_aux!(string, string, _split_on, Vec, 1, char, 1, char); + +/*/// Splits a vector based the first occurence of a primitive +pub fn _split_on_vector(vals: Vec>) -> Option>> +where + T: Clone + Eq, +{ + if vals[0].is_empty() { + return Some(vec![vals[1]]); + } + let mut final_vec = vec![]; + let mut temp_vec = vec![]; + for val in vals[1].windows(vals[0].len()) { + if &auxs[0] == val { + final_vec.push(temp_vec.clone()); + temp_vec.clear(); + continue; + } + temp_vec.push(val.clone()); + } + if !temp_vec.is_empty() { + final_vec.push(temp_vec); + } + Some(final_vec) +} +make_instruction_mult!(vector_int, vector_int, _split_on_vector, Vec, 1); +make_instruction_mult!( + vector_float, + vector_float, + _split_on_vector, + Vec, + 1 +); +make_instruction_mult!( + vector_string, + vector_string, + _split_on_vector, + Vec>, + 1 +); +make_instruction_mult!( + vector_boolean, + vector_boolean, + _split_on_vector, + Vec, + 1 +); +make_instruction_mult!(vector_char, vector_char, _split_on_vector, Vec, 1); +make_instruction_mult!(string, string, _split_on_vector, Vec, 1);*/ + +/// Replaces all values in a vector with respect to two primitives. The first primitive is +/// the search value and the second value is the one to replace. pub fn _replace(mut vals: Vec>, auxs: Vec) -> Option> where T: Clone, @@ -1168,6 +1304,64 @@ make_instruction_aux!( ); make_instruction_aux!(string, string, _replace, Vec, 1, char, 2, char); +/// Removes all values in a vector with respect to a primitives. If is equal, remove it. +pub fn _remove(vals: Vec>, auxs: Vec) -> Option> +where + T: Clone, + for<'a> &'a T: Eq, + Vec: FromIterator, +{ + let temp_vec = &vals[0]; + let ret_vec = temp_vec + .iter() + .filter(|&x| x != &auxs[0]) + .cloned() + .collect(); + Some(ret_vec) +} +make_instruction_aux!(vector_int, vector_int, _remove, Vec, 1, int, 1, i128); +make_instruction_aux!( + vector_float, + vector_float, + _remove, + Vec, + 1, + float, + 1, + Decimal +); +make_instruction_aux!( + vector_string, + vector_string, + _remove, + Vec>, + 1, + string, + 1, + Vec +); +make_instruction_aux!( + vector_boolean, + vector_boolean, + _remove, + Vec, + 1, + boolean, + 1, + bool +); +make_instruction_aux!( + vector_char, + vector_char, + _remove, + Vec, + 1, + char, + 1, + char +); +make_instruction_aux!(string, string, _remove, Vec, 1, char, 1, char); + #[cfg(test)] mod tests { use super::*; @@ -1732,6 +1926,45 @@ mod tests { assert_eq!(vec![vec![true, false, true]], test_state.vector_boolean); } + #[test] + fn parse_to_prim_test() { + let mut test_state = EMPTY_STATE; + + test_state.vector_int = vec![vec![0, 1, 2]]; + vector_int_parse_to_prim(&mut test_state); + assert_eq!(vec![vec![0], vec![1], vec![2]], test_state.vector_int); + } + + #[test] + fn split_on_test() { + let mut test_state = EMPTY_STATE; + + test_state.vector_int = vec![vec![0, 1, 2]]; + test_state.int = vec![1]; + vector_int_split_on(&mut test_state); + assert_eq!(vec![vec![0], vec![2]], test_state.vector_int); + + test_state.vector_int = vec![vec![0, 1, 2, 1, 5]]; + test_state.int = vec![1]; + vector_int_split_on(&mut test_state); + assert_eq!(vec![vec![0], vec![2], vec![5]], test_state.vector_int); + + test_state.vector_int = vec![vec![0, 1, 2, 1]]; + test_state.int = vec![1]; + vector_int_split_on(&mut test_state); + assert_eq!(vec![vec![0], vec![2]], test_state.vector_int); + + test_state.vector_int = vec![vec![0, 1, 2, 1]]; + test_state.int = vec![9]; + vector_int_split_on(&mut test_state); + assert_eq!(vec![vec![0, 1, 2, 1]], test_state.vector_int); + + test_state.vector_int = vec![vec![0, 1, 2, 3]]; + test_state.int = vec![3]; + vector_int_split_on(&mut test_state); + assert_eq!(vec![vec![0, 1, 2]], test_state.vector_int); + } + #[test] fn replace_test() { let mut test_state = EMPTY_STATE; @@ -1741,4 +1974,24 @@ mod tests { vector_int_replace(&mut test_state); assert_eq!(vec![vec![0, 1, 3, 3, 4, 5, 3]], test_state.vector_int); } + + #[test] + fn remove_test() { + let mut test_state = EMPTY_STATE; + + test_state.vector_int = vec![vec![0, 1, 2, 3, 4, 5, 2]]; + test_state.int = vec![3]; + vector_int_remove(&mut test_state); + assert_eq!(vec![vec![0, 1, 2, 4, 5, 2]], test_state.vector_int); + + test_state.vector_int = vec![vec![0, 1, 2, 3, 4, 5, 2]]; + test_state.int = vec![2]; + vector_int_remove(&mut test_state); + assert_eq!(vec![vec![0, 1, 3, 4, 5]], test_state.vector_int); + + test_state.vector_int = vec![vec![0, 1, 2, 3, 4, 5, 2]]; + test_state.int = vec![9]; + vector_int_remove(&mut test_state); + assert_eq!(vec![vec![0, 1, 2, 3, 4, 5, 2]], test_state.vector_int); + } }