Changes in api and upwards
- Removed out-of-stack error reporting - Revised module system to match previous Orchid system - Errors are now in a Vec everywhere - Implemented atoms and lexer - Started implementation of line parser - Tree is now ephemeral to avoid copying Atoms held inside - Moved numbers into std and the shared parser into base - Started implementation of Commands
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
use std::any::{type_name, Any, TypeId};
|
||||
use std::io::{Read, Write};
|
||||
use std::ops::Deref;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use dyn_clone::{clone_box, DynClone};
|
||||
use never::Never;
|
||||
use orchid_api::atom::{Atom, Fwd, LocalAtom};
|
||||
use orchid_api::expr::ExprTicket;
|
||||
use orchid_api_traits::{Coding, Decode, Request};
|
||||
@@ -10,9 +12,9 @@ use orchid_base::location::Pos;
|
||||
use orchid_base::reqnot::Requester;
|
||||
use trait_set::trait_set;
|
||||
|
||||
use crate::error::ProjectError;
|
||||
use crate::expr::{ExprHandle, GenExpr};
|
||||
use crate::system::{atom_info_for, DynSystem, DynSystemCard, SysCtx};
|
||||
use crate::error::{ProjectError, ProjectResult};
|
||||
use crate::expr::{ExprHandle, GenClause, GenExpr, OwnedExpr};
|
||||
use crate::system::{atom_info_for, downcast_atom, DynSystem, DynSystemCard, SysCtx};
|
||||
|
||||
pub trait AtomCard: 'static + Sized {
|
||||
type Data: Clone + Coding + Sized;
|
||||
@@ -40,7 +42,7 @@ pub trait AtomicFeaturesImpl<Variant: AtomicVariant> {
|
||||
type _Info: AtomDynfo;
|
||||
const _INFO: &'static Self::_Info;
|
||||
}
|
||||
impl<A: Atomic + AtomicFeaturesImpl<A::Variant>> AtomicFeatures for A {
|
||||
impl<A: Atomic + AtomicFeaturesImpl<A::Variant> + ?Sized> AtomicFeatures for A {
|
||||
fn factory(self) -> AtomFactory { self._factory() }
|
||||
type Info = <Self as AtomicFeaturesImpl<A::Variant>>::_Info;
|
||||
const INFO: &'static Self::Info = Self::_INFO;
|
||||
@@ -58,41 +60,65 @@ pub struct ForeignAtom {
|
||||
pub atom: Atom,
|
||||
pub pos: Pos,
|
||||
}
|
||||
impl ForeignAtom {}
|
||||
impl ForeignAtom {
|
||||
pub fn oex(self) -> OwnedExpr {
|
||||
let gen_expr = GenExpr { pos: self.pos, clause: GenClause::Atom(self.expr.tk, self.atom) };
|
||||
OwnedExpr { handle: self.expr, val: OnceLock::from(Box::new(gen_expr)) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NotTypAtom(pub Pos, pub OwnedExpr, pub &'static dyn AtomDynfo);
|
||||
impl ProjectError for NotTypAtom {
|
||||
const DESCRIPTION: &'static str = "Not the expected type";
|
||||
fn message(&self) -> String { format!("This expression is not a {}", self.2.name()) }
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TypAtom<A: AtomCard> {
|
||||
pub struct TypAtom<A: AtomicFeatures> {
|
||||
pub data: ForeignAtom,
|
||||
pub value: A::Data,
|
||||
}
|
||||
impl<A: AtomCard> TypAtom<A> {
|
||||
impl<A: AtomicFeatures> TypAtom<A> {
|
||||
pub fn downcast(expr: ExprHandle) -> Result<Self, NotTypAtom> {
|
||||
match OwnedExpr::new(expr).foreign_atom() {
|
||||
Err(oe) => Err(NotTypAtom(oe.get_data().pos.clone(), oe, A::INFO)),
|
||||
Ok(atm) => match downcast_atom::<A>(atm) {
|
||||
Err(fa) => Err(NotTypAtom(fa.pos.clone(), fa.oex(), A::INFO)),
|
||||
Ok(tatom) => Ok(tatom),
|
||||
},
|
||||
}
|
||||
}
|
||||
pub fn request<R: Coding + Into<A::Req> + Request>(&self, req: R) -> R::Response {
|
||||
R::Response::decode(
|
||||
&mut &self.data.expr.ctx.reqnot.request(Fwd(self.data.atom.clone(), req.enc_vec()))[..],
|
||||
)
|
||||
}
|
||||
}
|
||||
impl<A: AtomCard> Deref for TypAtom<A> {
|
||||
impl<A: AtomicFeatures> Deref for TypAtom<A> {
|
||||
type Target = A::Data;
|
||||
fn deref(&self) -> &Self::Target { &self.value }
|
||||
}
|
||||
|
||||
pub struct AtomCtx<'a>(pub &'a [u8], pub SysCtx);
|
||||
|
||||
pub trait AtomDynfo: Send + Sync + 'static {
|
||||
fn tid(&self) -> TypeId;
|
||||
fn decode(&self, data: &[u8]) -> Box<dyn Any>;
|
||||
fn call(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr;
|
||||
fn call_ref(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr;
|
||||
fn same(&self, buf: &[u8], ctx: SysCtx, buf2: &[u8]) -> bool;
|
||||
fn handle_req(&self, buf: &[u8], ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write);
|
||||
fn drop(&self, buf: &[u8], ctx: SysCtx);
|
||||
fn name(&self) -> &'static str;
|
||||
fn decode(&self, ctx: AtomCtx<'_>) -> Box<dyn Any>;
|
||||
fn call(&self, ctx: AtomCtx<'_>, arg: ExprTicket) -> GenExpr;
|
||||
fn call_ref(&self, ctx: AtomCtx<'_>, arg: ExprTicket) -> GenExpr;
|
||||
fn same(&self, ctx: AtomCtx<'_>, buf2: &[u8]) -> bool;
|
||||
fn handle_req(&self, ctx: AtomCtx<'_>, req: &mut dyn Read, rep: &mut dyn Write);
|
||||
fn command(&self, ctx: AtomCtx<'_>) -> ProjectResult<Option<GenExpr>>;
|
||||
fn drop(&self, ctx: AtomCtx<'_>);
|
||||
}
|
||||
|
||||
trait_set! {
|
||||
pub trait AtomFactoryFn = FnOnce(&dyn DynSystem) -> LocalAtom + DynClone;
|
||||
pub trait AtomFactoryFn = FnOnce(&dyn DynSystem) -> LocalAtom + DynClone + Send + Sync;
|
||||
}
|
||||
pub struct AtomFactory(Box<dyn AtomFactoryFn>);
|
||||
impl AtomFactory {
|
||||
pub fn new(f: impl FnOnce(&dyn DynSystem) -> LocalAtom + Clone + 'static) -> Self {
|
||||
pub fn new(f: impl FnOnce(&dyn DynSystem) -> LocalAtom + Clone + Send + Sync + 'static) -> Self {
|
||||
Self(Box::new(f))
|
||||
}
|
||||
pub fn build(self, sys: &dyn DynSystem) -> LocalAtom { (self.0)(sys) }
|
||||
@@ -105,3 +131,27 @@ pub struct ErrorNotCallable;
|
||||
impl ProjectError for ErrorNotCallable {
|
||||
const DESCRIPTION: &'static str = "This atom is not callable";
|
||||
}
|
||||
|
||||
pub struct ErrorNotCommand;
|
||||
impl ProjectError for ErrorNotCommand {
|
||||
const DESCRIPTION: &'static str = "This atom is not a command";
|
||||
}
|
||||
|
||||
pub trait ReqPck<T: AtomCard + ?Sized>: Sized {
|
||||
type W: Write + ?Sized;
|
||||
fn unpack<'a>(self) -> (T::Req, &'a mut Self::W)
|
||||
where Self: 'a;
|
||||
fn never(self)
|
||||
where T: AtomCard<Req = Never> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RequestPack<'a, T: AtomCard + ?Sized, W: Write + ?Sized>(pub T::Req, pub &'a mut W);
|
||||
|
||||
impl<'a, T: AtomCard + ?Sized, W: Write + ?Sized> ReqPck<T> for RequestPack<'a, T, W> {
|
||||
type W = W;
|
||||
fn unpack<'b>(self) -> (<T as AtomCard>::Req, &'b mut Self::W)
|
||||
where 'a: 'b {
|
||||
(self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user