erg_compiler/context/
test.rs

1//! test module for `Context`
2use erg_common::traits::StructuralEq;
3use erg_common::Str;
4
5use crate::ty::constructors::{func1, mono, mono_q, poly, refinement, ty_tp};
6use crate::ty::free::Constraint;
7use crate::ty::typaram::TyParam;
8use crate::ty::{Predicate, Type};
9use Type::*;
10
11use crate::context::Context;
12
13impl Context {
14    pub fn assert_var_type(&self, varname: &str, ty: &Type) -> Result<(), ()> {
15        let Some((_, vi)) = self.get_var_info(varname) else {
16            panic!("variable not found: {varname}");
17        };
18        println!("{varname}: {}", vi.t);
19        if vi.t.structural_eq(ty) {
20            Ok(())
21        } else {
22            println!("{varname} is not the type of {ty}");
23            Err(())
24        }
25    }
26
27    pub fn assert_attr_type(&self, receiver_t: &Type, attr: &str, ty: &Type) -> Result<(), ()> {
28        let Some(ctx) = self.get_nominal_type_ctx(receiver_t) else {
29            panic!("type not found: {receiver_t}");
30        };
31        let Some((_, vi)) = ctx.get_method_kv(attr) else {
32            panic!("attribute not found: {attr}");
33        };
34        println!("{attr}: {}", vi.t);
35        if vi.t.structural_eq(ty) {
36            Ok(())
37        } else {
38            println!("{attr} is not the type of {ty}");
39            Err(())
40        }
41    }
42
43    pub fn test_refinement_subtyping(&self) -> Result<(), ()> {
44        // Nat :> {I: Int | I >= 1} ?
45        let lhs = Nat;
46        let var = Str::ever("I");
47        let rhs = refinement(
48            var.clone(),
49            Type::Int,
50            Predicate::eq(var, TyParam::value(1)),
51        );
52        if self.supertype_of(&lhs, &rhs) {
53            Ok(())
54        } else {
55            Err(())
56        }
57    }
58
59    pub fn test_quant_subtyping(&self) -> Result<(), ()> {
60        let t = crate::ty::constructors::type_q("T");
61        let quant = func1(t.clone(), t).quantify();
62        let subr = func1(Obj, Never);
63        assert!(!self.subtype_of(&quant, &subr));
64        assert!(self.subtype_of(&subr, &quant));
65        Ok(())
66    }
67
68    pub fn test_resolve_trait_inner1(&self) -> Result<(), ()> {
69        let name = Str::ever("Add");
70        let params = vec![TyParam::t(Nat)];
71        let maybe_trait = poly(name, params);
72        let mut min = Type::Obj;
73        for pair in self.get_trait_impls(&maybe_trait) {
74            if self.supertype_of(&pair.sup_trait, &maybe_trait) {
75                min = self.min(&min, &pair.sub_type).unwrap_or(&min).clone();
76            }
77        }
78        if min == Nat {
79            Ok(())
80        } else {
81            Err(())
82        }
83    }
84
85    pub fn test_instantiation_and_generalization(&self) -> Result<(), ()> {
86        use crate::ty::free::HasLevel;
87        let t = mono_q("T", Constraint::new_subtype_of(mono("Eq")));
88        let unbound = func1(t.clone(), t);
89        let quantified = unbound.clone().quantify();
90        println!("quantified      : {quantified}");
91        let inst = self.instantiate_def_type(&unbound).map_err(|_| ())?;
92        println!("inst: {inst}");
93        inst.lift();
94        let quantified_again = self.generalize_t(inst);
95        println!("quantified_again: {quantified_again}");
96        assert!(quantified.structural_eq(&quantified_again));
97        Ok(())
98    }
99
100    pub fn test_patch(&self) -> Result<(), ()> {
101        use crate::ty::constructors::or;
102        assert!(self.subtype_of(&Int, &mono("Eq")));
103        assert!(self.subtype_of(&or(Int, NoneType), &mono("Eq")));
104        assert!(!self.subtype_of(&or(Int, Float), &mono("Eq")));
105        assert!(self.subtype_of(&Int, &poly("Sub", vec![ty_tp(Int)])));
106        assert!(self.subtype_of(&Nat, &poly("Sub", vec![ty_tp(Nat)])));
107        Ok(())
108    }
109
110    pub fn test_intersection(&self) -> Result<(), ()> {
111        assert!(self.subtype_of(&Code, &(Int | Str | Code | NoneType)));
112        assert!(self.subtype_of(&(Int | Str), &(Int | Str | Code | NoneType)));
113        Ok(())
114    }
115}