diman_unit_system 0.3.0

Internal procedural macros for diman.
Documentation
use std::collections::HashMap;

use syn::Ident;

use crate::{dimension_math::DimensionsAndFactor, expression::Expr, types::IntExponent};

use super::resolver::Resolvable;

pub enum IdentOrFactor {
    Factor(DimensionsAndFactor),
    Ident(Ident),
}

pub enum ValueOrExpr {
    Value(DimensionsAndFactor),
    Expr(Expr<IdentOrFactor, IntExponent>),
}

pub struct UnresolvedItem {
    pub name: Ident,
    pub val: ValueOrExpr,
}

pub struct ResolvedItem {
    pub val: DimensionsAndFactor,
}

impl Resolvable for UnresolvedItem {
    type Resolved = ResolvedItem;

    fn ident(&self) -> Ident {
        self.name.clone()
    }

    fn resolve(self, others: &HashMap<Ident, ResolvedItem>) -> Self::Resolved {
        match self.val {
            ValueOrExpr::Value(val) => ResolvedItem { val },
            ValueOrExpr::Expr(expr) => {
                let val = expr
                    .map(|val_or_expr| match val_or_expr {
                        IdentOrFactor::Factor(factor) => factor,
                        IdentOrFactor::Ident(ident) => others[&ident].val.clone(),
                    })
                    .eval();
                ResolvedItem { val }
            }
        }
    }

    fn is_resolvable(&self, others: &HashMap<Ident, ResolvedItem>) -> bool {
        match &self.val {
            ValueOrExpr::Value(_) => true,
            ValueOrExpr::Expr(expr) => expr.iter_vals().all(|val| match val {
                IdentOrFactor::Factor(_) => true,
                IdentOrFactor::Ident(ident) => others.contains_key(ident),
            }),
        }
    }
}