Skip to main content

onion_frontend/parser/comptime/
native.rs

1//! 原生函数包装模块:将 Rust 函数包装为 Onion VM 可调用的 Lambda。
2//!
3//! 本模块提供将 Rust 原生函数转换为 Onion VM Lambda 对象的机制,
4//! 支持参数绑定、捕获变量、以及在 VM 中的执行。主要用于编译时或运行时
5//! 向 VM 注入原生功能。
6
7use 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
23/// 原生函数生成器:将 Rust 函数包装为 VM 可执行的 Runnable。
24///
25/// 封装原生 Rust 函数,使其能在 Onion VM 中作为 Lambda 执行。
26/// 保存捕获的参数和函数引用,在 VM 调用时执行原生逻辑。
27pub 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    /// 执行原生函数,返回计算结果。
49    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    /// 格式化执行上下文信息,用于调试和错误报告。
56    fn format_context(&self) -> String {
57        // Use the type name of the function/closure to identify the native code.
58        let full_type_name = std::any::type_name_of_val(&self.function);
59
60        // Provide a shorter, more readable version of the type name.
61        let short_type_name = full_type_name.split("::").last().unwrap_or(full_type_name);
62
63        // Assemble all the information into a clear, structured block.
64        format!(
65            "-> Executing Native Function:\n   - Function: {} (Full Type: {})\n   - Argument: {:?}",
66            short_type_name,
67            full_type_name, // Include full name for disambiguation
68            self.captured,
69        )
70    }
71}
72
73/// 将 Rust 原生函数包装为 Onion VM 可调用的 Lambda 定义。
74///
75/// # 参数
76/// - `params`:Lambda 参数定义
77/// - `capture`:捕获的变量映射
78/// - `signature`:函数签名字符串
79/// - `string_pool`:字符串池
80/// - `function`:要包装的原生函数
81///
82/// # 返回
83/// 包装后的 Lambda 定义静态对象,可在 VM 中调用。
84pub 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}