diff --git a/CHANGELOG.md b/CHANGELOG.md index ddc3446e..23d2bb78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Improve field enum docs +### Changed + +- Bump dependencies: `syn`, `quote` and `proc_macro2` v1.0. + ## [v0.16.0] - 2019-08-05 ### Added diff --git a/Cargo.toml b/Cargo.toml index 76800d75..0f445acf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,9 +38,10 @@ env_logger = "~0.5" error-chain = "0.11.0" inflections = "1.1.0" log = { version = "~0.4", features = ["std"] } -quote = "0.3.15" +quote = "1.0" svd-parser = "0.7" +proc-macro2 = "1.0" [dependencies.syn] -version = "0.11.11" -features = ["full"] +version = "1.0" +features = ["full","extra-traits"] diff --git a/src/generate/device.rs b/src/generate/device.rs index c45666a4..44e18ec8 100644 --- a/src/generate/device.rs +++ b/src/generate/device.rs @@ -1,8 +1,8 @@ -use quote::{Tokens, ToTokens}; +use quote::ToTokens; +use proc_macro2::{TokenStream, Ident, Span}; use std::fs::File; use std::io::Write; use crate::svd::Device; -use syn::Ident; use crate::errors::*; use crate::util::{self, ToSanitizedUpperCase}; @@ -17,7 +17,7 @@ pub fn render( nightly: bool, generic_mod: bool, device_x: &mut String, -) -> Result> { +) -> Result> { let mut out = vec![]; let doc = format!( @@ -143,8 +143,7 @@ pub fn render( if generic_mod { writeln!(File::create("generic.rs").unwrap(), "{}", generic_file).unwrap(); } else { - let mut tokens = Tokens::new(); - (syn::parse_crate(generic_file)?).to_tokens(&mut tokens); + let tokens = syn::parse_file(generic_file).unwrap().into_token_stream(); out.push(quote! { #[allow(unused_imports)] @@ -177,7 +176,7 @@ pub fn render( } let p = p.name.to_sanitized_upper_case(); - let id = Ident::from(&*p); + let id = Ident::new(&p, Span::call_site()); fields.push(quote! { #[doc = #p] pub #id: #id @@ -185,10 +184,11 @@ pub fn render( exprs.push(quote!(#id: #id { _marker: PhantomData })); } + let span = Span::call_site(); let take = match target { - Target::CortexM => Some(Ident::from("cortex_m")), - Target::Msp430 => Some(Ident::from("msp430")), - Target::RISCV => Some(Ident::from("riscv")), + Target::CortexM => Some(Ident::new("cortex_m", span)), + Target::Msp430 => Some(Ident::new("msp430", span)), + Target::RISCV => Some(Ident::new("riscv", span)), Target::None => None, } .map(|krate| { diff --git a/src/generate/interrupt.rs b/src/generate/interrupt.rs index 297fe22a..fc94ae9f 100644 --- a/src/generate/interrupt.rs +++ b/src/generate/interrupt.rs @@ -2,9 +2,8 @@ use std::collections::HashMap; use std::fmt::Write; use cast::u64; -use quote::Tokens; +use proc_macro2::{TokenStream, Ident, Span}; use crate::svd::Peripheral; -use syn::Ident; use crate::errors::*; use crate::util::{self, ToSanitizedUpperCase}; @@ -15,7 +14,7 @@ pub fn render( target: Target, peripherals: &[Peripheral], device_x: &mut String, -) -> Result> { +) -> Result> { let interrupts = peripherals .iter() .flat_map(|p| p.interrupt.iter()) @@ -42,7 +41,7 @@ pub fn render( } pos += 1; - let name_uc = Ident::from(interrupt.name.to_sanitized_upper_case()); + let name_uc = Ident::new(&interrupt.name.to_sanitized_upper_case(), Span::call_site()); let description = format!( "{} - {}", interrupt.value, diff --git a/src/generate/peripheral.rs b/src/generate/peripheral.rs index d79b0708..07de6b72 100644 --- a/src/generate/peripheral.rs +++ b/src/generate/peripheral.rs @@ -2,10 +2,12 @@ use std::borrow::Cow; use std::cmp::Ordering; use std::collections::HashMap; -use quote::{ToTokens, Tokens}; +use quote::ToTokens; +use proc_macro2::TokenStream; use crate::svd::{Cluster, ClusterInfo, Defaults, Peripheral, Register, RegisterCluster, RegisterInfo}; -use syn::{self, Ident}; +use proc_macro2::{Ident, Span, Punct, Spacing}; use log::warn; +use syn::{parse_str, Token}; use crate::errors::*; use crate::util::{self, ToSanitizedSnakeCase, ToSanitizedUpperCase, BITS_PER_BYTE}; @@ -17,7 +19,7 @@ pub fn render( all_peripherals: &[Peripheral], defaults: &Defaults, nightly: bool, -) -> Result> { +) -> Result> { let mut out = vec![]; let p_derivedfrom = p_original.derived_from.as_ref().and_then(|s| { @@ -33,14 +35,15 @@ pub fn render( return Ok(out); } - let name_pc = Ident::from(&*p.name.to_sanitized_upper_case()); + let span = Span::call_site(); + let name_pc = Ident::new(&p.name.to_sanitized_upper_case(), span); let address = util::hex(p.base_address as u64); let description = util::respace(p.description.as_ref().unwrap_or(&p.name)); let derive_regs = p_derivedfrom.is_some() && p_original.registers.is_none(); - let name_sc = Ident::from(&*p.name.to_sanitized_snake_case()); + let name_sc = Ident::new(&p.name.to_sanitized_snake_case(), span); let base = if derive_regs { - Ident::from(&*p_derivedfrom.unwrap().name.to_sanitized_snake_case()) + Ident::new(&p_derivedfrom.unwrap().name.to_sanitized_snake_case(), span) } else { name_sc.clone() }; @@ -96,24 +99,12 @@ pub fn render( fn derive_reg_info(info: &RegisterInfo, ancestor: &RegisterInfo) -> RegisterInfo { let mut derived = info.clone(); - if derived.size.is_none() { - derived.size = ancestor.size.clone(); - } - if derived.access.is_none() { - derived.access = ancestor.access.clone(); - } - if derived.reset_value.is_none() { - derived.reset_value = ancestor.reset_value.clone(); - } - if derived.reset_mask.is_none() { - derived.reset_mask = ancestor.reset_mask.clone(); - } - if derived.fields.is_none() { - derived.fields = ancestor.fields.clone(); - } - if derived.write_constraint.is_none() { - derived.write_constraint = ancestor.write_constraint.clone(); - } + derived.size = derived.size.or(ancestor.size); + derived.access = derived.access.or(ancestor.access); + derived.reset_value = derived.reset_value.or(ancestor.reset_value); + derived.reset_mask = derived.reset_mask.or(ancestor.reset_mask); + derived.fields = derived.fields.or(ancestor.fields.clone()); + derived.write_constraint = derived.write_constraint.or(ancestor.write_constraint); derived } @@ -186,8 +177,8 @@ pub fn render( let description = util::escape_brackets(util::respace(p.description.as_ref().unwrap_or(&p.name)).as_ref()); - let open = Ident::from("{"); - let close = Ident::from("}"); + let open = Punct::new('{', Spacing::Alone); + let close = Punct::new('}', Spacing::Alone); out.push(quote! { #[doc = #description] @@ -231,7 +222,7 @@ impl Region { .iter() .filter_map(|f| match &f.field.ident { None => None, - Some(ident) => Some(ident.as_ref()), + Some(ident) => Some(ident.to_string()), }) .collect(); if idents.is_empty() { @@ -272,7 +263,7 @@ impl Region { .iter() .filter_map(|f| match &f.field.ident { None => None, - Some(ident) => Some(ident.as_ref()), + Some(ident) => Some(ident.to_string()), }) .collect(); @@ -439,9 +430,9 @@ fn register_or_cluster_block( defs: &Defaults, name: Option<&str>, _nightly: bool, -) -> Result { - let mut fields = Tokens::new(); - let mut accessors = Tokens::new(); +) -> Result { + let mut fields = TokenStream::new(); + let mut accessors = TokenStream::new(); let mut have_accessors = false; let ercs_expanded = expand(ercs, defs, name)?; @@ -458,18 +449,19 @@ fn register_or_cluster_block( // The end of the region for which we previously emitted a field into `fields` let mut last_end = 0; + let span = Span::call_site(); for (i, region) in regions.regions.iter().enumerate() { // Check if we need padding let pad = region.offset - last_end; if pad != 0 { - let name = Ident::from(format!("_reserved{}", i)); + let name = Ident::new(&format!("_reserved{}", i), span); let pad = pad as usize; - fields.append(quote! { + fields.extend(quote! { #name : [u8; #pad], }); } - let mut region_fields = Tokens::new(); + let mut region_fields = TokenStream::new(); let is_region_a_union = region.is_union(); for reg_block_field in ®ion.fields { @@ -481,11 +473,11 @@ fn register_or_cluster_block( if is_region_a_union { let name = ®_block_field.field.ident; - let mut_name = Ident::from(format!("{}_mut", name.as_ref().unwrap())); + let mut_name = Ident::new(&format!("{}_mut", name.as_ref().unwrap()), span); let ty = ®_block_field.field.ty; let offset = reg_block_field.offset as usize; have_accessors = true; - accessors.append(quote! { + accessors.extend(quote! { #[doc = #comment] #[inline(always)] pub fn #name(&self) -> &#ty { @@ -503,17 +495,17 @@ fn register_or_cluster_block( } }); } else { - region_fields.append(quote! { + region_fields.extend(quote! { #[doc = #comment] }); reg_block_field.field.to_tokens(&mut region_fields); - Ident::from(",").to_tokens(&mut region_fields); + Punct::new(',', Spacing::Alone).to_tokens(&mut region_fields); } } if !is_region_a_union { - fields.append(®ion_fields); + fields.extend(region_fields); } else { // Emit padding for the items that we're not emitting // as fields so that subsequent fields have the correct @@ -527,19 +519,23 @@ fn register_or_cluster_block( // name, along with the region number, falling back to // the offset and end in case we couldn't figure out a // nice identifier. - let name = Ident::from(format!("_reserved_{}_{}", i, region.compute_ident().unwrap_or_else(|| format!("{}_{}", region.offset, region.end)))); + let name = Ident::new(&format!( + "_reserved_{}_{}", + i, + region.compute_ident().unwrap_or_else(|| format!("{}_{}", region.offset, region.end)) + ), span); let pad = (region.end - region.offset) as usize; - fields.append(quote! { + fields.extend(quote! { #name: [u8; #pad], }) } last_end = region.end; } - let name = Ident::from(match name { + let name = Ident::new(&match name { Some(name) => name.to_sanitized_upper_case(), None => "RegisterBlock".into(), - }); + }, span); let accessors = if have_accessors { quote! { @@ -719,15 +715,15 @@ fn expand_register( Ok(register_expanded) } -/// Render a Cluster Block into `Tokens` +/// Render a Cluster Block into `TokenStream` fn cluster_block( c: &Cluster, defaults: &Defaults, p: &Peripheral, all_peripherals: &[Peripheral], nightly: bool, -) -> Result { - let mut mod_items: Vec = vec![]; +) -> Result { + let mut mod_items: Vec = vec![]; // name_sc needs to take into account array type. let description = util::escape_brackets(util::respace(&c.description).as_ref()); @@ -739,7 +735,7 @@ fn cluster_block( } .replace("[%s]", "") .replace("%s", ""); - let name_sc = Ident::from(&*mod_name.to_sanitized_snake_case()); + let name_sc = Ident::new(&mod_name.to_sanitized_snake_case(), Span::call_site()); let reg_size = c.size.or(defaults.size); let mut defaults = defaults.clone(); @@ -779,7 +775,7 @@ fn cluster_block( /// Takes a svd::Register which may be a register array, and turn in into /// a list of syn::Field where the register arrays have been expanded. fn expand_svd_register(register: &Register, name: Option<&str>) -> Vec { - let name_to_ty = |name: &String, ns: Option<&str>| -> syn::Ty { + let name_to_ty = |name: &String, ns: Option<&str>| -> syn::Type { let ident = if let Some(ns) = ns { Cow::Owned( String::from("self::") @@ -791,16 +787,7 @@ fn expand_svd_register(register: &Register, name: Option<&str>) -> Vec(&ident).unwrap()) }; let mut out = vec![]; @@ -835,15 +822,9 @@ fn expand_svd_register(register: &Register, name: Option<&str>) -> Vec) -> Vec) -> syn::Field { - let name_to_ty = |name: &String, ns: Option<&str>| -> syn::Ty { - let ident = if let Some(ns) = ns { - Cow::Owned( + let name_to_ty = |name: &String, ns: Option<&str>| -> String { + if let Some(ns) = ns { String::from("self::") + &ns.to_sanitized_snake_case() + "::" - + &name.to_sanitized_upper_case(), - ) + + &name.to_sanitized_upper_case() } else { - name.to_sanitized_upper_case() - }; - - syn::Ty::Path( - None, - syn::Path { - global: false, - segments: vec![syn::PathSegment { - ident: Ident::from(ident), - parameters: syn::PathParameters::none(), - }], - }, - ) + name.to_sanitized_upper_case().to_string() + } }; match register { - Register::Single(info) => syn::Field { - ident: Some(Ident::from(info.name.to_sanitized_snake_case())), - vis: syn::Visibility::Public, - attrs: vec![], - ty: name_to_ty(&info.name, name), - }, + Register::Single(info) => new_syn_field( + &info.name.to_sanitized_snake_case(), + syn::Type::Path(parse_str::(&name_to_ty(&info.name, name)).unwrap()) + ), Register::Array(info, array_info) => { let has_brackets = info.name.contains("[%s]"); @@ -892,22 +858,11 @@ fn convert_svd_register(register: &Register, name: Option<&str>) -> syn::Field { info.name.replace("%s", "") }; - let ident = Ident::from(nb_name.to_sanitized_snake_case()); - - let ty = syn::Ty::Array( - Box::new(name_to_ty(&nb_name, name)), - syn::ConstExpr::Lit(syn::Lit::Int( - u64::from(array_info.dim), - syn::IntTy::Unsuffixed, - )), - ); - - syn::Field { - ident: Some(ident), - vis: syn::Visibility::Public, - attrs: vec![], - ty, - } + let ty = syn::Type::Array(parse_str::( + &format!("[{};{}]", name_to_ty(&nb_name, name), u64::from(array_info.dim)) + ).unwrap()); + + new_syn_field(&nb_name.to_sanitized_snake_case(), ty) } } } @@ -915,17 +870,8 @@ fn convert_svd_register(register: &Register, name: Option<&str>) -> syn::Field { /// Takes a svd::Cluster which may contain a register array, and turn in into /// a list of syn::Field where the register arrays have been expanded. fn expand_svd_cluster(cluster: &Cluster) -> Vec { - let name_to_ty = |name: &String| -> syn::Ty { - syn::Ty::Path( - None, - syn::Path { - global: false, - segments: vec![syn::PathSegment { - ident: Ident::from(name.to_sanitized_upper_case()), - parameters: syn::PathParameters::none(), - }], - }, - ) + let name_to_ty = |name: &String| -> syn::Type { + syn::Type::Path(parse_str::(&name.to_sanitized_upper_case()).unwrap()) }; let mut out = vec![]; @@ -960,15 +906,9 @@ fn expand_svd_cluster(cluster: &Cluster) -> Vec { info.name.replace("%s", "") }; - let ident = Ident::from(name.to_sanitized_snake_case()); let ty = name_to_ty(&ty_name); - out.push(syn::Field { - ident: Some(ident), - vis: syn::Visibility::Public, - attrs: vec![], - ty, - }); + out.push(new_syn_field(&name.to_sanitized_snake_case(), ty)); } } } @@ -977,26 +917,11 @@ fn expand_svd_cluster(cluster: &Cluster) -> Vec { /// Convert a parsed `Cluster` into its `Field` equivalent fn convert_svd_cluster(cluster: &Cluster) -> syn::Field { - let name_to_ty = |name: &String| -> syn::Ty { - syn::Ty::Path( - None, - syn::Path { - global: false, - segments: vec![syn::PathSegment { - ident: Ident::from(name.to_sanitized_upper_case()), - parameters: syn::PathParameters::none(), - }], - }, - ) - }; - match cluster { - Cluster::Single(info) => syn::Field { - ident: Some(Ident::from(info.name.to_sanitized_snake_case())), - vis: syn::Visibility::Public, - attrs: vec![], - ty: name_to_ty(&info.name), - }, + Cluster::Single(info) => new_syn_field( + &info.name.to_sanitized_snake_case(), + syn::Type::Path(parse_str::(&info.name.to_sanitized_upper_case()).unwrap()) + ), Cluster::Array(info, array_info) => { let has_brackets = info.name.contains("[%s]"); @@ -1006,22 +931,22 @@ fn convert_svd_cluster(cluster: &Cluster) -> syn::Field { info.name.replace("%s", "") }; - let ident = Ident::from(name.to_sanitized_snake_case()); - - let ty = syn::Ty::Array( - Box::new(name_to_ty(&name)), - syn::ConstExpr::Lit(syn::Lit::Int( - u64::from(array_info.dim), - syn::IntTy::Unsuffixed, - )), - ); - - syn::Field { - ident: Some(ident), - vis: syn::Visibility::Public, - attrs: vec![], - ty, - } + let ty = syn::Type::Array(parse_str::( + &format!("[{};{}]", &name.to_sanitized_upper_case(), u64::from(array_info.dim)) + ).unwrap()); + + new_syn_field(&name.to_sanitized_snake_case(), ty) } } } + +fn new_syn_field(ident: &str, ty: syn::Type) -> syn::Field { + let span = Span::call_site(); + syn::Field { + ident: Some(Ident::new(ident, span)), + vis: syn::Visibility::Public(syn::VisPublic{ pub_token: Token![pub](span) }), + attrs: vec![], + colon_token: Some(Token![:](span)), + ty, + } +} diff --git a/src/generate/register.rs b/src/generate/register.rs index ff83bcb9..92d8afb4 100644 --- a/src/generate/register.rs +++ b/src/generate/register.rs @@ -4,8 +4,7 @@ use crate::svd::{ }; use cast::u64; use log::warn; -use quote::Tokens; -use syn::Ident; +use proc_macro2::{TokenStream, Ident, Span, Punct, Spacing}; use crate::errors::*; use crate::util::{self, ToSanitizedSnakeCase, ToSanitizedUpperCase, U32Ext}; @@ -16,12 +15,13 @@ pub fn render( peripheral: &Peripheral, all_peripherals: &[Peripheral], defs: &Defaults, -) -> Result> { +) -> Result> { let access = util::access_of(register); let name = util::name_of(register); - let name_pc = Ident::from(&*name.to_sanitized_upper_case()); - let _name_pc = Ident::from(format!("_{}", &*name.to_sanitized_upper_case())); - let name_sc = Ident::from(&*name.to_sanitized_snake_case()); + let span = Span::call_site(); + let name_pc = Ident::new(&name.to_sanitized_upper_case(), span); + let _name_pc = Ident::new(&format!("_{}", &name.to_sanitized_upper_case()), span); + let name_sc = Ident::new(&name.to_sanitized_snake_case(), span); let rsize = register .size .or(defs.size) @@ -115,8 +115,8 @@ pub fn render( } } - let open = Ident::from("{"); - let close = Ident::from("}"); + let open = Punct::new('{', Spacing::Alone); + let close = Punct::new('}', Spacing::Alone); if can_read { mod_items.push(quote! { @@ -209,9 +209,9 @@ pub fn fields( rty: &Ident, reset_value: Option, access: Access, - mod_items: &mut Vec, - r_impl_items: &mut Vec, - w_impl_items: &mut Vec, + mod_items: &mut Vec, + r_impl_items: &mut Vec, + w_impl_items: &mut Vec, ) -> Result<()> { impl<'a> F<'a> { fn from(f: &'a Field) -> Result { @@ -223,16 +223,17 @@ pub fn fields( } = f.bit_range; let sc = f.name.to_sanitized_snake_case(); let pc = f.name.to_sanitized_upper_case(); - let pc_r = Ident::from(&*format!("{}_A", pc)); - let _pc_r = Ident::from(&*format!("{}_R", pc)); - let pc_w = Ident::from(&*format!("{}_AW", pc)); - let _pc_w = Ident::from(&*format!("{}_W", pc)); - let _sc = Ident::from(&*format!("_{}", sc)); - let bits = if width == 1 { - Ident::from("bit") + let span = Span::call_site(); + let pc_r = Ident::new(&format!("{}_A", pc), span); + let _pc_r = Ident::new(&format!("{}_R", pc), span); + let pc_w = Ident::new(&format!("{}_AW", pc), span); + let _pc_w = Ident::new(&format!("{}_W", pc), span); + let _sc = Ident::new(&format!("_{}", sc), span); + let bits = Ident::new(if width == 1 { + "bit" } else { - Ident::from("bits") - }; + "bits" + }, Span::call_site()); let mut description_with_bits = if width == 1 { format!("Bit {}", offset) } else { @@ -240,7 +241,7 @@ pub fn fields( }; if let Some(d) = &f.description { description_with_bits.push_str(" - "); - description_with_bits.push_str(&*util::respace(&util::escape_brackets(d))); + description_with_bits.push_str(&util::respace(&util::escape_brackets(d))); } let description = if let Some(d) = &f.description { util::respace(&util::escape_brackets(d)) @@ -260,7 +261,7 @@ pub fn fields( width, access: f.access, evs: &f.enumerated_values, - sc: Ident::from(&*sc), + sc: Ident::new(&sc, Span::call_site()), mask: 1u64.wrapping_neg() >> (64-width), name: &f.name, offset: u64::from(offset), @@ -338,7 +339,7 @@ pub fn fields( base_pc_w = base.as_ref().map(|base| { let pc = base.field.to_sanitized_upper_case(); - let base_pc_r = Ident::from(&*format!("{}_A", pc)); + let base_pc_r = Ident::new(&format!("{}_A", pc), Span::call_site()); let base_pc_r = derive_from_base(mod_items, &base, &pc_r, &base_pc_r, description); let doc = format!("Reader of field `{}`", f.name); @@ -409,11 +410,11 @@ pub fn fields( let pc = &v.pc; let sc = &v.sc; - let is_variant = if sc.as_ref().starts_with('_') { - Ident::from(&*format!("is{}", sc)) + let is_variant = Ident::new(&if sc.to_string().starts_with('_') { + format!("is{}", sc) } else { - Ident::from(&*format!("is_{}", sc)) - }; + format!("is_{}", sc) + }, Span::call_site()); let doc = format!("Checks if the value of the field is `{}`", pc); enum_items.push(quote! { @@ -472,7 +473,7 @@ pub fn fields( base_pc_w = base.as_ref().map(|base| { let pc = base.field.to_sanitized_upper_case(); - let base_pc_w = Ident::from(&*format!("{}_AW", pc)); + let base_pc_w = Ident::new(&format!("{}_AW", pc), Span::call_site()); derive_from_base(mod_items, &base, &pc_w, &base_pc_w, description) }); @@ -594,7 +595,7 @@ fn unsafety(write_constraint: Option<&WriteConstraint>, width: u32) -> Option Some(Ident::from("unsafe")), + _ => Some(Ident::new("unsafe", Span::call_site())), } } @@ -607,6 +608,7 @@ struct Variant { impl Variant { fn from_enumerated_values(evs: &EnumeratedValues) -> Result> { + let span = Span::call_site(); evs.values .iter() // filter out all reserved variants, as we should not @@ -622,8 +624,8 @@ impl Variant { .description .clone() .unwrap_or_else(|| format!("`{:b}`", value)), - pc: Ident::from(&*ev.name.to_sanitized_upper_case()), - sc: Ident::from(&*ev.name.to_sanitized_snake_case()), + pc: Ident::new(&ev.name.to_sanitized_upper_case(), span), + sc: Ident::new(&ev.name.to_sanitized_snake_case(), span), value, }) }) @@ -631,7 +633,7 @@ impl Variant { } } -fn add_from_variants(mod_items: &mut Vec, variants: &Vec, pc: &Ident, f: &F, desc: &str, reset_value: Option) { +fn add_from_variants(mod_items: &mut Vec, variants: &Vec, pc: &Ident, f: &F, desc: &str, reset_value: Option) { let fty = &f.ty; let vars = variants @@ -681,12 +683,13 @@ fn add_from_variants(mod_items: &mut Vec, variants: &Vec, pc: & }); } -fn derive_from_base(mod_items: &mut Vec, base: &Base, pc: &Ident, base_pc: &Ident, desc: &str) -> quote::Tokens { +fn derive_from_base(mod_items: &mut Vec, base: &Base, pc: &Ident, base_pc: &Ident, desc: &str) -> TokenStream { + let span = Span::call_site(); if let (Some(peripheral), Some(register)) = (&base.peripheral, &base.register) { let pmod_ = peripheral.to_sanitized_snake_case(); let rmod_ = register.to_sanitized_snake_case(); - let pmod_ = Ident::from(&*pmod_); - let rmod_ = Ident::from(&*rmod_); + let pmod_ = Ident::new(&pmod_, span); + let rmod_ = Ident::new(&rmod_, span); mod_items.push(quote! { #[doc = #desc] @@ -699,7 +702,7 @@ fn derive_from_base(mod_items: &mut Vec, base: &Base, pc: &Ident, base_p } } else if let Some(register) = &base.register { let mod_ = register.to_sanitized_snake_case(); - let mod_ = Ident::from(&*mod_); + let mod_ = Ident::new(&mod_, span); mod_items.push(quote! { #[doc = #desc] diff --git a/src/util.rs b/src/util.rs index c67511fe..fe208a4f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,8 +2,8 @@ use std::borrow::Cow; use inflections::Inflect; use crate::svd::{Access, Cluster, Register, RegisterCluster}; -use syn::Ident; -use quote::Tokens; +use proc_macro2::{TokenStream, Ident, Span, Literal}; +use crate::quote::{TokenStreamExt, ToTokens}; use crate::errors::*; @@ -184,7 +184,7 @@ pub fn escape_brackets(s: &str) -> String { pub fn name_of(register: &Register) -> Cow { match register { - Register::Single(info) => Cow::from(&*info.name), + Register::Single(info) => Cow::from(&info.name), Register::Array(info, _) => { if info.name.contains("[%s]") { info.name.replace("[%s]", "").into() @@ -216,36 +216,36 @@ pub fn access_of(register: &Register) -> Access { } /// Turns `n` into an unsuffixed separated hex token -pub fn hex(n: u64) -> Tokens { - let mut t = Tokens::new(); +pub fn hex(n: u64) -> TokenStream { let (h4, h3, h2, h1) = ((n >> 48) & 0xffff, (n >> 32) & 0xffff, (n >> 16) & 0xffff, n & 0xffff); - t.append(if h4 != 0 { - Ident::from(format!("0x{:04x}_{:04x}_{:04x}_{:04x}", h4, h3, h2, h1)) - } else if h3 != 0 { - Ident::from(format!("0x{:04x}_{:04x}_{:04x}", h3, h2, h1)) - } else if h2 != 0 { - Ident::from(format!("0x{:04x}_{:04x}", h2, h1)) - } else if h1 & 0xff00 != 0 { - Ident::from(format!("0x{:04x}", h1)) - } else if h1 != 0 { - Ident::from(format!("0x{:02x}", h1 & 0xff)) - } else { - Ident::from("0") - }); - t + syn::parse_str::( + &(if h4 != 0 { + format!("0x{:04x}_{:04x}_{:04x}_{:04x}", h4, h3, h2, h1) + } else if h3 != 0 { + format!("0x{:04x}_{:04x}_{:04x}", h3, h2, h1) + } else if h2 != 0 { + format!("0x{:04x}_{:04x}", h2, h1) + } else if h1 & 0xff00 != 0 { + format!("0x{:04x}", h1) + } else if h1 != 0 { + format!("0x{:02x}", h1 & 0xff) + } else { + "0".to_string() + }) + ).unwrap().into_token_stream() } /// Turns `n` into an unsuffixed token -pub fn unsuffixed(n: u64) -> Tokens { - let mut t = Tokens::new(); - t.append(Ident::from(format!("{}", n))); +pub fn unsuffixed(n: u64) -> TokenStream { + let mut t = TokenStream::new(); + t.append(Literal::u64_unsuffixed(n)); t } -pub fn unsuffixed_or_bool(n: u64, width: u32) -> Tokens { +pub fn unsuffixed_or_bool(n: u64, width: u32) -> TokenStream { if width == 1 { - let mut t = Tokens::new(); - t.append(Ident::from(if n == 0 { "false" } else { "true" })); + let mut t = TokenStream::new(); + t.append(Ident::new(if n == 0 { "false" } else { "true" }, Span::call_site())); t } else { unsuffixed(n) @@ -259,12 +259,13 @@ pub trait U32Ext { impl U32Ext for u32 { fn to_ty(&self) -> Result { + let span = Span::call_site(); Ok(match *self { - 1 => Ident::from("bool"), - 2..=8 => Ident::from("u8"), - 9..=16 => Ident::from("u16"), - 17..=32 => Ident::from("u32"), - 33..=64 => Ident::from("u64"), + 1 => Ident::new("bool", span), + 2..=8 => Ident::new("u8", span), + 9..=16 => Ident::new("u16", span), + 17..=32 => Ident::new("u32", span), + 33..=64 => Ident::new("u64", span), _ => Err(format!( "can't convert {} bits into a Rust integral type", *self @@ -311,7 +312,7 @@ pub fn only_registers(ercs: &[RegisterCluster]) -> Vec<&Register> { registers } -pub fn build_rs() -> Tokens { +pub fn build_rs() -> TokenStream { quote! { use std::env; use std::fs::File;