microcad-lang 0.5.0

µcad language
Documentation
// Copyright © 2024-2026 The µcad authors <info@microcad.xyz>
// SPDX-License-Identifier: AGPL-3.0-or-later

//! µcad format expression syntax elements

mod format_expression;
mod format_spec;

pub use format_expression::*;
pub use format_spec::*;

use microcad_lang_base::{Refer, SrcRef, SrcReferrer};
use microcad_lang_proc_macros::SrcReferrer;

/// Format string item.
#[derive(Debug, Clone, PartialEq)]
pub enum FormatStringInner {
    /// String literal.
    String(Refer<String>),
    /// Format expression.
    FormatExpression(Box<FormatExpression>),
}

impl SrcReferrer for FormatStringInner {
    fn src_ref(&self) -> SrcRef {
        match self {
            FormatStringInner::String(s) => s.src_ref(),
            FormatStringInner::FormatExpression(e) => e.src_ref(),
        }
    }
}

/// Format string.
#[derive(Default, Clone, Debug, PartialEq, SrcReferrer)]
pub struct FormatString(pub Refer<Vec<FormatStringInner>>);

impl FormatString {
    /// Insert a string.
    pub fn push_string(&mut self, s: String, src_ref: SrcRef) {
        self.0
            .push(FormatStringInner::String(Refer::new(s, src_ref)));
    }

    /// Insert a format expression
    pub fn push_format_expr(&mut self, expr: FormatExpression) {
        self.0
            .push(FormatStringInner::FormatExpression(Box::new(expr)));
    }

    /// Return the number of sections (inserted elements)
    pub fn section_count(&self) -> usize {
        self.0.len()
    }
}

impl From<Refer<String>> for FormatString {
    fn from(value: Refer<String>) -> Self {
        FormatString(Refer {
            src_ref: value.src_ref.clone(),
            value: vec![FormatStringInner::String(value)],
        })
    }
}

impl std::fmt::Display for FormatString {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, r#"""#)?;
        for elem in &*self.0 {
            match elem {
                FormatStringInner::String(s) => write!(f, "{}", s.value)?,
                FormatStringInner::FormatExpression(expr) => write!(f, "{expr}")?,
            }
        }
        write!(f, r#"""#)?;
        Ok(())
    }
}