moduforge_rules_expression/functions/
defs.rs1use crate::functions::arguments::Arguments;
6use crate::variable::VariableType;
7use crate::Variable;
8use std::any::Any;
9use std::collections::HashSet;
10use std::rc::Rc;
11
12pub trait FunctionDefinition: Any {
16    fn required_parameters(&self) -> usize;
18    fn optional_parameters(&self) -> usize;
20    fn check_types(
22        &self,
23        args: &[Rc<VariableType>],
24    ) -> FunctionTypecheck;
25    fn call(
27        &self,
28        args: Arguments,
29    ) -> anyhow::Result<Variable>;
30    fn param_type(
32        &self,
33        index: usize,
34    ) -> Option<VariableType>;
35    fn param_type_str(
37        &self,
38        index: usize,
39    ) -> String;
40    fn return_type(&self) -> VariableType;
42    fn return_type_str(&self) -> String;
44}
45
46#[derive(Debug, Default)]
50pub struct FunctionTypecheck {
51    pub general: Option<String>,
53    pub arguments: Vec<(usize, String)>,
55    pub return_type: VariableType,
57}
58
59#[derive(Clone)]
63pub struct FunctionSignature {
64    pub parameters: Vec<VariableType>,
66    pub return_type: VariableType,
68}
69
70impl FunctionSignature {
71    pub fn single(
77        parameter: VariableType,
78        return_type: VariableType,
79    ) -> Self {
80        Self { parameters: vec![parameter], return_type }
81    }
82}
83
84#[derive(Clone)]
88pub struct StaticFunction {
89    pub signature: FunctionSignature,
91    pub implementation: Rc<dyn Fn(Arguments) -> anyhow::Result<Variable>>,
93}
94
95impl FunctionDefinition for StaticFunction {
96    fn required_parameters(&self) -> usize {
98        self.signature.parameters.len()
99    }
100
101    fn optional_parameters(&self) -> usize {
103        0
104    }
105
106    fn check_types(
108        &self,
109        args: &[Rc<VariableType>],
110    ) -> FunctionTypecheck {
111        let mut typecheck = FunctionTypecheck::default();
112        typecheck.return_type = self.signature.return_type.clone();
113
114        if args.len() != self.required_parameters() {
116            typecheck.general = Some(format!(
117                "期望 `{}` 参数, 实际 `{}` 参数.",
118                self.required_parameters(),
119                args.len()
120            ));
121        }
122
123        for (i, (arg, expected_type)) in
125            args.iter().zip(self.signature.parameters.iter()).enumerate()
126        {
127            if !arg.satisfies(expected_type) {
128                typecheck.arguments.push((
129                    i,
130                    format!(
131                        "参数类型 `{arg}` 不能赋值给参数类型 `{expected_type}`.",
132                    ),
133                ));
134            }
135        }
136
137        typecheck
138    }
139
140    fn call(
142        &self,
143        args: Arguments,
144    ) -> anyhow::Result<Variable> {
145        (&self.implementation)(args)
146    }
147
148    fn param_type(
150        &self,
151        index: usize,
152    ) -> Option<VariableType> {
153        self.signature.parameters.get(index).cloned()
154    }
155
156    fn param_type_str(
158        &self,
159        index: usize,
160    ) -> String {
161        self.signature
162            .parameters
163            .get(index)
164            .map(|x| x.to_string())
165            .unwrap_or_else(|| "never".to_string())
166    }
167
168    fn return_type(&self) -> VariableType {
170        self.signature.return_type.clone()
171    }
172
173    fn return_type_str(&self) -> String {
175        self.signature.return_type.to_string()
176    }
177}
178
179#[derive(Clone)]
183pub struct CompositeFunction {
184    pub signatures: Vec<FunctionSignature>,
186    pub implementation: Rc<dyn Fn(Arguments) -> anyhow::Result<Variable>>,
188}
189
190impl FunctionDefinition for CompositeFunction {
191    fn required_parameters(&self) -> usize {
193        self.signatures.iter().map(|x| x.parameters.len()).min().unwrap_or(0)
194    }
195
196    fn optional_parameters(&self) -> usize {
198        let required_params = self.required_parameters();
199        let max = self
200            .signatures
201            .iter()
202            .map(|x| x.parameters.len())
203            .max()
204            .unwrap_or(0);
205
206        max - required_params
207    }
208
209    fn check_types(
211        &self,
212        args: &[Rc<VariableType>],
213    ) -> FunctionTypecheck {
214        let mut typecheck = FunctionTypecheck::default();
215        if self.signatures.is_empty() {
216            typecheck.general = Some("No implementation".to_string());
217            return typecheck;
218        }
219
220        let required_params = self.required_parameters();
221        let optional_params = self.optional_parameters();
222        let total_params = required_params + optional_params;
223
224        if args.len() < required_params || args.len() > total_params {
226            typecheck.general = Some(format!(
227                "Expected `{required_params} - {total_params}` arguments, got `{}`.",
228                args.len()
229            ))
230        }
231
232        for signature in &self.signatures {
234            let all_match = args
235                .iter()
236                .zip(signature.parameters.iter())
237                .all(|(arg, param)| arg.satisfies(param));
238            if all_match {
239                typecheck.return_type = signature.return_type.clone();
240                return typecheck;
241            }
242        }
243
244        for (i, arg) in args.iter().enumerate() {
246            let possible_types: Vec<&VariableType> = self
247                .signatures
248                .iter()
249                .filter_map(|sig| sig.parameters.get(i))
250                .collect();
251
252            if !possible_types.iter().any(|param| arg.satisfies(param)) {
253                let type_union = self.param_type_str(i);
254                typecheck.arguments.push((
255                    i,
256                    format!(
257                        "Argument of type `{arg}` is not assignable to parameter of type `{type_union}`.",
258                    ),
259                ))
260            }
261        }
262
263        let available_signatures = self
265            .signatures
266            .iter()
267            .map(|sig| {
268                let param_list = sig
269                    .parameters
270                    .iter()
271                    .map(|x| x.to_string())
272                    .collect::<Vec<_>>()
273                    .join(", ");
274                format!("`({param_list}) -> {}`", sig.return_type)
275            })
276            .collect::<Vec<_>>()
277            .join("\n");
278        typecheck.general = Some(format!(
279            "No function overload matches provided arguments. Available overloads:\n{available_signatures}"
280        ));
281
282        typecheck
283    }
284
285    fn call(
287        &self,
288        args: Arguments,
289    ) -> anyhow::Result<Variable> {
290        (&self.implementation)(args)
291    }
292
293    fn param_type(
295        &self,
296        index: usize,
297    ) -> Option<VariableType> {
298        self.signatures
299            .iter()
300            .filter_map(|sig| sig.parameters.get(index))
301            .cloned()
302            .reduce(|a, b| a.merge(&b))
303    }
304
305    fn param_type_str(
307        &self,
308        index: usize,
309    ) -> String {
310        let possible_types: Vec<String> = self
311            .signatures
312            .iter()
313            .filter_map(|sig| sig.parameters.get(index))
314            .map(|x| x.to_string())
315            .collect();
316        if possible_types.is_empty() {
317            return String::from("never");
318        }
319
320        let is_optional = possible_types.len() != self.signatures.len();
321        let possible_types: Vec<String> = possible_types
322            .into_iter()
323            .collect::<HashSet<_>>()
324            .into_iter()
325            .collect();
326
327        let type_union = possible_types.join(" | ");
328        if is_optional {
329            return format!("Optional<{type_union}>");
330        }
331
332        type_union
333    }
334
335    fn return_type(&self) -> VariableType {
337        self.signatures
338            .iter()
339            .map(|sig| &sig.return_type)
340            .cloned()
341            .reduce(|a, b| a.merge(&b))
342            .unwrap_or(VariableType::Null)
343    }
344
345    fn return_type_str(&self) -> String {
347        let possible_types: Vec<String> = self
348            .signatures
349            .iter()
350            .map(|sig| sig.return_type.clone())
351            .map(|x| x.to_string())
352            .collect();
353        if possible_types.is_empty() {
354            return String::from("never");
355        }
356
357        possible_types
358            .into_iter()
359            .collect::<HashSet<_>>()
360            .into_iter()
361            .collect::<Vec<_>>()
362            .join(" | ")
363    }
364}