diff --git a/crates/objects/src/types.rs b/crates/objects/src/types.rs index 67ccba9..be52c28 100644 --- a/crates/objects/src/types.rs +++ b/crates/objects/src/types.rs @@ -512,14 +512,18 @@ impl ObjectStore { Ok(class) } + /// Store/VM/能力检查沿继承链查最近同名方法,返回借用函数,不自动绑定接收者。 pub fn lookup_method( &self, type_object: ObjectRef, name: &str, ) -> Result, VmError> { + // 从类型自身向父链查找,最近声明优先。 let mut current = Some(type_object); + // 基类固定于创建,逐层校验类型句柄而不是按名称检索。 while let Some(type_object) = current { let definition = self.payload::(type_object, "Type")?; + // 找到方法即返回借用身份,不替调用方 retain。 if let Some(function) = definition.methods.get(name) { return Ok(Some(*function)); } @@ -530,15 +534,22 @@ impl ObjectStore { /// Source positional parameters after receiver binding. None means the /// callable uses a native protocol without a source signature. + /// 旧式能力检查/宿主查询源码参数总数,扣除所有绑定接收者;原生协议返回 None。 pub fn positional_parameter_count( &self, function: ObjectRef, ) -> Result, VmError> { + // 从传入可调用对象开始逐层展开 BoundMethod。 let mut current = function; + // 累计已绑定接收者槽数,不能只扣一层。 let mut receivers = 0usize; + // 按链迭代而非递归,未知原生元数据保持 None。 loop { + // 通过 object 验证句柄并记录读取,随后仅借用载荷元数据。 let payload = self.object(current)?.payload(); + // 每层绑定都额外供应一个接收者,继续查询真实目标函数。 if let Some(bound) = payload.as_any().downcast_ref::() { + // 计数使用 checked_add,防极深包装使参数扣减绕回。 receivers = receivers .checked_add(1) .ok_or(VmError::ExecutionLimit("bound receivers"))?; @@ -547,6 +558,7 @@ impl ObjectStore { .as_any() .downcast_ref::() { + // 源码参数列表包含显式 self,默认值不改变总参数槽数。 let count = self .payload::(function.code(), "code")? .code() @@ -564,16 +576,21 @@ impl ObjectStore { } } - /// Validated direct native metadata. Bound methods delegate to their actual - /// target, so receiver slots remain explicit here. Returned handles are borrowed. + /// 查询直接原生元数据;完整签名保留显式接收者,返回类型句柄是借用。 + /// BoundMethod 本身没有完整签名,参数区间查询通过 call_arity 另行解包。 + /// 原生调用/契约分析查询当前载荷完整签名并校验;不会在这里展开 BoundMethod。 pub fn native_signature( &self, function: ObjectRef, ) -> Result, VmError> { + // 通过 object 验证句柄并记录读取,随后仅借用载荷元数据。 let payload = self.object(function)?.payload(); + // 查询当前载荷提供的签名快照,不执行回调,也不新增定义根。 let signature = payload.call_signature(); + // 存在完整签名才校验全部类型边及数量元数据一致性。 if let Some(signature) = &signature { signature.validate(self)?; + // 载荷若同时发布 arity,必须与完整签名完全一致。 if payload .call_arity() .is_some_and(|arity| arity != signature.arity) @@ -588,28 +605,38 @@ impl ObjectStore { /// native wrappers and source call graphs with unproved operations remain unknown. /// This query follows current globals, closure Cells and known receivers without /// executing code, freezing targets or retaining a cross-query cache. + /// VM/契约通过 effects 分析当前调用图快照,None 表示无法证明整体效果。 pub fn call_effect(&self, function: ObjectRef) -> Result, VmError> { self.infer_call_effect(function) } /// Unified source/native positional interval, after any bound receivers. /// None means no published native metadata (including generic Type construction). + /// VM 数量检查统一查询源码/原生区间,先解绑定方法再扣除接收者。 pub fn call_arity(&self, function: ObjectRef) -> Result, VmError> { + // 从传入可调用对象开始逐层展开 BoundMethod。 let mut current = function; + // 累计已绑定接收者槽数,不能只扣一层。 let mut receivers = 0usize; + // 按链迭代而非递归,未知原生元数据保持 None。 loop { + // 通过 object 验证句柄并记录读取,随后仅借用载荷元数据。 let payload = self.object(current)?.payload(); + // 每层绑定都额外供应一个接收者,继续查询真实目标函数。 if let Some(bound) = payload.as_any().downcast_ref::() { + // 计数使用 checked_add,防极深包装使参数扣减绕回。 receivers = receivers .checked_add(1) .ok_or(VmError::ExecutionLimit("bound receivers"))?; current = bound.function; continue; } + // 源码区间由总参数数减默认值数;原生优先完整签名,否则兼容独立 arity。 let arity = if let Some(function) = payload .as_any() .downcast_ref::() { + // 源码代码布局已经校验,函数 defaults 数量也经构造校验。 let maximum = self .payload::(function.code(), "code")? .code() @@ -626,7 +653,9 @@ impl ObjectStore { }; return arity .map(|arity| { + // 先校验原始区间,再调整已绑定接收者造成的可见数量。 let arity = arity.validate()?; + // 开放上界保持 usize::MAX,有限上界 checked_sub 防绑定超出参数容量。 let maximum = if arity.maximum == usize::MAX { usize::MAX } else { @@ -647,9 +676,12 @@ impl ObjectStore { } /// Returns one owned root, including for a newly bound inherited method. + /// eval LoadAttr/宿主获取可用属性;对象值 retain 一根,方法则分配拥有接收者和函数的绑定对象。 pub fn bind_attr(&mut self, receiver: ObjectRef, name: &str) -> Result { + // 借用查找与拥有结果分开:返回到执行栈的对象必须先取得根。 match self.lookup_attr(receiver, name)? { AttributeLookup::Value(value) => { + // 标量由 Rust 值直接持有,仅对象属性结果需要 retain。 if let Value::Object(object) = value { self.retain(object)?; } @@ -661,43 +693,54 @@ impl ObjectStore { } } + /// Store get_attr/bind_attr 与效果分析共用借用查找,不分配 BoundMethod 或创建结果根。 pub(crate) fn lookup_attr( &self, receiver: ObjectRef, name: &str, ) -> Result { + // 保留最初 receiver 身份,用于名义元数据、能力遮蔽检查与方法绑定。 let object = self.object(receiver)?; + // 已附着类型优先作为保留属性暴露,返回借用类型句柄。 if name == "type" && let Some(type_object) = self.type_of(receiver)? { return Ok(AttributeLookup::Value(Value::Object(type_object))); } + // 能力名称元数据优先于普通字段,但仍受方法遮蔽保护。 if name == "name" && let Some(capability) = object.payload().as_any().downcast_ref::() { self.check_typed_method_write(receiver, name)?; return Ok(AttributeLookup::Value(Value::Text(capability.name.clone()))); } + // 类型对象先处理自身 name/base 元数据和类方法表,不绑定为实例方法。 if let Some(definition) = object.payload().as_any().downcast_ref::() { + // 根类型 base 为 Nil,与没有这个元数据属性不同。 let metadata = match name { "name" => Some(Value::Text(definition.name.clone())), "base" => Some(definition.base.map(Value::Object).unwrap_or(Value::Nil)), _ => None, }; + // 元数据返回前核对类型化能力方法不能被同名属性遮蔽。 if let Some(value) = metadata { self.check_typed_method_write(receiver, name)?; return Ok(AttributeLookup::Value(value)); } + // 直接从类型对象取方法返回函数值,不绑定该类型为 self。 if let Some(function) = self.lookup_method(receiver, name)? { self.check_typed_method_write(receiver, name)?; return Ok(AttributeLookup::Value(Value::Object(function))); } } + // 普通字段沿 attribute_target 找最终存储,成功路径必非空。 let storage = *self .attribute_path(receiver)? .last() .expect("nonempty attribute path"); + // 存储缺字段/不允许属性时还可尝试实例类型方法;其他错误直接传播。 match self.heap.get_attr(storage, name) { + // 字段命中仍检查能力方法遮蔽,然后返回借用值。 Ok(value) => { self.check_typed_method_write(receiver, name)?; return Ok(AttributeLookup::Value(value)); @@ -705,7 +748,9 @@ impl ObjectStore { Err(VmError::AttributeNotFound(_) | VmError::UnsupportedOperation("attributes")) => {} Err(error) => return Err(error), } + // 根据接收者有效类型查实例方法,绑定的是原始 receiver 身份。 if let Some(type_object) = self.type_of(receiver)? { + // 实例方法返回函数/接收者对,由 bind_attr 决定是否分配绑定对象。 if let Some(function) = self.lookup_method(type_object, name)? { return Ok(AttributeLookup::Method { function, receiver }); } @@ -717,6 +762,7 @@ impl ObjectStore { } } +/// 内部借用查找结果;Method 延迟绑定,使只读分析不必分配 BoundMethod。 pub(crate) enum AttributeLookup { Value(Value), Method { @@ -726,27 +772,36 @@ pub(crate) enum AttributeLookup { } #[derive(Debug)] +/// 持有函数和原接收者的托管包装,由 bind_attr 分配一份外部根。 struct BoundMethod { + // 原始接收者强边,不一定是最终属性存储对象。 receiver: ObjectRef, + // 底层函数强边,委托调用时由 NativeContext 取得输出根。 function: ObjectRef, } impl ObjectPayload for BoundMethod { + /// 绑定方法按函数分类,可在 Store 分配时附着 Function 类型。 fn is_function(&self) -> bool { true } + /// 绑定方法/能力定义不实现原地赋值,允许只读局部重绑定引用。 fn reference_assignment_only(&self) -> bool { true } + /// Store 的载荷下转型接口,不是语言名义类型判断。 fn as_any(&self) -> &dyn std::any::Any { self } + /// 错误/诊断载荷类别。 fn kind_name(&self) -> &'static str { "bound-method" } + /// Heap 分配/更新载荷时枚举拥有边,重复边仍逐条报告。 fn trace(&self, visit: &mut dyn FnMut(ObjectRef)) { visit(self.receiver); visit(self.function); } + /// VM 取得绑定方法分派器,调用时由上下文保护其载荷边。 fn native_callable(&self) -> Option> { Some(Arc::new(CallBoundMethod)) } @@ -755,14 +810,17 @@ impl ObjectPayload for BoundMethod { #[derive(Debug)] struct CallBoundMethod; impl NativeCallable for CallBoundMethod { + /// VM 分派绑定方法,把接收者插在显式参数前并委托底层函数,不递归运行执行器。 fn invoke( &self, cx: &mut NativeContext<'_>, arguments: &[Value], ) -> Result { + // 绑定载荷中的强边由上下文保护,回调只借用其元数据。 let bound = cx .store() .payload::(cx.callee(), "bound method")?; + // 新参数向量先放 self 再放调用方参数,clone 本身不 retain。 let mut values = Vec::with_capacity(arguments.len() + 1); values.push(Value::Object(bound.receiver)); values.extend_from_slice(arguments); @@ -787,56 +845,73 @@ pub struct TypedMethodRequirement { pub signature: crate::CallSignature, } #[derive(Debug)] +/// 显式能力定义:最小数量要求与可选完整签名同属托管载荷,定义本身不可任意替换。 pub struct EndorTraitObject { name: String, requirements: Vec, signatures: BTreeMap, } impl EndorTraitObject { + /// 宿主/诊断借用能力名称,能力相等仍按身份。 pub fn name(&self) -> &str { &self.name } + /// 能力校验借用最小位置参数要求列表,不含绑定 self。 pub fn requirements(&self) -> &[MethodRequirement] { &self.requirements } + /// 契约校验借用指定方法完整签名,含显式 self,未声明返回 None。 pub fn signature(&self, name: &str) -> Option<&crate::CallSignature> { self.signatures.get(name) } } impl ObjectPayload for EndorTraitObject { + /// Heap 分配/更新载荷时枚举拥有边,重复边仍逐条报告。 fn trace(&self, visit: &mut dyn FnMut(ObjectRef)) { + // 能力完整签名的全部类型定义参与 trace,不只看当前调用到的分支。 for signature in self.signatures.values() { + // 每个引用都是拥有边,不能按身份去重。 for reference in signature.references() { visit(reference); } } } + /// 绑定方法/能力定义不实现原地赋值,允许只读局部重绑定引用。 fn reference_assignment_only(&self) -> bool { true } + /// Store 的载荷下转型接口,不是语言名义类型判断。 fn as_any(&self) -> &dyn std::any::Any { self } + /// 错误/诊断载荷类别。 fn kind_name(&self) -> &'static str { "trait" } + /// Store 显示能力名称,不执行方法或展开签名。 fn repr(&self, _: ObjectRef) -> Result { Ok(format!("", self.name)) } } impl ObjectStore { + /// VM/宿主创建只约束方法存在与参数数量的能力,返回一份外部根。 pub fn new_trait( &mut self, name: impl Into, requirements: Vec, ) -> Result { + // 持有能力名称,禁止空名称但不把名称作为名义身份。 let name = name.into(); + // 只约束列表内部去重,避免重复方法要求。 let mut names = std::collections::BTreeSet::new(); + // 能力名称必须非空。 if name.is_empty() { return Err(VmError::InvalidArgument("trait name must not be empty")); } + // 最小能力要求不含 self,usize::MAX 无法再加 self,提前拒绝。 for requirement in &requirements { + // 拒绝空/保留名、无法加接收者的数量与重复要求。 if requirement.name.is_empty() || requirement.name == "type" || requirement.parameters == usize::MAX @@ -854,20 +929,28 @@ impl ObjectStore { }) } + /// VM/宿主创建显式参数/返回/效果能力,要求含 self 的固定规范签名。 pub fn new_typed_trait( &mut self, name: impl Into, methods: Vec, ) -> Result { + // 持有能力名称,禁止空名称但不把名称作为名义身份。 let name = name.into(); + // 能力名称必须非空。 if name.is_empty() { return Err(VmError::InvalidArgument("trait name must not be empty")); } + // 完整方法签名按名保存,同时派生兼容的最小参数要求。 let mut signatures = BTreeMap::new(); + // 每份规范完整签名生成一个不含 self 的参数数量要求。 let mut requirements = Vec::new(); + // 全部元数据验证完后才分配能力,失败不产生半成品。 for method in methods { method.signature.validate(self)?; + // 类型化能力使用固定且至少含一接收者的规范签名,不接受可选接收者。 let arity = method.signature.arity; + // 数量必须 required==maximum 且有限,方法名也不能重复或占用 type。 if method.name.is_empty() || method.name == "type" || arity.required == 0