datex_core/values/core_values/
callable.rs

1use crate::runtime::execution::ExecutionError;
2use crate::stdlib::boxed::Box;
3use crate::stdlib::string::String;
4use crate::stdlib::vec::Vec;
5use crate::traits::apply::Apply;
6use crate::traits::structural_eq::StructuralEq;
7use crate::values::core_values::r#type::Type;
8use crate::values::value_container::ValueContainer;
9use core::fmt::Display;
10use core::fmt::Formatter;
11
12#[derive(Clone, Debug, PartialEq, Eq, Hash)]
13pub enum CallableKind {
14    // A pure function
15    Function,
16    // A procedure that may have side effects
17    Procedure,
18}
19
20impl Display for CallableKind {
21    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
22        match self {
23            CallableKind::Function => write!(f, "function"),
24            CallableKind::Procedure => write!(f, "procedure"),
25        }
26    }
27}
28
29pub type NativeCallable =
30    fn(&[ValueContainer]) -> Result<Option<ValueContainer>, ExecutionError>;
31
32#[derive(Clone, Debug, PartialEq, Eq, Hash)]
33pub enum CallableBody {
34    Native(NativeCallable),
35    DatexBytecode,
36}
37
38#[derive(Debug, Clone, PartialEq, Eq, Hash)]
39pub struct CallableSignature {
40    pub kind: CallableKind,
41    pub parameter_types: Vec<(Option<String>, Type)>,
42    pub rest_parameter_type: Option<(Option<String>, Box<Type>)>,
43    pub return_type: Option<Box<Type>>,
44    pub yeet_type: Option<Box<Type>>,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, Hash)]
48pub struct Callable {
49    pub name: Option<String>,
50    pub signature: CallableSignature,
51    pub body: CallableBody,
52}
53
54impl Callable {
55    pub fn call(
56        &self,
57        args: &[ValueContainer],
58    ) -> Result<Option<ValueContainer>, ExecutionError> {
59        match &self.body {
60            CallableBody::Native(func) => func(args),
61            CallableBody::DatexBytecode => {
62                todo!("#606 Calling Datex bytecode is not yet implemented")
63            }
64        }
65    }
66}
67
68impl Apply for Callable {
69    fn apply(
70        &self,
71        args: &[ValueContainer],
72    ) -> Result<Option<ValueContainer>, ExecutionError> {
73        self.call(args)
74    }
75    fn apply_single(
76        &self,
77        arg: &ValueContainer,
78    ) -> Result<Option<ValueContainer>, ExecutionError> {
79        self.call(&[arg.clone()])
80    }
81}
82
83impl StructuralEq for Callable {
84    fn structural_eq(&self, other: &Self) -> bool {
85        self == other
86    }
87}