From 9a41c4e205e25091d760e01302a4d2694853f3b7 Mon Sep 17 00:00:00 2001 From: Gregory Hill Date: Fri, 26 Mar 2021 16:34:17 +0000 Subject: [PATCH] implement support for associated constants Signed-off-by: Gregory Hill --- CHANGELOG.md | 3 +++ src/associated_const.rs | 17 +++++++++++++++++ src/field.rs | 4 ++++ src/fields.rs | 1 + src/function.rs | 6 +++--- src/impl.rs | 30 +++++++++++++++++++++++++++++ src/lib.rs | 3 ++- src/trait.rs | 42 +++++++++++++++++++++++++++++++++++++---- 8 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 src/associated_const.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dea49f..ba841ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # +### Added +- Add support for associated constants + ### Changed - updated the crate to rust 2018 edition diff --git a/src/associated_const.rs b/src/associated_const.rs new file mode 100644 index 0000000..76bbd2b --- /dev/null +++ b/src/associated_const.rs @@ -0,0 +1,17 @@ +use crate::bound::Bound; +use crate::r#type::Type; + +/// Defines an associated constant. +#[derive(Debug, Clone)] +pub struct AssociatedConst(pub Bound); + +impl AssociatedConst { + /// Set the bound on the associated constant. + pub fn bound(&mut self, ty: T) -> &mut Self + where + T: Into, + { + self.0.bound = vec![ty.into()]; + self + } +} diff --git a/src/field.rs b/src/field.rs index 769158f..6e43e3b 100644 --- a/src/field.rs +++ b/src/field.rs @@ -14,6 +14,9 @@ pub struct Field { /// Field annotation pub annotation: Vec, + + /// Field value + pub value: String, } impl Field { @@ -27,6 +30,7 @@ impl Field { ty: ty.into(), documentation: Vec::new(), annotation: Vec::new(), + value: String::new(), } } diff --git a/src/fields.rs b/src/fields.rs index 6878818..5ee959c 100644 --- a/src/fields.rs +++ b/src/fields.rs @@ -37,6 +37,7 @@ impl Fields { ty: ty.into(), documentation: Vec::new(), annotation: Vec::new(), + value: String::new(), }) } diff --git a/src/function.rs b/src/function.rs index 827ec6c..ef76fb9 100644 --- a/src/function.rs +++ b/src/function.rs @@ -129,11 +129,11 @@ impl Function { self.args.push(Field { name: name.to_string(), ty: ty.into(), - // While a `Field` is used here, both `documentation` - // and `annotation` does not make sense for function arguments. - // Simply use empty strings. + // While a `Field` is used here, the following + // arguments do not make sense so use empty strings. documentation: Vec::new(), annotation: Vec::new(), + value: String::new(), }); self diff --git a/src/impl.rs b/src/impl.rs index 6e411b5..96978ad 100644 --- a/src/impl.rs +++ b/src/impl.rs @@ -19,6 +19,9 @@ pub struct Impl { /// If implementing a trait impl_trait: Option, + /// Associated constants + assoc_csts: Vec, + /// Associated types assoc_tys: Vec, @@ -40,6 +43,7 @@ impl Impl { target: target.into(), generics: vec![], impl_trait: None, + assoc_csts: vec![], assoc_tys: vec![], bounds: vec![], fns: vec![], @@ -79,6 +83,22 @@ impl Impl { self } + /// Set an associated constant. + pub fn associate_const(&mut self, name: &str, ty: T, value: &str) -> &mut Self + where + T: Into, + { + self.assoc_csts.push(Field { + name: name.to_string(), + ty: ty.into(), + documentation: Vec::new(), + annotation: Vec::new(), + value: value.to_string(), + }); + + self + } + /// Set an associated type. pub fn associate_type(&mut self, name: &str, ty: T) -> &mut Self where @@ -89,6 +109,7 @@ impl Impl { ty: ty.into(), documentation: Vec::new(), annotation: Vec::new(), + value: String::new(), }); self @@ -138,6 +159,15 @@ impl Impl { fmt_bounds(&self.bounds, fmt)?; fmt.block(|fmt| { + // format associated constants + if !self.assoc_csts.is_empty() { + for cst in &self.assoc_csts { + write!(fmt, "const {}: ", cst.name)?; + cst.ty.fmt(fmt)?; + write!(fmt, " = {};\n", cst.value)?; + } + } + // format associated types if !self.assoc_tys.is_empty() { for ty in &self.assoc_tys { diff --git a/src/lib.rs b/src/lib.rs index 70b8675..7a20c5b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ //! println!("{}", scope.to_string()); //! ``` +mod associated_const; mod associated_type; mod block; mod body; @@ -47,7 +48,7 @@ mod r#struct; mod r#trait; mod r#type; - +pub use associated_const::*; pub use associated_type::*; pub use block::*; pub use field::*; diff --git a/src/trait.rs b/src/trait.rs index 7a8c069..a7dc9cc 100644 --- a/src/trait.rs +++ b/src/trait.rs @@ -1,5 +1,6 @@ use std::fmt::{self, Write}; +use crate::associated_const::AssociatedConst; use crate::associated_type::AssociatedType; use crate::bound::Bound; use crate::formatter::{fmt_bound_rhs, Formatter}; @@ -13,6 +14,7 @@ use crate::r#type::Type; pub struct Trait { type_def: TypeDef, parents: Vec, + associated_consts: Vec, associated_tys: Vec, fns: Vec, macros: Vec, @@ -24,6 +26,7 @@ impl Trait { Trait { type_def: TypeDef::new(name), parents: vec![], + associated_consts: vec![], associated_tys: vec![], fns: vec![], macros: vec![], @@ -77,6 +80,20 @@ impl Trait { self } + /// Add an associated const. Returns a mutable reference to the new + /// associated const for futher configuration. + pub fn associated_const(&mut self, name: &str, ty: T) -> &mut AssociatedConst + where + T: Into, + { + self.associated_consts.push(AssociatedConst(Bound { + name: name.to_string(), + bound: vec![ty.into()], + })); + + self.associated_consts.last_mut().unwrap() + } + /// Add an associated type. Returns a mutable reference to the new /// associated type for futher configuration. pub fn associated_type(&mut self, name: &str) -> &mut AssociatedType { @@ -108,11 +125,28 @@ impl Trait { self.type_def.fmt_head("trait", &self.parents, fmt)?; fmt.block(|fmt| { - let assoc = &self.associated_tys; + let assoc_csts = &self.associated_consts; + let assoc_tys = &self.associated_tys; + + // format associated types + if !assoc_csts.is_empty() { + for cst in assoc_csts { + let cst = &cst.0; + + write!(fmt, "const {}", cst.name)?; + + if !cst.bound.is_empty() { + write!(fmt, ": ")?; + fmt_bound_rhs(&cst.bound, fmt)?; + } + + write!(fmt, ";\n")?; + } + } // format associated types - if !assoc.is_empty() { - for ty in assoc { + if !assoc_tys.is_empty() { + for ty in assoc_tys { let ty = &ty.0; write!(fmt, "type {}", ty.name)?; @@ -127,7 +161,7 @@ impl Trait { } for (i, func) in self.fns.iter().enumerate() { - if i != 0 || !assoc.is_empty() { + if i != 0 || !assoc_tys.is_empty() || !assoc_csts.is_empty() { write!(fmt, "\n")?; }