better hints

This commit is contained in:
Simon Gardling 2022-05-10 14:58:05 -04:00
parent b7c734205d
commit 72943f5e2f
4 changed files with 76 additions and 34 deletions

14
Cargo.lock generated
View File

@ -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",

View File

@ -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" }

View File

@ -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<String>) -> Vec<(String, String)> {
fn compile_hashmap(data: Vec<String>) -> Vec<(String, String)> {
let mut seen = HashSet::new();
let tuple_list_1: Vec<(String, String)> = data

View File

@ -22,13 +22,20 @@ pub fn split_function(input: &str) -> Vec<String> {
.replace("exp", "\u{1fc93}") // stop-gap solution to fix the `exp` function
.chars()
.collect::<Vec<char>>(),
SplitType::Multiplication,
)
.iter()
.map(|x| x.replace("\u{1fc93}", "exp")) // Convert back to `exp` text
.collect::<Vec<String>>()
}
pub fn split_function_chars(chars: &[char]) -> Vec<String> {
#[derive(PartialEq)]
pub enum SplitType {
Multiplication,
Term,
}
pub fn split_function_chars(chars: &[char], split: SplitType) -> Vec<String> {
if chars.is_empty() {
return Vec::new();
}
@ -52,6 +59,7 @@ pub fn split_function_chars(chars: &[char]) -> Vec<String> {
/// 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<String> {
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<String> {
}
}
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<String> {
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<String> {
pub fn generate_hint<'a>(input: &str) -> &'a Hint<'a> {
if input.is_empty() {
return &HINT_EMPTY;
}
} else {
let chars: Vec<char> = input.chars().collect::<Vec<char>>();
let chars: Vec<char> = input.chars().collect::<Vec<char>>();
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::<Vec<char>>().as_slice()),
value
);
}
}
}