feat: suspend managed calls on generic awaitable operands
This commit is contained in:
@@ -394,7 +394,7 @@ fn verify(
|
||||
| Opcode::StoreDeref
|
||||
| Opcode::PopJumpIfFalse
|
||||
| Opcode::PopJumpIfTrue => (1, 1, 0),
|
||||
Opcode::ToBool | Opcode::UnaryNot | Opcode::LoadAttr => (1, 1, 1),
|
||||
Opcode::ToBool | Opcode::UnaryNot | Opcode::LoadAttr | Opcode::Await => (1, 1, 1),
|
||||
Opcode::CompareOp => (2, 2, 1),
|
||||
Opcode::StoreAttr => (2, 2, 0),
|
||||
Opcode::Copy => (argument, 0, 1),
|
||||
|
||||
@@ -123,6 +123,7 @@ impl ObjectStore {
|
||||
let argument = decoded.instruction.argument as usize;
|
||||
let mut stack = states[index].clone().expect("reachable effect state");
|
||||
match opcode {
|
||||
Opcode::Await => return Ok(None),
|
||||
Opcode::LoadConst => stack.push(Fact::value(code.constants()[argument].clone())),
|
||||
Opcode::LoadFast => stack.push(if argument == 0 {
|
||||
receiver.map(Fact::Object).unwrap_or(Fact::Unknown)
|
||||
|
||||
@@ -4,6 +4,8 @@ use std::fmt;
|
||||
/// retained for embedders; defining it here avoids a dependency on the VM.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum VmError {
|
||||
AwaitFailed(String),
|
||||
AwaitCancelled,
|
||||
ForeignHandle,
|
||||
InvalidHandle,
|
||||
IdentityExhausted,
|
||||
@@ -49,6 +51,8 @@ pub enum VmError {
|
||||
impl fmt::Display for VmError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::AwaitFailed(message) => write!(f, "await failed: {message}"),
|
||||
Self::AwaitCancelled => f.write_str("await cancelled"),
|
||||
Self::ForeignHandle => f.write_str("handle belongs to another VM"),
|
||||
Self::InvalidHandle => f.write_str("handle does not identify a live object"),
|
||||
Self::IdentityExhausted => f.write_str("process-local VM identities exhausted"),
|
||||
|
||||
@@ -35,6 +35,7 @@ pub enum Opcode {
|
||||
BuildMap = 27,
|
||||
MakeFunction = 28,
|
||||
BuildClass = 29,
|
||||
Await = 30,
|
||||
ExtendedArg = 255,
|
||||
}
|
||||
|
||||
@@ -71,6 +72,7 @@ impl Opcode {
|
||||
27 => Self::BuildMap,
|
||||
28 => Self::MakeFunction,
|
||||
29 => Self::BuildClass,
|
||||
30 => Self::Await,
|
||||
255 => Self::ExtendedArg,
|
||||
_ => return None,
|
||||
})
|
||||
@@ -85,6 +87,7 @@ impl Opcode {
|
||||
| Self::ReturnValue
|
||||
| Self::ToBool
|
||||
| Self::UnaryNot
|
||||
| Self::Await
|
||||
| Self::BuildClass
|
||||
)
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@ pub use number::{
|
||||
EndorDecimal, EndorInteger, EndorNumber, EndorNumberObject, EndorRational, EndorReal,
|
||||
};
|
||||
pub use object::{
|
||||
CompareOp, EndorNativeCall, EndorNativeFunctionObject, EndorObject, NativeCall, NativeFunction,
|
||||
ObjectHeader, ObjectPayload, Record, Value,
|
||||
AwaitPoll, CompareOp, EndorNativeCall, EndorNativeFunctionObject, EndorObject, NativeCall,
|
||||
NativeFunction, ObjectHeader, ObjectPayload, Record, Value,
|
||||
};
|
||||
pub use store::ObjectStore;
|
||||
pub use types::{
|
||||
|
||||
@@ -42,6 +42,14 @@ impl CompareOp {
|
||||
}
|
||||
}
|
||||
|
||||
/// Non-blocking awaitable observation. Ready object values are borrowed from
|
||||
/// the managed graph and must be retained by the consumer before dropping it.
|
||||
#[derive(Debug)]
|
||||
pub enum AwaitPoll {
|
||||
Pending,
|
||||
Ready(Value),
|
||||
}
|
||||
|
||||
/// Rust-side operation interface, not a language type or metaclass.
|
||||
///
|
||||
/// Implementations must report every payload-owned object reference in trace(),
|
||||
@@ -51,6 +59,10 @@ impl CompareOp {
|
||||
/// Rust Drop releases host resources when the payload is destroyed.
|
||||
/// Equal payloads must provide compatible hashes, or reject hashing explicitly.
|
||||
pub trait ObjectPayload: Any + fmt::Debug + Send + Sync {
|
||||
fn poll_await(&self) -> Result<AwaitPoll, VmError> {
|
||||
Err(VmError::UnsupportedOperation("await"))
|
||||
}
|
||||
|
||||
/// Explicit function category; callable Type objects are not functions.
|
||||
fn is_function(&self) -> bool {
|
||||
false
|
||||
|
||||
Reference in New Issue
Block a user