onion_frontend/
compile.rs

1//! Onion 语言编译主流程模块。
2//!
3//! 本模块负责将 Onion 源代码从 Token 流、AST、IR 直至最终字节码的完整编译流程。
4//! 包含诊断收集、循环依赖检测、编译时求值、语义分析、IR 生成与字节码翻译等核心步骤。
5//!
6//! # 编译流程概述
7//! 1. 词法分析:源码 → Token 流
8//! 2. 语法分析:Token 流 → AST
9//! 3. 编译时求值:处理 @ 表达式、宏、依赖等
10//! 4. 自动捕获与语义分析:变量作用域、类型检查
11//! 5. IR 生成:AST → 中间表示(IR)
12//! 6. 字节码生成:IR → 虚拟机指令
13//!
14//! # 主要函数
15//! - `build_code`:主编译入口,生成 IRPackage
16//! - `compile_to_bytecode`:IRPackage → 虚拟机字节码
17//!
18//! # 诊断与错误处理
19//! - 所有阶段均支持详细的错误收集与报告
20//! - 支持 IO 错误、借用错误、语法/语义/编译时错误等
21
22use std::collections::HashMap;
23use std::fs;
24use std::path::PathBuf;
25use std::sync::Arc;
26use std::sync::RwLock;
27
28use crate::diagnostics::Diagnostic;
29use crate::diagnostics::collector::DiagnosticCollector;
30use crate::ir_generator::ir_generator;
31use crate::parser::Source;
32use crate::parser::analyzer::analyze_ast;
33use crate::parser::analyzer::auto_capture_and_rebuild;
34use crate::parser::ast::ast_token_stream;
35use crate::parser::ast::build_ast;
36use crate::parser::comptime::solver::ComptimeSolver;
37use crate::parser::lexer::tokenizer;
38use crate::utils::cycle_detector::CycleDetector;
39use onion_vm::types::lambda::vm_instructions::instruction_set::VMInstructionPackage;
40use onion_vm::types::lambda::vm_instructions::ir::DebugInfo;
41use onion_vm::types::lambda::vm_instructions::ir::Functions;
42use onion_vm::types::lambda::vm_instructions::ir::IR;
43use onion_vm::types::lambda::vm_instructions::ir::IRPackage;
44use onion_vm::types::lambda::vm_instructions::ir_translator::IRTranslator;
45
46/// 编译阶段诊断信息。
47///
48/// 封装编译流程中可能出现的 IO、借用等错误。
49#[derive(Debug, Clone)]
50pub enum CompileDiagnostic {
51    /// IO 错误(如文件读取失败)
52    IOError(String),
53    /// 多线程借用错误(如锁定失败)
54    BorrowError(String),
55}
56
57impl Diagnostic for CompileDiagnostic {
58    fn severity(&self) -> crate::diagnostics::ReportSeverity {
59        match self {
60            CompileDiagnostic::IOError(_) => crate::diagnostics::ReportSeverity::Error,
61            CompileDiagnostic::BorrowError(_) => crate::diagnostics::ReportSeverity::Error,
62        }
63    }
64
65    fn title(&self) -> String {
66        "Compile Error".to_string()
67    }
68
69    fn message(&self) -> String {
70        match self {
71            CompileDiagnostic::IOError(msg) => format!("I/O Error: {}", msg),
72            CompileDiagnostic::BorrowError(msg) => format!("Borrow Error: {}", msg),
73        }
74    }
75
76    fn location(&self) -> Option<crate::diagnostics::SourceLocation> {
77        None
78    }
79
80    fn help(&self) -> Option<String> {
81        None
82    }
83
84    fn copy(&self) -> Box<dyn Diagnostic> {
85        Box::new(self.clone())
86    }
87}
88
89/// 主编译入口:从源码生成中间表示(IRPackage)。
90///
91/// # 步骤说明
92/// 1. 词法分析并过滤注释
93/// 2. 语法分析生成 AST
94/// 3. 检查导入循环(CycleDetector)
95/// 4. 编译时求值(ComptimeSolver)
96/// 5. 自动变量捕获与语义分析
97/// 6. 生成 IR 并追加主返回指令
98/// 7. 构建最终 IRPackage
99///
100/// # 错误处理
101/// - 词法/语法/语义/编译时错误均通过 DiagnosticCollector 收集
102/// - IO 错误、借用错误通过 CompileDiagnostic 上报
103///
104/// # 参数
105/// - `collector`:诊断信息收集器
106/// - `source`:源码对象
107///
108/// # 返回
109/// - `Ok(IRPackage)`:编译成功
110/// - `Err(())`:编译失败,错误已收集
111pub fn build_code(collector: &mut DiagnosticCollector, source: &Source) -> Result<IRPackage, ()> {
112    let tokens = tokenizer::tokenize(&source);
113    let tokens = tokenizer::reject_comment(&tokens);
114    let gathered = ast_token_stream::from_stream(&tokens);
115    let ast = build_ast(collector, gathered)?;
116
117    // 检查导入循环,初始化 CycleDetector
118    let no_path = PathBuf::from(".");
119    let import_cycle_detector = CycleDetector::new()
120        .enter(
121            fs::canonicalize(source.file_path().unwrap_or(&no_path))
122                .map_err(|e| collector.report(CompileDiagnostic::IOError(e.to_string())))?,
123        )
124        .expect("unreachable!");
125    let mut comptime_solver =
126        ComptimeSolver::new(Arc::new(RwLock::new(HashMap::new())), import_cycle_detector);
127    let solve_result = comptime_solver.solve(&ast);
128    match comptime_solver.diagnostics().read() {
129        Ok(diagnostics) => {
130            for diag in diagnostics.diagnostics() {
131                collector.report(diag.copy());
132            }
133        }
134        Err(_) => {
135            return collector.fatal(CompileDiagnostic::BorrowError(
136                "Failed to read diagnostics".to_string(),
137            ));
138        }
139    }
140
141    let ast = solve_result?;
142
143    let (_required_vars, ast) = auto_capture_and_rebuild(&ast);
144
145    let _analyze_result = analyze_ast(&ast, collector, &None)?;
146
147    let namespace = ir_generator::NameSpace::new("Main".to_string(), None);
148    let mut functions = Functions::new();
149    let mut ir_generator = ir_generator::IRGenerator::new(&mut functions, namespace);
150
151    let ir = ir_generator.generate(collector, &ast)?;
152
153    let mut ir = ir;
154    ir.push((DebugInfo::new((0, 0)), IR::Return));
155    functions.append("__main__".to_string(), ir);
156
157    Ok(functions.build_instructions(Some(source.content_str())))
158}
159
160/// IRPackage 编译为虚拟机字节码。
161///
162/// 将中间表示(IRPackage)翻译为 Onion 虚拟机可执行的指令包。
163///
164/// # 参数
165/// - `package`:IRPackage
166///
167/// # 返回
168/// - `Ok(VMInstructionPackage)`:翻译成功
169/// - `Err(String)`:翻译失败,返回错误信息
170pub fn compile_to_bytecode(package: &IRPackage) -> Result<VMInstructionPackage, String> {
171    let mut translator = IRTranslator::new(package);
172    match translator.translate() {
173        Ok(_) => Ok(translator.get_result()),
174        Err(e) => Err(format!("IR translation failed: {:?}", e)),
175    }
176}