Skip to main content

datex_core/values/core_values/
callable.rs

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