diff options
| author | Melody Horn <melody@boringcactus.com> | 2024-12-16 22:16:20 -0700 | 
|---|---|---|
| committer | Melody Horn <melody@boringcactus.com> | 2024-12-16 22:16:20 -0700 | 
| commit | 35ebe14f47d692f17ec04b7d94f4ac490b297e3e (patch) | |
| tree | 0ff57084631d42a6b6d4bd2934d72321e3ae7374 | |
| parent | 46cbd2994ac20b5ee02072cf2fe37f3c68ca934c (diff) | |
| download | makers-35ebe14f47d692f17ec04b7d94f4ac490b297e3e.tar.gz makers-35ebe14f47d692f17ec04b7d94f4ac490b297e3e.zip  | |
add intcmp function
| -rw-r--r-- | src/args.rs | 35 | ||||
| -rw-r--r-- | src/makefile/functions.rs | 203 | 
2 files changed, 220 insertions, 18 deletions
diff --git a/src/args.rs b/src/args.rs index 40f591f..57ac84c 100644 --- a/src/args.rs +++ b/src/args.rs @@ -540,24 +540,23 @@ mod test {      #[cfg(feature = "full")]      #[test]      fn makeflags_no_print_directory() { -        let args = -            Args { -                environment_overrides: false, -                makefile: vec![], -                ignore_errors: false, -                keep_going: false, -                dry_run: false, -                print_everything: false, -                question: false, -                no_builtin_rules: false, -                no_keep_going: false, -                silent: false, -                touch: false, -                directory: None, -                print_directory: false, -                no_print_directory: true, -                targets_or_macros: vec!["V=1".into()], -            }; +        let args = Args { +            environment_overrides: false, +            makefile: vec![], +            ignore_errors: false, +            keep_going: false, +            dry_run: false, +            print_everything: false, +            question: false, +            no_builtin_rules: false, +            no_keep_going: false, +            silent: false, +            touch: false, +            directory: None, +            print_directory: false, +            no_print_directory: true, +            targets_or_macros: vec!["V=1".into()], +        };          assert_eq!(args.makeflags(), "--no-print-directory V=1");      }  } 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(  |