diff --git a/crates/core/src/eval.rs b/crates/core/src/eval.rs index b8af5be..f5ec9b8 100644 --- a/crates/core/src/eval.rs +++ b/crates/core/src/eval.rs @@ -1050,7 +1050,9 @@ impl Vm { } } + /// 各操作码按下标读取语言值,返回 clone 的借用表示,不 retain;Null 或无对应项报字节码错误。 fn stack_value(frame: &EndorFrame, index: usize) -> Result { + // Rust clone 仅复制 Value/句柄,不能把借用读取当成新拥有根。 match frame.stack.get(index) { Some(StackEntry::Value(value)) => Ok(value.clone()), _ => Err(invalid( @@ -1060,15 +1062,18 @@ impl Vm { } } + /// 操作码读取栈顶语言值的快捷入口;栈非空由代码验证保证。 fn top_value(frame: &EndorFrame) -> Result { Self::stack_value(frame, frame.stack.len() - 1) } + /// StoreFast/StoreGlobal/StoreDeref 共用赋值选择:对象相同或共享引用原地更新成功时保留旧身份。 fn assignment_value( &mut self, previous: Option, incoming: Value, ) -> Result { + // 只有新旧均为对象才尝试原地赋值;标量/不支持协议时使用 incoming。 if let (Some(Value::Object(old)), Value::Object(new)) = (&previous, &incoming) && (old == new || self.objects.assign_from(*old, *new)?) { @@ -1077,23 +1082,31 @@ impl Vm { Ok(incoming) } + /// Load 类操作把借用值放入拥有栈槽,先验证/retain 成功才压栈。 fn push_borrowed(&mut self, frame: &mut EndorFrame, value: Value) -> Result<(), VmError> { + // retain 失败时保持栈不变,避免产生没有拥有根的栈项。 self.retain_value(&value)?; frame.stack.push(StackEntry::Value(value)); Ok(()) } + /// 操作码完成后丢弃已消费输入,每个对象槽归还一根,Null 不参与计数。 fn discard(&mut self, frame: &mut EndorFrame, count: usize) { + // 逐项弹栈,代码验证保证数量足够,不按对象身份去重释放。 for _ in 0..count { + // Null 仅是调用协议标记,不能作为语言对象根释放。 if let StackEntry::Value(value) = frame.stack.pop().expect("verified stack height") { self.drop_root(value); } } } + /// Load/Store/DeleteDeref 与 LoadClosure 取对应 Cell;索引布局已验证,仍检查载荷种类。 fn cell_slot(&self, frame: &EndorFrame, index: usize) -> Result { + // 槽必须已初始化为 Cell 对象,Cell 内部仍可为空。 match &frame.localsplus[index] { Some(Value::Object(reference)) => { + // 验证具体 Cell 载荷,不仅检查 Object 变体。 self.payload::(*reference, "cell")?; Ok(*reference) } @@ -1104,7 +1117,9 @@ impl Vm { } } + /// ToBool/UnaryNot/条件跳转共用真值规则,直接值就地判断,对象交载荷协议。 fn value_is_true(&self, value: &Value) -> Result { + // 直接数值/字符串与对象载荷分开处理,协议错误不被当成 false。 match value { Value::Nil => Ok(false), Value::Bool(value) => Ok(*value), @@ -1114,7 +1129,9 @@ impl Vm { } } + /// 比较把直接 Text 与堆字符串统一成拥有 String,非字符串 None,坏句柄报错。 fn text_value(&self, value: &Value) -> Result, VmError> { + // 仅尝试所需具体载荷,非目标类别是正常 None,不是 kind mismatch。 Ok(match value { Value::Text(text) => Some(text.clone()), Value::Object(reference) => self @@ -1127,10 +1144,12 @@ impl Vm { }) } + /// 比较/算术将直接 Number 与堆数值统一为借用数值,不转换表示或新增根。 fn number_value<'a>( &'a self, value: &'a Value, ) -> Result, VmError> { + // 仅尝试所需具体载荷,非目标类别是正常 None,不是 kind mismatch。 Ok(match value { Value::Number(n) => Some(n), Value::Object(o) => self @@ -1143,16 +1162,20 @@ impl Vm { }) } + /// CompareOp 指令的语言比较入口,优先数学数值与字符串内容,然后对象协议/直接值相等。 fn compare_values( &self, left: &Value, right: &Value, operation: CompareOp, ) -> Result { + // 两侧都先尝试识别数值,不能对混合表示直接使用 Rust Eq。 let (left_number, right_number) = (self.number_value(left)?, self.number_value(right)?); + // 直接与堆数值都走数学比较,因此整数、小数、分数可跨表示等价。 if let (Some(left), Some(right)) = (left_number, right_number) { return left.numeric_compare(right, operation); } + // 仅一侧是数值时相等为 false、不等为 true,有序关系明确拒绝。 if left_number.is_some() || right_number.is_some() { return match operation { CompareOp::Eq => Ok(false), @@ -1160,6 +1183,7 @@ impl Vm { _ => Err(VmError::UnsupportedOperation("mixed numeric ordering")), }; } + // 两侧均为文本时按字符串内容比较,不做大小写折叠或 Unicode 规范化。 if let (Some(left), Some(right)) = (self.text_value(left)?, self.text_value(right)?) { return Ok(match operation { CompareOp::Eq => left == right, @@ -1170,9 +1194,11 @@ impl Vm { CompareOp::Ge => left >= right, }); } + // 非数值/文本的双对象走 Store 正向、反向与身份回退协议。 if let (Value::Object(left), Value::Object(right)) = (left, right) { return self.compare(*left, *right, operation); } + // 其他直接值只支持相等/不等,不能凭 Rust 变体顺序定义语言大小。 match operation { CompareOp::Eq => Ok(left == right), CompareOp::Ne => Ok(left != right), @@ -1180,17 +1206,25 @@ impl Vm { } } + /// BuildMap 逐对读取栈上键值,构造字典拥有根;失败释放半成品,输入栈由调用方清理。 fn build_map(&mut self, frame: &EndorFrame, count: usize) -> Result { + // 新字典先取得一份根,所有插入成功才移交给 BuildMap 调用方。 let dictionary = self.new_dict()?; + // 闭包收拢插入错误,外层统一释放未交付字典根。 let result = (|| -> Result<(), VmError> { + // 输入是末尾 count 对交错键值;代码验证已检查栈高及数量乘法。 let start = frame.stack.len() - count * 2; + // 按源码顺序插入,重复相等键遵循字典保留首次键位置的规则。 for index in 0..count { + // 先复制键的借用表示,原栈根继续保护其对象。 let key = Self::stack_value(frame, start + index * 2)?; + // 读取对应值的借用表示,字典提交后自己持有内部强边。 let value = Self::stack_value(frame, start + index * 2 + 1)?; self.dict_set(dictionary, key, value)?; } Ok(()) })(); + // 失败字典可能已持有部分键值边,释放其根会一并归还这些边。 if let Err(error) = result { self.release(dictionary)?; return Err(error); @@ -1198,45 +1232,58 @@ impl Vm { Ok(dictionary) } + /// MakeFunction 从默认值、Cell 和代码栈布局构造函数,成功返回拥有根,不先弹出输入。 fn make_function(&mut self, frame: &EndorFrame, argument: u32) -> Result { + // 低/高 16 位计数决定默认值段与 Cell 段,最后一项固定为代码。 let (default_count, closure_count) = Instruction::function_counts(argument); + // 代码必须是对象,后续 payload 再检查确为 EndorCodeObject。 let Value::Object(code) = Self::top_value(frame)? else { return Err(VmError::ObjectKindMismatch("code")); }; + // 复制代码诊断名,避免持载荷借用跨可变函数分配。 let name = self .payload::(code, "code")? .code() .name() .to_owned(); + // 栈高度由验证器证明,默认值段在 Cell 段之前。 let start = frame.stack.len() - default_count - closure_count - 1; + // 收集借用默认值表示,不提前归还栈根。 let defaults = (start..start + default_count) .map(|index| Self::stack_value(frame, index)) .collect::, _>>()?; + // 捕获段每项必须是对象;是否 Cell 以及数量是否吻合由函数构造再次验证。 let closure = (start + default_count..frame.stack.len() - 1) .map(|index| match Self::stack_value(frame, index)? { Value::Object(cell) => Ok(cell), _ => Err(VmError::ObjectKindMismatch("cell")), }) .collect::, _>>()?; - // Keep every input root on the stack until allocation has validated - // and retained all function edges. Failure leaves cleanup to the frame. + // 所有输入根在验证并建立函数内部强边前一直留栈,失败时仍由帧统一清理。 self.new_function(name, code, frame.globals, defaults, closure) } + /// BuildClass 从四个栈项构造类,保留当前函数作为字段注解环境,输入保活至构造完成。 fn build_class(&mut self, frame: &EndorFrame) -> Result { + // 类构造输入固定为名称、基类、字段字典、方法字典。 let start = frame.stack.len() - 4; + // 类名必须是直接文本,与元数据里显示名称分开。 let Value::Text(name) = Self::stack_value(frame, start)? else { return Err(VmError::ObjectKindMismatch("class name")); }; + // 基类必须是对象,Store 类构造进一步校验 Type 载荷与继承分配策略。 let Value::Object(base) = Self::stack_value(frame, start + 1)? else { return Err(VmError::ObjectKindMismatch("base Type")); }; + // 字段说明必须来自字典对象,读取时再校验具体载荷。 let Value::Object(fields) = Self::stack_value(frame, start + 2)? else { return Err(VmError::ObjectKindMismatch("field map")); }; + // 方法说明必须来自字典对象,函数句柄有效性由 Store 类构造验证。 let Value::Object(methods) = Self::stack_value(frame, start + 3)? else { return Err(VmError::ObjectKindMismatch("method map")); }; + // 字段键值都须为直接文本,形成按字典插入顺序排列的 ClassField。 let fields = self .dict_items(fields)? .iter() @@ -1248,6 +1295,7 @@ impl Vm { _ => Err(VmError::ObjectKindMismatch("class field annotation")), }) .collect::, _>>()?; + // 方法键须文本、值须对象,收集为名称有序表,仍不额外保留函数根。 let methods = self .dict_items(methods)? .iter()