Add explicit managed traits and inherited method arity contracts

This commit is contained in:
2026-10-21 21:34:46 +08:00
parent b7daabdaad
commit eb60212428
16 changed files with 454 additions and 16 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
| 文件 | 职责 |
| --- | --- |
| [lib.rs](lib.rs) | VM 类型导出、objects 类型兼容重导出、宿主调用与字节码 rustdoc 示例 |
| [vm.rs](vm.rs) | Vm 拥有 ObjectStore 与错误位置记录;对象操作和宿主 new_class 注册显式委托给 objects |
| [vm.rs](vm.rs) | Vm 拥有 ObjectStore 与错误位置记录;对象操作和宿主 new_class 和显式Trait注册/关系查询显式委托给 objects |
| [frame.rs](frame.rs) | EndorFrame、栈条目、执行位置元数据、ExecutionLimits |
| [eval.rs](eval.rs) | execute/call、只读调用与依赖结果、参数绑定、帧切换、取指分派、MakeFunction、结果根转移与失败清理 |
+2 -2
View File
@@ -443,7 +443,7 @@ impl Vm {
};
let fields = self
.dict_items(fields)?
.into_iter()
.iter()
.map(|(name, type_name)| match (name, type_name) {
(Value::Text(name), Value::Text(type_name)) => Ok(crate::ClassField {
name: name.clone(),
@@ -454,7 +454,7 @@ impl Vm {
.collect::<Result<Vec<_>, _>>()?;
let methods = self
.dict_items(methods)?
.into_iter()
.iter()
.map(|(name, function)| match (name, function) {
(Value::Text(name), Value::Object(function)) => Ok((name.clone(), *function)),
_ => Err(VmError::ObjectKindMismatch("class method")),
+3 -1
View File
@@ -54,5 +54,7 @@ pub use objects::{
NativeResult, ObjectChange, ObjectHeader, ObjectPayload, ObjectRef, Opcode, Record, Value,
VmError, WeakObjectRef,
};
pub use objects::{ClassField, EndorTypeObject, RootTypes, TypeConstructor};
pub use objects::{
ClassField, EndorTraitObject, EndorTypeObject, MethodRequirement, RootTypes, TypeConstructor,
};
pub use vm::Vm;
+25
View File
@@ -14,6 +14,31 @@ pub struct Vm {
}
impl Vm {
pub fn new_trait(
&mut self,
name: impl Into<String>,
requirements: Vec<crate::MethodRequirement>,
) -> Result<ObjectRef, VmError> {
self.objects.new_trait(name, requirements)
}
pub fn implement_trait(
&mut self,
definition: ObjectRef,
capability: ObjectRef,
) -> Result<(), VmError> {
self.objects.implement_trait(definition, capability)
}
pub fn implements_trait(
&self,
definition: ObjectRef,
capability: ObjectRef,
) -> Result<bool, VmError> {
self.objects.implements_trait(definition, capability)
}
pub fn supports(&self, object: ObjectRef, capability: ObjectRef) -> Result<bool, VmError> {
self.objects.supports(object, capability)
}
pub fn define_method(
&mut self,
type_object: ObjectRef,
+1 -1
View File
@@ -7,7 +7,7 @@
| [runtime.rs](runtime.rs) | 空堆启动、默认操作、引用/借用、属性原子性、稳定地址、长链/循环、原生回调、VM 销毁 |
| [builtins.rs](builtins.rs) | 无损 Number、Unicode 字符串、Dict 顺序与键、Cell、函数环境/共享代码、异常数据 |
| [execution.rs](execution.rs) | wordcode 与校验、控制流、参数/默认值、嵌套帧、字节码函数创建/默认值/环境捕获、闭包、返回值存活、失败清理、限额 |
| [types.rs](types.rs) | 名义身份、继承与实例关系、类型边保活/循环回收、只读类型元数据与外来句柄;仅远端执行 |
| [types.rs](types.rs) | 名义身份、继承与实例关系、类型边保活/循环回收、只读类型元数据与外来句柄、显式Trait身份/继承/参数约束及后代更新原子性;仅远端执行 |
| [native_context.rs](native_context.rs) | 原生作用域根、分配失败清理、委托、只读结果分配/写入拒绝/依赖与失败恢复、弱引用过期及有界变更;仅远端执行 |
核心对象现由 objects 定义,本目录保留既有 endor_core 导入与 Vm 方法的兼容性检查。独立对象存储检查见 [objects/tests](../../objects/tests/README.md)。堆内部伪造句柄与计数溢出检查在 objects 的 src/heap.rs,公开示例由 src/lib.rs rustdoc 提供。文件职责见 [src](../src/README.md),检查方式和结果边界见 [验证](../../../docs/operations/validation.md)。本地不执行测试;存在测试文件不代表某次提交已通过。返回 [core](../README.md)。
+135
View File
@@ -63,3 +63,138 @@ fn foreign_type_edges_fail_without_changing_the_target() {
);
assert_eq!(second.type_of(object).unwrap(), None);
}
fn contract_method(vm: &mut Vm, parameters: usize) -> endor_core::ObjectRef {
use endor_core::{CodeLayout, EndorCode, EndorCodeObject, Instruction, Opcode};
let names: Vec<_> = (0..parameters).map(|index| format!("arg{index}")).collect();
let code = EndorCode::from_instructions(
&[
Instruction::new(Opcode::LoadConst, 0),
Instruction::simple(Opcode::ReturnValue),
],
vec![Value::Nil],
CodeLayout {
parameters: names.clone(),
locals: names,
..CodeLayout::default()
},
)
.unwrap();
let code = vm.allocate(EndorCodeObject::new(code)).unwrap();
let globals = vm.new_dict().unwrap();
let function = vm
.new_function("contract method", code, globals, vec![], vec![])
.unwrap();
vm.release(code).unwrap();
vm.release(globals).unwrap();
function
}
#[test]
fn explicit_traits_inherit_validate_overrides_and_own_definition_edges() {
use endor_core::MethodRequirement;
let mut vm = Vm::new().unwrap();
let roots = vm.bootstrap_types().unwrap();
let base = vm
.new_type("Base", roots.object, TypeConstructor::Record)
.unwrap();
let valid = contract_method(&mut vm, 2);
let invalid = contract_method(&mut vm, 1);
vm.define_method(base, "render", valid).unwrap();
let capability = vm
.new_trait(
"Drawable",
vec![MethodRequirement {
name: "render".into(),
parameters: 1,
}],
)
.unwrap();
let same_name = vm.new_trait("Drawable", vec![]).unwrap();
assert!(!vm.implements_trait(base, capability).unwrap());
vm.implement_trait(base, capability).unwrap();
assert!(!vm.implements_trait(base, same_name).unwrap());
let child = vm
.new_class("Child", base, vec![], std::collections::BTreeMap::new())
.unwrap();
assert!(vm.implements_trait(child, capability).unwrap());
assert!(matches!(
vm.define_method(base, "render", invalid),
Err(VmError::TraitViolation { .. })
));
assert_eq!(
vm.object_store().lookup_method(base, "render").unwrap(),
Some(valid)
);
assert!(
vm.new_class("Bad", base, vec![], [("render".into(), invalid)].into())
.is_err()
);
let Value::Object(instance) = vm.call(child, &[]).unwrap() else {
panic!("instance required");
};
vm.release(capability).unwrap();
assert!(vm.supports(instance, capability).unwrap());
assert!(vm.replace_payload(capability, endor_core::Record).is_err());
for object in [
roots.object,
roots.type_type,
base,
child,
valid,
invalid,
same_name,
instance,
] {
vm.release(object).unwrap();
}
vm.collect_cycles();
assert_eq!(vm.object_count(), 0);
}
#[test]
fn late_trait_registration_and_ancestor_updates_validate_existing_descendants() {
use endor_core::MethodRequirement;
let mut vm = Vm::new().unwrap();
let roots = vm.bootstrap_types().unwrap();
let base = vm
.new_type("Base", roots.object, TypeConstructor::Record)
.unwrap();
let good = contract_method(&mut vm, 2);
let bad = contract_method(&mut vm, 1);
vm.define_method(base, "render", good).unwrap();
let child = vm
.new_class("Child", base, vec![], [("render".into(), bad)].into())
.unwrap();
let capability = vm
.new_trait(
"Drawable",
vec![MethodRequirement {
name: "render".into(),
parameters: 1,
}],
)
.unwrap();
assert!(vm.implement_trait(base, capability).is_err());
assert!(!vm.implements_trait(base, capability).unwrap());
vm.define_method(child, "render", good).unwrap();
let inheriting = vm
.new_class(
"Inheriting",
base,
vec![],
std::collections::BTreeMap::new(),
)
.unwrap();
vm.implement_trait(inheriting, capability).unwrap();
assert!(vm.define_method(base, "render", bad).is_err());
assert_eq!(
vm.object_store().lookup_method(base, "render").unwrap(),
Some(good)
);
let foreign = Vm::new().unwrap();
assert_eq!(
foreign.implements_trait(base, capability),
Err(VmError::ForeignHandle)
);
}
+5 -5
View File
@@ -4,19 +4,19 @@
| 文件 | 职责 |
| --- | --- |
| [lib.rs](lib.rs) | 包边界、对象类型/ObjectStore 公开导出与独立存储 rustdoc 示例 |
| [lib.rs](lib.rs) | 包边界、对象类型/ObjectStore 公开导出(含Trait/MethodRequirement)与独立存储 rustdoc 示例 |
| [object.rs](object.rs) | Value、CompareOp、ObjectPayload、ObjectHeader、EndorObject、Record、NativeFunction |
| [types.rs](types.rs) | 托管名义类型、显式 Object/Type 引导、继承查询、受管方法表/接收者绑定、类字段与原生构造委托 |
| [native.rs](native.rs) | NativeContext、上下文原生函数、作用域语言函数工厂、根与非递归委托调用 |
| [types.rs](types.rs) | 托管名义类型、显式 Object/Type 引导、继承查询、受管方法表/接收者绑定、类字段、显式Trait定义/声明/方法参数约束、原生构造委托 |
| [native.rs](native.rs) | NativeContext、上下文原生函数、作用域语言函数工厂、显式能力声明入口、根与非递归委托调用 |
| [changes.rs](changes.rs) | 合并变更批次、变更键与有界通知额度 |
| [number.rs](number.rs) | Integer/Decimal/Rational/BinaryFloat/Complex 的无损表示和装箱载荷 |
| [builtins.rs](builtins.rs) | String、Dict、Cell、Function、BaseException 载荷与 trace 边 |
| [heap.rs](heap.rs) | 私有 Heap、不可伪造 ObjectRef、稳定 Box、引用事务、迭代释放、循环回收、只读变更屏障/全调用及嵌套子调用读取跟踪及私有边界测试 |
| [heap.rs](heap.rs) | 私有 Heap、不可伪造 ObjectRef、稳定 Box、引用事务、迭代释放、循环回收、后代契约更新的私有借用枚举、只读变更屏障/全调用及嵌套子调用读取跟踪及私有边界测试 |
| [store.rs](store.rs) | ObjectStore、空堆创建、对象操作、retain/release 和回收入口 |
| [store_builtins.rs](store_builtins.rs) | 载荷校验、代码/函数工厂、Dict/Cell 操作及键语义 |
| [instruction.rs](instruction.rs) | Opcode、Instruction、wordcode 编解码、MakeFunction/比较参数与跳转读取接口 |
| [code.rs](code.rs) | CodeLayout、EndorCode/EndorCodeObject、共享不可变代码和操作数/控制流/栈验证 |
| [error.rs](error.rs) | 对象、代码与执行共用的 VmError,避免反向依赖 core |
| [error.rs](error.rs) | 对象、代码与执行共用的 VmError(含能力/方法定位的TraitViolation),避免反向依赖 core |
对象操作变更同步 [对象模型](../../../docs/runtime/objects.md),内置载荷同步 [基本对象](../../../docs/runtime/builtins.md)。新增操作码需要同时修改本包 instruction.rs/code.rs 和 core 的 eval.rs 分派,见 [字节码 VM](../../../docs/runtime/bytecode.md)。
+10
View File
@@ -13,6 +13,11 @@ pub enum VmError {
UnsupportedOperation(&'static str),
InvalidArgument(&'static str),
ObjectKindMismatch(&'static str),
TraitViolation {
capability: String,
method: String,
reason: &'static str,
},
EmptyCell,
InvalidBytecode {
offset: usize,
@@ -43,6 +48,11 @@ impl fmt::Display for VmError {
}
Self::InvalidArgument(message) => f.write_str(message),
Self::ObjectKindMismatch(expected) => write!(f, "expected {expected} object"),
Self::TraitViolation {
capability,
method,
reason,
} => write!(f, "trait {capability} method {method}: {reason}"),
Self::EmptyCell => f.write_str("cell is empty"),
Self::InvalidBytecode { offset, reason } => {
write!(f, "invalid bytecode at code unit {offset}: {reason}")
+10
View File
@@ -69,6 +69,16 @@ impl Heap {
})
}
pub(crate) fn live_references(&self) -> impl Iterator<Item = ObjectRef> + '_ {
self.slots.iter().enumerate().filter_map(|(index, slot)| {
slot.object.as_ref().map(|_| ObjectRef {
heap_id: self.id,
index,
generation: slot.generation,
})
})
}
pub(crate) fn begin_read_only(&mut self) -> usize {
let protected = self
.slots
+3 -1
View File
@@ -44,4 +44,6 @@ pub use object::{
ObjectHeader, ObjectPayload, Record, Value,
};
pub use store::ObjectStore;
pub use types::{ClassField, EndorTypeObject, RootTypes, TypeConstructor};
pub use types::{
ClassField, EndorTraitObject, EndorTypeObject, MethodRequirement, RootTypes, TypeConstructor,
};
+8
View File
@@ -44,6 +44,14 @@ impl<'a> NativeContext<'a> {
self.store.attach_type(object, type_object)
}
pub fn implement_trait(
&mut self,
definition: ObjectRef,
capability: ObjectRef,
) -> Result<(), VmError> {
self.store.implement_trait(definition, capability)
}
pub fn store(&self) -> &ObjectStore {
self.store
}
+10
View File
@@ -77,6 +77,16 @@ impl ObjectStore {
"replace immutable type definition",
));
}
if self
.object(reference)?
.payload()
.as_any()
.is::<crate::EndorTraitObject>()
{
return Err(VmError::UnsupportedOperation(
"replace immutable trait definition",
));
}
self.validate_builtin(&payload)?;
self.heap.replace_payload(reference, payload)
}
+225 -2
View File
@@ -28,13 +28,14 @@ pub struct ClassField {
/// Nominal definition with immutable identity/base and a managed method table.
/// Its base, constructor and metatype are traced
/// edges; no registry outside the heap keeps unused definitions alive.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct EndorTypeObject {
name: String,
base: Option<ObjectRef>,
constructor: TypeConstructor,
methods: BTreeMap<String, ObjectRef>,
fields: Vec<ClassField>,
traits: Vec<ObjectRef>,
}
impl EndorTypeObject {
@@ -68,6 +69,9 @@ impl ObjectPayload for EndorTypeObject {
{
visit(function);
}
for capability in &self.traits {
visit(*capability);
}
for method in self.methods.values() {
visit(*method);
}
@@ -145,6 +149,7 @@ impl ObjectStore {
constructor: TypeConstructor::Record,
methods: BTreeMap::new(),
fields: Vec::new(),
traits: Vec::new(),
})?;
let mut allocated_type = None;
let result = (|| {
@@ -154,6 +159,7 @@ impl ObjectStore {
constructor: TypeConstructor::Abstract,
methods: BTreeMap::new(),
fields: Vec::new(),
traits: Vec::new(),
})?;
allocated_type = Some(type_type);
self.attach_type(object, type_type)?;
@@ -194,6 +200,7 @@ impl ObjectStore {
constructor,
methods: BTreeMap::new(),
fields,
traits: Vec::new(),
})?;
if let Err(error) = self.attach_type(definition, metatype) {
self.release(definition)?;
@@ -269,6 +276,7 @@ impl ObjectStore {
));
}
let mut methods = definition.methods.clone();
self.validate_method_update(type_object, &name, function)?;
methods.insert(name, function);
let updated = EndorTypeObject {
name: definition.name.clone(),
@@ -276,6 +284,7 @@ impl ObjectStore {
constructor: definition.constructor,
methods,
fields: definition.fields.clone(),
traits: definition.traits.clone(),
};
self.heap.replace_payload(type_object, updated)
}
@@ -331,8 +340,12 @@ impl ObjectStore {
constructor,
methods,
fields,
traits: Vec::new(),
})?;
if let Err(error) = self.attach_type(class, metatype) {
if let Err(error) = self
.validate_inherited_traits(class)
.and_then(|()| self.attach_type(class, metatype))
{
self.release(class)?;
return Err(error);
}
@@ -417,6 +430,11 @@ impl ObjectStore {
{
return Ok(AttributeLookup::Value(Value::Object(type_object)));
}
if name == "name"
&& let Some(capability) = object.payload().as_any().downcast_ref::<EndorTraitObject>()
{
return Ok(AttributeLookup::Value(Value::Text(capability.name.clone())));
}
if let Some(definition) = object.payload().as_any().downcast_ref::<EndorTypeObject>() {
let metadata = match name {
"name" => Some(Value::Text(definition.name.clone())),
@@ -503,3 +521,208 @@ impl NativeCallable for CallBoundMethod {
})
}
}
/// Minimal explicit capability contract. Arity excludes the bound receiver.
/// Parameter/return types, default implementations and syntax are host concerns.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MethodRequirement {
pub name: String,
pub parameters: usize,
}
#[derive(Debug)]
pub struct EndorTraitObject {
name: String,
requirements: Vec<MethodRequirement>,
}
impl EndorTraitObject {
pub fn name(&self) -> &str {
&self.name
}
pub fn requirements(&self) -> &[MethodRequirement] {
&self.requirements
}
}
impl ObjectPayload for EndorTraitObject {
fn reference_assignment_only(&self) -> bool {
true
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn kind_name(&self) -> &'static str {
"trait"
}
fn repr(&self, _: ObjectRef) -> Result<String, VmError> {
Ok(format!("<trait {}>", self.name))
}
}
impl ObjectStore {
pub fn new_trait(
&mut self,
name: impl Into<String>,
requirements: Vec<MethodRequirement>,
) -> Result<ObjectRef, VmError> {
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"));
}
for requirement in &requirements {
if requirement.name.is_empty()
|| requirement.name == "type"
|| requirement.parameters == usize::MAX
|| !names.insert(&requirement.name)
{
return Err(VmError::InvalidArgument(
"invalid or duplicate trait requirement",
));
}
}
self.allocate(EndorTraitObject { name, requirements })
}
fn inherited_traits(&self, definition: ObjectRef) -> Result<Vec<ObjectRef>, VmError> {
let mut found = std::collections::BTreeSet::new();
let mut current = Some(definition);
while let Some(definition) = current {
let definition = self.payload::<EndorTypeObject>(definition, "Type")?;
found.extend(definition.traits.iter().copied());
current = definition.base;
}
Ok(found.into_iter().collect())
}
fn validate_requirement(
&self,
capability: ObjectRef,
requirement: &MethodRequirement,
function: Option<ObjectRef>,
) -> Result<(), VmError> {
let invalid = |reason| VmError::TraitViolation {
capability: self
.payload::<EndorTraitObject>(capability, "Trait")
.expect("validated trait")
.name
.clone(),
method: requirement.name.clone(),
reason,
};
let function = function.ok_or_else(|| invalid("required method is missing"))?;
if let Some(count) = self.positional_parameter_count(function)? {
if count != requirement.parameters + 1 {
return Err(invalid(
"positional parameter count does not match (including self)",
));
}
} else if self.object(function)?.payload().native_callable().is_none() {
return Err(invalid("required member is not callable"));
}
Ok(())
}
fn validate_trait(&self, definition: ObjectRef, capability: ObjectRef) -> Result<(), VmError> {
let contract = self.payload::<EndorTraitObject>(capability, "Trait")?;
for requirement in &contract.requirements {
self.validate_requirement(
capability,
requirement,
self.lookup_method(definition, &requirement.name)?,
)?;
}
Ok(())
}
fn validate_inherited_traits(&self, definition: ObjectRef) -> Result<(), VmError> {
for capability in self.inherited_traits(definition)? {
self.validate_trait(definition, capability)?;
}
Ok(())
}
// Enumerate borrowed heap handles only while validating a definition update;
// no global type registry or owning descendant index is introduced.
fn descendant_types(&self, base: ObjectRef) -> Result<Vec<ObjectRef>, VmError> {
self.payload::<EndorTypeObject>(base, "Type")?;
let mut found = vec![];
for reference in self.heap.live_references() {
if self
.object(reference)?
.payload()
.as_any()
.is::<EndorTypeObject>()
&& self.is_subtype(reference, base)?
{
found.push(reference);
}
}
Ok(found)
}
fn validate_method_update(
&self,
changed: ObjectRef,
name: &str,
function: ObjectRef,
) -> Result<(), VmError> {
for descendant in self.descendant_types(changed)? {
let mut current = Some(descendant);
let mut affected = false;
while let Some(definition) = current {
if definition == changed {
affected = true;
break;
}
let definition = self.payload::<EndorTypeObject>(definition, "Type")?;
if definition.methods.contains_key(name) {
break;
}
current = definition.base;
}
if !affected {
continue;
}
for capability in self.inherited_traits(descendant)? {
for requirement in &self
.payload::<EndorTraitObject>(capability, "Trait")?
.requirements
{
if requirement.name == name {
self.validate_requirement(capability, requirement, Some(function))?;
}
}
}
}
Ok(())
}
pub fn implement_trait(
&mut self,
definition: ObjectRef,
capability: ObjectRef,
) -> Result<(), VmError> {
self.payload::<EndorTraitObject>(capability, "Trait")?;
for descendant in self.descendant_types(definition)? {
self.validate_trait(descendant, capability)?;
}
let mut updated = self.payload::<EndorTypeObject>(definition, "Type")?.clone();
if !updated.traits.contains(&capability) {
updated.traits.push(capability);
self.heap.replace_payload(definition, updated)?;
}
Ok(())
}
pub fn implements_trait(
&self,
definition: ObjectRef,
capability: ObjectRef,
) -> Result<bool, VmError> {
self.payload::<EndorTraitObject>(capability, "Trait")?;
let declared = self.inherited_traits(definition)?.contains(&capability);
if declared {
self.validate_trait(definition, capability)?;
}
Ok(declared)
}
pub fn supports(&self, object: ObjectRef, capability: ObjectRef) -> Result<bool, VmError> {
self.payload::<EndorTraitObject>(capability, "Trait")?;
match self.type_of(object)? {
Some(definition) => self.implements_trait(definition, capability),
None => Ok(false),
}
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
| 解释执行、资源修订与引擎升级 | [执行与版本](architecture/execution-and-versions.md) | frontend/compiler/core |
| EndorObject、句柄、默认操作 | [对象模型](runtime/objects.md) | objects/src |
| 原生上下文、只读调用、子调用读取依赖、委托与变更通知 | [原生调用](runtime/native-calls.md) | objects/src/native.rs、changes.rs、core/src/eval.rs |
| 托管类型、宿主类注册、原生分配继承与字段存储 | [名义类型](runtime/types.md) | objects/src/types.rs |
| 托管类型、宿主类注册、原生分配继承、字段存储与显式能力约束 | [名义类型](runtime/types.md) | objects/src/types.rs |
| Number、String、Dict、Cell、Function | [基本对象](runtime/builtins.md) | objects/src |
| 源码读取与来源 | [Reader](runtime/reader.md) | frontend/src/reader.rs |
| 词法、语法、裸赋值和诊断 | [Frontend](runtime/frontend.md) | frontend/src/lexer.peg/grammar.peg |
+1 -1
View File
@@ -10,7 +10,7 @@ Aster 是可嵌入引擎,只保留 objects、core、frontend、compiler。Obje
## 已实现
- EndorObject、稳定 Box、代际句柄、显式强引用及手动循环回收;VM 从空堆启动,宿主可显式引导托管 Object/Type 和名义继承;普通源码 class、字段构造和继承方法分派已接入,显式 NativeTyped 原生分配继承已接入,trait 仍待完成,见[类型机制](../runtime/types.md)。
- EndorObject、稳定 Box、代际句柄、显式强引用及手动循环回收;VM 从空堆启动,宿主可显式引导托管 Object/Type 和名义继承;普通源码 class、字段构造和继承方法分派已接入,显式 NativeTyped 原生分配继承已接入,宿主显式Trait身份/继承/必需方法及参数约束已接入;正式trait语法和完整类型/效果仍待完成,见[类型机制](../runtime/types.md)。
- Function、NativeFunction、Dict、Cell、异常数据、UTF-8 String 和无损表示优先的 Number。
- 小型 wordcode、共享代码对象、操作数/控制流/栈校验、显式执行帧及 execute/call;MakeFunction 可在执行中创建带默认参数与共享闭包 Cell 的函数。对象返回值持有根,用后 release_value;借用读取不自动 retain。
- EndorReader 在 lexer 前提供字符串/流/文件/宿主 URI provider 输入,产出不可变 SourceUnit,保存来源与不透明修订标签;带来源的词法/语法错误保留行列,Lyra parse 支持文件和 stdin。没有平台 URI 后端或版本锁实现,见 [阅读器](../runtime/reader.md)。
+14 -1
View File
@@ -56,7 +56,7 @@ class DetailedCounter: Counter {
方法表本身是类型对象拥有的托管边。宿主 define_method 可显式替换条目,不改变类型身份、基类或已有绑定方法选中的函数。bind_attr 返回一份拥有式根;get_attr 返回借用值和未绑定方法,宿主不能把两者的调用/释放协议混用。positional_parameter_count 会扣除绑定的接收者,供宿主判断事件回调的剩余源码参数。
这是一份实现子集说明:构造器只按字段赋值,没有默认值、命名字段构造或隐式 init;字段/参数/返回注解保留名称,尚未实施类型检查。源码类可继承 Record 或 NativeTyped 分配器;未选择支持继承的旧 Native 分配器仍明确报错。继承会保留分配器和父类字段,不能伪造带原生名义身份的普通 Record。字段构造参数如何与原生参数组合由宿主分配器负责;Tessera 使用原生参数在前、继承及本类字段在后的协议。trait 和用户自定义测量/绘制协议仍待实现。正式语言文档的候选语法不因这一实现被自动确认为规范。
这是一份实现子集说明:构造器只按字段赋值,没有默认值、命名字段构造或隐式 init;字段/参数/返回注解保留名称,尚未实施类型检查。源码类可继承 Record 或 NativeTyped 分配器;未选择支持继承的旧 Native 分配器仍明确报错。继承会保留分配器和父类字段,不能伪造带原生名义身份的普通 Record。字段构造参数如何与原生参数组合由宿主分配器负责;Tessera 使用原生参数在前、继承及本类字段在后的协议。trait 的正式源码语法、参数/返回类型约束和效果系统仍待实现;宿主显式能力子集见下文。正式语言文档的候选语法不因这一实现被自动确认为规范。
## 可转移的字段存储
@@ -64,3 +64,16 @@ class DetailedCounter: Counter {
ObjectPayload 可选择实现 `attribute_target(store)`,把实例字段放在另一个受托管强边保活的对象上。`attribute_path` 验证完整路径,拒绝跨堆句柄及循环;get_attr/set_attr/del_attr 读取或修改最终存储对象。名义类型、方法选择及绑定接收者仍取原对象,字段存储不代替类型身份。默认返回 None,普通对象行为不变。
反应式宿主订阅路径中各中间对象的 Contents,以及最终对象的 Attribute(field);重定向字段存储时必须发布 Contents 变化。否则仅监听外壳字段会漏掉实际存储更新。Tessera 的 Block 把字段存在当前内容的托管 Record 中,共享替换后别名会跟随新存储,旧字段及其引用可正常回收。实现回归见 [attribute_storage.rs](../../crates/objects/tests/attribute_storage.rs);本地仅编译。
## 显式能力关系
宿主可调用new_trait(name, requirements)建立EndorTraitObject,每项MethodRequirement记录方法名和绑定接收者之后的固定位置参数数量。定义保持名义身份、不可替换载荷,name只读;同名能力不自动相等。new_trait返回拥有式根,是否附加某个宿主提供的Trait实例类型由宿主决定。
implement_trait(Type, Trait)明确建立能力关系并校验必需方法。只有同名成员不算实现。implements_trait(Type, Trait)检查声明和继承;supports(instance, Trait)先查实际类型;未分类对象返回false,非法句柄或非定义参数报错。一个类型可显式实现多个能力,派生类继承关系。声明由Type的受管强边持有,查询和临时后代扫描不保活定义。
源码函数必须具有要求数量加self的参数;原生可调用对象的签名由注册宿主保证,当前没有原生形参元数据。缺少方法、非可调用成员或参数数量错误以TraitViolation报告能力名、方法名和原因。本子集不验证注解、关联类型、返回类型、效果或可选形参的替换兼容性;没有默认实现和trait源码语法。
建立声明前检查已有后代;构造源码子类检查继承的所有能力。define_method更新前检查受影响后代的显式/继承契约,被后代自己的覆盖遮蔽的方法不受该祖先更新影响。失败保留原方法表和关系。内部扫描只枚举当前借用句柄,不引入全局强类型注册表。声明更新通过普通堆写屏障与trace进行,既有类型的只读作用域内变更会被拒绝。NativeContext也可使用同一implement_trait入口,仍受该屏障约束。
相关回归加入core/tests/types.rs,仅编译,不在本地执行。Tessera提供的Visual/EventTarget/Children/Presentable以及运行时返回值校验属于宿主,Aster不内置GUI类型。