aboutsummaryrefslogtreecommitdiff
path: root/src/makefile/inference_rules.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/makefile/inference_rules.rs')
-rw-r--r--src/makefile/inference_rules.rs55
1 files changed, 49 insertions, 6 deletions
diff --git a/src/makefile/inference_rules.rs b/src/makefile/inference_rules.rs
index 3d18730..dfbb07c 100644
--- a/src/makefile/inference_rules.rs
+++ b/src/makefile/inference_rules.rs
@@ -1,19 +1,62 @@
use std::fmt;
-use crate::makefile::command_line::CommandLine;
+use eyre::{eyre, Result};
+use regex::Captures;
+
+use super::command_line::CommandLine;
+use super::pattern::r#match;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct InferenceRule {
- /// POSIX calls this ".s1" but that's not useful.
- pub product: String,
- /// POSIX calls this ".s2" but that's not useful.
- pub prereq: String,
+ pub products: Vec<String>,
+ pub prerequisites: Vec<String>,
pub commands: Vec<CommandLine>,
}
+impl InferenceRule {
+ /// s1 is the product, s2 is the prereq
+ pub fn new_suffix(s1: String, s2: String, commands: Vec<CommandLine>) -> Self {
+ Self {
+ products: vec![format!("%.{}", s1)],
+ prerequisites: vec![format!("%.{}", s2)],
+ commands,
+ }
+ }
+
+ fn first_match<'s, 't: 's>(&'s self, target_name: &'t str) -> Result<Option<Captures<'t>>> {
+ self.products
+ .iter()
+ .map(|pattern| r#match(pattern, target_name))
+ .try_fold(None, |x, y| y.map(|y| x.or(y)))
+ }
+
+ pub fn matches(&self, target_name: &str) -> Result<bool> {
+ self.first_match(target_name).map(|x| x.is_some())
+ }
+
+ pub fn prereqs<'s>(
+ &'s self,
+ target_name: &'s str,
+ ) -> Result<impl Iterator<Item = String> + 's> {
+ let capture = self
+ .first_match(target_name)?
+ .ok_or_else(|| eyre!("asked non-matching inference rule for prerequisites"))?;
+ let percent_expansion = capture.get(1).expect("should've matched the %").as_str();
+ Ok(self
+ .prerequisites
+ .iter()
+ .map(move |p| p.replace('%', percent_expansion)))
+ }
+}
+
impl fmt::Display for InferenceRule {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- writeln!(f, "{}{}:", &self.prereq, &self.product)?;
+ writeln!(
+ f,
+ "{}: {}",
+ self.products.join(" "),
+ self.prerequisites.join(" ")
+ )?;
for command in &self.commands {
writeln!(f, "\t{}", command)?;
}