raekna-common 0.1.1

This crate contains common types and functionality for the raekna project.
Documentation
use std::fmt;

use crate::function_name::FunctionName;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Literal {
    Integer(i64),
    Float(f64),
}

impl Literal {
    pub fn maybe_truncate(self) -> Self {
        match self {
            Self::Float(value) if value.fract().abs() < f64::EPSILON => Self::Integer(value as i64),
            _ => self,
        }
    }
}

impl std::fmt::Display for Literal {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let as_str = match self {
            Literal::Integer(value) => value.to_string(),
            Literal::Float(value) => value.to_string(),
        };
        write!(f, "{as_str}")
    }
}

impl From<i64> for Literal {
    fn from(value: i64) -> Self {
        Self::Integer(value)
    }
}

impl From<f64> for Literal {
    fn from(value: f64) -> Self {
        if value.fract().abs() < f64::EPSILON {
            Self::Integer(value as i64)
        } else {
            Self::Float(value)
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
    Literal(Literal),
    Variable(String, Box<Expression>),
    VariableRef(String),
    Function(FunctionName, Vec<Expression>),
}

impl fmt::Display for Expression {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Expression::Literal(literal) => write!(f, "{literal}"),
            Expression::Variable(name, expr) => write!(f, "{name}: {expr}"),
            Expression::VariableRef(name) => write!(f, "{name}"),
            Expression::Function(function_name, arguments) => {
                let args = arguments
                    .iter()
                    .map(|e| e.to_string())
                    .collect::<Vec<_>>()
                    .join(", ");
                write!(f, "{function_name}({args})",)
            }
        }
    }
}