mers_lib/program/configs/gen/
function.rs1use 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
31pub 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 } 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}