qalam 0.3.1

Interpreter for the Qalam programming language. Qalam is a dead-simple, Urdu inspired, interpreted programming langauge.
Documentation
use crate::callable::instance::QalamInstance;
use crate::callable::QalamCallable;
use crate::hashable::HashableRcRefCell;
use ordered_float::OrderedFloat;
use colored::Colorize;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct QalamArray {
    pub elements: Vec<Option<Literal>>,
}

impl QalamArray {
    pub fn init() -> Self {
        return Self {
            elements: Vec::new(),
        };
    }

    pub fn construct(size: usize, val: Option<Literal>) -> Self {
        return Self {
            elements: vec![val; size],
        };
    }

    pub fn from_vec(vec: Vec<Option<Literal>>) -> Self {
        return Self { elements: vec };
    }

    pub fn to_string(&self) -> String {
        let values = self
            .elements
            .iter()
            .map(|opt| Literal::option_string(opt.clone()))
            .collect::<Vec<String>>()
            .join(", ");
        return format!("[ {} ]", values);
    }
}

#[derive(Debug, Clone, Eq, Hash)]
pub enum Literal {
    Number(OrderedFloat<f64>),
    String(String),
    Bool(bool),
    Callable(Box<dyn QalamCallable>),
    Instance(HashableRcRefCell<QalamInstance>),
    Array(HashableRcRefCell<QalamArray>),
}

impl PartialEq for Literal {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Literal::Number(a), Literal::Number(b)) => a == b,
            (Literal::String(a), Literal::String(b)) => a == b,
            (Literal::Bool(a), Literal::Bool(b)) => a == b,
            (Literal::Callable(a), Literal::Callable(b)) => std::ptr::eq(&**a, &**b),
            (Literal::Array(a), Literal::Array(b)) => a == b,
            (Literal::Instance(a), Literal::Instance(b)) => a == b,
            _ => false,
        }
    }
}

impl Literal {
    pub fn to_qalam_string(&self) -> String {
        match self {
            Self::Bool(val) => format!("{}", if *val { "sach".yellow().to_string() } else { "jhoot".yellow().to_string() }),
            Self::Number(val) => format!("{}", val).yellow().to_string(),
            Self::String(val) => val.to_owned(),
            Self::Callable(val) => val.to_string().cyan().to_string(),
            Self::Instance(val) => val.0.borrow().to_string().cyan().to_string(),
            Self::Array(val) => val.0.borrow().to_string(),
        }
    }

    pub fn option_string(value: Option<Literal>) -> String {
        match value {
            Some(val) => val.to_qalam_string(),
            None => String::from("khali"),
        }
    }
}