aboutsummaryrefslogtreecommitdiff
path: root/src/makefile/inference_rules.rs
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2021-04-03 18:01:04 -0600
committerMelody Horn <melody@boringcactus.com>2021-04-03 18:01:04 -0600
commitf73d0b2256f2afc05995929c930b2eeab6800ecf (patch)
tree8c580ae21e50a5d3c166a568bbc5955ffcb341ad /src/makefile/inference_rules.rs
parent7c2a09e5c75d87d5dd728623517899ca7cada630 (diff)
downloadmakers-f73d0b2256f2afc05995929c930b2eeab6800ecf.tar.gz
makers-f73d0b2256f2afc05995929c930b2eeab6800ecf.zip
implement GNUish '%'-based inference rules
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)?;
}