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| ¶m.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}