Skip to content

Commit

Permalink
Merge pull request #816 from rust-embedded/reexport_enum
Browse files Browse the repository at this point in the history
reexport enum
  • Loading branch information
burrbull authored Feb 25, 2024
2 parents 0a1d951 + 4813f56 commit 11937f2
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 69 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- Add `base-address-shift` config flag
- Use `PascalCase` for type idents, fix case changing bugs, add `--ident-format` (`-f`) option flag
- Add `enum_read_name` for `read-only` enums, `RWEnum` helper
- Reexport enums inside register again

## [v0.31.5] - 2024-01-04

Expand Down
1 change: 1 addition & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub struct Config {
pub reexport_interrupt: bool,
pub ident_formats: IdentFormats,
pub ident_formats_theme: Option<IdentFormatsTheme>,
pub field_names_for_enums: bool,
pub base_address_shift: u64,
}

Expand Down
154 changes: 85 additions & 69 deletions src/generate/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,9 @@ pub fn fields(

// Hack for #625
let mut enum_derives = HashSet::new();
let mut read_enum_derives = HashSet::new();
let mut write_enum_derives = HashSet::new();
let mut reader_derives = HashSet::new();
let mut writer_enum_derives = HashSet::new();
let mut writer_derives = HashSet::new();

// TODO enumeratedValues
Expand Down Expand Up @@ -737,32 +738,35 @@ pub fn fields(

// If this field can be read, generate read proxy structure and value structure.
if can_read {
// get the type of value structure. It can be generated from either name field
// in enumeratedValues if it's an enumeration, or from field name directly if it's not.
// collect information on items in enumeration to generate it later.
let mut enum_items = TokenStream::new();

// if this is an enumeratedValues not derived from base, generate the enum structure
// and implement functions for each value in enumeration.
let value_read_ty = if let Some(ev) = rwenum.read_enum() {
let fmt = if rwenum.different_enums() {
"enum_read_name"
let derives;
let fmt;
if rwenum.different_enums() {
derives = &mut read_enum_derives;
fmt = "enum_read_name";
} else {
"enum_name"
derives = &mut enum_derives;
fmt = "enum_name";
};
ident(
ev.values().name.as_deref().unwrap_or(&name),
// get the type of value structure. It can be generated from either name field
// in enumeratedValues if it's an enumeration, or from field name directly if it's not.
let value_read_ty = ident(
if config.field_names_for_enums {
&name
} else {
ev.values().name.as_deref().unwrap_or(&name)
},
config,
fmt,
span,
)
} else {
// raw_field_value_read_ty
fty.clone()
};

// collect information on items in enumeration to generate it later.
let mut enum_items = TokenStream::new();
);

if let Some(ev) = rwenum.read_enum() {
match ev {
// if this is an enumeratedValues not derived from base, generate the enum structure
// and implement functions for each value in enumeration.
EV::New(evs) => {
// parse enum variants from enumeratedValues svd record
let mut variants = Variant::from_enumerated_values(evs, config)?;
Expand Down Expand Up @@ -909,24 +913,31 @@ pub fn fields(
}
}
EV::Derived(_, base) => {
// only pub use enum when derived from another register.
// If field is in the same register it emits
// pub use enum from same module which is not expected
if base.register() != fpath.register() {
// use the same enum structure name
if !enum_derives.contains(&value_read_ty) {
let base_path =
base_syn_path(base, &fpath, &value_read_ty, config)?;
mod_items.extend(quote! {
#[doc = #description]
pub use #base_path as #value_read_ty;
});
enum_derives.insert(value_read_ty.clone());
}
let base_ident = if config.field_names_for_enums {
ident(
&util::replace_suffix(&base.field().name, ""),
config,
fmt,
span,
)
} else {
ident(&base.name, config, fmt, span)
};
if !derives.contains(&value_read_ty) {
let base_path = base_syn_path(base, &fpath, &base_ident, config)?;
mod_items.extend(quote! {
#[doc = #description]
pub use #base_path as #value_read_ty;
});
}
}
}
}
derives.insert(value_read_ty.clone());
value_read_ty
} else {
// raw_field_value_read_ty
fty.clone()
};

// get a brief description for this field
// the suffix string from field name is removed in brief description.
Expand Down Expand Up @@ -1083,29 +1094,32 @@ pub fn fields(
// If this field can be written, generate write proxy. Generate write value if it differs from
// the read value, or else we reuse read value.
if can_write {
let mut proxy_items = TokenStream::new();
let mut unsafety = unsafety(f.write_constraint.as_ref(), width);

// if we writes to enumeratedValues, generate its structure if it differs from read structure.
let value_write_ty = if let Some(ev) = rwenum.write_enum() {
let fmt = if rwenum.different_enums() {
"enum_write_name"
let derives;
let fmt;
if rwenum.different_enums() {
derives = &mut write_enum_derives;
fmt = "enum_write_name";
} else {
"enum_name"
derives = &mut enum_derives;
fmt = "enum_name";
};
ident(
ev.values().name.as_deref().unwrap_or(&name),
let value_write_ty = ident(
if config.field_names_for_enums {
&name
} else {
ev.values().name.as_deref().unwrap_or(&name)
},
config,
fmt,
span,
)
} else {
// raw_field_value_write_ty
fty.clone()
};
);

let mut proxy_items = TokenStream::new();
let mut unsafety = unsafety(f.write_constraint.as_ref(), width);

if let Some(ev) = rwenum.write_enum() {
match ev {
// if we writes to enumeratedValues, generate its structure if it differs from read structure.
EV::New(evs) => {
// parse variants from enumeratedValues svd record
let mut variants = Variant::from_enumerated_values(evs, config)?;
Expand Down Expand Up @@ -1167,24 +1181,31 @@ pub fn fields(
}
}
EV::Derived(_, base) => {
// If field is in the same register it emits pub use structure from same module.
if base.register() != fpath.register() {
// use the same enum structure name
if rwenum.generate_write_enum()
&& !writer_enum_derives.contains(&value_write_ty)
{
let base_path =
base_syn_path(base, &fpath, &value_write_ty, config)?;
mod_items.extend(quote! {
#[doc = #description]
pub use #base_path as #value_write_ty;
});
writer_enum_derives.insert(value_write_ty.clone());
}
let base_ident = if config.field_names_for_enums {
ident(
&util::replace_suffix(&base.field().name, ""),
config,
fmt,
span,
)
} else {
ident(&base.name, config, fmt, span)
};
if rwenum.generate_write_enum() && !derives.contains(&value_write_ty) {
let base_path = base_syn_path(base, &fpath, &base_ident, config)?;
mod_items.extend(quote! {
#[doc = #description]
pub use #base_path as #value_write_ty;
});
}
}
}
}
derives.insert(value_write_ty.clone());
value_write_ty
} else {
// raw_field_value_write_ty
fty.clone()
};

let mwv = f.modified_write_values.or(rmwv).unwrap_or_default();

Expand Down Expand Up @@ -1238,11 +1259,6 @@ pub fn fields(
});
}
Some(EV::Derived(_, base)) => {
// if base.register == None, derive write from the same module. This is allowed because both
// the generated and source write proxy are in the same module.
// we never reuse writer for writer in different module does not have the same _SPEC strcuture,
// thus we cannot write to current register using re-exported write proxy.

// generate pub use field_1 writer as field_2 writer
let base_field = util::replace_suffix(&base.field.name, "");
let base_w = ident(&base_field, config, "field_writer", span);
Expand Down
8 changes: 8 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,18 @@ Allowed cases are `unchanged` (''), `pascal` ('p'), `constant` ('c') and `snake`
.arg(
Arg::new("ident_formats_theme")
.long("ident-formats-theme")
.alias("ident_formats_theme")
.help("A set of `ident_format` settings. `new` or `legacy`")
.action(ArgAction::Set)
.value_name("THEME"),
)
.arg(
Arg::new("field_names_for_enums")
.long("field-names-for-enums")
.alias("field_names_for_enums")
.action(ArgAction::SetTrue)
.help("Use field name for enumerations even when enumeratedValues has a name"),
)
.arg(
Arg::new("max_cluster_size")
.long("max-cluster-size")
Expand Down

0 comments on commit 11937f2

Please sign in to comment.