Skip to content

Commit

Permalink
add support for include/exclude regexes in transforms.
Browse files Browse the repository at this point in the history
  • Loading branch information
Dirbaio committed Nov 14, 2024
1 parent 0b2cebe commit ac05c84
Show file tree
Hide file tree
Showing 18 changed files with 177 additions and 110 deletions.
113 changes: 104 additions & 9 deletions src/transform/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,105 @@ use std::collections::{BTreeMap, BTreeSet};

use crate::ir::*;

pub(crate) fn make_regex(r: &str) -> Result<regex::Regex, regex::Error> {
regex::Regex::new(&format!("^{}$", r))
#[derive(Debug, Clone)]
pub struct RegexSet {
include: Vec<regex::Regex>,
exclude: Vec<regex::Regex>,
}

impl RegexSet {
pub fn captures<'h>(&self, haystack: &'h str) -> Option<regex::Captures<'h>> {
for r in &self.exclude {
if r.is_match(haystack) {
return None;
}
}
for r in &self.include {
if let Some(c) = r.captures(haystack) {
return Some(c);
}
}
None
}

pub fn is_match(&self, haystack: &str) -> bool {
for r in &self.exclude {
if r.is_match(haystack) {
return false;
}
}
for r in &self.include {
if r.is_match(haystack) {
return true;
}
}
false
}
}

impl<'de> Deserialize<'de> for RegexSet {
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
fn make_regex(r: &str) -> Result<regex::Regex, regex::Error> {
regex::Regex::new(&format!("^{}$", r))
}

#[derive(Deserialize)]
#[serde(untagged)]
enum VecOrString {
One(String),
Many(Vec<String>),
}
impl VecOrString {
fn regexes(self) -> Vec<regex::Regex> {
let strs = match self {
VecOrString::Many(s) => s,
VecOrString::One(s) => vec![s],
};
strs.into_iter().map(|s| make_regex(&s).unwrap()).collect()
}
}

impl Default for VecOrString {
fn default() -> Self {
Self::Many(vec![])
}
}

#[derive(Deserialize)]
#[serde(untagged)]
enum Inner {
String(String),
Complex {
include: VecOrString,
#[serde(default)]
exclude: VecOrString,
},
}

let x = Inner::deserialize(de)?;
match x {
Inner::String(s) => Ok(RegexSet {
include: vec![make_regex(&s).unwrap()],
exclude: vec![],
}),
Inner::Complex { include, exclude } => Ok(RegexSet {
include: include.regexes(),
exclude: exclude.regexes(),
}),
}
}
}

impl Serialize for RegexSet {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
todo!()
}
}

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Serialize, Deserialize)]
Expand Down Expand Up @@ -154,7 +251,7 @@ pub(crate) fn check_mergeable_fieldsets_inner(
Ok(())
}

