diff --git a/src/patch/peripheral.rs b/src/patch/peripheral.rs index 2935aa4..8a16820 100644 --- a/src/patch/peripheral.rs +++ b/src/patch/peripheral.rs @@ -247,9 +247,11 @@ pub(crate) trait RegisterBlockExt: Name { /// Remove fields from rname and mark it as derivedFrom rderive. /// Update all derivedFrom referencing rname fn derive_register(&mut self, rspec: &str, rderive: &Yaml, bpath: &BlockPath) -> PatchResult { - let (rderive, info) = if let Some(rderive) = rderive.as_str() { + let (rspec, ignore) = rspec.spec(); + let (rderive, dim, info) = if let Some(rderive) = rderive.as_str() { ( rderive, + None, RegisterInfo::builder().derived_from(Some(rderive.into())), ) } else if let Some(hash) = rderive.as_hash() { @@ -258,6 +260,7 @@ pub(crate) trait RegisterBlockExt: Name { })?; ( rderive, + make_dim_element(hash)?, make_register(hash, Some(bpath))?.derived_from(Some(rderive.into())), ) } else { @@ -277,15 +280,24 @@ pub(crate) trait RegisterBlockExt: Name { })?; } + let rtags = self.iter_registers(rspec).collect::>(); let mut found = Vec::new(); - for register in self.iter_registers(rspec) { - found.push(register.name.to_string()); - register.modify_from(info.clone(), VAL_LVL)?; - } - if found.is_empty() { + if !rtags.is_empty() { + for rtag in rtags { + found.push(rtag.name.to_string()); + modify_dim_element(rtag, &dim)?; + rtag.modify_from(info.clone(), VAL_LVL)?; + } + } else if !ignore { super::check_dimable_name(rspec)?; - let register = info.name(rspec.into()).build(VAL_LVL)?.single(); - self.add_child(RegisterCluster::Register(register)); + let reg = info.name(rspec.into()).build(VAL_LVL)?; + self.add_child(RegisterCluster::Register({ + if let Some(dim) = dim { + reg.array(dim.build(VAL_LVL)?) + } else { + reg.single() + } + })); } for rname in found { for r in self diff --git a/src/patch/register.rs b/src/patch/register.rs index 7552d3a..cd85e4c 100644 --- a/src/patch/register.rs +++ b/src/patch/register.rs @@ -289,10 +289,16 @@ impl RegisterExt for Register { } fn modify_field(&mut self, fspec: &str, fmod: &Hash, rpath: &RegisterPath) -> PatchResult { + let (fspec, ignore) = fspec.spec(); let ftags = self.iter_fields(fspec).collect::>(); let field_builder = make_field(fmod, Some(rpath))?; let dim = make_dim_element(fmod)?; - if !ftags.is_empty() { + if ftags.is_empty() && !ignore { + let present = self.present_fields(); + return Err(anyhow!( + "Could not find `{rpath}:{fspec}. Present fields: {present}.`" + )); + } else { for ftag in ftags { modify_dim_element(ftag, &dim)?; if let Some(value) = fmod @@ -362,28 +368,39 @@ impl RegisterExt for Register { dpath.into() } } - let info = if let Some(dpath) = fderive.as_str() { - FieldInfo::builder().derived_from(Some(make_path(dpath, rpath))) + let (fspec, ignore) = fspec.spec(); + let (dim, info) = if let Some(dpath) = fderive.as_str() { + ( + None, + FieldInfo::builder().derived_from(Some(make_path(dpath, rpath))), + ) } else if let Some(hash) = fderive.as_hash() { let dpath = hash.get_str("_from")?.ok_or_else(|| { anyhow!("derive: source field not given, please add a _from field to {fspec}") })?; - make_field(hash, Some(rpath))?.derived_from(Some(make_path(dpath, rpath))) + ( + make_dim_element(hash)?, + make_field(hash, Some(rpath))?.derived_from(Some(make_path(dpath, rpath))), + ) } else { return Err(anyhow!("derive: incorrect syntax for {fspec}")); }; - - let mut found = false; - for field in self.iter_fields(fspec) { - found = true; - field.modify_from(info.clone(), VAL_LVL)?; - } - if !found { - { - super::check_dimable_name(fspec)?; - let field = info.name(fspec.into()).build(VAL_LVL)?.single(); - self.fields.get_or_insert(Vec::new()).push(field); - } + let ftags = self.iter_fields(fspec).collect::>(); + if !ftags.is_empty() { + for ftag in ftags { + modify_dim_element(ftag, &dim)?; + ftag.modify_from(info.clone(), VAL_LVL)?; + } + } else if !ignore { + super::check_dimable_name(fspec)?; + let field = info.name(fspec.into()).build(VAL_LVL)?; + self.fields.get_or_insert(Vec::new()).push({ + if let Some(dim) = dim { + field.array(dim.build(VAL_LVL)?) + } else { + field.single() + } + }); } Ok(()) }