lang_interpreter/interpreter/data/function/
native.rs1use 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 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 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 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 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 #[unsafe_ignore_trace]
292 function_body: Box<dyn NativeFunctionAdapter>,
293 #[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 {}