mihama 0.0.1

A Modern Functional and Dependent Type Programming Language Base on Rust
Documentation
use crate::checker::object::{TypeObject, PRIMIVE_TYPES};
use crate::evaluator::object::Object;
use crate::parser::ast::Expr;
use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct Env<'a, T: Clone> {
    pub parent: Option<&'a Env<'a, T>>,
    pub binds: HashMap<String, T>,
}

#[derive(Debug, Clone)]
pub enum EnvError {
    RedefinedBinding(String),
}

impl<T: Clone> PartialEq for Env<'_, T> {
    fn eq(&self, _: &Self) -> bool {
        false
    }
}

impl<'a, T: Clone> Env<'a, T> {
    pub fn new() -> Self {
        Env {
            parent: None,
            binds: HashMap::new(),
        }
    }

    pub fn extend(parent: &'a Env<'a, T>) -> Env<'a, T> {
        Env {
            parent: Some(parent),
            binds: HashMap::new(),
        }
    }

    pub fn insert_bind(&mut self, name: String, value: T) -> Result<(), EnvError> {
        if self.binds.contains_key(&name) {
            Err(EnvError::RedefinedBinding(name))
        } else {
            self.binds.insert(name, value);
            Ok(())
        }
    }

    pub fn get_bind(&self, name: &str) -> Option<T> {
        if let Some(bind) = self.get_own_bind(name) {
            Some(bind)
        } else if let Some(ref parent) = self.parent {
            parent.get_bind(name)
        } else {
            None
        }
    }

    pub fn get_own_bind(&self, name: &str) -> Option<T> {
        if let Some(bind) = self.binds.get(name) {
            Some(bind.clone())
        } else {
            None
        }
    }
}

pub fn new_checker_env<'a>() -> CheckerEnv<'a> {
    let mut env = Env::<'_, TypeObject>::new();
    for t in PRIMIVE_TYPES.iter() {
        env.insert_bind(t.to_string(), t.clone()).unwrap();
    }
    env.insert_bind(
        "print".to_string(),
        TypeObject::Function(
            Box::new(TypeObject::Any.into()),
            Box::new(TypeObject::Unit.into()),
        ),
    )
    .unwrap();
    env.insert_bind(
        "get_timestrap".to_string(),
        TypeObject::Function(
            Box::new(TypeObject::Unit.into()),
            Box::new(TypeObject::Float.into()),
        ),
    )
    .unwrap();
    env
}

pub fn new_evaluator_env<'a>() -> EvaluatorEnv<'a> {
    let mut env = Env::<'_, Object>::new();
    for t in PRIMIVE_TYPES.iter() {
        env.insert_bind(t.to_string(), Object::Type(t.clone()))
            .unwrap();
    }
    env.insert_bind(
        "print".to_string(),
        Object::Function {
            type_params: vec![],
            params: vec![("...args".to_string(), Box::new(TypeObject::Any.into()))],
            body: Box::new(Expr::Ident("print".to_string())),
            return_type: Box::new(TypeObject::Unit.into()),
        },
    )
    .unwrap();
    env.insert_bind(
        "get_timestrap".to_string(),
        Object::Function {
            type_params: vec![],
            params: vec![],
            body: Box::new(Expr::Ident("get_timestrap".to_string())),
            return_type: Box::new(TypeObject::Float.into()),
        },
    )
    .unwrap();
    env
}

pub type CheckerEnv<'a> = Env<'a, TypeObject>;
pub type EvaluatorEnv<'a> = Env<'a, Object>;