Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions src/transform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,18 @@ impl std::fmt::Debug for NameCollisionErrors {
}
}

fn rename_opt(s: &mut Option<String>, f: impl Fn(&mut String)) {
fn rename_opt(s: &mut Option<String>, 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);
}
}

Expand All @@ -80,42 +80,42 @@ 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);
}
}
}

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);
Expand Down Expand Up @@ -191,7 +191,7 @@ pub fn map_descriptions(ir: &mut IR, mut ff: impl FnMut(&str) -> String) -> anyh
fn remap_names<T>(
kind: NameKind,
x: &mut BTreeMap<String, T>,
f: impl Fn(&mut String),
mut f: impl FnMut(&mut String),
) -> Result<(), NameCollisionErrors> {
let mut res = BTreeMap::new();
let mut errs = HashSet::new();
Expand Down
69 changes: 57 additions & 12 deletions src/transform/rename.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
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,
Device,
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)]
Expand All @@ -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(())
Expand Down
28 changes: 7 additions & 21 deletions src/transform/rename_interrupts.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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)
}
}
28 changes: 7 additions & 21 deletions src/transform/rename_peripherals.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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)
}
}