Correctly halts

This commit is contained in:
2025-09-16 22:54:14 +02:00
parent ee45dbd28e
commit 7971a2b4eb
29 changed files with 381 additions and 195 deletions

View File

@@ -10,6 +10,7 @@ ordered-float = "5.0.0"
orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" }
futures = { version = "0.3.31", features = ["std"], default-features = false }
itertools = "0.14.0"
[dev-dependencies]
test_executors = "0.3.2"

View File

@@ -1,14 +1,28 @@
use std::fmt;
use std::num::NonZeroU64;
use itertools::Itertools;
use orchid_api_derive::{Coding, Hierarchy};
use orchid_api_traits::Request;
use crate::{
ExprTicket, Expression, ExtHostReq, FormattingUnit, HostExtNotif, HostExtReq, OrcResult, SysId,
TStrv,
ExprTicket, Expression, ExtHostReq, FormattingUnit, HostExtReq, OrcResult, SysId, TStrv,
};
pub type AtomData = Vec<u8>;
#[derive(Clone, Coding)]
pub struct AtomData(pub Vec<u8>);
impl fmt::Debug for AtomData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut byte_strings = self.0.iter().map(|b| format!("{b:02x}"));
if self.0.len() < 32 {
write!(f, "AtomData({})", byte_strings.join(" "))
} else {
let data_table =
byte_strings.chunks(32).into_iter().map(|mut chunk| chunk.join(" ")).join("\n");
write!(f, "AtomData(\n{}\n)", data_table)
}
}
}
/// Unique ID associated with atoms that have an identity
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Coding)]
@@ -16,7 +30,7 @@ pub struct AtomId(pub NonZeroU64);
/// An atom owned by an implied system. Usually used in responses from a system.
/// This has the same semantics as [Atom] except in that the owner is implied.
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding)]
#[derive(Clone, Debug, Coding)]
pub struct LocalAtom {
pub drop: Option<AtomId>,
pub data: AtomData,
@@ -27,7 +41,7 @@ impl LocalAtom {
/// An atom representation that can be serialized and sent around. Atoms
/// represent the smallest increment of work.
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding)]
#[derive(Clone, Debug, Coding)]
pub struct Atom {
/// Instance ID of the system that created the atom
pub owner: SysId,
@@ -49,7 +63,7 @@ pub struct Atom {
}
/// Attempt to apply an atom as a function to an expression
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(AtomReq, HostExtReq)]
pub struct CallRef(pub Atom, pub ExprTicket);
impl Request for CallRef {
@@ -59,14 +73,14 @@ impl Request for CallRef {
/// Attempt to apply an atom as a function, consuming the atom and enabling the
/// library to reuse its datastructures rather than duplicating them. This is an
/// optimization over [CallRef] followed by [AtomDrop].
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(AtomReq, HostExtReq)]
pub struct FinalCall(pub Atom, pub ExprTicket);
impl Request for FinalCall {
type Response = Expression;
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(AtomReq, HostExtReq)]
pub struct SerializeAtom(pub Atom);
impl Request for SerializeAtom {
@@ -81,14 +95,14 @@ impl Request for DeserAtom {
}
/// A request blindly routed to the system that provides an atom.
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(AtomReq, HostExtReq)]
pub struct Fwded(pub Atom, pub TStrv, pub Vec<u8>);
impl Request for Fwded {
type Response = Option<Vec<u8>>;
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(ExtHostReq)]
pub struct Fwd(pub Atom, pub TStrv, pub Vec<u8>);
impl Request for Fwd {
@@ -100,7 +114,7 @@ pub enum NextStep {
Continue(Expression),
Halt,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(AtomReq, HostExtReq)]
pub struct Command(pub Atom);
impl Request for Command {
@@ -111,17 +125,20 @@ impl Request for Command {
/// isn't referenced anywhere. This should have no effect if the atom's `drop`
/// flag is false.
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[extends(HostExtNotif)]
#[extends(HostExtReq)]
pub struct AtomDrop(pub SysId, pub AtomId);
impl Request for AtomDrop {
type Response = ();
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(AtomReq, HostExtReq)]
pub struct AtomPrint(pub Atom);
impl Request for AtomPrint {
type Response = FormattingUnit;
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(ExtHostReq)]
pub struct ExtAtomPrint(pub Atom);
impl Request for ExtAtomPrint {
@@ -129,7 +146,7 @@ impl Request for ExtAtomPrint {
}
/// Requests that apply to an existing atom instance
#[derive(Clone, Debug, Hash, PartialEq, Eq, Coding, Hierarchy)]
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(HostExtReq)]
#[extendable]
pub enum AtomReq {

View File

@@ -1,3 +1,4 @@
use std::fmt;
use std::num::NonZeroU64;
use orchid_api_derive::{Coding, Hierarchy};
@@ -10,8 +11,13 @@ use crate::{Atom, ExtHostNotif, ExtHostReq, Location, OrcError, SysId, TStrv};
/// [Acquire].
///
/// The ID is globally unique within its lifetime, but may be reused.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Coding)]
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Coding)]
pub struct ExprTicket(pub NonZeroU64);
impl fmt::Debug for ExprTicket {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ExprTicket({:x})", self.0.get())
}
}
/// Acquire a strong reference to an expression. This keeps it alive until a
/// corresponding [Release] is emitted. The number of times a system has
@@ -62,7 +68,7 @@ pub enum ExpressionKind {
Arg(u64),
/// Insert the specified host-expression in the template here. When the clause
/// is used in the const tree, this variant is forbidden.
Slot(ExprTicket),
Slot { tk: ExprTicket, by_value: bool },
/// The lhs must be fully processed before the rhs can be processed.
/// Equivalent to Haskell's function of the same name
Seq(Box<Expression>, Box<Expression>),

View File

@@ -68,10 +68,7 @@ pub enum ParsedMemberKind {
/// the macro engine could run here.
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(HostExtReq)]
pub struct FetchParsedConst {
pub sys: SysId,
pub id: ParsedConstId,
}
pub struct FetchParsedConst(pub SysId, pub ParsedConstId);
impl Request for FetchParsedConst {
type Response = Expression;
}

View File

@@ -120,14 +120,14 @@ pub enum HostExtReq {
ParseLine(parser::ParseLine),
FetchParsedConst(parser::FetchParsedConst),
GetMember(tree::GetMember),
SystemDrop(system::SystemDrop),
AtomDrop(atom::AtomDrop),
}
/// Notifications sent from the host to the extension
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extendable]
pub enum HostExtNotif {
SystemDrop(system::SystemDrop),
AtomDrop(atom::AtomDrop),
/// The host can assume that after this notif is sent, a correctly written
/// extension will eventually exit.
Exit,

View File

@@ -5,7 +5,7 @@ use orchid_api_derive::{Coding, Hierarchy};
use orchid_api_traits::Request;
use ordered_float::NotNan;
use crate::{CharFilter, ExtHostReq, HostExtNotif, HostExtReq, MemberKind, TStr, TStrv};
use crate::{CharFilter, ExtHostReq, HostExtReq, MemberKind, TStr, TStrv};
/// ID of a system type
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Coding)]
@@ -67,8 +67,11 @@ pub struct NewSystemResponse {
}
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(HostExtNotif)]
#[extends(HostExtReq)]
pub struct SystemDrop(pub SysId);
impl Request for SystemDrop {
type Response = ();
}
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extends(SysReq, HostExtReq)]