mers_lib/program/configs/gen/
function.rs

1use std::marker::PhantomData;
2
3use crate::{
4    data::{self, Data, MersData, Type},
5    errors::CheckError,
6};
7
8use super::{FromMersData, ToMersData};
9
10pub fn fun<I: FromMersData + 'static, O: ToMersData + 'static>(
11    f: fn(I, &mut crate::program::run::Info) -> Result<O, CheckError>,
12) -> impl StaticMersFunc {
13    Box::new(f)
14}
15pub fn func<I: FromMersData + 'static, O: ToMersData + 'static>(
16    f: fn(I, &mut crate::program::run::Info) -> Result<O, CheckError>,
17) -> data::function::Function {
18    Box::new(f).mers_func()
19}
20pub fn func_end<I: FromMersData + 'static>(
21    f: fn(I, &mut crate::program::run::Info) -> !,
22) -> data::function::Function {
23    Box::new(f).mers_func()
24}
25pub fn func_err<I: FromMersData + 'static>(
26    f: fn(I, &mut crate::program::run::Info) -> CheckError,
27) -> data::function::Function {
28    Box::new(f).mers_func()
29}
30
31// fn this_works() {
32//     let cfg = ();
33//     // type: `(Int -> Float, Byte -> Int)`
34//     // todo: maybe add an Iterable<T> "type" that we can use like `[Itarable<Int>] (1, 2, 3)`
35//     cfg.add_var(
36//         "test".to_owned(),
37//         Data::new(
38//             TwoFuncs(
39//                 OneFunc::new(|num: isize| Ok(num as f64 / 2.0)),
40//                 OneFunc::new(|num: u8| Ok(num as isize)),
41//             )
42//             .to_mers_func(),
43//         ),
44//     );
45// }
46
47pub trait StaticMersFunc: Sized + 'static + Send + Sync {
48    fn types() -> Vec<(Type, Type)>;
49    fn run(
50        &self,
51        a: &(impl MersData + ?Sized),
52        info: &mut crate::program::run::Info,
53    ) -> Option<Result<Data, CheckError>>;
54    fn mers_func(self) -> data::function::Function {
55        data::function::Function::new_static(Self::types(), move |a, i| {
56            match self.run(a.get().as_ref(), i) {
57                Some(Ok(v)) => Ok(v),
58                Some(Err(e)) => Err(e),
59                None => Err(CheckError::from(format!(
60                    "unexpected argument of type {}, expected {}",
61                    a.get().as_type().with_info(i),
62                    {
63                        let mut o = Type::empty();
64                        for t in Self::types() {
65                            o.add_all(&t.0);
66                        }
67                        o
68                    }
69                    .with_info(i)
70                ))),
71            }
72        })
73    }
74}
75
76pub struct Funcs<A: StaticMersFunc, B: StaticMersFunc>(pub A, pub B);
77
78pub trait Func: Send + Sync + 'static {
79    type I: FromMersData;
80    type O: ToMersData;
81    fn run_func(
82        &self,
83        i: Self::I,
84        info: &mut crate::program::run::Info,
85    ) -> Result<Self::O, CheckError>;
86}
87impl<I: FromMersData + 'static, O: ToMersData + 'static> Func
88    for fn(I, &mut crate::program::run::Info) -> Result<O, CheckError>
89{
90    type I = I;
91    type O = O;
92    fn run_func(
93        &self,
94        i: Self::I,
95        info: &mut crate::program::run::Info,
96    ) -> Result<Self::O, CheckError> {
97        self(i, info)
98    }
99}
100
101pub struct UnreachableDontConstruct(PhantomData<Self>);
102impl ToMersData for UnreachableDontConstruct {
103    fn as_type_to() -> Type {
104        Type::empty()
105    }
106    fn represent(self) -> Data {
107        unreachable!()
108    }
109}
110impl<I: FromMersData + 'static> Func for fn(I, &mut crate::program::run::Info) -> ! {
111    type I = I;
112    type O = UnreachableDontConstruct;
113    fn run_func(
114        &self,
115        i: Self::I,
116        info: &mut crate::program::run::Info,
117    ) -> Result<Self::O, CheckError> {
118        self(i, info);
119    }
120}
121impl<I: FromMersData + 'static> Func for fn(I, &mut crate::program::run::Info) -> CheckError {
122    type I = I;
123    type O = UnreachableDontConstruct;
124    fn run_func(
125        &self,
126        i: Self::I,
127        info: &mut crate::program::run::Info,
128    ) -> Result<Self::O, CheckError> {
129        Err(self(i, info))
130    }
131}
132
133impl<F: Func + ?Sized> StaticMersFunc for Box<F> {
134    fn types() -> Vec<(Type, Type)> {
135        vec![(F::I::as_type_from(), F::O::as_type_to())]
136    }
137    fn run(
138        &self,
139        a: &(impl MersData + ?Sized),
140        info: &mut crate::program::run::Info,
141    ) -> Option<Result<Data, CheckError>> {
142        F::I::try_represent(a, |v| {
143            v.map(|v| self.run_func(v, info).map(|v| v.represent()))
144        })
145    }
146}
147
148impl<A: StaticMersFunc, B: StaticMersFunc> StaticMersFunc for Funcs<A, B> {
149    fn types() -> Vec<(Type, Type)> {
150        let mut o = A::types();
151        for t in B::types() {
152            if o.iter().any(|o| t.0.is_included_in(&o.0)) {
153                // other function fully covers this case already,
154                // ignore it in type signature as we will always call the first function instead of the 2nd one
155            } else {
156                o.push(t);
157            }
158        }
159        o
160    }
161    fn run(
162        &self,
163        a: &(impl MersData + ?Sized),
164        info: &mut crate::program::run::Info,
165    ) -> Option<Result<Data, CheckError>> {
166        self.0.run(a, info).or_else(|| self.1.run(a, info))
167    }
168}