Skip to main content

onion_frontend/parser/comptime/
solver.rs

1//! 编译时求解器模块:提供 Onion 语言编译期表达式求值、AST 扩展和状态管理。
2//!
3//! 本模块实现了编译时代码执行机制,支持在编译期运行 Onion 代码、管理编译时状态、
4//! 处理模块导入、以及 AST 的动态扩展。主要用于实现宏、编译时计算、条件编译等功能。
5//!
6//! # 核心功能
7//! - 编译时表达式求值(`solve` 方法)
8//! - AST 节点扩展(`expand` 方法)
9//! - 状态管理和变量定义(def/undef/ifdef)
10//! - 模块导入和循环检测(include)
11//! - 内置函数和 AST 构造绑定
12//!
13//! # 用法示例
14//! ```ignore
15//! let mut solver = ComptimeSolver::new(user_defs, cycle_detector);
16//! let expanded_ast = solver.solve(&original_ast)?;
17//! ```
18
19use std::{
20    collections::HashMap,
21    path::PathBuf,
22    sync::{Arc, RwLock},
23};
24
25use onion_vm::{
26    GC,
27    lambda::{
28        runnable::{Runnable, RuntimeError, StepResult},
29        scheduler::scheduler::Scheduler,
30    },
31    types::{
32        lambda::{
33            definition::{LambdaBody, LambdaType, OnionLambdaDefinition},
34            launcher::OnionLambdaRunnableLauncher,
35            parameter::LambdaParameter,
36            vm_instructions::{
37                instruction_set::VMInstructionPackage,
38                ir::{DebugInfo, Functions, IR},
39                ir_translator::{IRTranslator, IRTranslatorError},
40            },
41        },
42        object::{OnionObject, OnionObjectCell, OnionStaticObject},
43        tuple::OnionTuple,
44    },
45    unwrap_object,
46    utils::fastmap::{OnionFastMap, OnionKeyPool},
47};
48
49use crate::{
50    diagnostics::{Diagnostic, SourceLocation, collector::DiagnosticCollector},
51    ir_generator::ir_generator::{IRGenerator, NameSpace},
52    parser::{
53        Source,
54        analyzer::{analyze_ast, auto_capture_and_rebuild},
55        ast::{ASTNode, ASTNodeType},
56        comptime::{OnionASTObject, ast_bindings, native::wrap_native_function},
57    },
58    utils::cycle_detector::CycleDetector,
59};
60
61/// 编译时状态管理器。
62///
63/// 维护编译时的内置定义和用户定义,支持状态注入到 VM 执行环境。
64#[derive(Debug)]
65pub struct ComptimeState {
66    builtin_definitions: Arc<HashMap<String, OnionStaticObject>>,
67    user_definitions: Arc<RwLock<HashMap<String, OnionStaticObject>>>,
68}
69
70impl ComptimeState {
71    /// 将编译时状态注入到 VM 捕获环境中。
72    ///
73    /// # 参数
74    /// - `capture`:VM 捕获环境映射。
75    ///
76    /// # 返回
77    /// 成功时返回 `Ok(())`,失败时返回 `RuntimeError`。
78    pub fn inject_state(
79        &self,
80        capture: &mut OnionFastMap<Box<str>, OnionObject>,
81    ) -> Result<(), RuntimeError> {
82        // Inject state logic here
83
84        for (key, value) in self
85            .user_definitions
86            .read()
87            .map_err(|e| RuntimeError::BorrowError(e.to_string().into()))?
88            .iter()
89        {
90            capture.push(key.as_str(), value.weak().clone());
91        }
92
93        for (key, value) in self.builtin_definitions.iter() {
94            capture.push(key.as_str(), value.weak().clone());
95        }
96
97        Ok(())
98    }
99}
100
101/// 编译时诊断信息类型。
102///
103/// 封装编译时过程中可能出现的各种错误,包括运行时错误、借用错误、IR 翻译错误等。
104#[derive(Debug, Clone)]
105pub enum ComptimeDiagnostic {
106    /// 运行时错误。
107    RuntimeError(Option<SourceLocation>, RuntimeError),
108    /// 借用检查错误。
109    BorrowError(Option<SourceLocation>, String),
110    /// IR 翻译错误。
111    IRTranslatorError(Option<SourceLocation>, IRTranslatorError),
112    /// 自定义抛出错误。
113    CustomError(Option<SourceLocation>, String),
114    /// 自定义警告。
115    CustomWarning(Option<SourceLocation>, String),
116}
117
118impl Diagnostic for ComptimeDiagnostic {
119    fn severity(&self) -> crate::diagnostics::ReportSeverity {
120        match self {
121            ComptimeDiagnostic::RuntimeError(_, _) => crate::diagnostics::ReportSeverity::Error,
122            ComptimeDiagnostic::BorrowError(_, _) => crate::diagnostics::ReportSeverity::Error,
123            ComptimeDiagnostic::IRTranslatorError(_, _) => {
124                crate::diagnostics::ReportSeverity::Error
125            }
126            ComptimeDiagnostic::CustomError(_, _) => crate::diagnostics::ReportSeverity::Error,
127            ComptimeDiagnostic::CustomWarning(_, _) => crate::diagnostics::ReportSeverity::Warning,
128        }
129    }
130
131    fn title(&self) -> String {
132        match self {
133            ComptimeDiagnostic::RuntimeError(_, _) => "Runtime Error".to_string(),
134            ComptimeDiagnostic::BorrowError(_, _) => "Borrow Error".to_string(),
135            ComptimeDiagnostic::IRTranslatorError(_, _) => "IR Translator Error".to_string(),
136            ComptimeDiagnostic::CustomError(_, _) => "Custom Error".to_string(),
137            ComptimeDiagnostic::CustomWarning(_, _) => "Custom Warning".to_string(),
138        }
139    }
140
141    fn message(&self) -> String {
142        match self {
143            ComptimeDiagnostic::RuntimeError(_, err) => format!("Runtime Error: {}", err),
144            ComptimeDiagnostic::BorrowError(_, msg) => format!("Borrow Error: {}", msg),
145            ComptimeDiagnostic::IRTranslatorError(_, err) => {
146                format!("IR Translator Error: {}", err)
147            }
148            ComptimeDiagnostic::CustomError(_, msg) => msg.clone(),
149            ComptimeDiagnostic::CustomWarning(_, msg) => msg.clone(),
150        }
151    }
152
153    fn location(&self) -> Option<crate::diagnostics::SourceLocation> {
154        match self {
155            ComptimeDiagnostic::RuntimeError(loc, _) => loc.clone(),
156            ComptimeDiagnostic::BorrowError(loc, _) => loc.clone(),
157            ComptimeDiagnostic::IRTranslatorError(loc, _) => loc.clone(),
158            ComptimeDiagnostic::CustomError(loc, _) => loc.clone(),
159            ComptimeDiagnostic::CustomWarning(loc, _) => loc.clone(),
160        }
161    }
162
163    fn help(&self) -> Option<String> {
164        None
165    }
166
167    fn copy(&self) -> Box<dyn Diagnostic> {
168        Box::new(self.clone())
169    }
170}
171
172/// 编译时求解器主结构。
173///
174/// 负责编译时 AST 的求解、扩展、以及编译时代码的执行。
175/// 集成了状态管理、诊断收集、VM 执行等功能。
176#[derive(Debug)]
177pub struct ComptimeSolver {
178    state: ComptimeState,
179    diagnostics: Arc<RwLock<DiagnosticCollector>>,
180}
181
182impl ComptimeSolver {
183    /// 创建新的编译时求解器。
184    ///
185    /// # 参数
186    /// - `user_definitions`:用户定义的变量映射。
187    /// - `import_cycle_detector`:导入循环检测器。
188    ///
189    /// # 返回
190    /// 新的 `ComptimeSolver` 实例。
191    pub fn new(
192        user_definitions: Arc<RwLock<HashMap<String, OnionStaticObject>>>,
193        import_cycle_detector: CycleDetector<PathBuf>,
194    ) -> Self {
195        let user_definitions_ref = user_definitions.clone();
196
197        let diagnostics = Arc::new(RwLock::new(DiagnosticCollector::new()));
198        let diagnostics_ref = diagnostics.clone();
199
200        let mut builtin_definitions = HashMap::new();
201        builtin_definitions.insert(
202            "def".into(),
203            wrap_native_function(
204                LambdaParameter::top("def"),
205                OnionFastMap::default(),
206                "comptime::def",
207                OnionKeyPool::create(vec!["def".into()]),
208                Arc::new(
209                    move |argument: &OnionFastMap<Box<str>, OnionStaticObject>,
210                          _gc: &mut GC<OnionObjectCell>|
211                          -> Result<OnionStaticObject, RuntimeError> {
212                        match argument.get("def") {
213                            Some(v) => v.weak().with_data(|v| match v {
214                                OnionObject::Pair(pair) => {
215                                    let k = pair.get_key().to_string(&vec![])?;
216                                    let v = pair.get_value().stabilize();
217                                    let mut state = user_definitions_ref.write().map_err(|e| {
218                                        RuntimeError::BorrowError(e.to_string().into())
219                                    })?;
220                                    state.insert(k, v);
221                                    Ok(OnionObject::Undefined(None).stabilize())
222                                }
223                                _ => Err(RuntimeError::InvalidType("Expect Pair for 'def'".into())),
224                            }),
225                            None => {
226                                Err(RuntimeError::DetailedError("No 'def' in arguments".into()))
227                            }
228                        }
229                    },
230                ),
231            ),
232        );
233
234        let user_definitions_ref = user_definitions.clone();
235        builtin_definitions.insert(
236            "undef".into(),
237            wrap_native_function(
238                LambdaParameter::top("name"),
239                OnionFastMap::default(),
240                "comptime::undef",
241                OnionKeyPool::create(vec!["name".into()]),
242                Arc::new(
243                    move |argument: &OnionFastMap<Box<str>, OnionStaticObject>,
244                          _gc: &mut GC<OnionObjectCell>|
245                          -> Result<OnionStaticObject, RuntimeError> {
246                        match argument.get("name") {
247                            Some(v) => v.weak().with_data(|v| match v {
248                                OnionObject::String(name) => {
249                                    let mut state = user_definitions_ref.write().map_err(|e| {
250                                        RuntimeError::BorrowError(e.to_string().into())
251                                    })?;
252                                    state.remove(name.as_ref());
253                                    Ok(OnionObject::Undefined(None).stabilize())
254                                }
255                                _ => Err(RuntimeError::InvalidType(
256                                    "Expect String for 'name'".into(),
257                                )),
258                            }),
259                            None => {
260                                Err(RuntimeError::DetailedError("No 'name' in arguments".into()))
261                            }
262                        }
263                    },
264                ),
265            ),
266        );
267
268        let user_definitions_ref = user_definitions.clone();
269        builtin_definitions.insert(
270            "ifdef".into(),
271            wrap_native_function(
272                LambdaParameter::top("name"),
273                OnionFastMap::default(),
274                "comptime::ifdef",
275                OnionKeyPool::create(vec!["name".into()]),
276                Arc::new(
277                    move |argument: &OnionFastMap<Box<str>, OnionStaticObject>,
278                          _gc: &mut GC<OnionObjectCell>|
279                          -> Result<OnionStaticObject, RuntimeError> {
280                        match argument.get("name") {
281                            Some(v) => v.weak().with_data(|v| match v {
282                                OnionObject::String(name) => {
283                                    let state = user_definitions_ref.read().map_err(|e| {
284                                        RuntimeError::BorrowError(e.to_string().into())
285                                    })?;
286                                    Ok(OnionObject::Boolean(state.contains_key(name.as_ref()))
287                                        .stabilize())
288                                }
289                                _ => Err(RuntimeError::InvalidType(
290                                    "Expect String for 'name'".into(),
291                                )),
292                            }),
293                            None => {
294                                Err(RuntimeError::DetailedError("No 'name' in arguments".into()))
295                            }
296                        }
297                    },
298                ),
299            ),
300        );
301
302        builtin_definitions.insert(
303            "required".into(),
304            wrap_native_function(
305                LambdaParameter::top("name"),
306                OnionFastMap::default(),
307                "comptime::required",
308                OnionKeyPool::create(vec!["name".into()]),
309                Arc::new(
310                    move |argument: &OnionFastMap<Box<str>, OnionStaticObject>,
311                          _gc: &mut GC<OnionObjectCell>|
312                          -> Result<OnionStaticObject, RuntimeError> {
313                        match argument.get("name") {
314                            Some(v) => v.weak().with_data(|v| match v {
315                                OnionObject::String(name) => Ok(OnionObject::Custom(Arc::new(
316                                    OnionASTObject::new(ASTNode {
317                                        node_type: ASTNodeType::Required(name.to_string()),
318                                        source_location: None,
319                                        children: vec![],
320                                    }),
321                                ))
322                                .stabilize()),
323                                _ => Err(RuntimeError::InvalidType(
324                                    "Expect String for 'name'".into(),
325                                )),
326                            }),
327                            None => {
328                                Err(RuntimeError::DetailedError("No 'name' in arguments".into()))
329                            }
330                        }
331                    },
332                ),
333            ),
334        );
335
336        let cloned_ref = user_definitions.clone();
337        builtin_definitions.insert(
338            "include".into(),
339            wrap_native_function(
340                LambdaParameter::top("path"),
341                OnionFastMap::default(),
342                "comptime::include",
343                OnionKeyPool::create(vec!["path".into()]),
344                Arc::new(
345                    move |argument: &OnionFastMap<Box<str>, OnionStaticObject>,
346                          _gc: &mut GC<OnionObjectCell>|
347                          -> Result<OnionStaticObject, RuntimeError> {
348                        match argument.get("path") {
349                            Some(v) => v.weak().with_data(|v| match v {
350                                OnionObject::String(path) => {
351                                    let abs_path =
352                                        match import_cycle_detector.last() {
353                                            Some(file) => {
354                                                let dir = file.parent().unwrap_or(file.as_path());
355                                                let mut target_path = PathBuf::from(path.as_ref());
356                                                if !target_path.is_absolute() {
357                                                    target_path = dir.join(&target_path);
358                                                }
359                                                target_path.canonicalize().map_err(|e| {
360                                                    RuntimeError::DetailedError(
361                                                        format!("Failed to canonicalize path: {e}")
362                                                            .into(),
363                                                    )
364                                                })?
365                                            }
366                                            None => {
367                                                let mut target_path = PathBuf::from(path.as_ref());
368                                                if !target_path.is_absolute() {
369                                                    target_path =
370                                                        std::env::current_dir()
371                                                            .map_err(|e| {
372                                                                RuntimeError::DetailedError(
373                        format!("Failed to get current dir: {e}").into(),
374                    )
375                                                            })?
376                                                            .join(&target_path);
377                                                }
378                                                target_path.canonicalize().map_err(|e| {
379                                                    RuntimeError::DetailedError(
380                                                        format!("Failed to canonicalize path: {e}")
381                                                            .into(),
382                                                    )
383                                                })?
384                                            }
385                                        };
386                                    // 读取文件内容
387                                    let source = Source::from_file(&abs_path).map_err(|e| {
388                                        RuntimeError::DetailedError(
389                                            format!(
390                                                "Failed to read file {}: {e}",
391                                                abs_path.display()
392                                            )
393                                            .into(),
394                                        )
395                                    })?;
396
397                                    // 词法分析、AST 构建
398                                    use crate::parser::ast::{ast_token_stream, build_ast};
399                                    use crate::parser::lexer::tokenizer;
400                                    let tokens = tokenizer::tokenize(&source);
401                                    let tokens = tokenizer::reject_comment(&tokens);
402                                    let gathered = ast_token_stream::from_stream(&tokens);
403
404                                    let mut collector = diagnostics_ref.write().map_err(|e| {
405                                        RuntimeError::BorrowError(e.to_string().into())
406                                    })?;
407
408                                    let ast =
409                                        build_ast(&mut collector, gathered).map_err(|_| {
410                                            RuntimeError::DetailedError(
411                                                "Solver failed to build AST".into(),
412                                            )
413                                        })?;
414
415                                    if collector.has_errors() {
416                                        return Err(RuntimeError::DetailedError(
417                                            "Solver produced errors while building AST".into(),
418                                        ));
419                                    }
420
421                                    let mut sub_solver = ComptimeSolver::new(
422                                        cloned_ref.clone(),
423                                        import_cycle_detector.enter(abs_path).map_err(|path| {
424                                            RuntimeError::DetailedError(
425                                                format!("Cyclic reference detected: {:?}", path)
426                                                    .into(),
427                                            )
428                                        })?,
429                                    );
430
431                                    let result = sub_solver.solve(&ast);
432                                    for diagnostic in sub_solver
433                                        .diagnostics
434                                        .read()
435                                        .map_err(|e| {
436                                            RuntimeError::BorrowError(e.to_string().into())
437                                        })?
438                                        .diagnostics()
439                                    {
440                                        collector.report(diagnostic.copy());
441                                    }
442
443                                    if result.is_err() {
444                                        return Err(RuntimeError::DetailedError(
445                                            "Sub-solver failed".into(),
446                                        ));
447                                    }
448
449                                    if sub_solver
450                                        .diagnostics
451                                        .read()
452                                        .map_err(|e| {
453                                            RuntimeError::BorrowError(e.to_string().into())
454                                        })?
455                                        .has_errors()
456                                    {
457                                        return Err(RuntimeError::DetailedError(
458                                            "Sub-solver produced errors while executing expression"
459                                                .into(),
460                                        ));
461                                    }
462
463                                    Ok(OnionObject::Custom(Arc::new(OnionASTObject::new(
464                                        result.unwrap(),
465                                    )))
466                                    .consume_and_stabilize())
467                                }
468                                _ => Err(RuntimeError::InvalidType(
469                                    "Expect String for 'path'".into(),
470                                )),
471                            }),
472                            None => {
473                                Err(RuntimeError::DetailedError("No 'path' in arguments".into()))
474                            }
475                        }
476                    },
477                ),
478            ),
479        );
480
481        let diagnostics_ref_for_error = diagnostics.clone();
482        builtin_definitions.insert(
483            "error".into(),
484            wrap_native_function(
485                LambdaParameter::top("message"),
486                OnionFastMap::default(),
487                "comptime::error",
488                OnionKeyPool::create(vec!["message".into()]),
489                Arc::new(
490                    move |argument: &OnionFastMap<Box<str>, OnionStaticObject>,
491                          _gc: &mut GC<OnionObjectCell>|
492                          -> Result<OnionStaticObject, RuntimeError> {
493                        match argument.get("message") {
494                            Some(v) => v.weak().with_data(|v| match v {
495                                OnionObject::String(message) => {
496                                    let mut collector =
497                                        diagnostics_ref_for_error.write().map_err(|e| {
498                                            RuntimeError::BorrowError(e.to_string().into())
499                                        })?;
500                                    collector.report(ComptimeDiagnostic::CustomError(
501                                        None, // TODO: 可以从运行时上下文获取位置信息
502                                        message.to_string(),
503                                    ));
504                                    Err(RuntimeError::DetailedError(
505                                        format!("Comptime error: {}", message).into(),
506                                    ))
507                                }
508                                _ => Err(RuntimeError::InvalidType(
509                                    "Expect String for 'message'".into(),
510                                )),
511                            }),
512                            None => Err(RuntimeError::DetailedError(
513                                "No 'message' in arguments".into(),
514                            )),
515                        }
516                    },
517                ),
518            ),
519        );
520
521        let diagnostics_ref_for_warning = diagnostics.clone();
522        builtin_definitions.insert(
523            "warning".into(),
524            wrap_native_function(
525                LambdaParameter::top("message"),
526                OnionFastMap::default(),
527                "comptime::warning",
528                OnionKeyPool::create(vec!["message".into()]),
529                Arc::new(
530                    move |argument: &OnionFastMap<Box<str>, OnionStaticObject>,
531                          _gc: &mut GC<OnionObjectCell>|
532                          -> Result<OnionStaticObject, RuntimeError> {
533                        match argument.get("message") {
534                            Some(v) => v.weak().with_data(|v| match v {
535                                OnionObject::String(message) => {
536                                    let mut collector =
537                                        diagnostics_ref_for_warning.write().map_err(|e| {
538                                            RuntimeError::BorrowError(e.to_string().into())
539                                        })?;
540                                    collector.report(ComptimeDiagnostic::CustomWarning(
541                                        None, // TODO: 可以从运行时上下文获取位置信息
542                                        message.to_string(),
543                                    ));
544                                    Ok(OnionObject::Undefined(None).stabilize())
545                                }
546                                _ => Err(RuntimeError::InvalidType(
547                                    "Expect String for 'message'".into(),
548                                )),
549                            }),
550                            None => Err(RuntimeError::DetailedError(
551                                "No 'message' in arguments".into(),
552                            )),
553                        }
554                    },
555                ),
556            ),
557        );
558
559        builtin_definitions.insert("ast".to_string(), ast_bindings::build_module());
560
561        ComptimeSolver {
562            state: ComptimeState {
563                builtin_definitions: Arc::new(builtin_definitions),
564                user_definitions,
565            },
566            diagnostics: diagnostics,
567        }
568    }
569
570    /// 获取诊断收集器的引用。
571    pub fn diagnostics(&self) -> &Arc<RwLock<DiagnosticCollector>> {
572        &self.diagnostics
573    }
574
575    /// 递归求解 AST 节点,处理编译时表达式。
576    ///
577    /// # 参数
578    /// - `ast`:要求解的 AST 节点。
579    ///
580    /// # 返回
581    /// 求解后的 AST 节点,或错误。
582    #[stacksafe::stacksafe]
583    pub fn solve(&mut self, ast: &ASTNode) -> Result<ASTNode, ()> {
584        let mut iteration_result = ast.clone();
585        loop {
586            let mut children = Vec::new();
587            for child in &iteration_result.children {
588                children.push(self.solve(child)?);
589            }
590            let result = ASTNode {
591                node_type: iteration_result.node_type.clone(),
592                source_location: iteration_result.source_location.clone(),
593                children,
594            };
595            match self.expand(&result)? {
596                Some(expanded_ast) => {
597                    if expanded_ast == iteration_result {
598                        return Ok(expanded_ast);
599                    } else {
600                        iteration_result = expanded_ast;
601                    }
602                }
603                None => {
604                    return Ok(result);
605                }
606            }
607        }
608    }
609
610    /// 扩展给定的 AST 节点(如果是编译时节点)。
611    ///
612    /// # 参数
613    /// - `ast`:要扩展的 AST 节点。
614    ///
615    /// # 返回
616    /// - `Ok(Some(expanded))`:节点已扩展
617    /// - `Ok(None)`:节点无需扩展
618    /// - `Err(())`:扩展失败
619    pub fn expand(&mut self, ast: &ASTNode) -> Result<Option<ASTNode>, ()> {
620        let ASTNodeType::Comptime = ast.node_type else {
621            return Ok(None);
622        };
623
624        let mut collector = self
625            .diagnostics
626            .write()
627            .expect("Failed to lock diagnostics collector");
628        let mut context = vec![];
629        context.extend(
630            self.state
631                .builtin_definitions
632                .iter()
633                .map(|(name, _)| ASTNode {
634                    node_type: ASTNodeType::Required(name.clone()),
635                    source_location: None,
636                    children: vec![],
637                })
638                .collect::<Vec<_>>(),
639        );
640        context.extend(
641            self.state
642                .user_definitions
643                .read()
644                .map_err(|e| {
645                    collector.report(ComptimeDiagnostic::BorrowError(
646                        ast.source_location.clone(),
647                        e.to_string(),
648                    ));
649                    ()
650                })?
651                .iter()
652                .map(|(name, _)| ASTNode {
653                    node_type: ASTNodeType::Required(name.clone()),
654                    source_location: None,
655                    children: vec![],
656                })
657                .collect::<Vec<_>>(),
658        );
659        context.extend(ast.children.iter().cloned());
660
661        let ast_with_context = ASTNode {
662            node_type: ASTNodeType::Expressions,
663            source_location: ast.source_location.clone(),
664            children: context,
665        };
666
667        let (_required_vars, rebuilt_ast) = auto_capture_and_rebuild(&ast_with_context);
668
669        let _ = analyze_ast(&rebuilt_ast, &mut collector, &None)?;
670
671        let namespace = NameSpace::new("Main".to_string(), None);
672        let mut functions = Functions::new();
673        let mut ir_generator = IRGenerator::new(&mut functions, namespace);
674
675        let mut ir = ir_generator.generate(&mut collector, &rebuilt_ast)?;
676
677        ir.push((DebugInfo::new((0, 0)), IR::Return));
678        functions.append("__main__".to_string(), ir);
679
680        let package = functions.build_instructions(None);
681        let mut translator = IRTranslator::new(&package);
682
683        let byte_code = match translator.translate() {
684            Ok(_) => translator.get_result(),
685            Err(e) => {
686                collector.report(ComptimeDiagnostic::IRTranslatorError(
687                    ast.source_location.clone(),
688                    e,
689                ));
690                return Err(());
691            }
692        };
693
694        drop(collector); // 释放锁,允许其他线程访问 diagnostics
695        let result = match self.execute(&byte_code) {
696            Ok(result) => result,
697            Err(err) => {
698                let mut collector = self
699                    .diagnostics
700                    .write()
701                    .expect("Failed to lock diagnostics collector");
702                collector.report(ComptimeDiagnostic::RuntimeError(
703                    ast.source_location.clone(),
704                    err,
705                ));
706                return Err(());
707            }
708        };
709        match OnionASTObject::from_onion(result.weak()) {
710            Ok(ast_object) => Ok(Some(ast_object)),
711            Err(err) => {
712                let mut collector = self
713                    .diagnostics
714                    .write()
715                    .expect("Failed to lock diagnostics collector");
716                collector.report(ComptimeDiagnostic::RuntimeError(
717                    ast.source_location.clone(),
718                    err,
719                ));
720                Err(())
721            }
722        }
723    }
724
725    /// 执行编译时代码并返回结果。
726    ///
727    /// # 参数
728    /// - `vm_instructions_package`:要执行的 VM 指令包。
729    ///
730    /// # 返回
731    /// 执行结果的静态对象,或运行时错误。
732    fn execute(
733        &mut self,
734        vm_instructions_package: &VMInstructionPackage,
735    ) -> Result<OnionStaticObject, RuntimeError> {
736        let mut gc = GC::new_with_memory_threshold(1024 * 1024); // 1 MB threshold
737
738        if let Err(e) = VMInstructionPackage::validate(vm_instructions_package) {
739            return Err(RuntimeError::DetailedError(
740                format!("Invalid VM instruction package: {e}").into(),
741            ));
742        }
743        let mut capture = OnionFastMap::new(vm_instructions_package.create_key_pool());
744
745        self.state.inject_state(&mut capture)?;
746
747        // Create Lambda definition
748        let lambda = OnionLambdaDefinition::new_static(
749            LambdaParameter::Multiple(Box::new([])),
750            LambdaBody::Instruction(Arc::new(vm_instructions_package.clone())),
751            capture,
752            "__main__".into(),
753            LambdaType::Atomic,
754        );
755
756        let args = OnionTuple::new_static(vec![]);
757
758        let mut scheduler: Box<dyn Runnable> = Box::new(Scheduler::new(vec![Box::new(
759            OnionLambdaRunnableLauncher::new(lambda.weak(), args, Ok)?,
760        )]));
761        // Execute code
762        loop {
763            match scheduler.step(&mut gc) {
764                StepResult::Continue => {
765                    // Continue to next step
766                }
767                StepResult::SpawnRunnable(_) => {
768                    return Err(RuntimeError::DetailedError(
769                        "Cannot spawn async task in sync context".into(),
770                    ));
771                }
772                StepResult::Error(ref error) => {
773                    if let RuntimeError::Pending = error {
774                        // Pending 状态,正常继续
775                        continue;
776                    }
777                    return Err(error.clone());
778                }
779                StepResult::NewRunnable(_) => {
780                    unreachable!()
781                }
782                StepResult::ReplaceRunnable(_) => {
783                    unreachable!()
784                }
785                StepResult::Return(ref result) => {
786                    let result_borrowed = result.weak();
787                    let result = unwrap_object!(result_borrowed, OnionObject::Pair)?;
788                    let success = *unwrap_object!(result.get_key(), OnionObject::Boolean)?;
789                    if !success {
790                        let value_text = result.get_value().with_data(|data| match data {
791                            OnionObject::Undefined(Some(str)) => Ok(str.to_string()),
792                            _ => Ok(data.to_string(&vec![]).unwrap_or_else(|e| {
793                                format!("[Failed to convert value to string: {e}]")
794                            })),
795                        })?;
796
797                        let mut error_text =
798                            format!("{} {}", "Execution returned a failure value:", value_text);
799
800                        // 打印上下文以帮助调试为什么会返回失败
801                        error_text.push_str(&format!("\n{}", "Context at Time of Failure Return:"));
802                        error_text.push_str(&scheduler.format_context());
803
804                        return Err(RuntimeError::DetailedError(error_text.into()));
805                    }
806                    return Ok(result.get_value().stabilize());
807                }
808            }
809        }
810    }
811}