use std::fmt::{self, Display, Write};
use crate::{Doc, Expr, Formatter, Type};
#[derive(Debug, Clone)]
pub struct Variable {
name: String,
ty: Type,
value: Option<Expr>,
is_static: bool,
is_extern: bool,
doc: Option<Doc>,
}
impl Variable {
pub fn new(name: &str, ty: Type) -> Self {
Variable::with_string(String::from(name), ty)
}
pub fn with_string(name: String, ty: Type) -> Self {
Variable {
name,
ty,
value: None,
is_static: false,
is_extern: false,
doc: None,
}
}
pub fn to_expr(&self) -> Expr {
Expr::Variable {
name: self.name.clone(),
ty: self.ty.clone(),
}
}
pub fn with_value(name: &str, ty: Type, val: Expr) -> Self {
Variable::with_string_and_value(String::from(name), ty, val)
}
pub fn with_string_and_value(name: String, ty: Type, val: Expr) -> Self {
Variable {
name,
ty,
value: Some(val),
is_static: false,
is_extern: false,
doc: None,
}
}
pub fn to_type(&self) -> Type {
self.ty.clone()
}
pub fn as_type(&self) -> &Type {
&self.ty
}
pub fn push_doc_str(&mut self, doc: &str) -> &mut Self {
if let Some(d) = &mut self.doc {
d.add_text(doc);
} else {
self.doc = Some(Doc::with_str(doc));
}
self
}
pub fn doc(&mut self, doc: Doc) -> &mut Self {
self.doc = Some(doc);
self
}
pub fn toggle_static(&mut self, val: bool) -> &mut Self {
if val {
self.is_extern = false;
}
self.is_static = val;
self
}
pub fn set_static(&mut self) -> &mut Self {
self.toggle_static(true)
}
pub fn toggle_extern(&mut self, val: bool) -> &mut Self {
if val {
self.is_static = false;
}
self.is_extern = val;
self
}
pub fn set_extern(&mut self) -> &mut Self {
self.toggle_extern(true)
}
pub fn set_value(&mut self, val: Expr) -> &mut Self {
self.value = Some(val);
self
}
pub fn set_value_raw(&mut self, val: &str) -> &mut Self {
self.set_value(Expr::Raw(String::from(val)))
}
pub fn do_fmt(&self, fmt: &mut Formatter<'_>, decl_only: bool) -> fmt::Result {
if let Some(ref docs) = self.doc {
docs.fmt(fmt)?;
}
if self.is_extern {
write!(fmt, "extern ")?;
}
if self.is_static {
write!(fmt, "static ")?;
}
self.ty.fmt(fmt)?;
write!(fmt, " {}", self.name)?;
if decl_only || self.value.is_none() || self.is_extern {
writeln!(fmt, ";")
} else {
if let Some(v) = &self.value {
write!(fmt, " = {v}")?;
}
writeln!(fmt, ";")
}
}
pub fn fmt_decl(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
self.do_fmt(fmt, true)
}
pub fn fmt_def(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
self.do_fmt(fmt, false)
}
pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
self.fmt_decl(fmt)
}
}
impl Display for Variable {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut ret = String::new();
self.fmt(&mut Formatter::new(&mut ret)).unwrap();
write!(f, "{ret}")
}
}