lang_interpreter/interpreter/data/function/
native.rs

1use std::any::Any;
2use std::error::Error;
3use std::fmt::{Debug, Display, Formatter};
4use std::sync::atomic::{AtomicUsize, Ordering};
5use gc::{Finalize, Trace};
6use crate::interpreter::data::{DataObjectRef, DataTypeConstraintError, LangObjectRef, OptionDataObjectRef, OptionLangObjectRef};
7use crate::interpreter::{operators, Interpreter};
8use crate::interpreter::data::function::native::dyn_fn_lang_native_function_return_type::ReturnType;
9use crate::lexer::CodePosition;
10
11pub type Result<T> = std::result::Result<T, NativeError>;
12
13mod dyn_fn_lang_native_function_return_type {
14    use super::Result;
15
16    use crate::interpreter::data::{DataObjectRef, OptionDataObjectRef};
17
18    pub trait ReturnType {
19        fn into(self) -> Result<OptionDataObjectRef>;
20    }
21
22    impl ReturnType for Result<OptionDataObjectRef> {
23        #[inline(always)]
24        fn into(self) -> Result<OptionDataObjectRef> {
25            self
26        }
27    }
28
29    impl ReturnType for Result<DataObjectRef> {
30        #[inline(always)]
31        fn into(self) -> Result<OptionDataObjectRef> {
32            self.map(Some)
33        }
34    }
35
36    impl ReturnType for Result<()> {
37        #[inline(always)]
38        fn into(self) -> Result<OptionDataObjectRef> {
39            self.map(|_| None)
40        }
41    }
42
43    impl ReturnType for OptionDataObjectRef {
44        #[inline(always)]
45        fn into(self) -> Result<OptionDataObjectRef> {
46            Ok(self)
47        }
48    }
49
50    impl ReturnType for DataObjectRef {
51        #[inline(always)]
52        fn into(self) -> Result<OptionDataObjectRef> {
53            Ok(Some(self))
54        }
55    }
56
57    impl ReturnType for () {
58        #[inline(always)]
59        fn into(self) -> Result<OptionDataObjectRef> {
60            Ok(None)
61        }
62    }
63}
64
65pub trait FromLangArgs: Sized {
66    fn from_lang_args(
67        this_object: OptionLangObjectRef,
68        args: Vec<DataObjectRef>,
69    ) -> Result<Self>;
70
71    fn lang_parameter_count() -> usize;
72    fn is_method() -> bool;
73}
74
75mod tuple_from_lang_args {
76    use std::mem;
77    use super::*;
78
79    crate::internal_tuple_from_lang_args_impl! { 1 }
80    crate::internal_tuple_from_lang_args_impl! { 2 }
81    crate::internal_tuple_from_lang_args_impl! { 3 }
82    crate::internal_tuple_from_lang_args_impl! { 4 }
83    crate::internal_tuple_from_lang_args_impl! { 5 }
84    crate::internal_tuple_from_lang_args_impl! { 6 }
85    crate::internal_tuple_from_lang_args_impl! { 7 }
86    crate::internal_tuple_from_lang_args_impl! { 8 }
87    crate::internal_tuple_from_lang_args_impl! { 9 }
88    crate::internal_tuple_from_lang_args_impl! { 10 }
89    crate::internal_tuple_from_lang_args_impl! { 11 }
90    crate::internal_tuple_from_lang_args_impl! { 12 }
91
92    //No args
93    impl FromLangArgs for () {
94        fn from_lang_args(
95            this_object: OptionLangObjectRef,
96            args: Vec<DataObjectRef>,
97        ) -> Result<Self> {
98            if !args.is_empty() {
99                return Err(NativeError::new("Invalid argument count for native function", None));
100            }
101
102            if this_object.is_some() {
103                return Err(NativeError::new("This object may not be set for native function without a this parameter", None));
104            }
105
106            Ok(())
107        }
108
109        fn lang_parameter_count() -> usize {
110            0
111        }
112
113        fn is_method() -> bool {
114            false
115        }
116    }
117
118    //VarArgs only
119    impl FromLangArgs for (Vec<DataObjectRef>,) {
120        fn from_lang_args(
121            this_object: OptionLangObjectRef,
122            args: Vec<DataObjectRef>,
123        ) -> Result<Self> {
124            if this_object.is_some() {
125                return Err(NativeError::new("This object may not be set for native function without a this parameter", None));
126            }
127
128            Ok((args,))
129        }
130
131        fn lang_parameter_count() -> usize {
132            1
133        }
134
135        fn is_method() -> bool {
136            false
137        }
138    }
139
140    //This arg only
141    impl FromLangArgs for (LangObjectRef,) {
142        fn from_lang_args(
143            this_object: OptionLangObjectRef,
144            args: Vec<DataObjectRef>,
145        ) -> Result<Self> {
146            if !args.is_empty() {
147                return Err(NativeError::new("Invalid argument count for native function", None));
148            }
149
150            let Some(this_object) = this_object.as_ref() else {
151                return Err(NativeError::new("This object must be set for native function with a this parameter", None));
152            };
153
154            Ok((this_object.clone(),))
155        }
156
157        fn lang_parameter_count() -> usize {
158            0
159        }
160
161        fn is_method() -> bool {
162            true
163        }
164    }
165
166    //This arg + VarArgs
167    impl FromLangArgs for (LangObjectRef, Vec<DataObjectRef>) {
168        fn from_lang_args(
169            this_object: OptionLangObjectRef,
170            args: Vec<DataObjectRef>,
171        ) -> Result<Self> {
172            let Some(this_object) = this_object.as_ref() else {
173                return Err(NativeError::new("This object must be set for native function with a this parameter", None));
174            };
175
176            Ok((this_object.clone(), args))
177        }
178
179        fn lang_parameter_count() -> usize {
180            1
181        }
182
183        fn is_method() -> bool {
184            true
185        }
186    }
187}
188
189mod private {
190    pub trait Sealed {}
191}
192
193pub trait ConvertToFuncTrait<F> {
194    fn func_trait(self) -> F;
195}
196
197pub trait NativeFunctionAdapter: private::Sealed {
198    fn lang_call(
199        &self,
200        interpreter: &mut Interpreter,
201        this_object: OptionLangObjectRef,
202        args: Vec<DataObjectRef>,
203    ) -> Result<OptionDataObjectRef>;
204
205    fn lang_parameter_count(&self) -> usize;
206    fn is_method(&self) -> bool;
207}
208
209mod native_function_adapter {
210    use super::*;
211
212    crate::internal_native_function_adapter_impl! { 1 }
213    crate::internal_native_function_adapter_impl! { 2 }
214    crate::internal_native_function_adapter_impl! { 3 }
215    crate::internal_native_function_adapter_impl! { 4 }
216    crate::internal_native_function_adapter_impl! { 5 }
217    crate::internal_native_function_adapter_impl! { 6 }
218    crate::internal_native_function_adapter_impl! { 7 }
219    crate::internal_native_function_adapter_impl! { 8 }
220    crate::internal_native_function_adapter_impl! { 9 }
221    crate::internal_native_function_adapter_impl! { 10 }
222    crate::internal_native_function_adapter_impl! { 11 }
223    crate::internal_native_function_adapter_impl! { 12 }
224
225    impl<
226        Ret: ReturnType,
227        F: Fn(&mut Interpreter) -> Ret + 'static,
228    > ConvertToFuncTrait<Box<dyn Fn(&mut Interpreter) -> Ret + 'static>> for F {
229        #[inline(always)]
230        fn func_trait(self) -> Box<dyn Fn(&mut Interpreter) -> Ret + 'static> {
231            Box::new(self)
232        }
233    }
234
235    impl<
236        Ret: ReturnType,
237    > NativeFunctionAdapter for Box<dyn Fn(&mut Interpreter) -> Ret> {
238        fn lang_call(
239            &self,
240            interpreter: &mut Interpreter,
241            this_object: OptionLangObjectRef,
242            args: Vec<DataObjectRef>,
243        ) -> Result<OptionDataObjectRef> {
244            <()>::from_lang_args(this_object, args)?;
245
246            self(interpreter).into()
247        }
248
249        fn lang_parameter_count(&self) -> usize {
250            <()>::lang_parameter_count()
251        }
252
253        fn is_method(&self) -> bool {
254            <()>::is_method()
255        }
256    }
257
258    impl<
259        Ret: ReturnType,
260    > private::Sealed for Box<dyn Fn(&mut Interpreter) -> Ret> {}
261}
262
263impl Debug for dyn NativeFunctionAdapter {
264    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
265        write!(f, "Native function at {:p}", self)
266    }
267}
268
269pub fn create_native_function(
270    func: Box<dyn NativeFunctionAdapter>,
271    func_id: NativeFuncId,
272    value_dependencies: Vec<Box<dyn AnyWithEq>>,
273) -> NativeFunction {
274    NativeFunction::new(func, func_id, value_dependencies)
275}
276
277#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
278pub struct NativeFuncId(usize);
279
280pub fn gen_next_native_func_id() -> NativeFuncId {
281    static NEXT_NATIVE_FUNC_ID: AtomicUsize = AtomicUsize::new(0);
282
283    let id = NEXT_NATIVE_FUNC_ID.fetch_add(1, Ordering::Relaxed);
284
285    NativeFuncId(id)
286}
287
288#[derive(Debug, Trace, Finalize)]
289pub struct NativeFunction {
290    //SAFETY: There are no GC reference inside NativeFunctionAdapter
291    #[unsafe_ignore_trace]
292    function_body: Box<dyn NativeFunctionAdapter>,
293    //SAFETY: There are no GC reference inside NativeFuncId
294    #[unsafe_ignore_trace]
295    func_id: NativeFuncId,
296
297    value_dependencies: Vec<Box<dyn AnyWithEq>>,
298}
299
300impl NativeFunction {
301    fn new(function_body: Box<dyn NativeFunctionAdapter>, func_id: NativeFuncId, value_dependencies: Vec<Box<dyn AnyWithEq>>) -> Self {
302        Self { function_body, func_id, value_dependencies }
303    }
304
305    pub fn is_equals(&self, other: &Self, interpreter: &mut Interpreter, pos: CodePosition) -> bool {
306        self.func_id == other.func_id && self.value_dependencies.len() == other.value_dependencies.len() &&
307                self.value_dependencies.iter().zip(other.value_dependencies.iter()).
308                        all(|(s, o)|
309                                s.is_equals(o.as_ref(), interpreter, pos))
310    }
311
312    pub fn is_strict_equals(&self, other: &Self, interpreter: &mut Interpreter, pos: CodePosition) -> bool {
313        self.func_id == other.func_id && self.value_dependencies.len() == other.value_dependencies.len() &&
314                self.value_dependencies.iter().zip(other.value_dependencies.iter()).
315                        all(|(s, o)|
316                                s.is_strict_equals(o.as_ref(), interpreter, pos))
317    }
318
319    pub fn function_body(&self) -> &dyn NativeFunctionAdapter {
320        self.function_body.as_ref()
321    }
322
323    pub fn lang_parameter_count(&self) -> usize {
324        self.function_body.lang_parameter_count()
325    }
326
327    pub fn is_method(&self) -> bool {
328        self.function_body.is_method()
329    }
330}
331
332pub trait AnyWithEq: Debug + Trace + Finalize {
333    fn as_any(&self) -> &dyn Any;
334
335    fn is_equals(&self, other: &dyn AnyWithEq, interpreter: &mut Interpreter, pos: CodePosition) -> bool;
336    fn is_strict_equals(&self, other: &dyn AnyWithEq, interpreter: &mut Interpreter, pos: CodePosition) -> bool;
337}
338
339impl<T: 'static + PartialEq> AnyWithEq for T where T: Debug + Trace + Finalize {
340    fn as_any(&self) -> &dyn Any {
341        self
342    }
343
344    fn is_equals(&self, other: &dyn AnyWithEq, _interpreter: &mut Interpreter, _pos: CodePosition) -> bool {
345        other.as_any().downcast_ref::<T>().is_some_and(|o| self == o)
346    }
347
348    fn is_strict_equals(&self, other: &dyn AnyWithEq, _interpreter: &mut Interpreter, _pos: CodePosition) -> bool {
349        other.as_any().downcast_ref::<T>().is_some_and(|o| self == o)
350    }
351}
352
353impl AnyWithEq for DataObjectRef {
354    fn as_any(&self) -> &dyn Any {
355        self
356    }
357
358    fn is_equals(&self, other: &dyn AnyWithEq, interpreter: &mut Interpreter, pos: CodePosition) -> bool {
359        other.as_any().downcast_ref::<Self>().
360                is_some_and(|o| operators::is_equals(
361                    interpreter,
362                    &self.clone(),
363                    &o.clone(),
364                    pos,
365                ))
366    }
367
368    fn is_strict_equals(&self, other: &dyn AnyWithEq, interpreter: &mut Interpreter, pos: CodePosition) -> bool {
369        other.as_any().downcast_ref::<Self>().
370                is_some_and(|o| operators::is_strict_equals(
371                    interpreter,
372                    &self.clone(),
373                    &o.clone(),
374                    pos,
375                ))
376    }
377}
378
379impl Display for NativeFunction {
380    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
381        write!(f, "Native function (ID: {}) at {:p}", self.func_id.0, self.function_body.as_ref())
382    }
383}
384
385#[derive(Debug)]
386pub struct NativeError {
387    message: String,
388    cause: Option<Box<dyn Error>>,
389}
390
391impl NativeError {
392    pub fn new(message: &str, cause: Option<Box<dyn Error>>) -> Self {
393        Self {
394            message: message.into(),
395            cause,
396        }
397    }
398
399    pub fn from_error<E>(cause: E) -> Self
400    where E: Error + 'static {
401        Self {
402            message: "Native Error".to_string(),
403            cause: Some(Box::new(cause)),
404        }
405    }
406
407    pub fn from_error_with_message<E>(message: &str, cause: E) -> Self
408    where E: Error + 'static {
409        Self {
410            message: message.into(),
411            cause: Some(Box::new(cause)),
412        }
413    }
414
415    pub fn apply<E>(cause: E) -> Self
416    where E: Error + 'static {
417        Self {
418            message: "Native Error".to_string(),
419            cause: Some(Box::new(cause)),
420        }
421    }
422
423    pub fn apply_with_message<E>(message: &str) -> impl FnOnce(E) -> Self + 'static
424    where E: Error + 'static {
425        let message = message.into();
426        
427        move |cause: E| {
428            Self {
429                message,
430                cause: Some(Box::new(cause)),
431            }
432        }
433    }
434
435    pub fn message(&self) -> &str {
436        &self.message
437    }
438
439    pub fn cause(&self) -> Option<&dyn Error> {
440        self.cause.as_deref()
441    }
442}
443
444impl From<DataTypeConstraintError> for NativeError {
445    fn from(value: DataTypeConstraintError) -> Self {
446        Self::new("Data Type Constraint error", Some(value.into()))
447    }
448}
449
450impl From<Box<dyn Error>> for NativeError {
451    fn from(value: Box<dyn Error>) -> Self {
452        Self::new("Native Error", Some(value))
453    }
454}
455
456impl Display for NativeError {
457    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
458        if let Some(cause) = &self.cause {
459            write!(f, "{}\nCaused by:\n{}", &self.message, cause)
460        }else {
461            write!(f, "{}", &self.message)
462        }
463    }
464}
465
466impl Error for NativeError {}