Skip to main content

onion_vm/types/lambda/
runnable.rs

1//! Onion Lambda 可执行模块。
2//!
3//! 提供 Onion 语言中 Lambda 函数的虚拟机执行环境,包括指令执行、调用栈管理、
4//! 错误处理和调试信息输出等核心功能。支持高性能的字节码执行和完整的运行时环境。
5
6use std::{ptr::addr_eq, sync::Arc};
7
8use arc_gc::gc::GC;
9use unicode_width::UnicodeWidthStr;
10
11use crate::{
12    lambda::runnable::{Runnable, RuntimeError, StepResult},
13    types::{
14        lambda::vm_instructions::opcode::{
15            self, OpcodeArgument, build_operand_argument, decode_opcode, get_operand_arg,
16            get_processed_opcode,
17        },
18        object::{OnionObject, OnionObjectCell, OnionStaticObject},
19    },
20    utils::{fastmap::OnionFastMap, find_line_and_col_from_source},
21};
22
23use super::{
24    context::{Context, Frame},
25    vm_instructions::{
26        self,
27        instruction_set::{VMInstruction, VMInstructionPackage},
28        opcode::ProcessedOpcode,
29    },
30};
31
32/// 指令处理函数类型定义。
33///
34/// 每个虚拟机指令对应一个处理函数,用于执行具体的操作逻辑。
35///
36/// # 参数
37/// - `&mut OnionLambdaRunnable`: 可执行对象的可变引用,用于访问执行上下文和状态
38/// - `&ProcessedOpcode`: 已解码的操作码,包含指令类型和操作数
39/// - `&mut GC<OnionObjectCell>`: 垃圾收集器的可变引用,用于内存管理
40///
41/// # 返回
42/// 执行步骤的结果,包括继续执行、返回值、错误等状态
43type InstructionHandler =
44    fn(&mut OnionLambdaRunnable, &ProcessedOpcode, &mut GC<OnionObjectCell>) -> StepResult;
45
46/// 静态指令表,在程序启动时初始化一次。
47///
48/// 使用指令枚举值作为索引,直接映射到对应的处理函数,
49/// 实现 O(1) 时间复杂度的指令分发,提升虚拟机执行性能。
50///
51/// 表大小固定为 256,覆盖所有可能的 8 位操作码值。
52/// 未定义的操作码将映射到默认错误处理函数。
53static INSTRUCTION_TABLE: std::sync::LazyLock<Vec<InstructionHandler>> =
54    std::sync::LazyLock::new(|| {
55        let mut instruction_table: Vec<InstructionHandler> = vec![
56        |_, opcode, _| StepResult::Error(RuntimeError::DetailedError(format!("Invalid instruction: {:?}", opcode).into())); // 默认处理函数 - 返回无效指令错误
57        256 // 数组大小,确保能容纳所有可能的操作码
58    ];
59
60        // 使用枚举值作为索引,填充对应的处理函数
61        // 栈操作
62        instruction_table[VMInstruction::LoadNull as usize] = vm_instructions::load_null;
63        instruction_table[VMInstruction::LoadInt32 as usize] = vm_instructions::load_int;
64        instruction_table[VMInstruction::LoadInt64 as usize] = vm_instructions::load_int;
65        instruction_table[VMInstruction::LoadFloat32 as usize] = vm_instructions::load_float;
66        instruction_table[VMInstruction::LoadFloat64 as usize] = vm_instructions::load_float;
67        instruction_table[VMInstruction::LoadString as usize] = vm_instructions::load_string;
68        instruction_table[VMInstruction::LoadBytes as usize] = vm_instructions::load_bytes;
69        instruction_table[VMInstruction::LoadBool as usize] = vm_instructions::load_bool;
70        instruction_table[VMInstruction::LoadLambda as usize] = vm_instructions::load_lambda;
71        instruction_table[VMInstruction::LoadUndefined as usize] = vm_instructions::load_undefined;
72
73        // 数据结构构建
74        instruction_table[VMInstruction::BuildTuple as usize] = vm_instructions::build_tuple;
75        instruction_table[VMInstruction::BuildKeyValue as usize] = vm_instructions::build_pair;
76        instruction_table[VMInstruction::BuildRange as usize] = vm_instructions::build_range;
77        instruction_table[VMInstruction::BuildSet as usize] = vm_instructions::build_set;
78        // 二元操作符
79        instruction_table[VMInstruction::BinaryIn as usize] = vm_instructions::is_in;
80        instruction_table[VMInstruction::BinaryIs as usize] = vm_instructions::check_is_same_object;
81
82        instruction_table[VMInstruction::BinaryAdd as usize] = vm_instructions::binary_add;
83        instruction_table[VMInstruction::BinarySub as usize] = vm_instructions::binary_subtract;
84        instruction_table[VMInstruction::BinaryMul as usize] = vm_instructions::binary_multiply;
85        instruction_table[VMInstruction::BinaryDiv as usize] = vm_instructions::binary_divide;
86        instruction_table[VMInstruction::BinaryMod as usize] = vm_instructions::binary_modulus;
87        instruction_table[VMInstruction::BinaryPow as usize] = vm_instructions::binary_power;
88        instruction_table[VMInstruction::BinaryBitAnd as usize] =
89            vm_instructions::binary_bitwise_and;
90        instruction_table[VMInstruction::BinaryBitOr as usize] = vm_instructions::binary_bitwise_or;
91        instruction_table[VMInstruction::BinaryBitXor as usize] =
92            vm_instructions::binary_bitwise_xor;
93        instruction_table[VMInstruction::BinaryShl as usize] = vm_instructions::binary_shift_left;
94        instruction_table[VMInstruction::BinaryShr as usize] = vm_instructions::binary_shift_right;
95        instruction_table[VMInstruction::BinaryEq as usize] = vm_instructions::binary_equal;
96        instruction_table[VMInstruction::BinaryNe as usize] = vm_instructions::binary_not_equal;
97        instruction_table[VMInstruction::BinaryGt as usize] = vm_instructions::binary_greater;
98        instruction_table[VMInstruction::BinaryLt as usize] = vm_instructions::binary_less;
99        instruction_table[VMInstruction::BinaryGe as usize] = vm_instructions::binary_greater_equal;
100        instruction_table[VMInstruction::BinaryLe as usize] = vm_instructions::binary_less_equal;
101        instruction_table[VMInstruction::MapTo as usize] = vm_instructions::map_to;
102
103        // 一元操作
104        instruction_table[VMInstruction::UnaryBitNot as usize] = vm_instructions::unary_bitwise_not;
105        instruction_table[VMInstruction::UnaryAbs as usize] = vm_instructions::unary_plus;
106        instruction_table[VMInstruction::UnaryNeg as usize] = vm_instructions::unary_minus;
107
108        // 变量与引用
109        instruction_table[VMInstruction::StoreVar as usize] = vm_instructions::let_var;
110        instruction_table[VMInstruction::LoadVar as usize] = vm_instructions::get_var;
111        instruction_table[VMInstruction::SetValue as usize] = vm_instructions::set_var;
112        instruction_table[VMInstruction::GetAttr as usize] = vm_instructions::get_attr;
113        instruction_table[VMInstruction::KeyOf as usize] = vm_instructions::key_of;
114        instruction_table[VMInstruction::ValueOf as usize] = vm_instructions::value_of;
115        instruction_table[VMInstruction::TypeOf as usize] = vm_instructions::type_of;
116        instruction_table[VMInstruction::Swap as usize] = vm_instructions::swap;
117        instruction_table[VMInstruction::LengthOf as usize] = vm_instructions::get_length;
118        instruction_table[VMInstruction::Mut as usize] = vm_instructions::mutablize;
119        instruction_table[VMInstruction::Const as usize] = vm_instructions::immutablize;
120        instruction_table[VMInstruction::ForkInstruction as usize] =
121            vm_instructions::fork_instruction;
122        instruction_table[VMInstruction::Launch as usize] = vm_instructions::launch_thread;
123        instruction_table[VMInstruction::Spawn as usize] = vm_instructions::spawn_task;
124        instruction_table[VMInstruction::MakeAtomic as usize] = vm_instructions::make_atomic;
125        instruction_table[VMInstruction::MakeAsync as usize] = vm_instructions::make_async;
126        instruction_table[VMInstruction::MakeSync as usize] = vm_instructions::make_sync;
127
128        // 控制流
129        instruction_table[VMInstruction::Apply as usize] = vm_instructions::apply;
130        instruction_table[VMInstruction::Return as usize] = vm_instructions::return_value;
131        instruction_table[VMInstruction::Raise as usize] = vm_instructions::raise;
132        instruction_table[VMInstruction::Jump as usize] = vm_instructions::jump;
133        instruction_table[VMInstruction::JumpIfFalse as usize] = vm_instructions::jump_if_false;
134
135        // 帧操作
136        instruction_table[VMInstruction::NewFrame as usize] = vm_instructions::new_frame;
137        instruction_table[VMInstruction::PopFrame as usize] = vm_instructions::pop_frame;
138        instruction_table[VMInstruction::ResetStack as usize] = vm_instructions::clear_stack;
139        instruction_table[VMInstruction::Pop as usize] = vm_instructions::discard_top;
140
141        // 模块操作
142        instruction_table[VMInstruction::Import as usize] = vm_instructions::import;
143
144        instruction_table[VMInstruction::Assert as usize] = vm_instructions::assert;
145
146        instruction_table
147    });
148
149/// Onion Lambda 可执行对象。
150///
151/// 表示一个可执行的 Lambda 函数实例,包含完整的执行上下文、
152/// 指令指针和字节码指令包。每个 Lambda 调用都会创建一个新的
153/// 可执行对象实例,提供独立的执行环境。
154///
155/// # 执行模型
156/// - 基于栈的虚拟机架构
157/// - 支持增量执行和暂停/恢复
158/// - 提供完整的调试信息和错误处理
159/// - 支持垃圾回收和内存管理
160///
161/// # 示例
162/// ```ignore
163/// let runnable = OnionLambdaRunnable::new(
164///     &arguments,     // 函数参数
165///     &captures,      // 闭包捕获的变量
166///     &self_object,   // self 引用
167///     &this_lambda,   // this 引用
168///     instruction,    // 字节码指令包
169///     0,              // 起始指令指针
170/// )?;
171/// ```
172pub struct OnionLambdaRunnable {
173    /// 执行上下文,包含变量作用域、操作数栈等运行时状态
174    pub(super) context: Context,
175    /// 当前指令指针,指向下一条要执行的指令
176    pub(super) ip: isize,
177    /// 执行步骤前的指令指针,用于错误报告和调试
178    pub(super) ip_before_step: isize,
179    /// 字节码指令包,包含指令序列、常量池等数据
180    pub(super) instruction: Arc<VMInstructionPackage>,
181}
182
183impl OnionLambdaRunnable {
184    /// 创建新的 Lambda 可执行对象。
185    ///
186    /// 初始化完整的执行环境,包括变量绑定、作用域设置和内置变量配置。
187    /// 会验证参数池和捕获池与指令包的字符串池一致性,确保执行安全。
188    ///
189    /// # 参数
190    /// - `argument`: 函数参数映射,键为参数名索引,值为参数值
191    /// - `capture`: 闭包捕获的变量映射,键为变量名索引,值为变量值
192    /// - `self_object`: self 引用对象,用于方法调用
193    /// - `this_lambda`: this 引用对象,指向当前 Lambda 函数
194    /// - `instruction`: 字节码指令包,包含可执行代码和元数据
195    /// - `ip`: 起始指令指针位置
196    ///
197    /// # 返回
198    /// - `Ok(OnionLambdaRunnable)`: 成功创建的可执行对象
199    /// - `Err(RuntimeError)`: 初始化失败,如缺少必要变量或池不匹配
200    ///
201    /// # 错误
202    /// - `InvalidOperation`: 字符串池不匹配或缺少必要的内置变量
203    ///
204    /// # 内置变量
205    /// 自动设置以下内置变量:
206    /// - `this`: 当前 Lambda 函数引用
207    /// - `self`: 方法调用的对象引用
208    /// - 函数参数:按名称绑定到对应值
209    /// - 捕获变量:闭包捕获的外部作用域变量
210    pub fn new(
211        argument: &OnionFastMap<Box<str>, OnionStaticObject>,
212        capture: &OnionFastMap<Box<str>, OnionObject>,
213        self_object: &OnionObject,
214        this_lambda: &OnionStaticObject,
215        instruction: Arc<VMInstructionPackage>,
216        ip: isize,
217    ) -> Result<Self, RuntimeError> {
218        if !addr_eq(argument.pool().keys(), instruction.get_string_pool()) {
219            panic!(
220                "Argument pool does not match instruction string pool: {:?} != {:?}",
221                argument.pool().keys(),
222                instruction.get_string_pool()
223            );
224        }
225        if !addr_eq(capture.pool().keys(), instruction.get_string_pool()) {
226            panic!(
227                "Capture pool does not match instruction string pool: {:?} != {:?}",
228                capture.pool().keys(),
229                instruction.get_string_pool()
230            );
231        }
232
233        let mut new_context = Context::new();
234        Context::push_frame(&mut new_context, Frame::new());
235
236        let index_this = instruction.get_string_index("this").ok_or_else(|| {
237            RuntimeError::InvalidOperation(
238                "Missing required variable 'this' in string pool"
239                    .to_string()
240                    .into(),
241            )
242        })?;
243        let index_self = instruction.get_string_index("self").ok_or_else(|| {
244            RuntimeError::InvalidOperation(
245                "Missing required variable 'self' in string pool"
246                    .to_string()
247                    .into(),
248            )
249        })?;
250        /*
251        let index_arguments = string_pool
252            .iter()
253            .position(|s| s == "arguments")
254            .ok_or_else(|| {
255                RuntimeError::InvalidOperation(
256                    "Missing required variable 'arguments' in string pool"
257                        .to_string()
258                        .into(),
259                )
260            })?;
261        */
262
263        // 设置内置变量
264        new_context
265            .let_variable(index_this, this_lambda.clone())
266            .map_err(|e| {
267                RuntimeError::InvalidOperation(
268                    format!("Failed to initialize 'this' variable: {}", e).into(),
269                )
270            })?;
271
272        new_context
273            .let_variable(index_self, self_object.stabilize())
274            .map_err(|e| {
275                RuntimeError::InvalidOperation(
276                    format!("Failed to initialize 'self' variable: {}", e).into(),
277                )
278            })?;
279
280        // new_context
281        //     .let_variable(index_arguments, build_dict_from_hashmap(argument))
282        //     .map_err(|e| {
283        //         RuntimeError::InvalidOperation(
284        //             format!("Failed to initialize 'arguments' variable: {}", e).into(),
285        //         )
286        //     })?;
287
288        for (argument_index, value) in argument.pairs() {
289            new_context
290                .let_variable(*argument_index, value.clone())
291                .map_err(|e| {
292                    RuntimeError::InvalidOperation(
293                        format!("Failed to initialize argument '{}': {}", argument_index, e).into(),
294                    )
295                })?;
296        }
297
298        // 设置捕获的变量
299        for (capture_index, value) in capture.pairs() {
300            new_context
301                .let_variable(*capture_index, value.stabilize())
302                .map_err(|e| {
303                    RuntimeError::InvalidOperation(
304                        format!(
305                            "Failed to initialize captured variable '{}': {}",
306                            capture_index, e
307                        )
308                        .into(),
309                    )
310                })?;
311        }
312
313        Ok(OnionLambdaRunnable {
314            context: new_context,
315            ip,
316            ip_before_step: ip,
317            instruction,
318        })
319    }
320}
321
322impl Runnable for OnionLambdaRunnable {
323    /// 接收其他可执行对象的执行结果。
324    ///
325    /// 当前仅支持接收返回值结果,将其推入操作数栈中。
326    /// 这主要用于处理子函数调用的返回值或异步操作的结果。
327    ///
328    /// # 参数
329    /// - `step_result`: 要接收的执行步骤结果
330    /// - `_gc`: 垃圾收集器引用(当前未使用)
331    ///
332    /// # 返回
333    /// - `Ok(())`: 成功接收结果
334    /// - `Err(RuntimeError)`: 接收失败或不支持的结果类型
335    ///
336    /// # 错误
337    /// - `DetailedError`: 当接收非返回值类型的结果时
338    fn receive(
339        &mut self,
340        step_result: &StepResult,
341        _gc: &mut GC<OnionObjectCell>,
342    ) -> Result<(), RuntimeError> {
343        if let StepResult::Return(result) = step_result {
344            self.context.push_object(result.as_ref().clone())?;
345            Ok(())
346        } else {
347            Err(RuntimeError::DetailedError(
348                "receive not implemented for cases except 'Return'"
349                    .to_string()
350                    .into(),
351            ))
352        }
353    }
354
355    /// 执行一个或多个指令步骤。
356    ///
357    /// 实现高性能的指令执行循环,支持批量执行以减少函数调用开销。
358    /// 通过静态指令表实现 O(1) 指令分发,提供优异的执行性能。
359    ///
360    /// # 执行策略
361    /// - 批量执行最多 1024 条指令以优化性能
362    /// - 使用 unsafe 代码避免重复边界检查
363    /// - 通过静态函数表实现快速指令分发
364    /// - 保存错误时的指令指针用于调试
365    ///
366    /// # 参数
367    /// - `gc`: 垃圾收集器的可变引用,用于内存管理
368    ///
369    /// # 返回
370    /// - `StepResult::Continue`: 需要继续执行更多指令
371    /// - `StepResult::Return(value)`: 函数执行完成,返回结果值
372    /// - `StepResult::Error(error)`: 执行过程中发生错误
373    /// - `StepResult::Call(runnable)`: 需要调用其他可执行对象
374    ///
375    /// # 安全性
376    /// 使用 unsafe 代码进行性能优化,但通过边界检查确保内存安全。
377    /// 指令指针越界会立即返回错误而不是导致未定义行为。
378    fn step(&mut self, gc: &mut GC<OnionObjectCell>) -> StepResult {
379        const MAX_INLINE_STEPS: usize = 1024;
380
381        let mut steps = 0;
382
383        // 获取代码的原始指针和长度,避免借用冲突
384        let (code_ptr, code_len) = {
385            let code = self.instruction.get_code();
386            (code.as_ptr(), code.len())
387        };
388
389        loop {
390            if steps >= MAX_INLINE_STEPS {
391                break;
392            }
393            steps += 1;
394
395            let mut ip = self.ip as usize;
396            if ip >= code_len {
397                return StepResult::Error(RuntimeError::DetailedError(
398                    "Instruction pointer out of bounds".into(),
399                ));
400            }
401
402            // 使用 unsafe 从原始指针创建切片
403            let code = unsafe { std::slice::from_raw_parts(code_ptr, code_len) };
404            let pending_ip = ip;
405            let opcode = get_processed_opcode(code, &mut ip);
406
407            let handler = unsafe { *INSTRUCTION_TABLE.get_unchecked(opcode.instruction as usize) };
408            self.ip = ip as isize;
409            self.ip_before_step = pending_ip as isize; // 保存上一步的 IP
410
411            match handler(self, &opcode, gc) {
412                StepResult::Continue => continue,
413                StepResult::Error(e) => {
414                    self.ip = pending_ip as isize; // 恢复 IP
415                    return StepResult::Error(e);
416                }
417                v => return v,
418            }
419        }
420
421        StepResult::Continue
422    }
423
424    /// 格式化当前执行上下文为可读字符串。
425    ///
426    /// 生成详细的调试信息,包括源码位置、当前指令和执行状态。
427    /// 优先显示源码级别的调试信息,如果不可用则回退到字节码级别。
428    ///
429    /// # 输出格式
430    /// 1. **源码位置**(如果可用):
431    ///    - 行号和列号
432    ///    - 带有错误高亮的源码片段
433    /// 2. **字节码信息**(回退选项):
434    ///    - 当前指令指针位置
435    ///    - 反汇编的指令内容
436    /// 3. **执行状态**:
437    ///    - 调用栈信息
438    ///    - 操作数栈状态
439    ///    - 变量作用域内容
440    ///
441    /// # 返回
442    /// 格式化的多行字符串,包含完整的调试上下文信息
443    ///
444    /// # 示例输出
445    /// ```text
446    /// -> at 15:8
447    ///     15 | let x = 10 / 0;
448    ///        |         ^^^^^^
449    ///
450    /// --- Lambda Execution State ---
451    /// Frame 0:
452    ///   Variables: x=10, y="hello"
453    ///   Stack: [Integer(10), Integer(0)]
454    /// ```
455    fn format_context(&self) -> String {
456        let ip = self.ip_before_step as usize;
457        let mut parts = Vec::new();
458
459        // 尝试获取详细的源码位置信息
460        if let Some(location) = get_source_location_for_ip(&self.instruction, ip) {
461            // --- Part 1: 高级、人类可读的上下文 ---
462            parts.push(format!("-> at {}:{}", location.line, location.column));
463            parts.push(location.code_snippet);
464        } else {
465            // --- Part 1 (回退): 原始的、无源码的上下文 ---
466            let disassembly = disassemble_instruction(&self.instruction, ip); // 假设这个函数存在
467            parts.push(format!("-> Executing VM Code at ip: {}", ip));
468            parts.push(format!("  - Current Instruction: {}", disassembly));
469        }
470
471        // --- Part 2: VM 调用栈和操作数栈状态 ---
472        let context_state = self.context.format_context(self.instruction.as_ref());
473        parts.push("\n--- Lambda Execution State ---".to_string());
474        parts.push(context_state);
475
476        parts.join("\n")
477    }
478}
479
480/// 反汇编函数:将给定 IP 位置的指令转换为人类可读的字符串。
481///
482/// 解析变长指令格式,提取操作码和操作数,并格式化为易读的汇编代码形式。
483/// 支持所有虚拟机指令类型,包括立即数、字符串引用、字节数组引用等。
484///
485/// # 指令格式
486/// - 第一个 u32 word:元数据,包含操作码和操作数类型标志
487/// - 后续 words:操作数的实际值,根据类型标志解释
488///
489/// # 参数
490/// - `package`: 字节码指令包,包含指令序列和常量池
491/// - `ip`: 要反汇编的指令指针位置
492///
493/// # 返回
494/// 人类可读的指令字符串,包含指令名称和格式化的操作数
495///
496/// # 示例输出
497/// ```text
498/// LoadInt32 42
499/// LoadString Str(5) -> "hello"
500/// BinaryAdd
501/// Jump 15
502/// ```
503///
504/// # 错误处理
505/// 如果指令指针越界,返回包含错误信息的字符串而不是 panic
506///
507/// 此版本适配了变长指令集,其中第一个 u32 word 是元数据,
508/// 后续的 words 是操作数的实际值。
509pub fn disassemble_instruction(package: &VMInstructionPackage, ip: usize) -> String {
510    let code = package.get_code();
511    if ip >= code.len() {
512        return format!("<IP:{} out of bounds>", ip);
513    }
514
515    // --- 1. 解码元数据 ---
516    // 我们需要一个可变的指针来模拟执行过程,但不能影响原始 ip
517    let mut temp_ip = ip;
518    let opcode_word = opcode::take_u32(code, &mut temp_ip);
519    let decoded_opcode = decode_opcode(opcode_word);
520
521    // --- 2. 获取操作数的原始值 ---
522    // 注意:这里我们只读取值,但不解释它们,因为格式化依赖于标志
523    let mut next_ip = temp_ip; // 保存操作数开始的位置
524    let raw_operand1 = get_operand_arg(code, &mut next_ip, decoded_opcode.operand1());
525    let raw_operand2 = get_operand_arg(code, &mut next_ip, decoded_opcode.operand2());
526    let raw_operand3 = get_operand_arg(code, &mut next_ip, decoded_opcode.operand3());
527
528    // --- 3. 格式化每个操作数 ---
529    // 这是一个辅助闭包,用于将单个操作数格式化为字符串
530    let format_operand = |flag: u8, raw_value: u64| -> Option<String> {
531        // 使用你的 'build_operand_argument' 来获取结构化的操作数类型
532        let arg = build_operand_argument(flag, raw_value);
533
534        match arg {
535            OpcodeArgument::None => None,
536            OpcodeArgument::Int32(v) => Some(format!("{}", v)),
537            OpcodeArgument::Int64(v) => Some(format!("{}L", v)), // 'L' for long
538            OpcodeArgument::Float32(v) => Some(format!("{}f", v)), // 'f' for float
539            OpcodeArgument::Float64(v) => Some(format!("{}", v)),
540            OpcodeArgument::String(idx) => {
541                let s = package
542                    .get_string_pool()
543                    .get(idx as usize)
544                    .map(|s| format!("Str({}) -> \"{}\"", idx, s))
545                    .unwrap_or_else(|| format!("Str({}) -> <Invalid>", idx));
546                Some(s)
547            }
548            OpcodeArgument::ByteArray(idx) => {
549                let b = package
550                    .get_bytes_pool()
551                    .get(idx as usize)
552                    .map(|b| format!("Bytes({}) -> {:X?}", idx, b))
553                    .unwrap_or_else(|| format!("Bytes({}) -> <Invalid>", idx));
554                Some(b)
555            }
556        }
557    };
558
559    let op1_str = format_operand(decoded_opcode.operand1(), raw_operand1);
560    let op2_str = format_operand(decoded_opcode.operand2(), raw_operand2);
561    let op3_str = format_operand(decoded_opcode.operand3(), raw_operand3);
562
563    // --- 4. 组合最终的字符串 ---
564    let instruction_name = VMInstruction::from_opcode(decoded_opcode.instruction())
565        .map(|instr| format!("{:?}", instr))
566        .unwrap_or_else(|| format!("Invalid({})", decoded_opcode.instruction()));
567
568    let parts = vec![op1_str, op2_str, op3_str];
569    // 过滤掉 None 的操作数
570    let operands_str = parts
571        .into_iter()
572        .filter_map(|p| p)
573        .collect::<Vec<String>>()
574        .join(", ");
575
576    if operands_str.is_empty() {
577        instruction_name
578    } else {
579        format!("{} {}", instruction_name, operands_str)
580    }
581}
582
583/// 源码位置信息。
584///
585/// 包含与特定指令指针位置对应的源码行列信息和代码片段,
586/// 用于生成高质量的错误消息和调试输出。
587///
588/// # 字段
589/// - `line`: 源码行号(从 1 开始)
590/// - `column`: 源码列号(从 1 开始)
591/// - `code_snippet`: 格式化的代码片段,包含行号和错误高亮
592///
593/// # 代码片段格式
594/// ```text
595///    15 | let x = 10 / 0;
596///       |         ^^^^^^
597/// ```
598/// 其中 `^^^^^^` 标记了错误发生的具体位置。
599#[derive(Debug)]
600struct SourceLocation {
601    /// 源码行号(从 1 开始计数)
602    pub line: usize,
603    /// 源码列号(从 1 开始计数)
604    pub column: usize,
605    /// 包含高亮的代码片段,格式化为多行字符串
606    ///
607    /// 示例格式:
608    /// ```text
609    ///   "  12 | let x = 10 / 0;\n"
610    ///   "     |         ^^^^^^"
611    /// ```
612    pub code_snippet: String,
613}
614
615/// 根据指令指针获取对应的源码位置信息。
616///
617/// 通过调试信息将虚拟机指令指针映射回原始源码位置,
618/// 生成包含行列号和高亮代码片段的详细位置信息。
619///
620/// # 参数
621/// - `package`: 字节码指令包,包含调试信息和源码
622/// - `ip`: 指令指针位置
623///
624/// # 返回
625/// - `Some(SourceLocation)`: 成功映射到源码位置
626/// - `None`: 无法映射(缺少源码或调试信息)
627///
628/// # 功能特性
629/// - 支持 Unicode 字符的正确宽度计算
630/// - 生成美观的错误高亮显示
631/// - 处理多字节字符的对齐问题
632/// - 提供上下文行信息
633///
634/// # 错误处理
635/// 当源码或调试信息不可用时返回 None,调用方应提供回退方案。
636fn get_source_location_for_ip(package: &VMInstructionPackage, ip: usize) -> Option<SourceLocation> {
637    let source = package.get_source().as_ref()?;
638    let debug_info = package.get_debug_info().get(&ip)?;
639
640    let (span_start, span_end) = debug_info.token_span();
641
642    if span_start >= span_end {
643        return None;
644    }
645
646    let (line_idx, col_char_idx) = find_line_and_col_from_source(span_start, source);
647    let line_content = source.lines().nth(line_idx).unwrap_or("");
648
649    let error_token_text: String = source
650        .chars()
651        .skip(span_start)
652        .take(span_end - span_start)
653        .collect();
654
655    let display_offset = line_content
656        .chars()
657        .take(col_char_idx)
658        .collect::<String>()
659        .width();
660
661    let underline_width = error_token_text.width();
662
663    let line_num_width = 5;
664    let line_num = line_idx + 1;
665
666    let code_snippet = format!(
667        " {:>width$} | {}\n {empty:>width$} | {padding}{underline}",
668        line_num,
669        line_content,
670        empty = "",
671        padding = " ".repeat(display_offset),
672        underline = "^".repeat(underline_width),
673        width = line_num_width
674    );
675
676    Some(SourceLocation {
677        line: line_num,
678        column: col_char_idx + 1,
679        code_snippet,
680    })
681}
682
683#[cfg(test)]
684mod size_tests {
685    use super::*;
686
687    /// 打印关键数据结构的内存大小。
688    ///
689    /// 输出 `StepResult` 和 `RuntimeError` 等核心类型的字节大小,
690    /// 用于性能分析和内存优化决策。
691    ///
692    /// # 注意
693    /// 这些大小可能因编译器版本、目标平台和编译选项而有所不同。
694    #[test]
695    fn print_sizes() {
696        println!("StepResult size: {}", std::mem::size_of::<StepResult>());
697        println!("RuntimeError size: {}", std::mem::size_of::<RuntimeError>());
698        println!("StepResult size: {}", std::mem::size_of::<StepResult>());
699    }
700}