pub(crate) fn match_all(set: impl Iterator<Item = String>, re: &regex::Regex) -> BTreeSet<String> {
pub(crate) fn match_all(set: impl Iterator<Item = String>, re: &RegexSet) -> BTreeSet<String> {
let mut ids: BTreeSet<String> = BTreeSet::new();
for id in set {
if re.is_match(&id) {
Expand All @@ -166,7 +263,7 @@ pub(crate) fn match_all(set: impl Iterator<Item = String>, re: &regex::Regex) ->

pub(crate) fn match_groups(
set: impl Iterator<Item = String>,
re: &regex::Regex,
re: &RegexSet,
to: &str,
) -> BTreeMap<String, BTreeSet<String>> {
let mut groups: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
Expand All @@ -184,7 +281,7 @@ pub(crate) fn match_groups(
groups
}

pub(crate) fn match_expand(s: &str, regex: &regex::Regex, res: &str) -> Option<String> {
pub(crate) fn match_expand(s: &str, regex: &RegexSet, res: &str) -> Option<String> {
let m = regex.captures(s)?;
let mut dst = String::new();
m.expand(res, &mut dst);
Expand Down Expand Up @@ -299,14 +396,12 @@ pub(crate) fn calc_array(mut offsets: Vec<u32>, mode: ArrayMode) -> anyhow::Resu
// filter enum by enum name, then copy variant description
pub(crate) fn extract_variant_desc(
ir: &IR,
enum_names: &str,
enum_names: &RegexSet,
bit_size: Option<u32>,
) -> anyhow::Result<BTreeMap<String, String>> {
let re = make_regex(enum_names)?;

let mut enum_desc_pair: BTreeMap<String, String> = BTreeMap::new();
for (e_name, e_struct) in ir.enums.iter().filter(|(e_name, e_struct)| {
bit_size.map_or(true, |s| s == e_struct.bit_size) && re.is_match(e_name)
bit_size.map_or(true, |s| s == e_struct.bit_size) && enum_names.is_match(e_name)
}) {
let variant_desc_str = e_struct.variants.iter().fold(String::new(), |mut acc, v| {
acc.push_str(
Expand Down
10 changes: 4 additions & 6 deletions src/transform/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,14 @@ use crate::ir::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct Delete {
pub from: String,
pub from: RegexSet,
}

impl Delete {
pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> {
let re = make_regex(&self.from)?;

let mut ids: BTreeSet<String> = BTreeSet::new();
for (id, _fs) in ir.fieldsets.iter() {
if re.is_match(id) {
if self.from.is_match(id) {
info!("deleting fieldset {}", id);
ids.insert(id.clone());
}
Expand All @@ -30,7 +28,7 @@ impl Delete {

let mut ids: BTreeSet<String> = BTreeSet::new();
for (id, _e) in ir.enums.iter() {
if re.is_match(id) {
if self.from.is_match(id) {
info!("deleting enum {}", id);
ids.insert(id.clone());
}
Expand All @@ -44,7 +42,7 @@ impl Delete {

let mut ids: BTreeSet<String> = BTreeSet::new();
for (id, _b) in ir.blocks.iter() {
if re.is_match(id) {
if self.from.is_match(id) {
info!("deleting block {}", id);
ids.insert(id.clone());
}
Expand Down
6 changes: 2 additions & 4 deletions src/transform/delete_enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::ir::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct DeleteEnums {
pub from: String,
pub from: RegexSet,
pub bit_size: Option<u32>,
#[serde(default)]
pub soft: bool,
Expand All @@ -21,12 +21,10 @@ impl DeleteEnums {
append_variant_desc_to_field(ir, &variant_desc, self.bit_size);
}

let re = make_regex(&self.from)?;

let mut ids: BTreeSet<String> = BTreeSet::new();
for (id, e) in ir.enums.iter() {
let bit_size_matches = self.bit_size.map_or(true, |s| s == e.bit_size);
if re.is_match(id) && bit_size_matches {
if self.from.is_match(id) && bit_size_matches {
info!("deleting enum {}", id);
ids.insert(id.clone());
}
Expand Down
5 changes: 2 additions & 3 deletions src/transform/delete_enums_used_in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,17 @@ use crate::ir::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct DeleteEnumsUsedIn {
pub fieldsets: String,
pub fieldsets: RegexSet,
#[serde(default)]
pub soft: bool,
}

impl DeleteEnumsUsedIn {
pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> {
let re = make_regex(&self.fieldsets)?;
let mut ids: BTreeSet<String> = BTreeSet::new();

for (id, fs) in ir.fieldsets.iter() {
if re.is_match(id) {
if self.fieldsets.is_match(id) {
info!("matched fieldset {}", id);
for f in &fs.fields {
if let Some(id) = &f.enumm {
Expand Down
6 changes: 2 additions & 4 deletions src/transform/delete_fieldsets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::ir::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct DeleteFieldsets {
pub from: String,
pub from: RegexSet,
#[serde(default)]
pub useless: bool,
#[serde(default)]
Expand All @@ -16,11 +16,9 @@ pub struct DeleteFieldsets {

impl DeleteFieldsets {
pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> {
let re = make_regex(&self.from)?;

let mut ids: BTreeSet<String> = BTreeSet::new();
for (id, fs) in ir.fieldsets.iter() {
if re.is_match(id) && (!self.useless | is_useless(fs)) {
if self.from.is_match(id) && (!self.useless | is_useless(fs)) {
info!("deleting fieldset {}", id);
ids.insert(id.clone());
}
Expand Down
10 changes: 4 additions & 6 deletions src/transform/delete_registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ use crate::ir::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct DeleteRegisters {
pub block: String,
pub from: String,
pub block: RegexSet,
pub from: RegexSet,
}

impl DeleteRegisters {
pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> {
let path_re = make_regex(&self.block)?;
let re = make_regex(&self.from)?;
for id in match_all(ir.blocks.keys().cloned(), &path_re) {
for id in match_all(ir.blocks.keys().cloned(), &self.block) {
let b = ir.blocks.get_mut(&id).unwrap();
b.items.retain(|i| !re.is_match(&i.name));
b.items.retain(|i| !self.from.is_match(&i.name));
}
Ok(())
}
Expand Down
16 changes: 9 additions & 7 deletions src/transform/make_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@ use crate::ir::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct MakeBlock {
pub blocks: String,
pub from: String,
pub blocks: RegexSet,
pub from: RegexSet,
pub to_outer: String,
pub to_block: String,
pub to_inner: String,
}

impl MakeBlock {
pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> {
let path_re = make_regex(&self.blocks)?;
let re = make_regex(&self.from)?;
for id in match_all(ir.blocks.keys().cloned(), &path_re) {
for id in match_all(ir.blocks.keys().cloned(), &self.blocks) {
let b = ir.blocks.get_mut(&id).unwrap();
let groups = match_groups(b.items.iter().map(|f| f.name.clone()), &re, &self.to_outer);
let groups = match_groups(
b.items.iter().map(|f| f.name.clone()),
&self.from,
&self.to_outer,
);
for (to, group) in groups {
let b = ir.blocks.get_mut(&id).unwrap();
info!("blockifizing to {}", to);
Expand Down Expand Up @@ -48,7 +50,7 @@ impl MakeBlock {
.iter()
.map(|&i| {
let mut i = i.clone();
i.name = match_expand(&i.name, &re, &self.to_inner).unwrap();
i.name = match_expand(&i.name, &self.from, &self.to_inner).unwrap();
i.byte_offset -= byte_offset;
i
})
Expand Down
14 changes: 8 additions & 6 deletions src/transform/make_field_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ use crate::ir::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct MakeFieldArray {
pub fieldsets: String,
pub from: String,
pub fieldsets: RegexSet,
pub from: RegexSet,
pub to: String,
#[serde(default)]
pub mode: ArrayMode,
}

impl MakeFieldArray {
pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> {
let path_re = make_regex(&self.fieldsets)?;
let re = make_regex(&self.from)?;
for id in match_all(ir.fieldsets.keys().cloned(), &path_re) {
for id in match_all(ir.fieldsets.keys().cloned(), &self.fieldsets) {
let b = ir.fieldsets.get_mut(&id).unwrap();
let groups = match_groups(b.fields.iter().map(|f| f.name.clone()), &re, &self.to);
let groups = match_groups(
b.fields.iter().map(|f| f.name.clone()),
&self.from,
&self.to,
);
for (to, group) in groups {
info!("arrayizing to {}", to);

Expand Down
10 changes: 4 additions & 6 deletions src/transform/make_register_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@ use crate::ir::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct MakeRegisterArray {
pub blocks: String,
pub from: String,
pub blocks: RegexSet,
pub from: RegexSet,
pub to: String,
#[serde(default)]
pub mode: ArrayMode,
}

impl MakeRegisterArray {
pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> {
let path_re = make_regex(&self.blocks)?;
let re = make_regex(&self.from)?;
for id in match_all(ir.blocks.keys().cloned(), &path_re) {
for id in match_all(ir.blocks.keys().cloned(), &self.blocks) {
let b = ir.blocks.get_mut(&id).unwrap();
let groups = match_groups(b.items.iter().map(|f| f.name.clone()), &re, &self.to);
let groups = match_groups(b.items.iter().map(|f| f.name.clone()), &self.from, &self.to);
for (to, group) in groups {
info!("arrayizing to {}", to);

Expand Down
Loading

0 comments on commit ac05c84

Please sign in to comment.