Skip to main content

onion_vm/types/lambda/
definition.rs

1//! Onion 虚拟机 Lambda 定义与实现。
2//!
3//! - `OnionLambdaDefinition`:完整的 Lambda 定义,支持参数、捕获、原生与字节码体。
4//! - `LambdaBody`:Lambda 体类型,支持字节码与原生函数。
5//! - `LambdaType`:Lambda 类型(普通、异步、同步)。
6//! - 提供 Lambda 的构造、运行、属性访问、GC 跟踪等。
7
8use std::{
9    collections::VecDeque,
10    fmt::{Debug, Display},
11    sync::Arc,
12};
13
14use arc_gc::{
15    arc::{GCArc, GCArcWeak},
16    gc::GC,
17    traceable::GCTraceable,
18};
19
20use crate::{
21    lambda::runnable::{Runnable, RuntimeError},
22    types::{
23        lambda::{
24            parameter::LambdaParameter, vm_instructions::instruction_set::VMInstructionPackage,
25        },
26        object::{OnionObject, OnionObjectCell, OnionStaticObject},
27    },
28    utils::fastmap::{OnionFastMap, OnionKeyPool},
29};
30
31use super::runnable::OnionLambdaRunnable;
32
33/// Lambda 体类型。
34///
35/// 支持字节码(Instruction)和原生函数(NativeFunction)。
36pub enum LambdaBody {
37    /// 字节码实现
38    Instruction(Arc<VMInstructionPackage>),
39    /// 原生函数实现(带字符串池),用于启动一个 Runnable
40    NativeFunction(
41        (
42            Arc<
43                dyn Fn(
44                        &OnionObject,                               // self_object
45                        &OnionFastMap<Box<str>, OnionStaticObject>, // argument
46                        &OnionFastMap<Box<str>, OnionObject>,       // captured_vars
47                        &mut GC<OnionObjectCell>,                   // gc
48                    ) -> Box<dyn Runnable>
49                    + Send
50                    + Sync,
51            >,
52            OnionKeyPool<Box<str>>,
53        ),
54    ),
55}
56
57impl Clone for LambdaBody {
58    fn clone(&self) -> Self {
59        match self {
60            LambdaBody::Instruction(instruction) => LambdaBody::Instruction(instruction.clone()),
61            LambdaBody::NativeFunction(native_function) => {
62                LambdaBody::NativeFunction(native_function.clone())
63            }
64        }
65    }
66}
67
68impl LambdaBody {
69    fn create_string_pool(&self) -> OnionKeyPool<Box<str>> {
70        match self {
71            LambdaBody::Instruction(instruction) => instruction.create_key_pool(),
72            LambdaBody::NativeFunction((_, key_pool)) => key_pool.clone(),
73        }
74    }
75}
76
77impl Debug for LambdaBody {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        match self {
80            LambdaBody::Instruction(_) => write!(f, "Instruction(...)"),
81            LambdaBody::NativeFunction(_) => write!(f, "NativeFunction"),
82        }
83    }
84}
85
86impl Display for LambdaBody {
87    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88        match self {
89            LambdaBody::Instruction(_) => write!(f, "Instruction(...)"),
90            LambdaBody::NativeFunction(_) => write!(f, "NativeFunction"),
91        }
92    }
93}
94
95/// Lambda 类型。
96pub enum LambdaType {
97    /// 普通 Lambda
98    Atomic,
99    /// 异步调度器
100    AsyncLauncher,
101    /// 同步调度器
102    SyncLauncher,
103}
104
105/// Onion 虚拟机 Lambda 定义。
106///
107/// 封装参数、捕获、Lambda 体、签名、类型等。
108pub struct OnionLambdaDefinition {
109    /// 参数定义
110    parameter: LambdaParameter,
111    /// 展平后的参数名
112    flatten_param_keys: Box<[Box<str>]>,
113    /// 展平后的参数约束
114    flatten_param_constraints: Box<[OnionObject]>,
115    /// Lambda 体
116    body: LambdaBody,
117    /// 捕获变量
118    capture: OnionFastMap<Box<str>, OnionObject>,
119    /// 签名字符串
120    signature: Box<str>,
121    /// Lambda 类型
122    lambda_type: LambdaType,
123}
124
125impl OnionLambdaDefinition {
126    pub fn new_static(
127        parameter: LambdaParameter,
128        body: LambdaBody,
129        capture: OnionFastMap<Box<str>, OnionObject>,
130        signature: Box<str>,
131        lambda_type: LambdaType,
132    ) -> OnionStaticObject {
133        let flatten_param_keys = parameter.flatten_keys();
134        let flatten_param_constraints = parameter.flatten_constraints();
135        OnionObject::Lambda((
136            OnionLambdaDefinition {
137                parameter,
138                flatten_param_keys,
139                flatten_param_constraints,
140                body,
141                capture,
142                signature,
143                lambda_type,
144            }
145            .into(),
146            OnionObject::Undefined(None).into(),
147        ))
148        .consume_and_stabilize()
149    }
150
151    pub fn new_static_with_self(
152        parameter: LambdaParameter,
153        body: LambdaBody,
154        capture: OnionFastMap<Box<str>, OnionObject>,
155        self_object: &OnionObject,
156        signature: Box<str>,
157        lambda_type: LambdaType,
158    ) -> OnionStaticObject {
159        let flatten_param_keys = parameter.flatten_keys();
160        let flatten_param_constraints = parameter.flatten_constraints();
161        OnionObject::Lambda((
162            OnionLambdaDefinition {
163                parameter,
164                flatten_param_keys,
165                flatten_param_constraints,
166                body,
167                capture,
168                signature,
169                lambda_type,
170            }
171            .into(),
172            self_object.clone().into(),
173        ))
174        .consume_and_stabilize()
175    }
176
177    // 从定义创建可用字符串池,Lambda自身只能使用这个字符串池中的字符串
178    pub fn create_key_pool(&self) -> OnionKeyPool<Box<str>> {
179        self.body.create_string_pool()
180    }
181
182    pub fn with_lambda_type(&self, lambda_type: LambdaType) -> Self {
183        OnionLambdaDefinition {
184            parameter: self.parameter.clone(),
185            flatten_param_keys: self.flatten_param_keys.clone(),
186            flatten_param_constraints: self.flatten_param_constraints.clone(),
187            body: self.body.clone(),
188            capture: self.capture.clone(),
189            signature: self.signature.clone(),
190            lambda_type,
191        }
192    }
193
194    pub fn lambda_type(&self) -> &LambdaType {
195        &self.lambda_type
196    }
197
198    // 显然我们在Launcher里已经严格保证argument所使用的字符串池是Lambda定义的字符串池
199    pub fn create_runnable(
200        &self,
201        argument: &OnionFastMap<Box<str>, OnionStaticObject>,
202        this_lambda: &OnionStaticObject,
203        self_object: &OnionObject,
204        gc: &mut GC<OnionObjectCell>,
205    ) -> Result<Box<dyn Runnable>, RuntimeError> {
206        match &self.body {
207            LambdaBody::Instruction(instruction) => {
208                let runnable = OnionLambdaRunnable::new(
209                    argument,
210                    &self.capture,
211                    self_object,
212                    this_lambda,
213                    instruction.clone(),
214                    match instruction.get_table().get(self.signature.as_ref()) {
215                        Some(ip) => *ip as isize,
216                        None => {
217                            return Err(RuntimeError::InvalidOperation(
218                                format!(
219                                    "Signature '{}' not found in instruction package",
220                                    self.signature
221                                )
222                                .into(),
223                            ));
224                        }
225                    },
226                )?;
227                Ok(Box::new(runnable))
228            }
229            LambdaBody::NativeFunction((native_function, _)) => {
230                Ok(native_function(self_object, argument, &self.capture, gc))
231            }
232        }
233    }
234
235    pub fn get_signature(&self) -> &str {
236        &self.signature
237    }
238
239    pub fn get_parameter(&self) -> &LambdaParameter {
240        &self.parameter
241    }
242
243    pub fn get_flatten_param_keys(&self) -> &[Box<str>] {
244        &self.flatten_param_keys
245    }
246
247    pub fn get_flatten_param_constraints(&self) -> &[OnionObject] {
248        &self.flatten_param_constraints
249    }
250
251    pub fn get_capture(&self) -> &OnionFastMap<Box<str>, OnionObject> {
252        &self.capture
253    }
254
255    pub fn get_body(&self) -> &LambdaBody {
256        &self.body
257    }
258
259    pub fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>) {
260        self.parameter.upgrade(collected);
261        for (_, obj) in self.capture.pairs() {
262            obj.upgrade(collected);
263        }
264    }
265
266    pub fn with_attribute<F, R>(&self, key: &OnionObject, f: &F) -> Result<R, RuntimeError>
267    where
268        F: Fn(&OnionObject) -> Result<R, RuntimeError>,
269    {
270        match key {
271            OnionObject::String(s) if s.as_ref() == "$parameter" => {
272                let parameter = self.parameter.to_onion();
273                f(parameter.weak())
274            }
275            OnionObject::String(s) if s.as_ref() == "$signature" => {
276                f(&OnionObject::String(Arc::from(self.signature.clone())))
277            }
278            OnionObject::String(s) => {
279                if let Some(value) = self.capture.get(s.as_ref()) {
280                    f(value)
281                } else {
282                    Err(RuntimeError::InvalidOperation(
283                        format!("Attribute '{:?}' not found in lambda definition", key).into(),
284                    ))
285                }
286            }
287            _ => Err(RuntimeError::InvalidOperation(
288                format!("Attribute '{:?}' not found in lambda definition", key).into(),
289            )),
290        }
291    }
292}
293
294impl GCTraceable<OnionObjectCell> for OnionLambdaDefinition {
295    fn collect(&self, queue: &mut VecDeque<GCArcWeak<OnionObjectCell>>) {
296        self.parameter.collect(queue);
297        for (_, obj) in self.capture.pairs() {
298            obj.collect(queue);
299        }
300    }
301}
302
303impl Debug for OnionLambdaDefinition {
304    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
305        write!(
306            f,
307            "OnionLambdaDefinition {{ parameter: {:?}, body: {:?}, capture: {:?} }}",
308            self.parameter, self.body, self.capture
309        )
310    }
311}