diff --git a/src/transform/mod.rs b/src/transform/mod.rs index cb3e33b6..b129650e 100644 --- a/src/transform/mod.rs +++ b/src/transform/mod.rs @@ -55,18 +55,18 @@ impl std::fmt::Debug for NameCollisionErrors { } } -fn rename_opt(s: &mut Option, f: impl Fn(&mut String)) { +fn rename_opt(s: &mut Option, mut f: impl FnMut(&mut String)) { if let Some(s) = s { f(s) } } -pub fn map_block_names(ir: &mut IR, f: impl Fn(&mut String)) { - remap_names(NameKind::Block, &mut ir.blocks, &f).unwrap(); +pub fn map_block_names(ir: &mut IR, mut f: impl FnMut(&mut String)) { + remap_names(NameKind::Block, &mut ir.blocks, &mut f).unwrap(); for (_, d) in ir.devices.iter_mut() { for p in &mut d.peripherals { - rename_opt(&mut p.block, &f); + rename_opt(&mut p.block, &mut f); } } @@ -80,34 +80,34 @@ pub fn map_block_names(ir: &mut IR, f: impl Fn(&mut String)) { } } -pub fn map_fieldset_names(ir: &mut IR, f: impl Fn(&mut String)) { - remap_names(NameKind::Fieldset, &mut ir.fieldsets, &f).unwrap(); +pub fn map_fieldset_names(ir: &mut IR, mut f: impl FnMut(&mut String)) { + remap_names(NameKind::Fieldset, &mut ir.fieldsets, &mut f).unwrap(); for (_, b) in ir.blocks.iter_mut() { for i in b.items.iter_mut() { match &mut i.inner { BlockItemInner::Block(_p) => {} - BlockItemInner::Register(r) => rename_opt(&mut r.fieldset, &f), + BlockItemInner::Register(r) => rename_opt(&mut r.fieldset, &mut f), } } } } -pub fn map_enum_names(ir: &mut IR, f: impl Fn(&mut String)) { - remap_names(NameKind::Enum, &mut ir.enums, &f).unwrap(); +pub fn map_enum_names(ir: &mut IR, mut f: impl FnMut(&mut String)) { + remap_names(NameKind::Enum, &mut ir.enums, &mut f).unwrap(); for (_, fs) in ir.fieldsets.iter_mut() { for ff in fs.fields.iter_mut() { - rename_opt(&mut ff.enumm, &f); + rename_opt(&mut ff.enumm, &mut f); } } } -pub fn map_device_names(ir: &mut IR, f: impl Fn(&mut String)) { - remap_names(NameKind::Device, &mut ir.devices, &f).unwrap(); +pub fn map_device_names(ir: &mut IR, f: impl FnMut(&mut String)) { + remap_names(NameKind::Device, &mut ir.devices, f).unwrap(); } -pub fn map_device_interrupt_names(ir: &mut IR, f: impl Fn(&mut String)) { +pub fn map_device_interrupt_names(ir: &mut IR, mut f: impl FnMut(&mut String)) { for (_, d) in ir.devices.iter_mut() { for i in &mut d.interrupts { f(&mut i.name); @@ -115,7 +115,7 @@ pub fn map_device_interrupt_names(ir: &mut IR, f: impl Fn(&mut String)) { } } -pub fn map_device_peripheral_names(ir: &mut IR, f: impl Fn(&mut String)) { +pub fn map_device_peripheral_names(ir: &mut IR, mut f: impl FnMut(&mut String)) { for (_, d) in ir.devices.iter_mut() { for p in &mut d.peripherals { f(&mut p.name); @@ -191,7 +191,7 @@ pub fn map_descriptions(ir: &mut IR, mut ff: impl FnMut(&str) -> String) -> anyh fn remap_names( kind: NameKind, x: &mut BTreeMap, - f: impl Fn(&mut String), + mut f: impl FnMut(&mut String), ) -> Result<(), NameCollisionErrors> { let mut res = BTreeMap::new(); let mut errs = HashSet::new(); diff --git a/src/transform/rename.rs b/src/transform/rename.rs index 22bdf88a..c984a1e1 100644 --- a/src/transform/rename.rs +++ b/src/transform/rename.rs @@ -1,9 +1,13 @@ +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; + use serde::{Deserialize, Serialize}; use super::common::*; use crate::ir::*; -#[derive(Debug, Serialize, Deserialize, Default)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] pub enum RenameType { #[default] All, @@ -11,6 +15,23 @@ pub enum RenameType { Block, Fieldset, Enum, + Interrupt, + Peripheral, +} + +impl RenameType { + pub fn fmt<'a>(&self) -> impl Fn(String) -> String + 'a { + let me = *self; + move |name: String| match me { + RenameType::All => unimplemented!(), + RenameType::Device => format!("device {name}"), + RenameType::Block => format!("block {name}"), + RenameType::Fieldset => format!("fieldset {name}"), + RenameType::Enum => format!("enum {name}"), + RenameType::Interrupt => format!("interrupt {name}"), + RenameType::Peripheral => format!("peripheral {name}"), + } + } } #[derive(Debug, Serialize, Deserialize)] @@ -19,27 +40,51 @@ pub struct Rename { pub to: String, #[serde(default)] pub r#type: RenameType, + #[serde(default = "get_true")] + pub error_on_duplicate: bool, } impl Rename { pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> { - let renamer = |name: &mut String| { - if let Some(res) = match_expand(name, &self.from, &self.to) { - *name = res + let had_duplicates = Rc::new(RefCell::new(false)); + + let renamer = |ty: RenameType| { + let mut state = HashMap::new(); + let had_duplicates = had_duplicates.clone(); + let eod = self.error_on_duplicate; + + move |name: &mut String| { + if let Some(res) = match_expand(name, &self.from, &self.to) { + *had_duplicates.borrow_mut() |= + !can_rename(eod, &mut state, &res, name, ty.fmt()); + *name = res + } } }; match self.r#type { RenameType::All => { - super::map_device_names(ir, renamer); - super::map_block_names(ir, renamer); - super::map_fieldset_names(ir, renamer); - super::map_enum_names(ir, renamer); + super::map_device_names(ir, renamer(RenameType::Device)); + super::map_block_names(ir, renamer(RenameType::Block)); + super::map_fieldset_names(ir, renamer(RenameType::Fieldset)); + super::map_enum_names(ir, renamer(RenameType::Enum)); + super::map_device_interrupt_names(ir, renamer(RenameType::Interrupt)); + super::map_device_peripheral_names(ir, renamer(RenameType::Peripheral)); + } + RenameType::Device => super::map_device_names(ir, renamer(RenameType::Device)), + RenameType::Block => super::map_block_names(ir, renamer(RenameType::Block)), + RenameType::Fieldset => super::map_fieldset_names(ir, renamer(RenameType::Fieldset)), + RenameType::Enum => super::map_enum_names(ir, renamer(RenameType::Enum)), + RenameType::Interrupt => { + super::map_device_interrupt_names(ir, renamer(RenameType::Interrupt)) + } + RenameType::Peripheral => { + super::map_device_peripheral_names(ir, renamer(RenameType::Peripheral)) } - RenameType::Device => super::map_device_names(ir, renamer), - RenameType::Block => super::map_block_names(ir, renamer), - RenameType::Fieldset => super::map_fieldset_names(ir, renamer), - RenameType::Enum => super::map_enum_names(ir, renamer), + } + + if *had_duplicates.borrow() && self.error_on_duplicate { + anyhow::bail!("Failed to rename interrupts"); } Ok(()) diff --git a/src/transform/rename_interrupts.rs b/src/transform/rename_interrupts.rs index 89d505b8..a9f8c6d6 100644 --- a/src/transform/rename_interrupts.rs +++ b/src/transform/rename_interrupts.rs @@ -1,9 +1,8 @@ -use std::collections::HashMap; - use serde::{Deserialize, Serialize}; use super::common::*; use crate::ir::*; +use crate::transform::rename::{Rename, RenameType}; #[derive(Debug, Serialize, Deserialize)] pub struct RenameInterrupts { @@ -15,25 +14,12 @@ pub struct RenameInterrupts { impl RenameInterrupts { pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> { - let mut had_duplicate = false; - - for (dev_name, d) in ir.devices.iter_mut() { - let mut renames = HashMap::new(); - let fmt = |itr| format!("interrupt {itr} for device {dev_name}"); - - for i in &mut d.interrupts { - if let Some(name) = match_expand(&i.name, &self.from, &self.to) { - had_duplicate |= - !can_rename(self.error_on_duplicate, &mut renames, &name, &i.name, fmt); - i.name = name; - } - } + Rename { + from: self.from.clone(), + to: self.to.clone(), + r#type: RenameType::Interrupt, + error_on_duplicate: self.error_on_duplicate, } - - if had_duplicate && self.error_on_duplicate { - anyhow::bail!("Failed to rename interrupts"); - } - - Ok(()) + .run(ir) } } diff --git a/src/transform/rename_peripherals.rs b/src/transform/rename_peripherals.rs index 99985922..786d977d 100644 --- a/src/transform/rename_peripherals.rs +++ b/src/transform/rename_peripherals.rs @@ -1,9 +1,8 @@ -use std::collections::HashMap; - use serde::{Deserialize, Serialize}; use super::common::*; use crate::ir::*; +use crate::transform::rename::{Rename, RenameType}; #[derive(Debug, Serialize, Deserialize)] pub struct RenamePeripherals { @@ -15,25 +14,12 @@ pub struct RenamePeripherals { impl RenamePeripherals { pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> { - let mut had_duplicate = false; - - for (dev_name, d) in ir.devices.iter_mut() { - let mut renames = HashMap::new(); - let fmt = |peri| format!("peripheral {peri} for device {dev_name}"); - - for p in &mut d.peripherals { - if let Some(name) = match_expand(&p.name, &self.from, &self.to) { - had_duplicate |= - !can_rename(self.error_on_duplicate, &mut renames, &name, &p.name, fmt); - p.name = name; - } - } + Rename { + from: self.from.clone(), + to: self.to.clone(), + r#type: RenameType::Peripheral, + error_on_duplicate: self.error_on_duplicate, } - - if had_duplicate && self.error_on_duplicate { - anyhow::bail!("Failed to rename peripherals"); - } - - Ok(()) + .run(ir) } }