erg_compiler 0.4.3

Centimetre: the Erg compiler
Documentation
//! test module for `Context`
use erg_common::Str;
use erg_common::{enum_unwrap, set};

use erg_type::constructors::{func1, mono_q, poly, quant, refinement};
use erg_type::typaram::TyParam;
use erg_type::{Predicate, TyBound, Type};
use Type::*;

use crate::context::instantiate::TyVarContext;
use crate::context::Context;

impl Context {
    pub fn test_refinement_subtyping(&self) -> Result<(), ()> {
        // Nat :> {I: Int | I >= 1} ?
        let lhs = Nat;
        let var = Str::ever("I");
        let rhs = refinement(
            var.clone(),
            Type::Int,
            set! { Predicate::eq(var, TyParam::value(1)) },
        );
        if self.supertype_of(&lhs, &rhs) {
            Ok(())
        } else {
            Err(())
        }
    }

    pub fn test_resolve_trait(&self) -> Result<(), ()> {
        let t = poly("Add", vec![TyParam::t(Nat)]);
        match self.resolve_trait(t) {
            Ok(Nat) => Ok(()),
            Ok(other) => {
                print!("other: {other}");
                Err(())
            }
            Err(err) => {
                use erg_common::error::ErrorDisplay;
                err.write_to_stderr();
                Err(())
            }
        }
    }

    pub fn test_resolve_trait_inner1(&self) -> Result<(), ()> {
        let name = Str::ever("Add");
        let params = vec![TyParam::t(Nat)];
        let maybe_trait = poly(name.clone(), params);
        let mut min = Type::Obj;
        for pair in self.rec_get_trait_impls(&name) {
            if self.supertype_of(&pair.sup_trait, &maybe_trait) {
                min = self.min(&min, &pair.sub_type).unwrap_or(&min).clone();
            }
        }
        if min == Nat {
            Ok(())
        } else {
            Err(())
        }
    }

    pub fn test_instantiation_and_generalization(&self) -> Result<(), ()> {
        let t = mono_q("T");
        let eq = poly("Eq", vec![TyParam::t(t.clone())]);
        let bound = TyBound::subtype_of(t.clone(), eq);
        let bounds = set! {bound};
        let unbound_t = func1(t.clone(), t);
        let quantified = quant(unbound_t.clone(), bounds.clone());
        println!("quantified      : {quantified}");
        let mut tv_ctx = TyVarContext::new(self.level + 1, bounds, self);
        println!("tv_ctx: {tv_ctx}");
        let inst = Self::instantiate_t(unbound_t, &mut tv_ctx);
        println!("inst: {inst}");
        let quantified_again = self.generalize_t(inst);
        println!("quantified_again: {quantified_again}");
        assert_eq!(quantified, quantified_again);
        let unbound_t = *enum_unwrap!(quantified_again, Type::Quantified).unbound_callable;
        // 同じtv_ctxで2回instantiateしないこと
        let inst = Self::instantiate_t(unbound_t, &mut tv_ctx); // (?T(<: Eq('T))[2]) -> ?T(<: Eq('T))[2]
        println!("inst: {inst}");
        let quantified_again = self.generalize_t(inst);
        println!("quantified_again: {quantified_again}");
        if quantified_again == quantified {
            // 結果的に同じにはなる
            Ok(())
        } else {
            Err(())
        }
    }
}