This commit is contained in:
Simon Gardling
2023-03-07 10:05:37 -05:00
parent 9a8f8a6539
commit b37a6223bc
15 changed files with 919 additions and 862 deletions

View File

@@ -10,13 +10,13 @@ description = "Parsing library for YTBN-Graphing-Software"
[lib]
[dependencies]
phf = { version = "0.10", no-default-features = true }
phf = { version = "0.11", no-default-features = true }
exmex = { git = "https://github.com/bertiqwerty/exmex.git", branch = "main", features = [
"partial",
] }
[build-dependencies]
phf_codegen = { version = "0.10", no-default-features = true }
phf_codegen = { version = "0.11", no-default-features = true }
[package.metadata.cargo-all-features]
skip_optional_dependencies = true #don't test optional dependencies, only features

View File

@@ -25,7 +25,7 @@ pub fn compile_hashmap(data: Vec<String>) -> Vec<(String, String)> {
let mut seen_3: HashSet<String> = HashSet::new();
for (key, value) in tuple_list_1.iter() {
if seen_3.contains(&*key) {
if seen_3.contains(key) {
continue;
}
@@ -33,18 +33,20 @@ pub fn compile_hashmap(data: Vec<String>) -> Vec<(String, String)> {
let count_keys = keys.iter().filter(|a| a == &&key).count();
if count_keys == 1 {
output.push((key.clone(), format!(r#"Hint::Single("{}")"#, value)));
} else if count_keys > 1 {
let mut multi_data = tuple_list_1
.iter()
.filter(|(a, _)| a == key)
.map(|(_, b)| b)
.collect::<Vec<&String>>();
multi_data.sort_unstable_by(|a, b| compare_len_reverse_alpha(a, b));
output.push((key.clone(), format!("Hint::Many(&{:?})", multi_data)));
} else {
panic!("Number of values for {key} is 0!");
match count_keys.cmp(&1usize) {
Ordering::Less => {
panic!("Number of values for {key} is 0!");
}
Ordering::Greater => {
let mut multi_data = tuple_list_1
.iter()
.filter(|(a, _)| a == key)
.map(|(_, b)| b)
.collect::<Vec<&String>>();
multi_data.sort_unstable_by(|a, b| compare_len_reverse_alpha(a, b));
output.push((key.clone(), format!("Hint::Many(&{:?})", multi_data)));
}
Ordering::Equal => output.push((key.clone(), format!(r#"Hint::Single("{}")"#, value))),
}
}

View File

@@ -26,12 +26,7 @@ impl FlatExWrapper {
fn partial(&self, x: usize) -> Self {
self.func
.as_ref()
.map(|f| {
f.clone()
.partial(x)
.map(|a| Self::new(a))
.unwrap_or(Self::EMPTY)
})
.map(|f| f.clone().partial(x).map(Self::new).unwrap_or(Self::EMPTY))
.unwrap_or(Self::EMPTY)
}
@@ -44,8 +39,8 @@ impl FlatExWrapper {
.as_ref()
.map(|f| {
f.clone()
.partial_iter((0..=n).map(|_| 0).into_iter())
.map(|a| Self::new(a))
.partial_iter((0..=n).map(|_| 0))
.map(Self::new)
.unwrap_or(Self::EMPTY)
})
.unwrap_or(Self::EMPTY)
@@ -151,8 +146,7 @@ impl BackingFunction {
/// Get string relating to the nth derivative
pub fn get_nth_derivative_str(&self) -> &str {
&self
.nth_derivative
self.nth_derivative
.as_ref()
.map(|a| a.2.as_str())
.unwrap_or("")
@@ -207,6 +201,6 @@ pub fn process_func_str(function_in: &str) -> String {
return String::new();
}
crate::suggestions::split_function(&function_in, crate::suggestions::SplitType::Multiplication)
crate::suggestions::split_function(function_in, crate::suggestions::SplitType::Multiplication)
.join("*")
}

View File

@@ -25,11 +25,11 @@ pub fn split_function(input: &str, split: SplitType) -> Vec<String> {
split,
)
.iter()
.map(|x| x.replace("\u{1fc93}", "exp")) // Convert back to `exp` text
.map(|x| x.replace('\u{1fc93}', "exp")) // Convert back to `exp` text
.collect::<Vec<String>>()
}
#[derive(PartialEq)]
#[derive(PartialEq, Debug)]
pub enum SplitType {
Multiplication,
Term,
@@ -108,7 +108,7 @@ pub fn split_function_chars(chars: &[char], split: SplitType) -> Vec<String> {
const fn splitable(&self, c: &char, other: &BoolSlice, split: &SplitType) -> bool {
if (*c == '*') | (matches!(split, &SplitType::Term) && other.open_parens) {
return true;
true
} else if other.closing_parens {
// Cases like `)x`, `)2`, and `)(`
return (*c == '(')
@@ -131,11 +131,8 @@ pub fn split_function_chars(chars: &[char], split: SplitType) -> Vec<String> {
&& (other.is_unmasked_number() | other.letter)
{
return true;
} else if self.is_unmasked_number() && other.is_unmasked_variable() {
// Cases like `x2`
return true;
} else {
return false;
return self.is_unmasked_number() && other.is_unmasked_variable();
}
}
}
@@ -173,7 +170,7 @@ pub fn split_function_chars(chars: &[char], split: SplitType) -> Vec<String> {
/// Generate a hint based on the input `input`, returns an `Option<String>`
pub fn generate_hint<'a>(input: &str) -> &'a Hint<'a> {
if input.is_empty() {
return &HINT_EMPTY;
&HINT_EMPTY
} else {
let chars: Vec<char> = input.chars().collect::<Vec<char>>();
@@ -181,8 +178,16 @@ pub fn generate_hint<'a>(input: &str) -> &'a Hint<'a> {
assume(!chars.is_empty());
}
if let Some(hint) = COMPLETION_HASHMAP.get(get_last_term(&chars).as_str()) {
return hint;
let key = get_last_term(&chars);
match key {
Some(key) => {
if let Some(hint) = COMPLETION_HASHMAP.get(&key) {
return hint;
}
}
None => {
return &Hint::None;
}
}
let mut open_parens: usize = 0;
@@ -197,21 +202,17 @@ pub fn generate_hint<'a>(input: &str) -> &'a Hint<'a> {
return &HINT_CLOSED_PARENS;
}
return &Hint::None;
&Hint::None
}
}
pub fn get_last_term(chars: &[char]) -> String {
assert!(!chars.is_empty());
pub fn get_last_term(chars: &[char]) -> Option<String> {
if chars.is_empty() {
return None;
}
let mut result = split_function_chars(chars, SplitType::Term);
unsafe {
assume(!result.is_empty());
assume(result.len() > 0);
let output = result.pop();
assume(output.is_some());
output.unwrap_unchecked()
}
result.pop()
}
#[derive(PartialEq, Clone, Copy)]
@@ -225,13 +226,13 @@ impl<'a> std::fmt::Display for Hint<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Hint::Single(single_data) => {
return write!(f, "{}", single_data);
write!(f, "{}", single_data)
}
Hint::Many(multi_data) => {
return write!(f, "{:?}", multi_data);
write!(f, "{:?}", multi_data)
}
Hint::None => {
return write!(f, "None");
write!(f, "None")
}
}
}
@@ -277,3 +278,33 @@ impl<'a> Hint<'a> {
}
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
#[cfg(test)]
fn assert_test(input: &str, expected: &[&str], split: SplitType) {
let output = split_function("sin(x)cos(x)", SplitType::Multiplication);
let expected_owned = expected
.iter()
.map(|&x| x.to_owned())
.collect::<Vec<String>>();
if output != expected_owned {
panic!(
"split type: {:?} of {} resulted in {:?} not {:?}",
split, input, output, expected
);
}
}
#[test]
fn split_function_test() {
assert_test(
"sin(x)cos(x)",
&["sin(x)", "cos(x)"],
SplitType::Multiplication,
);
assert_test(
"tanh(cos(x)xx)cos(x)",
&["tanh(cos(x)", "x", "x)", "cos(x)"],
SplitType::Multiplication,
);
}