py_declare/
filter.rs

1use std::marker::PhantomData;
2
3use terl::{Span, WithSpan};
4
5use crate::{Defs, Type, Types};
6
7pub trait BranchFilter<T: Types>: WithSpan {
8    fn satisfy(&self, ty: &Type) -> bool;
9
10    fn expect(&self, defs: &Defs) -> String;
11}
12
13pub struct CustomFilter<T: Types, Fs, Fe>
14where
15    Fs: Fn(&Type) -> bool,
16    Fe: Fn(&Defs) -> String,
17{
18    satisfy: Fs,
19    expect: Fe,
20    at: Span,
21    _p: PhantomData<T>,
22}
23
24impl<T: Types, Fs, Fe> CustomFilter<T, Fs, Fe>
25where
26    Fs: Fn(&Type) -> bool,
27    Fe: Fn(&Defs) -> String,
28{
29    pub fn new(satisfy: Fs, expect: Fe, at: Span) -> Self {
30        Self {
31            satisfy,
32            expect,
33            at,
34            _p: PhantomData,
35        }
36    }
37}
38
39impl<T: Types, Fs, Fe> WithSpan for CustomFilter<T, Fs, Fe>
40where
41    Fs: Fn(&Type) -> bool,
42    Fe: Fn(&Defs) -> String,
43{
44    fn get_span(&self) -> Span {
45        self.at
46    }
47}
48
49impl<T: Types, Fs, Fe> BranchFilter<T> for CustomFilter<T, Fs, Fe>
50where
51    Fs: Fn(&Type) -> bool,
52    Fe: Fn(&Defs) -> String,
53{
54    fn satisfy(&self, ty: &Type) -> bool {
55        (self.satisfy)(ty)
56    }
57
58    fn expect(&self, defs: &Defs) -> String {
59        (self.expect)(defs)
60    }
61}
62
63pub mod filters {
64
65    use super::*;
66    use crate::{Directly, Overload};
67    use py_ir::types::TypeDefine;
68    use std::any::TypeId;
69
70    pub struct TypeEqual<'t> {
71        expect: &'t TypeDefine,
72        at: Span,
73    }
74
75    impl<'t> TypeEqual<'t> {
76        pub fn new(expect: &'t TypeDefine, at: Span) -> Self {
77            Self { expect, at }
78        }
79    }
80
81    impl WithSpan for TypeEqual<'_> {
82        fn get_span(&self) -> Span {
83            self.at
84        }
85    }
86
87    impl<T: Types> BranchFilter<T> for TypeEqual<'_> {
88        fn satisfy(&self, ty: &Type) -> bool {
89            ty.get_type() == self.expect
90        }
91
92        fn expect(&self, _: &Defs) -> String {
93            if TypeId::of::<T>() == TypeId::of::<Overload>() {
94                format!("a function whose return type is {}", self.expect)
95            } else if TypeId::of::<T>() == TypeId::of::<Directly>() {
96                format!("a val whose type is {}", self.expect)
97            } else {
98                unreachable!()
99            }
100        }
101    }
102
103    pub struct FnParamLen<'n> {
104        name: Option<&'n str>,
105        expect: usize,
106        at: Span,
107    }
108
109    impl<'n> FnParamLen<'n> {
110        pub fn new(name: Option<&'n str>, expect: usize, at: Span) -> Self {
111            Self { name, expect, at }
112        }
113    }
114
115    impl WithSpan for FnParamLen<'_> {
116        fn get_span(&self) -> Span {
117            self.at
118        }
119    }
120
121    impl BranchFilter<Overload> for FnParamLen<'_> {
122        fn satisfy(&self, ty: &Type) -> bool {
123            ty.overload().params.len() == self.expect
124        }
125
126        fn expect(&self, defs: &Defs) -> String {
127            let mut msg = format!("a funcion with {} parameters", self.expect);
128
129            if let Some(name) = self.name {
130                msg += "\nexist overloads whose length is expected:\n";
131                let satisfies = defs
132                    .get_unmangled(name)
133                    .unwrap()
134                    .iter()
135                    .filter(|ol| ol.params.len() == self.expect)
136                    .map(|ol| ol.to_string())
137                    .collect::<Vec<_>>();
138                if satisfies.is_empty() {
139                    msg += "emm, no-overload a matched :("
140                } else {
141                    msg += &satisfies.join("\n");
142                }
143            }
144            msg
145        }
146    }
147
148    pub struct NthParamTyEqual<'t> {
149        pub at: Span,
150        pub nth: usize,
151        pub expect: &'t TypeDefine,
152    }
153
154    impl<'t> NthParamTyEqual<'t> {
155        pub fn new(nth: usize, expect: &'t TypeDefine, at: Span) -> Self {
156            Self { at, nth, expect }
157        }
158    }
159
160    impl WithSpan for NthParamTyEqual<'_> {
161        fn get_span(&self) -> Span {
162            self.at
163        }
164    }
165
166    impl BranchFilter<Overload> for NthParamTyEqual<'_> {
167        fn satisfy(&self, ty: &Type) -> bool {
168            ty.overload()
169                .params
170                .get(self.nth)
171                .is_some_and(|param| &param.ty == self.expect)
172        }
173
174        fn expect(&self, _defs: &Defs) -> String {
175            format!(
176                "a function whose {}th parameter is {}",
177                self.nth, self.expect
178            )
179        }
180    }
181}