docs(objects): explain type construction and definition lifecycle
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
//! 类型、能力与实例共享同一托管堆;Store 定义身份/继承规则,VM 负责构造调用的执行调度。
|
||||
//! contracts 校验方法替换与能力契约,effects 查询当前快照的调用效果。
|
||||
//! Nominal type identities in the same managed heap as their instances.
|
||||
#[path = "contracts.rs"]
|
||||
mod contracts;
|
||||
@@ -13,21 +15,28 @@ use crate::{
|
||||
// A host type_target may read its receiver's raw attributes. Validate the
|
||||
// outer lookup after resolution without recursively re-entering its guard.
|
||||
struct AttributeCheckGuard<'a> {
|
||||
/// 借用当前 Store 的属性检查递归表。
|
||||
store: &'a ObjectStore,
|
||||
/// 进入检查时的线程,用于隔离递归标记。
|
||||
thread: std::thread::ThreadId,
|
||||
/// 当前被检查对象,守卫不为其建立根。
|
||||
object: ObjectRef,
|
||||
}
|
||||
impl Drop for AttributeCheckGuard<'_> {
|
||||
/// 属性/类型重入检查的 RAII 清理,移除本线程当前对象,不清除其他活跃检查。
|
||||
fn drop(&mut self) {
|
||||
// 锁内定位递归检查表,守卫保证当前项此前已插入。
|
||||
let mut checks = self
|
||||
.store
|
||||
.active_attribute_checks
|
||||
.lock()
|
||||
.expect("attribute checker poisoned");
|
||||
// 仅删除本线程该对象的检查项,嵌套其他对象仍保持活跃。
|
||||
let active = checks
|
||||
.get_mut(&self.thread)
|
||||
.expect("active attribute check");
|
||||
active.remove(&self.object);
|
||||
// 线程内无剩余对象检查时移除空集合。
|
||||
if active.is_empty() {
|
||||
checks.remove(&self.thread);
|
||||
}
|
||||
@@ -43,11 +52,13 @@ pub enum TypeConstructor {
|
||||
/// Opt-in allocator inheritance. The requested nominal type is prepended
|
||||
/// to the constructor arguments; the allocator must create that real type.
|
||||
NativeTyped(ObjectRef),
|
||||
/// 禁止直接构造,源码派生沿用该策略后仍为抽象类型。
|
||||
Abstract,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ClassField {
|
||||
/// 字段存储名称,源码类创建时检查重复及保留名。
|
||||
pub name: String,
|
||||
/// Source annotation resolved at checked construction/field writes.
|
||||
pub type_name: String,
|
||||
@@ -58,60 +69,81 @@ pub struct ClassField {
|
||||
/// edges; no registry outside the heap keeps unused definitions alive.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EndorTypeObject {
|
||||
/// 诊断名称,名义身份仍由对象句柄决定。
|
||||
name: String,
|
||||
/// 固定基类强边,根 Object 为 None。
|
||||
base: Option<ObjectRef>,
|
||||
/// 实例创建策略,类型可调用路径按此分派。
|
||||
constructor: TypeConstructor,
|
||||
/// 方法名到函数的拥有边,更新走 define_method。
|
||||
methods: BTreeMap<String, ObjectRef>,
|
||||
/// 继承字段在前的完整构造布局。
|
||||
fields: Vec<ClassField>,
|
||||
// Declaring execution environment; a managed edge, never an external root.
|
||||
/// 自有字段注解的声明函数环境强边,不是外部根。
|
||||
field_scope: Option<ObjectRef>,
|
||||
/// 本层显式能力定义的强边,继承能力另沿基类查询。
|
||||
traits: Vec<ObjectRef>,
|
||||
}
|
||||
|
||||
impl EndorTypeObject {
|
||||
/// 宿主/诊断借用类型声明名称,不代表仅按名称判断类型相等。
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
/// 继承查找借用固定基类句柄,不产生外部根。
|
||||
pub fn base(&self) -> Option<ObjectRef> {
|
||||
self.base
|
||||
}
|
||||
/// 构造器和宿主借用完整字段序列,包含从父类复制的字段。
|
||||
pub fn fields(&self) -> &[ClassField] {
|
||||
&self.fields
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectPayload for EndorTypeObject {
|
||||
/// 类型定义不实现旧式原地赋值,允许只读局部重绑定引用。
|
||||
fn reference_assignment_only(&self) -> bool {
|
||||
true
|
||||
}
|
||||
/// Store 下转型为具体类型载荷的入口。
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
/// 错误与默认诊断使用载荷类别,名义类型关系另外判断。
|
||||
fn kind_name(&self) -> &'static str {
|
||||
"type"
|
||||
}
|
||||
/// Heap 分配/受控更新类型时登记基类、构造器、字段环境、能力及方法强边。
|
||||
fn trace(&self, visit: &mut dyn FnMut(ObjectRef)) {
|
||||
// 基类本身是一条拥有边,不依赖堆外注册表维持存活。
|
||||
if let Some(base) = self.base {
|
||||
visit(base);
|
||||
}
|
||||
// 两类原生构造都持有函数强边;Record/Abstract 不包含函数。
|
||||
if let TypeConstructor::Native(function) | TypeConstructor::NativeTyped(function) =
|
||||
self.constructor
|
||||
{
|
||||
visit(function);
|
||||
}
|
||||
// 字段声明环境必须由类型拥有,否则稍后注解解析可能失去环境。
|
||||
if let Some(scope) = self.field_scope {
|
||||
visit(scope);
|
||||
}
|
||||
// 逐项登记已声明能力,重复引用也按拥有次数计算。
|
||||
for capability in &self.traits {
|
||||
visit(*capability);
|
||||
}
|
||||
// 方法表每个槽拥有函数强边,不因同一函数多名注册而去重。
|
||||
for method in self.methods.values() {
|
||||
visit(*method);
|
||||
}
|
||||
}
|
||||
/// Store 显示类型名称,不展开方法表或执行构造器。
|
||||
fn repr(&self, _: ObjectRef) -> Result<String, VmError> {
|
||||
Ok(format!("<type {}>", self.name))
|
||||
}
|
||||
/// VM 把类型作为可调用对象时取得构造分派器;Type 可调用但不是函数分类。
|
||||
fn native_callable(&self) -> Option<Arc<dyn NativeCallable>> {
|
||||
Some(Arc::new(Construct))
|
||||
}
|
||||
@@ -120,19 +152,24 @@ impl ObjectPayload for EndorTypeObject {
|
||||
#[derive(Debug)]
|
||||
struct Construct;
|
||||
impl NativeCallable for Construct {
|
||||
/// NativeContext 构造入口:按类型的构造策略返回实例或委托 VM 调用分配器。
|
||||
fn invoke(
|
||||
&self,
|
||||
cx: &mut NativeContext<'_>,
|
||||
arguments: &[Value],
|
||||
) -> Result<NativeResult, VmError> {
|
||||
// 当前被调用对象就是类型,借用身份已由上下文保护。
|
||||
let type_object = cx.callee();
|
||||
// 只读借用构造策略;下方修改前先复制需要跨修改使用的元数据。
|
||||
let definition = cx.store().payload::<EndorTypeObject>(type_object, "Type")?;
|
||||
// 原生委托交回 VM 帧循环,不能递归调用执行器;抽象类型明确拒绝。
|
||||
match definition.constructor {
|
||||
TypeConstructor::Native(function) => Ok(NativeResult::Invoke {
|
||||
function,
|
||||
arguments: arguments.to_vec(),
|
||||
}),
|
||||
TypeConstructor::NativeTyped(function) => {
|
||||
// NativeTyped 把实际请求类型放在首位,让继承分配器创建正确的派生载荷。
|
||||
let mut values = Vec::with_capacity(arguments.len() + 1);
|
||||
values.push(Value::Object(type_object));
|
||||
values.extend_from_slice(arguments);
|
||||
@@ -145,6 +182,7 @@ impl NativeCallable for Construct {
|
||||
Err(VmError::UnsupportedOperation("abstract type construction"))
|
||||
}
|
||||
TypeConstructor::Record => {
|
||||
// Record 字段按位置一一对应,缺少或多余都在分配实例前拒绝。
|
||||
if arguments.len() != definition.fields.len() {
|
||||
return Err(VmError::ArgumentCount {
|
||||
name: definition.name.clone(),
|
||||
@@ -153,11 +191,14 @@ impl NativeCallable for Construct {
|
||||
provided: arguments.len(),
|
||||
});
|
||||
}
|
||||
// 释放类型载荷借用后仍需要字段名,因此复制布局,不复制托管对象。
|
||||
let fields = definition.fields.clone();
|
||||
cx.store()
|
||||
.check_class_field_arguments(type_object, arguments)?;
|
||||
// 分配临时根后再附着类型/写字段,失败时上下文统一清理半成品。
|
||||
let instance = cx.new_object()?;
|
||||
cx.attach_type(instance, type_object)?;
|
||||
// 按继承字段在前的布局依次写入,克隆 Value 不自动 retain,由属性拥有边承担持有。
|
||||
for (field, value) in fields.iter().zip(arguments) {
|
||||
cx.set_attr(instance, &field.name, value.clone())?;
|
||||
}
|
||||
@@ -170,14 +211,18 @@ impl NativeCallable for Construct {
|
||||
/// Each field owns one external root; the caller must release both.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct RootTypes {
|
||||
/// Object 根类型的一份外部拥有根,调用方须 release。
|
||||
pub object: ObjectRef,
|
||||
/// Type 元类型的一份外部拥有根,调用方须 release。
|
||||
pub type_type: ObjectRef,
|
||||
}
|
||||
|
||||
impl ObjectStore {
|
||||
/// Explicit bootstrap preserves the empty-store contract. Inheritance:
|
||||
/// Type -> Object; instance relations: Object : Type and Type : Type.
|
||||
/// 宿主/VM 显式创建 Object/Type;不改变 Store::new 保持空堆的约定。
|
||||
pub fn bootstrap_types(&mut self) -> Result<RootTypes, VmError> {
|
||||
// 先创建无元类型的 Object 定义,随后建立自举关系。
|
||||
let object = self.allocate(EndorTypeObject {
|
||||
name: "Object".into(),
|
||||
base: None,
|
||||
@@ -187,8 +232,11 @@ impl ObjectStore {
|
||||
field_scope: None,
|
||||
traits: Vec::new(),
|
||||
})?;
|
||||
// 记录第二次分配是否成功,便于后续任何错误清理已建对象。
|
||||
let mut allocated_type = None;
|
||||
// 闭包归拢 Type 分配与关系附着错误,外层统一释放自举临时根。
|
||||
let result = (|| {
|
||||
// Type 以 Object 为基类,随后自己以 Type 为类型,形成合法类型图环。
|
||||
let type_type = self.allocate(EndorTypeObject {
|
||||
name: "Type".into(),
|
||||
base: Some(object),
|
||||
@@ -203,7 +251,9 @@ impl ObjectStore {
|
||||
self.attach_type(type_type, type_type)?;
|
||||
Ok(RootTypes { object, type_type })
|
||||
})();
|
||||
// 自举失败归还已有根并收集可能形成的环,避免半初始化定义泄漏。
|
||||
if result.is_err() {
|
||||
// 只有成功分配 Type 后才需要归还其根。
|
||||
if let Some(type_type) = allocated_type {
|
||||
self.release(type_type)?;
|
||||
}
|
||||
@@ -214,23 +264,29 @@ impl ObjectStore {
|
||||
}
|
||||
|
||||
/// Base links are fixed at allocation, preventing inheritance cycles.
|
||||
/// 宿主创建派生类型,复制父字段布局并沿用元类型;返回一份外部拥有根。
|
||||
pub fn new_type(
|
||||
&mut self,
|
||||
name: impl Into<String>,
|
||||
base: ObjectRef,
|
||||
constructor: TypeConstructor,
|
||||
) -> Result<ObjectRef, VmError> {
|
||||
// 父字段复制成新类型布局;后续不能私自改变继承前缀。
|
||||
let fields = self
|
||||
.payload::<EndorTypeObject>(base, "Type")?
|
||||
.fields
|
||||
.clone();
|
||||
// 新类型继承基类的有效元类型,缺失元类型时拒绝构造。
|
||||
let metatype = self
|
||||
.type_of(base)?
|
||||
.ok_or(VmError::InvalidArgument("base type has no metatype"))?;
|
||||
// 持有名称用于新载荷与诊断,后续校验借用该字符串。
|
||||
let name = name.into();
|
||||
// 类型名称不允许空串,但身份判断仍使用句柄而非文本。
|
||||
if name.is_empty() {
|
||||
return Err(VmError::InvalidArgument("type name must not be empty"));
|
||||
}
|
||||
// 分配时基类/构造器/方法环境等由 trace 登记边,返回一份外部根。
|
||||
let definition = self.allocate(EndorTypeObject {
|
||||
name,
|
||||
base: Some(base),
|
||||
@@ -240,6 +296,7 @@ impl ObjectStore {
|
||||
field_scope: None,
|
||||
traits: Vec::new(),
|
||||
})?;
|
||||
// 元类型附着失败则归还新定义根,不交付无元类型半成品。
|
||||
if let Err(error) = self.attach_type(definition, metatype) {
|
||||
self.release(definition)?;
|
||||
return Err(error);
|
||||
@@ -247,12 +304,14 @@ impl ObjectStore {
|
||||
Ok(definition)
|
||||
}
|
||||
|
||||
/// 宿主/构造器先检查类型和能力存储约束,再交 Heap 建立不可替换的类型强边。
|
||||
pub fn attach_type(
|
||||
&mut self,
|
||||
object: ObjectRef,
|
||||
type_object: ObjectRef,
|
||||
) -> Result<(), VmError> {
|
||||
self.payload::<EndorTypeObject>(type_object, "Type")?;
|
||||
// 逐项登记已声明能力,重复引用也按拥有次数计算。
|
||||
for capability in self.inherited_traits(type_object)? {
|
||||
self.check_capability_storage(object, capability)?;
|
||||
}
|
||||
@@ -260,16 +319,23 @@ impl ObjectStore {
|
||||
}
|
||||
|
||||
/// Borrowed type reference; legacy/untyped host objects return None.
|
||||
/// VM/契约查询有效类型,沿 type_target 转发,最终返回头部的借用类型或 None。
|
||||
pub fn type_of(&self, object: ObjectRef) -> Result<Option<ObjectRef>, VmError> {
|
||||
// 从门面对象出发追踪实际类型目标,不直接忽略 type_target 协议。
|
||||
let mut current = object;
|
||||
// 保存已访问身份,防宿主转发环导致无限循环。
|
||||
let mut visited = std::collections::BTreeSet::new();
|
||||
// 逐跳验证存活句柄和载荷,直到无类型转发目标。
|
||||
loop {
|
||||
// 同一身份再出现说明转发环,返回明确协议错误。
|
||||
if !visited.insert(current) {
|
||||
return Err(VmError::InvalidArgument(
|
||||
"cyclic shared-reference type target",
|
||||
));
|
||||
}
|
||||
// 分配临时根后再附着类型/写字段,失败时上下文统一清理半成品。
|
||||
let instance = self.object(current)?;
|
||||
// 有转发目标则继续,无目标时读取当前对象头部名义类型。
|
||||
match instance.payload().type_target(self)? {
|
||||
Some(target) => current = target,
|
||||
None => return Ok(instance.header().type_object()),
|
||||
@@ -277,11 +343,16 @@ impl ObjectStore {
|
||||
}
|
||||
}
|
||||
|
||||
/// 注解/替换检查沿单继承链比较名义身份,包含类型自身。
|
||||
pub fn is_subtype(&self, candidate: ObjectRef, expected: ObjectRef) -> Result<bool, VmError> {
|
||||
self.payload::<EndorTypeObject>(expected, "Type")?;
|
||||
// 从候选类型本身开始,因此自反子类型关系成立。
|
||||
let mut current = Some(candidate);
|
||||
// 基类在创建时固定且指向已有类型,正常类型图不会出现继承环。
|
||||
while let Some(type_object) = current {
|
||||
// 借用类型载荷验证身份和种类,再读字段、基类或方法表。
|
||||
let definition = self.payload::<EndorTypeObject>(type_object, "Type")?;
|
||||
// 比较完整名义身份,不接受仅同名的另一个类型。
|
||||
if type_object == expected {
|
||||
return Ok(true);
|
||||
}
|
||||
@@ -290,8 +361,10 @@ impl ObjectStore {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// VM/宿主判断实例有效类型是否为 expected 的子类型,无类型旧对象返回 false。
|
||||
pub fn is_instance(&self, object: ObjectRef, expected: ObjectRef) -> Result<bool, VmError> {
|
||||
self.payload::<EndorTypeObject>(expected, "Type")?;
|
||||
// 有效类型可来自转发对象;无类型不是 InvalidHandle,而是正常 false。
|
||||
match self.type_of(object)? {
|
||||
Some(type_object) => self.is_subtype(type_object, expected),
|
||||
None => Ok(false),
|
||||
@@ -299,6 +372,7 @@ impl ObjectStore {
|
||||
}
|
||||
|
||||
/// Updating the managed method table preserves nominal identity and base.
|
||||
/// 宿主/VM 受控更新方法表,身份/基类不变,先验证覆盖及能力约束再替换载荷。
|
||||
pub fn define_method(
|
||||
&mut self,
|
||||
type_object: ObjectRef,
|
||||
@@ -306,20 +380,26 @@ impl ObjectStore {
|
||||
function: ObjectRef,
|
||||
) -> Result<(), VmError> {
|
||||
self.object(function)?;
|
||||
// 持有名称用于新载荷与诊断,后续校验借用该字符串。
|
||||
let name = name.into();
|
||||
// 类型名称不允许空串,但身份判断仍使用句柄而非文本。
|
||||
if name.is_empty() || name == "type" {
|
||||
return Err(VmError::InvalidArgument("reserved or empty method name"));
|
||||
}
|
||||
// 借用类型载荷验证身份和种类,再读字段、基类或方法表。
|
||||
let definition = self.payload::<EndorTypeObject>(type_object, "Type")?;
|
||||
// 实例字段与类型方法不能同名,避免构造/查找产生歧义。
|
||||
if definition.fields.iter().any(|field| field.name == name) {
|
||||
return Err(VmError::InvalidArgument(
|
||||
"method conflicts with class field",
|
||||
));
|
||||
}
|
||||
// 先准备独立方法表副本,契约失败时真实载荷保持原状。
|
||||
let mut methods = definition.methods.clone();
|
||||
self.validate_override_update(type_object, &name, function)?;
|
||||
self.validate_method_update(type_object, &name, function)?;
|
||||
methods.insert(name, function);
|
||||
// 保留名称、基类、构造、字段和能力,只替换方法表;Heap 再更新强边和版本。
|
||||
let updated = EndorTypeObject {
|
||||
name: definition.name.clone(),
|
||||
base: definition.base,
|
||||
@@ -335,6 +415,7 @@ impl ObjectStore {
|
||||
/// Atomically build a source class, including inherited constructor fields.
|
||||
/// Only explicitly inheritable native allocators are reused. Abstract
|
||||
/// subclasses remain abstract; no Record can forge a native payload.
|
||||
/// eval/宿主创建源码类的无字段声明环境入口,转交统一构造路径。
|
||||
pub fn new_class(
|
||||
&mut self,
|
||||
name: impl Into<String>,
|
||||
@@ -347,6 +428,7 @@ impl ObjectStore {
|
||||
|
||||
/// Source class builder with a traced function environment for field names.
|
||||
/// None supports primitive annotations and the declaring class itself.
|
||||
/// eval 创建源码类,组合继承字段、当前方法与声明环境,完成契约检查后才交付根。
|
||||
pub fn new_class_with_scope(
|
||||
&mut self,
|
||||
name: impl Into<String>,
|
||||
@@ -355,19 +437,27 @@ impl ObjectStore {
|
||||
methods: BTreeMap<String, ObjectRef>,
|
||||
scope: Option<ObjectRef>,
|
||||
) -> Result<ObjectRef, VmError> {
|
||||
// 字段声明环境必须由类型拥有,否则稍后注解解析可能失去环境。
|
||||
if let Some(scope) = scope {
|
||||
self.payload::<crate::EndorFunctionObject>(scope, "function")?;
|
||||
}
|
||||
// 没有自有字段时无需持有当前声明环境,继承字段仍通过其声明层解析。
|
||||
let field_scope = if own_fields.is_empty() { None } else { scope };
|
||||
// 借用类型载荷验证身份和种类,再读字段、基类或方法表。
|
||||
let definition = self.payload::<EndorTypeObject>(base, "Type")?;
|
||||
// Native 未显式允许源码继承分配,不能用普通 Record 伪造原生载荷。
|
||||
if matches!(definition.constructor, TypeConstructor::Native(_)) {
|
||||
return Err(VmError::UnsupportedOperation(
|
||||
"native allocator does not opt into source subclass construction",
|
||||
));
|
||||
}
|
||||
// 源码派生沿用允许继承的策略,Abstract 仍为 Abstract,NativeTyped 得到请求类型。
|
||||
let constructor = definition.constructor;
|
||||
// 继承字段保持前缀,再按源码顺序附加新字段。
|
||||
let mut fields = definition.fields.clone();
|
||||
// 逐个检查重复、保留名及继承方法冲突,不允许覆盖已有字段布局。
|
||||
for field in own_fields {
|
||||
// 名称与注解都不能空,字段不能重复或遮蔽父方法。
|
||||
if field.name.is_empty()
|
||||
|| field.type_name.is_empty()
|
||||
|| field.name == "type"
|
||||
@@ -380,21 +470,27 @@ impl ObjectStore {
|
||||
}
|
||||
fields.push(field);
|
||||
}
|
||||
// 方法提交前验证函数句柄,拒绝与完整继承字段序列重名。
|
||||
for (name, method) in &methods {
|
||||
self.object(*method)?;
|
||||
// 类型名称不允许空串,但身份判断仍使用句柄而非文本。
|
||||
if name.is_empty() || name == "type" || fields.iter().any(|field| field.name == *name) {
|
||||
return Err(VmError::InvalidArgument(
|
||||
"method conflicts with class field",
|
||||
));
|
||||
}
|
||||
}
|
||||
// 新类型继承基类的有效元类型,缺失元类型时拒绝构造。
|
||||
let metatype = self
|
||||
.type_of(base)?
|
||||
.ok_or(VmError::InvalidArgument("base type has no metatype"))?;
|
||||
// 持有名称用于新载荷与诊断,后续校验借用该字符串。
|
||||
let name = name.into();
|
||||
// 类型名称不允许空串,但身份判断仍使用句柄而非文本。
|
||||
if name.is_empty() {
|
||||
return Err(VmError::InvalidArgument("type name must not be empty"));
|
||||
}
|
||||
// 一次构造完整类载荷,后面的验证失败只需释放这份新根。
|
||||
let class = self.allocate(EndorTypeObject {
|
||||
name,
|
||||
base: Some(base),
|
||||
@@ -404,6 +500,7 @@ impl ObjectStore {
|
||||
field_scope,
|
||||
traits: Vec::new(),
|
||||
})?;
|
||||
// 继承能力、普通覆盖和元类型附着按顺序完成,任一失败都不交付该类。
|
||||
if let Err(error) = self
|
||||
.validate_inherited_traits(class)
|
||||
.and_then(|()| self.validate_class_overrides(class))
|
||||
|
||||
Reference in New Issue
Block a user