Represent nullable and union native contracts with traced alternatives
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
| 文件 | 职责 |
|
||||
| --- | --- |
|
||||
| [lib.rs](lib.rs) | 包边界、对象类型/ObjectStore 公开导出(含Trait/MethodRequirement/SourceSignature/AnnotationType/CallArity/CallSignature/CallEffect/ReadAccess)与独立存储 rustdoc 示例 |
|
||||
| [lib.rs](lib.rs) | 包边界、对象类型/ObjectStore 公开导出(含Trait/MethodRequirement/SourceSignature/AnnotationType/CallArity/CallSignature/CallType/CallEffect/ReadAccess)与独立存储 rustdoc 示例 |
|
||||
| [object.rs](object.rs) | Value、CompareOp、ObjectPayload(含显式函数标记)、ObjectHeader、EndorObject、Record、可发布数量元数据的 NativeFunction |
|
||||
| [types.rs](types.rs) | 托管名义类型、显式 Object/Type 引导、继承查询、受管方法表/接收者绑定、类字段、显式Trait定义/声明/方法参数约束、原生构造委托、统一源码/原生/绑定方法参数区间查询与能力验证、声明环境托管边、字段构造/写入检查与标记为校验读取的注解解析/匹配 |
|
||||
| [native.rs](native.rs) | NativeContext、CallArity/CallSignature 类型与效果元数据、调用前检查、签名类型强边、上下文原生函数、作用域语言函数工厂、显式能力声明入口、函数标记、根与非递归委托调用 |
|
||||
|
||||
@@ -36,8 +36,8 @@ pub use error::VmError;
|
||||
pub use heap::{ObjectRef, ReadAccess, WeakObjectRef};
|
||||
pub use instruction::{DecodedInstruction, Instruction, Opcode};
|
||||
pub use native::{
|
||||
CallArity, CallEffect, CallSignature, ContextNativeFunction, NativeCallable, NativeContext,
|
||||
NativeResult,
|
||||
CallArity, CallEffect, CallSignature, CallType, ContextNativeFunction, NativeCallable,
|
||||
NativeContext, NativeResult,
|
||||
};
|
||||
pub use number::{
|
||||
EndorDecimal, EndorInteger, EndorNumber, EndorNumberObject, EndorRational, EndorReal,
|
||||
|
||||
@@ -59,14 +59,91 @@ pub enum CallEffect {
|
||||
External,
|
||||
}
|
||||
|
||||
/// Resolved native value contract. A union is flat, nonempty and preserves
|
||||
/// all definition edges even when an earlier alternative already matches.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CallType {
|
||||
Single(crate::AnnotationType),
|
||||
Union(Vec<crate::AnnotationType>),
|
||||
}
|
||||
impl From<crate::AnnotationType> for CallType {
|
||||
fn from(value: crate::AnnotationType) -> Self {
|
||||
Self::Single(value)
|
||||
}
|
||||
}
|
||||
impl CallType {
|
||||
pub fn nullable(value: crate::AnnotationType) -> Self {
|
||||
Self::Union(vec![value, crate::AnnotationType::Unit])
|
||||
}
|
||||
fn alternatives(&self) -> &[crate::AnnotationType] {
|
||||
match self {
|
||||
Self::Single(value) => std::slice::from_ref(value),
|
||||
Self::Union(values) => values,
|
||||
}
|
||||
}
|
||||
pub fn references(&self) -> impl Iterator<Item = ObjectRef> + '_ {
|
||||
self.alternatives()
|
||||
.iter()
|
||||
.copied()
|
||||
.filter_map(crate::AnnotationType::reference)
|
||||
}
|
||||
pub fn is_any(&self) -> bool {
|
||||
self.alternatives()
|
||||
.iter()
|
||||
.any(|value| matches!(value, crate::AnnotationType::Any))
|
||||
}
|
||||
pub fn validate(&self, store: &ObjectStore) -> Result<(), VmError> {
|
||||
if self.alternatives().is_empty() {
|
||||
return Err(VmError::InvalidArgument("empty native union type"));
|
||||
}
|
||||
for value in self.alternatives() {
|
||||
match *value {
|
||||
crate::AnnotationType::Nominal(reference) => {
|
||||
store.payload::<crate::EndorTypeObject>(reference, "Type")?;
|
||||
}
|
||||
crate::AnnotationType::Capability(reference) => {
|
||||
store.payload::<crate::EndorTraitObject>(reference, "Trait")?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn check(
|
||||
&self,
|
||||
store: &ObjectStore,
|
||||
name: &str,
|
||||
position: String,
|
||||
value: &Value,
|
||||
) -> Result<(), VmError> {
|
||||
self.validate(store)?;
|
||||
for expected in self.alternatives() {
|
||||
if store.matches_annotation(value, *expected)? {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
let names = self
|
||||
.alternatives()
|
||||
.iter()
|
||||
.map(|expected| store.annotation_type_name(*expected))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Err(VmError::TypeMismatch {
|
||||
function: name.into(),
|
||||
position,
|
||||
expected: names.join(" | "),
|
||||
actual: store.value_type_name(value)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Immutable native contract, including an explicit receiver where applicable.
|
||||
/// Missing fixed slots are covered by variadic; optionality comes from arity.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CallSignature {
|
||||
pub arity: CallArity,
|
||||
pub parameters: Vec<crate::AnnotationType>,
|
||||
pub variadic: Option<crate::AnnotationType>,
|
||||
pub returns: crate::AnnotationType,
|
||||
pub parameters: Vec<CallType>,
|
||||
pub variadic: Option<CallType>,
|
||||
pub returns: CallType,
|
||||
pub effect: CallEffect,
|
||||
}
|
||||
impl CallSignature {
|
||||
@@ -77,19 +154,18 @@ impl CallSignature {
|
||||
) -> Self {
|
||||
Self {
|
||||
arity: CallArity::exact(parameters.len()),
|
||||
parameters,
|
||||
parameters: parameters.into_iter().map(CallType::from).collect(),
|
||||
variadic: None,
|
||||
returns,
|
||||
returns: returns.into(),
|
||||
effect,
|
||||
}
|
||||
}
|
||||
pub fn references(&self) -> impl Iterator<Item = ObjectRef> + '_ {
|
||||
self.parameters
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(self.variadic)
|
||||
.chain([self.returns])
|
||||
.filter_map(crate::AnnotationType::reference)
|
||||
.chain(self.variadic.as_ref())
|
||||
.chain([&self.returns])
|
||||
.flat_map(CallType::references)
|
||||
}
|
||||
pub fn validate(&self, store: &ObjectStore) -> Result<(), VmError> {
|
||||
self.arity.validate()?;
|
||||
@@ -101,19 +177,10 @@ impl CallSignature {
|
||||
for expected in self
|
||||
.parameters
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(self.variadic)
|
||||
.chain([self.returns])
|
||||
.chain(self.variadic.as_ref())
|
||||
.chain([&self.returns])
|
||||
{
|
||||
match expected {
|
||||
crate::AnnotationType::Nominal(reference) => {
|
||||
store.payload::<crate::EndorTypeObject>(reference, "Type")?;
|
||||
}
|
||||
crate::AnnotationType::Capability(reference) => {
|
||||
store.payload::<crate::EndorTraitObject>(reference, "Trait")?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
expected.validate(store)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -134,16 +201,9 @@ impl CallSignature {
|
||||
let expected = self
|
||||
.parameters
|
||||
.get(index)
|
||||
.copied()
|
||||
.or(self.variadic)
|
||||
.or(self.variadic.as_ref())
|
||||
.ok_or(VmError::InvalidArgument("incomplete native signature"))?;
|
||||
self.check_value(
|
||||
store,
|
||||
name,
|
||||
format!("parameter {}", index + 1),
|
||||
value,
|
||||
expected,
|
||||
)?;
|
||||
expected.check(store, name, format!("parameter {}", index + 1), value)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -153,25 +213,7 @@ impl CallSignature {
|
||||
name: &str,
|
||||
value: &Value,
|
||||
) -> Result<(), VmError> {
|
||||
self.check_value(store, name, "return".into(), value, self.returns)
|
||||
}
|
||||
fn check_value(
|
||||
&self,
|
||||
store: &ObjectStore,
|
||||
name: &str,
|
||||
position: String,
|
||||
value: &Value,
|
||||
expected: crate::AnnotationType,
|
||||
) -> Result<(), VmError> {
|
||||
if !store.matches_annotation(value, expected)? {
|
||||
return Err(VmError::TypeMismatch {
|
||||
function: name.into(),
|
||||
position,
|
||||
expected: store.annotation_type_name(expected)?,
|
||||
actual: store.value_type_name(value)?,
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
self.returns.check(store, name, "return".into(), value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user