aboutsummaryrefslogtreecommitdiff
path: root/src/makefile/functions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/makefile/functions.rs')
-rw-r--r--src/makefile/functions.rs203
1 files changed, 203 insertions, 0 deletions
diff --git a/src/makefile/functions.rs b/src/makefile/functions.rs
index 05f6750..a6a2db1 100644
--- a/src/makefile/functions.rs
+++ b/src/makefile/functions.rs
@@ -109,6 +109,18 @@ pub fn expand_call(
assert!(!args.is_empty());
conditional::and(stack, args.iter(), eval_context)
}
+ "intcmp" => {
+ assert!(2 <= args.len() && args.len() <= 5);
+ conditional::intcmp(
+ stack,
+ &args[0],
+ &args[1],
+ args.get(2),
+ args.get(3),
+ args.get(4),
+ eval_context,
+ )
+ }
"foreach" => {
assert_eq!(args.len(), 3);
@@ -466,7 +478,11 @@ mod file_name {
// Functions for Conditionals
mod conditional {
+ use std::borrow::Cow;
+ use std::cmp::Ordering;
+
use super::*;
+ use eyre::eyre;
pub fn r#if(
stack: &MacroScopeStack,
@@ -517,6 +533,51 @@ mod conditional {
}
Ok(last)
}
+
+ pub fn intcmp<'a>(
+ stack: &MacroScopeStack,
+ lhs: &TokenString,
+ rhs: &TokenString,
+ lt_part: Option<&TokenString>,
+ eq_part: Option<&TokenString>,
+ gt_part: Option<&TokenString>,
+ mut eval_context: Option<&mut DeferredEvalContext<impl BufRead>>,
+ ) -> Result<String> {
+ let raw_lhs_value = stack.expand(lhs, eval_context.as_deref_mut())?;
+ let raw_rhs_value = stack.expand(rhs, eval_context.as_deref_mut())?;
+ let lhs_value: i64 = raw_lhs_value.parse()?;
+ let rhs_value: i64 = raw_rhs_value.parse()?;
+ let cmp = lhs_value.cmp(&rhs_value);
+
+ // defaults are a bit of a mess
+ let mut lt_part = lt_part.map(Cow::Borrowed);
+ let mut eq_part = eq_part.map(Cow::Borrowed);
+ let mut gt_part = gt_part.map(Cow::Borrowed);
+ if lt_part.is_none() && eq_part.is_none() && gt_part.is_none() {
+ lt_part = Some(Cow::Owned(TokenString::empty()));
+ // not just reusing lhs param since expansion could have a side effect
+ eq_part = Some(Cow::Owned(TokenString::text(raw_lhs_value)));
+ gt_part = Some(Cow::Owned(TokenString::empty()));
+ }
+ if eq_part.is_none() {
+ eq_part = Some(Cow::Owned(TokenString::empty()));
+ }
+ if gt_part.is_none() {
+ gt_part = eq_part.clone();
+ }
+
+ let lt_part = lt_part.ok_or_else(|| eyre!("intcmp defaults failed"))?;
+ let eq_part = eq_part.ok_or_else(|| eyre!("intcmp defaults failed"))?;
+ let gt_part = gt_part.ok_or_else(|| eyre!("intcmp defaults failed"))?;
+
+ let result = match cmp {
+ Ordering::Less => lt_part,
+ Ordering::Equal => eq_part,
+ Ordering::Greater => gt_part,
+ };
+
+ stack.expand(&result, eval_context.as_deref_mut())
+ }
}
pub fn foreach(
@@ -854,6 +915,148 @@ mod test {
}
#[test]
+ fn intcmp() -> R {
+ assert_eq!(
+ call(
+ "intcmp",
+ &[TokenString::text("1"), TokenString::text("2")],
+ &MacroSet::new()
+ )?,
+ ""
+ );
+ assert_eq!(
+ call(
+ "intcmp",
+ &[TokenString::text("2"), TokenString::text("2")],
+ &MacroSet::new()
+ )?,
+ "2"
+ );
+
+ assert_eq!(
+ call(
+ "intcmp",
+ &[
+ TokenString::text("1"),
+ TokenString::text("2"),
+ TokenString::text("a")
+ ],
+ &MacroSet::new()
+ )?,
+ "a"
+ );
+ assert_eq!(
+ call(
+ "intcmp",
+ &[
+ TokenString::text("2"),
+ TokenString::text("2"),
+ TokenString::text("a")
+ ],
+ &MacroSet::new()
+ )?,
+ ""
+ );
+ assert_eq!(
+ call(
+ "intcmp",
+ &[
+ TokenString::text("3"),
+ TokenString::text("2"),
+ TokenString::text("a")
+ ],
+ &MacroSet::new()
+ )?,
+ ""
+ );
+
+ assert_eq!(
+ call(
+ "intcmp",
+ &[
+ TokenString::text("1"),
+ TokenString::text("2"),
+ TokenString::text("a"),
+ TokenString::text("b")
+ ],
+ &MacroSet::new()
+ )?,
+ "a"
+ );
+ assert_eq!(
+ call(
+ "intcmp",
+ &[
+ TokenString::text("2"),
+ TokenString::text("2"),
+ TokenString::text("a"),
+ TokenString::text("b")
+ ],
+ &MacroSet::new()
+ )?,
+ "b"
+ );
+ assert_eq!(
+ call(
+ "intcmp",
+ &[
+ TokenString::text("3"),
+ TokenString::text("2"),
+ TokenString::text("a"),
+ TokenString::text("b")
+ ],
+ &MacroSet::new()
+ )?,
+ "b"
+ );
+
+ assert_eq!(
+ call(
+ "intcmp",
+ &[
+ TokenString::text("1"),
+ TokenString::text("2"),
+ TokenString::text("a"),
+ TokenString::text("b"),
+ TokenString::text("c")
+ ],
+ &MacroSet::new()
+ )?,
+ "a"
+ );
+ assert_eq!(
+ call(
+ "intcmp",
+ &[
+ TokenString::text("2"),
+ TokenString::text("2"),
+ TokenString::text("a"),
+ TokenString::text("b"),
+ TokenString::text("c")
+ ],
+ &MacroSet::new()
+ )?,
+ "b"
+ );
+ assert_eq!(
+ call(
+ "intcmp",
+ &[
+ TokenString::text("3"),
+ TokenString::text("2"),
+ TokenString::text("a"),
+ TokenString::text("b"),
+ TokenString::text("c")
+ ],
+ &MacroSet::new()
+ )?,
+ "c"
+ );
+
+ Ok(())
+ }
+
+ #[test]
fn foreach() -> R {
let mut macros = MacroSet::new();
macros.set(