onion_frontend/parser/comptime/
native.rs1use std::sync::Arc;
8
9use onion_vm::{
10 GC,
11 lambda::runnable::{Runnable, RuntimeError, StepResult},
12 types::{
13 lambda::{
14 definition::{LambdaBody, LambdaType, OnionLambdaDefinition},
15 parameter::LambdaParameter,
16 },
17 object::{OnionObject, OnionObjectCell, OnionStaticObject},
18 },
19 unwrap_step_result,
20 utils::fastmap::{OnionFastMap, OnionKeyPool},
21};
22
23pub struct NativeFunctionGenerator<F>
28where
29 F: Fn(
30 &OnionFastMap<Box<str>, OnionStaticObject>,
31 &mut GC<OnionObjectCell>,
32 ) -> Result<OnionStaticObject, RuntimeError>,
33{
34 captured: OnionFastMap<Box<str>, OnionStaticObject>,
35 function: Arc<F>,
36}
37
38impl<F> Runnable for NativeFunctionGenerator<F>
39where
40 F: Fn(
41 &OnionFastMap<Box<str>, OnionStaticObject>,
42 &mut GC<OnionObjectCell>,
43 ) -> Result<OnionStaticObject, RuntimeError>
44 + Send
45 + Sync
46 + 'static,
47{
48 fn step(&mut self, gc: &mut GC<OnionObjectCell>) -> StepResult {
50 unwrap_step_result!(
51 (self.function)(&self.captured, gc).map(|result| StepResult::Return(result.into()))
52 )
53 }
54
55 fn format_context(&self) -> String {
57 let full_type_name = std::any::type_name_of_val(&self.function);
59
60 let short_type_name = full_type_name.split("::").last().unwrap_or(full_type_name);
62
63 format!(
65 "-> Executing Native Function:\n - Function: {} (Full Type: {})\n - Argument: {:?}",
66 short_type_name,
67 full_type_name, self.captured,
69 )
70 }
71}
72
73pub fn wrap_native_function<F>(
85 params: LambdaParameter,
86 capture: OnionFastMap<Box<str>, OnionObject>,
87 signature: &str,
88 string_pool: OnionKeyPool<Box<str>>,
89 function: Arc<F>,
90) -> OnionStaticObject
91where
92 F: Fn(
93 &OnionFastMap<Box<str>, OnionStaticObject>,
94 &mut GC<OnionObjectCell>,
95 ) -> Result<OnionStaticObject, RuntimeError>
96 + Send
97 + Sync
98 + 'static,
99{
100 let cloned_pool = string_pool.clone();
101 OnionLambdaDefinition::new_static(
102 params,
103 LambdaBody::NativeFunction((
104 Arc::new(
105 move |_,
106 argument: &OnionFastMap<Box<str>, OnionStaticObject>,
107 capture: &OnionFastMap<Box<str>, OnionObject>,
108 _| {
109 let mut captured = argument.clone();
110 for (key, value) in capture.pairs() {
111 captured.push_with_index(*key, value.stabilize());
112 }
113 Box::new(NativeFunctionGenerator {
114 captured,
115 function: function.clone(),
116 })
117 },
118 ),
119 cloned_pool,
120 )),
121 capture,
122 signature.into(),
123 LambdaType::Atomic,
124 )
125}