diff --git a/Cargo.lock b/Cargo.lock index 9dd599f..0dbcc32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1374,15 +1374,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.1" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" dependencies = [ "bitflags", - "cc", "cfg-if 1.0.0", "libc", - "memoffset", ] [[package]] @@ -1746,9 +1744,9 @@ dependencies = [ [[package]] name = "pprof" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2324292407eab69d4ace0eed1524fe612ac37c98aa22b0d868355b17fada530" +checksum = "6f9307de92566887d485ac6f20df17b0fe1704fffdbad0bdbc05a3864d3082f6" dependencies = [ "backtrace", "cfg-if 1.0.0", @@ -1756,7 +1754,7 @@ dependencies = [ "inferno", "libc", "log", - "nix 0.23.1", + "nix 0.24.1", "once_cell", "parking_lot 0.12.0", "smallvec", @@ -1939,7 +1937,7 @@ dependencies = [ [[package]] name = "ruzstd" version = "0.2.4" -source = "git+https://github.com/Titaniumtown/zstd-rs.git?branch=ringbuffer#b89410c7a25135e9caff80df2a82d322debd2644" +source = "git+https://github.com/Titaniumtown/zstd-rs.git?branch=ringbuffer#56972fa1fe8b188ad2f1f54fe1fe35d9479a2d9f" dependencies = [ "byteorder", "twox-hash", diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index 1fe2902..fe93c7e 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -7,7 +7,7 @@ license = "AGPL-3.0" [lib] [dependencies] -pprof = { version = "0.8", features = ["flamegraph"] } +pprof = { version = "0.9", features = ["flamegraph"] } criterion = "0.3" criterion-macro = "0.3" parsing = { path = "../parsing" } diff --git a/parsing/src/autocomplete_helper.rs b/parsing/src/autocomplete_helper.rs index ea6147d..5a9b3ae 100644 --- a/parsing/src/autocomplete_helper.rs +++ b/parsing/src/autocomplete_helper.rs @@ -11,7 +11,7 @@ fn compare_len_reverse_alpha(a: &String, b: &String) -> Ordering { /// Generates hashmap (well really a vector of tuple of strings that are then turned into a hashmap by phf) #[allow(dead_code)] -pub(crate) fn compile_hashmap(data: Vec) -> Vec<(String, String)> { +fn compile_hashmap(data: Vec) -> Vec<(String, String)> { let mut seen = HashSet::new(); let tuple_list_1: Vec<(String, String)> = data diff --git a/parsing/src/suggestions.rs b/parsing/src/suggestions.rs index 39710cd..69ea01c 100644 --- a/parsing/src/suggestions.rs +++ b/parsing/src/suggestions.rs @@ -22,13 +22,20 @@ pub fn split_function(input: &str) -> Vec { .replace("exp", "\u{1fc93}") // stop-gap solution to fix the `exp` function .chars() .collect::>(), + SplitType::Multiplication, ) .iter() .map(|x| x.replace("\u{1fc93}", "exp")) // Convert back to `exp` text .collect::>() } -pub fn split_function_chars(chars: &[char]) -> Vec { +#[derive(PartialEq)] +pub enum SplitType { + Multiplication, + Term, +} + +pub fn split_function_chars(chars: &[char], split: SplitType) -> Vec { if chars.is_empty() { return Vec::new(); } @@ -52,6 +59,7 @@ pub fn split_function_chars(chars: &[char]) -> Vec { /// Used to store info about a character struct BoolSlice { closing_parens: bool, + open_parens: bool, number: bool, letter: bool, variable: bool, @@ -65,6 +73,7 @@ pub fn split_function_chars(chars: &[char]) -> Vec { let isvariable = is_variable(c); Self { closing_parens: *c == ')', + open_parens: *c == '(', number: isnumber, letter: c.is_ascii_alphabetic(), variable: isvariable, @@ -101,8 +110,8 @@ pub fn split_function_chars(chars: &[char]) -> Vec { } } - const fn splitable(&self, c: &char, other: &BoolSlice) -> bool { - if *c == '*' { + fn splitable(&self, c: &char, other: &BoolSlice, split: &SplitType) -> bool { + if (c == &'*') | ((split == &SplitType::Term) && other.open_parens) { return true; } else if other.closing_parens { // Cases like `)x`, `)2`, and `)(` @@ -147,13 +156,13 @@ pub fn split_function_chars(chars: &[char]) -> Vec { curr_c.calculate_mask(&prev_char); // Append split - if curr_c.splitable(c, &prev_char) { + if curr_c.splitable(c, &prev_char, &split) { data.push(String::new()); last = unsafe { data.last_mut().unwrap_unchecked() }; } // Exclude asterisks - if *c != '*' { + if c != &'*' { last.push(*c); } @@ -168,29 +177,42 @@ pub fn split_function_chars(chars: &[char]) -> Vec { pub fn generate_hint<'a>(input: &str) -> &'a Hint<'a> { if input.is_empty() { return &HINT_EMPTY; - } + } else { + let chars: Vec = input.chars().collect::>(); - let chars: Vec = input.chars().collect::>(); + unsafe { + assume(!chars.is_empty()); + } + + if let Some(hint) = COMPLETION_HASHMAP.get(get_last_term(&chars).as_str()) { + return hint; + } + + let mut open_parens: usize = 0; + let mut closed_parens: usize = 0; + chars.iter().for_each(|chr| match *chr { + '(' => open_parens += 1, + ')' => closed_parens += 1, + _ => {} + }); + + if open_parens > closed_parens { + return &HINT_CLOSED_PARENS; + } + + return &Hint::None; + } +} + +fn get_last_term(chars: &[char]) -> String { + assert!(!chars.is_empty()); unsafe { - assume(!chars.is_empty()); + split_function_chars(chars, SplitType::Term) + .last() + .unwrap_unchecked() + .to_owned() } - - let mut open_parens: usize = 0; - let mut closed_parens: usize = 0; - chars.iter().for_each(|chr| match *chr { - '(' => open_parens += 1, - ')' => closed_parens += 1, - _ => {} - }); - - if open_parens > closed_parens { - return &HINT_CLOSED_PARENS; - } - - COMPLETION_HASHMAP - .get(&unsafe { split_function_chars(&chars).last().unwrap_unchecked() }.as_str()) - .unwrap_or(&Hint::None) } #[derive(PartialEq)] @@ -253,6 +275,7 @@ mod tests { ("ln(x)", Hint::None), ("ln(x)cos", Hint::Many(&["(", "h("])), ("ln(x)*cos", Hint::Many(&["(", "h("])), + ("sin(cos", Hint::Many(&["(", "h("])), ]); for (key, value) in values { @@ -350,4 +373,25 @@ mod tests { assert!(!hint.is_single()); } } + + #[test] + fn get_last_term() { + let values = HashMap::from([ + ("cos(x)", "x)"), + ("cos(", "cos("), + ("aaaaaaaaaaa", "aaaaaaaaaaa"), + ("x", "x"), + ("xxx", "x"), + ("x*x", "x"), + ("10*10", "10"), + ("sin(cos", "cos"), + ]); + + for (key, value) in values { + assert_eq!( + super::get_last_term(key.chars().collect::>().as_slice()), + value + ); + } + } }