forked from Orchid/orchid
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::borrow::Cow;
|
||||
use std::io::{Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::num::NonZeroU64;
|
||||
use std::sync::Arc;
|
||||
|
||||
use orchid_api::atom::LocalAtom;
|
||||
use orchid_api::expr::ExprTicket;
|
||||
@@ -10,8 +11,10 @@ use orchid_api_traits::{Decode, Encode};
|
||||
use orchid_base::id_store::{IdRecord, IdStore};
|
||||
|
||||
use crate::atom::{
|
||||
AtomCard, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrorNotCallable,
|
||||
AtomCard, AtomCtx, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant,
|
||||
ErrorNotCallable, ErrorNotCommand, ReqPck, RequestPack,
|
||||
};
|
||||
use crate::error::ProjectResult;
|
||||
use crate::expr::{bot, ExprHandle, GenExpr};
|
||||
use crate::system::{atom_info_for, SysCtx};
|
||||
|
||||
@@ -38,22 +41,26 @@ fn with_atom<U>(mut b: &[u8], f: impl FnOnce(IdRecord<'_, Box<dyn DynOwnedAtom>>
|
||||
pub struct OwnedAtomDynfo<T: OwnedAtom>(PhantomData<T>);
|
||||
impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn decode(&self, data: &[u8]) -> Box<dyn Any> {
|
||||
fn name(&self) -> &'static str { type_name::<T>() }
|
||||
fn decode(&self, AtomCtx(data, _): AtomCtx) -> Box<dyn Any> {
|
||||
Box::new(<T as AtomCard>::Data::decode(&mut &data[..]))
|
||||
}
|
||||
fn call(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||
fn call(&self, AtomCtx(buf, ctx): AtomCtx, arg: ExprTicket) -> GenExpr {
|
||||
with_atom(buf, |a| a.remove().dyn_call(ctx, arg))
|
||||
}
|
||||
fn call_ref(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||
fn call_ref(&self, AtomCtx(buf, ctx): AtomCtx, arg: ExprTicket) -> GenExpr {
|
||||
with_atom(buf, |a| a.dyn_call_ref(ctx, arg))
|
||||
}
|
||||
fn same(&self, buf: &[u8], ctx: SysCtx, buf2: &[u8]) -> bool {
|
||||
fn same(&self, AtomCtx(buf, ctx): AtomCtx, buf2: &[u8]) -> bool {
|
||||
with_atom(buf, |a1| with_atom(buf2, |a2| a1.dyn_same(ctx, &**a2)))
|
||||
}
|
||||
fn handle_req(&self, buf: &[u8], ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write) {
|
||||
fn handle_req(&self, AtomCtx(buf, ctx): AtomCtx, req: &mut dyn Read, rep: &mut dyn Write) {
|
||||
with_atom(buf, |a| a.dyn_handle_req(ctx, req, rep))
|
||||
}
|
||||
fn drop(&self, buf: &[u8], ctx: SysCtx) { with_atom(buf, |a| a.remove().dyn_free(ctx)) }
|
||||
fn command(&self, AtomCtx(buf, ctx): AtomCtx<'_>) -> ProjectResult<Option<GenExpr>> {
|
||||
with_atom(buf, |a| a.remove().dyn_command(ctx))
|
||||
}
|
||||
fn drop(&self, AtomCtx(buf, ctx): AtomCtx) { with_atom(buf, |a| a.remove().dyn_free(ctx)) }
|
||||
}
|
||||
|
||||
/// Atoms that have a [Drop]
|
||||
@@ -75,7 +82,9 @@ pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Send + Sync + Any + Clone
|
||||
);
|
||||
false
|
||||
}
|
||||
fn handle_req(&self, ctx: SysCtx, req: Self::Req, rep: &mut (impl Write + ?Sized));
|
||||
fn handle_req(&self, ctx: SysCtx, pck: impl ReqPck<Self>);
|
||||
#[allow(unused_variables)]
|
||||
fn command(self, ctx: SysCtx) -> ProjectResult<Option<GenExpr>> { Err(Arc::new(ErrorNotCommand)) }
|
||||
#[allow(unused_variables)]
|
||||
fn free(self, ctx: SysCtx) {}
|
||||
}
|
||||
@@ -87,6 +96,7 @@ pub trait DynOwnedAtom: Send + Sync + 'static {
|
||||
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: ExprTicket) -> GenExpr;
|
||||
fn dyn_same(&self, ctx: SysCtx, other: &dyn DynOwnedAtom) -> bool;
|
||||
fn dyn_handle_req(&self, ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write);
|
||||
fn dyn_command(self: Box<Self>, ctx: SysCtx) -> ProjectResult<Option<GenExpr>>;
|
||||
fn dyn_free(self: Box<Self>, ctx: SysCtx);
|
||||
}
|
||||
impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
@@ -107,7 +117,10 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
self.same(ctx, other_self)
|
||||
}
|
||||
fn dyn_handle_req(&self, ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write) {
|
||||
self.handle_req(ctx, <Self as AtomCard>::Req::decode(req), rep)
|
||||
self.handle_req(ctx, RequestPack::<T, dyn Write>(<Self as AtomCard>::Req::decode(req), rep))
|
||||
}
|
||||
fn dyn_command(self: Box<Self>, ctx: SysCtx) -> ProjectResult<Option<GenExpr>> {
|
||||
self.command(ctx)
|
||||
}
|
||||
fn dyn_free(self: Box<Self>, ctx: SysCtx) { self.free(ctx) }
|
||||
}
|
||||
|
||||
@@ -2,15 +2,17 @@ use std::any::{type_name, Any, TypeId};
|
||||
use std::fmt;
|
||||
use std::io::Write;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
use orchid_api::atom::LocalAtom;
|
||||
use orchid_api::expr::ExprTicket;
|
||||
use orchid_api_traits::{Coding, Decode, Encode};
|
||||
|
||||
use crate::atom::{
|
||||
get_info, AtomCard, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant,
|
||||
ErrorNotCallable,
|
||||
get_info, AtomCard, AtomCtx, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant,
|
||||
ErrorNotCallable, ReqPck, RequestPack,
|
||||
};
|
||||
use crate::error::ProjectResult;
|
||||
use crate::expr::{bot, ExprHandle, GenExpr};
|
||||
use crate::system::SysCtx;
|
||||
|
||||
@@ -31,20 +33,31 @@ impl<A: ThinAtom + Atomic<Variant = ThinVariant>> AtomicFeaturesImpl<ThinVariant
|
||||
pub struct ThinAtomDynfo<T: ThinAtom>(PhantomData<T>);
|
||||
impl<T: ThinAtom> AtomDynfo for ThinAtomDynfo<T> {
|
||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn decode(&self, mut data: &[u8]) -> Box<dyn Any> { Box::new(T::decode(&mut data)) }
|
||||
fn call(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||
fn name(&self) -> &'static str { type_name::<T>() }
|
||||
fn decode(&self, AtomCtx(data, _): AtomCtx) -> Box<dyn Any> {
|
||||
Box::new(T::decode(&mut &data[..]))
|
||||
}
|
||||
fn call(&self, AtomCtx(buf, ctx): AtomCtx, arg: ExprTicket) -> GenExpr {
|
||||
T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg))
|
||||
}
|
||||
fn call_ref(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||
fn call_ref(&self, AtomCtx(buf, ctx): AtomCtx, arg: ExprTicket) -> GenExpr {
|
||||
T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg))
|
||||
}
|
||||
fn handle_req(&self, buf: &[u8], ctx: SysCtx, req: &mut dyn std::io::Read, rep: &mut dyn Write) {
|
||||
T::decode(&mut &buf[..]).handle_req(ctx, Decode::decode(req), rep)
|
||||
fn handle_req(
|
||||
&self,
|
||||
AtomCtx(buf, ctx): AtomCtx,
|
||||
req: &mut dyn std::io::Read,
|
||||
rep: &mut dyn Write,
|
||||
) {
|
||||
T::decode(&mut &buf[..]).handle_req(ctx, RequestPack::<T, dyn Write>(Decode::decode(req), rep))
|
||||
}
|
||||
fn same(&self, buf: &[u8], ctx: SysCtx, buf2: &[u8]) -> bool {
|
||||
fn same(&self, AtomCtx(buf, ctx): AtomCtx, buf2: &[u8]) -> bool {
|
||||
T::decode(&mut &buf[..]).same(ctx, &T::decode(&mut &buf2[..]))
|
||||
}
|
||||
fn drop(&self, buf: &[u8], _ctx: SysCtx) {
|
||||
fn command(&self, AtomCtx(buf, ctx): AtomCtx<'_>) -> ProjectResult<Option<GenExpr>> {
|
||||
T::decode(&mut &buf[..]).command(ctx)
|
||||
}
|
||||
fn drop(&self, AtomCtx(buf, _): AtomCtx) {
|
||||
eprintln!("Received drop signal for non-drop atom {:?}", T::decode(&mut &buf[..]))
|
||||
}
|
||||
}
|
||||
@@ -60,5 +73,9 @@ pub trait ThinAtom: AtomCard<Data = Self> + Coding + fmt::Debug + Send + Sync +
|
||||
);
|
||||
false
|
||||
}
|
||||
fn handle_req(&self, ctx: SysCtx, req: Self::Req, rep: &mut (impl Write + ?Sized));
|
||||
fn handle_req(&self, ctx: SysCtx, pck: impl ReqPck<Self>);
|
||||
#[allow(unused_variables)]
|
||||
fn command(&self, ctx: SysCtx) -> ProjectResult<Option<GenExpr>> {
|
||||
Err(Arc::new(ErrorNotCallable))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,49 @@
|
||||
use std::num::{NonZeroU16, NonZeroU64};
|
||||
use std::num::NonZero;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{mem, thread};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use orchid_api::atom::{Atom, AtomDrop, AtomReq, AtomSame, CallRef, Command, FinalCall, Fwded};
|
||||
use orchid_api::atom::{
|
||||
Atom, AtomDrop, AtomReq, AtomSame, CallRef, Command, FinalCall, Fwded, NextStep,
|
||||
};
|
||||
use orchid_api::interner::Sweep;
|
||||
use orchid_api::parser::{CharFilter, Lex, Lexed, ParserReq};
|
||||
use orchid_api::parser::{CharFilter, LexExpr, LexedExpr, ParserReq};
|
||||
use orchid_api::proto::{ExtMsgSet, ExtensionHeader, HostExtNotif, HostExtReq, HostHeader, Ping};
|
||||
use orchid_api::system::{SysId, SystemDrop, SystemInst};
|
||||
use orchid_api::tree::{GetConstTree, Tree, TreeId};
|
||||
use orchid_api::system::{SysDeclId, SysId, SystemDrop, SystemInst};
|
||||
use orchid_api::tree::{GetMember, TreeId};
|
||||
use orchid_api::vfs::{EagerVfs, GetVfs, VfsId, VfsRead, VfsReq};
|
||||
use orchid_api_traits::{Decode, Encode};
|
||||
use orchid_base::char_filter::{char_filter_union, mk_char_filter};
|
||||
use orchid_base::char_filter::{char_filter_match, char_filter_union, mk_char_filter};
|
||||
use orchid_base::clone;
|
||||
use orchid_base::interner::{deintern, init_replica, sweep_replica};
|
||||
use orchid_base::name::PathSlice;
|
||||
use orchid_base::reqnot::{ReqNot, Requester};
|
||||
|
||||
use crate::atom::AtomDynfo;
|
||||
use crate::error::{err_or_ref_to_api, unpack_err};
|
||||
use crate::atom::{AtomCtx, AtomDynfo};
|
||||
use crate::error::errv_to_apiv;
|
||||
use crate::fs::VirtFS;
|
||||
use crate::lexer::LexContext;
|
||||
use crate::lexer::{CascadingError, LexContext, NotApplicableLexerError};
|
||||
use crate::msg::{recv_parent_msg, send_parent_msg};
|
||||
use crate::system::{atom_by_idx, SysCtx};
|
||||
use crate::system::{atom_by_idx, resolv_atom, SysCtx};
|
||||
use crate::system_ctor::{CtedObj, DynSystemCtor};
|
||||
use crate::tree::LazyTreeFactory;
|
||||
use crate::tree::{LazyMemberFactory, TIACtxImpl};
|
||||
|
||||
pub struct ExtensionData {
|
||||
pub systems: &'static [&'static dyn DynSystemCtor],
|
||||
}
|
||||
|
||||
pub enum TreeRecord {
|
||||
Gen(LazyTreeFactory),
|
||||
Res(Tree),
|
||||
pub enum MemberRecord {
|
||||
Gen(LazyMemberFactory),
|
||||
Res,
|
||||
}
|
||||
|
||||
pub struct SystemRecord {
|
||||
cted: CtedObj,
|
||||
vfses: HashMap<VfsId, &'static dyn VirtFS>,
|
||||
declfs: EagerVfs,
|
||||
tree: Tree,
|
||||
subtrees: HashMap<TreeId, TreeRecord>,
|
||||
lazy_members: HashMap<TreeId, MemberRecord>,
|
||||
}
|
||||
|
||||
pub fn with_atom_record<T>(
|
||||
@@ -63,7 +64,7 @@ pub fn extension_main(data: ExtensionData) {
|
||||
let mut buf = Vec::new();
|
||||
let decls = (data.systems.iter().enumerate())
|
||||
.map(|(id, sys)| (u16::try_from(id).expect("more than u16max system ctors"), sys))
|
||||
.map(|(id, sys)| sys.decl(NonZeroU16::new(id + 1).unwrap()))
|
||||
.map(|(id, sys)| sys.decl(SysDeclId(NonZero::new(id + 1).unwrap())))
|
||||
.collect_vec();
|
||||
let systems = Arc::new(Mutex::new(HashMap::<SysId, SystemRecord>::new()));
|
||||
ExtensionHeader { systems: decls.clone() }.encode(&mut buf);
|
||||
@@ -77,7 +78,7 @@ pub fn extension_main(data: ExtensionData) {
|
||||
mem::drop(systems.lock().unwrap().remove(&sys_id)),
|
||||
HostExtNotif::AtomDrop(AtomDrop(atom)) => {
|
||||
with_atom_record(&systems, &atom, |rec, cted, data| {
|
||||
rec.drop(data, SysCtx{ reqnot, id: atom.owner, cted })
|
||||
rec.drop(AtomCtx(data, SysCtx{ reqnot, id: atom.owner, cted }))
|
||||
})
|
||||
}
|
||||
}),
|
||||
@@ -91,44 +92,36 @@ pub fn extension_main(data: ExtensionData) {
|
||||
let lex_filter = cted.inst().dyn_lexers().iter().fold(CharFilter(vec![]), |cf, lx| {
|
||||
char_filter_union(&cf, &mk_char_filter(lx.char_filter().iter().cloned()))
|
||||
});
|
||||
let mut subtrees = HashMap::new();
|
||||
let mut lazy_mems = HashMap::new();
|
||||
let const_root = (cted.inst().dyn_env().into_iter())
|
||||
.map(|(k, v)| {
|
||||
(k.marker(), v.into_api(&mut TIACtxImpl{ lazy: &mut lazy_mems, sys: &*cted.inst()}))
|
||||
})
|
||||
.collect();
|
||||
systems.lock().unwrap().insert(new_sys.id, SystemRecord {
|
||||
declfs: cted.inst().dyn_vfs().to_api_rec(&mut vfses),
|
||||
vfses,
|
||||
tree: cted.inst().dyn_env().into_api(&*cted.inst(), &mut |gen| {
|
||||
let id = TreeId::new((subtrees.len() + 2) as u64).unwrap();
|
||||
subtrees.insert(id, TreeRecord::Gen(gen.clone()));
|
||||
id
|
||||
}),
|
||||
cted,
|
||||
subtrees
|
||||
lazy_members: lazy_mems
|
||||
});
|
||||
req.handle(new_sys, &SystemInst {
|
||||
lex_filter, const_root_id: NonZeroU64::new(1).unwrap()
|
||||
lex_filter,
|
||||
const_root,
|
||||
parses_lines: vec!()
|
||||
})
|
||||
}
|
||||
HostExtReq::GetConstTree(get_tree@GetConstTree(sys_id, tree_id)) => {
|
||||
HostExtReq::GetMember(get_tree@GetMember(sys_id, tree_id)) => {
|
||||
let mut systems_g = systems.lock().unwrap();
|
||||
let sys = systems_g.get_mut(sys_id).expect("System not found");
|
||||
if tree_id.get() == 1 {
|
||||
req.handle(get_tree, &sys.tree);
|
||||
} else {
|
||||
let subtrees = &mut sys.subtrees;
|
||||
let tree_rec = subtrees.get_mut(tree_id).expect("Tree for ID not found");
|
||||
match tree_rec {
|
||||
TreeRecord::Res(tree) => req.handle(get_tree, tree),
|
||||
TreeRecord::Gen(cb) => {
|
||||
let tree = cb.build();
|
||||
let reply_tree = tree.into_api(&*sys.cted.inst(), &mut |cb| {
|
||||
let id = NonZeroU64::new((subtrees.len() + 2) as u64).unwrap();
|
||||
subtrees.insert(id, TreeRecord::Gen(cb.clone()));
|
||||
id
|
||||
});
|
||||
req.handle(get_tree, &reply_tree);
|
||||
subtrees.insert(*tree_id, TreeRecord::Res(reply_tree));
|
||||
}
|
||||
}
|
||||
}
|
||||
let lazy = &mut sys.lazy_members;
|
||||
let cb = match lazy.insert(*tree_id, MemberRecord::Res) {
|
||||
None => panic!("Tree for ID not found"),
|
||||
Some(MemberRecord::Res) => panic!("This tree has already been transmitted"),
|
||||
Some(MemberRecord::Gen(cb)) => cb,
|
||||
};
|
||||
let tree = cb.build();
|
||||
let reply_tree = tree.into_api(&mut TIACtxImpl{ sys: &*sys.cted.inst(), lazy });
|
||||
req.handle(get_tree, &reply_tree);
|
||||
}
|
||||
HostExtReq::VfsReq(VfsReq::GetVfs(get_vfs@GetVfs(sys_id))) => {
|
||||
let systems_g = systems.lock().unwrap();
|
||||
@@ -139,8 +132,8 @@ pub fn extension_main(data: ExtensionData) {
|
||||
let path = path.iter().map(|t| deintern(*t)).collect_vec();
|
||||
req.handle(vfs_read, &systems_g[sys_id].vfses[vfs_id].load(PathSlice::new(&path)))
|
||||
}
|
||||
HostExtReq::ParserReq(ParserReq::Lex(lex)) => {
|
||||
let Lex{ sys, text, pos, id } = *lex;
|
||||
HostExtReq::ParserReq(ParserReq::LexExpr(lex)) => {
|
||||
let LexExpr{ sys, text, pos, id } = *lex;
|
||||
let systems_g = systems.lock().unwrap();
|
||||
let lexers = systems_g[&sys].cted.inst().dyn_lexers();
|
||||
mem::drop(systems_g);
|
||||
@@ -148,22 +141,56 @@ pub fn extension_main(data: ExtensionData) {
|
||||
let tk = req.will_handle_as(lex);
|
||||
thread::spawn(clone!(systems; move || {
|
||||
let ctx = LexContext { sys, id, pos, reqnot: req.reqnot(), text: &text };
|
||||
let lex_res = lexers.iter().find_map(|lx| lx.lex(&text[pos as usize..], &ctx));
|
||||
req.handle_as(tk, &lex_res.map(|r| match r {
|
||||
Ok((s, data)) => {
|
||||
let systems_g = systems.lock().unwrap();
|
||||
let data = data.into_api(&*systems_g[&sys].cted.inst());
|
||||
Ok(Lexed { data, pos: (text.len() - s.len()) as u32 })
|
||||
},
|
||||
Err(e) => Err(unpack_err(e).into_iter().map(err_or_ref_to_api).collect_vec())
|
||||
}))
|
||||
let first_char = text.chars().next().unwrap();
|
||||
for lx in lexers.iter().filter(|l| char_filter_match(l.char_filter(), first_char)) {
|
||||
match lx.lex(&text[pos as usize..], &ctx) {
|
||||
Err(e) if e.as_any_ref().is::<NotApplicableLexerError>() => continue,
|
||||
Err(e) if e.as_any_ref().is::<CascadingError>() => return req.handle_as(tk, &None),
|
||||
Err(e) => return req.handle_as(tk, &Some(Err(errv_to_apiv([e])))),
|
||||
Ok((s, expr)) => {
|
||||
let systems_g = systems.lock().unwrap();
|
||||
let expr = expr.into_api(&*systems_g[&sys].cted.inst());
|
||||
let pos = (text.len() - s.len()) as u32;
|
||||
return req.handle_as(tk, &Some(Ok(LexedExpr{ pos, expr })))
|
||||
}
|
||||
}
|
||||
}
|
||||
req.handle_as(tk, &None)
|
||||
}));
|
||||
},
|
||||
HostExtReq::AtomReq(AtomReq::AtomSame(same@AtomSame(l, r))) => todo!("subsys nimpl"),
|
||||
HostExtReq::AtomReq(AtomReq::Fwded(call@Fwded(atom, req))) => todo!("subsys nimpl"),
|
||||
HostExtReq::AtomReq(AtomReq::CallRef(call@CallRef(atom, arg))) => todo!("subsys nimpl"),
|
||||
HostExtReq::AtomReq(AtomReq::FinalCall(call@FinalCall(atom, arg))) => todo!("subsys nimpl"),
|
||||
HostExtReq::AtomReq(AtomReq::Command(cmd@Command(atom))) => todo!("subsys impl"),
|
||||
HostExtReq::AtomReq(atom_req) => {
|
||||
let systems_g = systems.lock().unwrap();
|
||||
let atom = atom_req.get_atom();
|
||||
let sys = &systems_g[&atom.owner];
|
||||
let ctx = SysCtx { cted: sys.cted.clone(), id: atom.owner, reqnot: req.reqnot() };
|
||||
let dynfo = resolv_atom(&*sys.cted.inst(), atom);
|
||||
let actx = AtomCtx(&atom.data[8..], ctx);
|
||||
match atom_req {
|
||||
AtomReq::AtomSame(same@AtomSame(_, r)) => {
|
||||
// different systems or different type tags
|
||||
if atom.owner != r.owner || atom.data[..8] != r.data[..8] {
|
||||
return req.handle(same, &false)
|
||||
}
|
||||
req.handle(same, &dynfo.same(actx, &r.data[8..]))
|
||||
},
|
||||
AtomReq::Fwded(fwded@Fwded(_, payload)) => {
|
||||
let mut reply = Vec::new();
|
||||
dynfo.handle_req(actx, &mut &payload[..], &mut reply);
|
||||
req.handle(fwded, &reply)
|
||||
}
|
||||
AtomReq::CallRef(call@CallRef(_, arg))
|
||||
=> req.handle(call, &dynfo.call_ref(actx, *arg).to_api(&*sys.cted.inst())),
|
||||
AtomReq::FinalCall(call@FinalCall(_, arg))
|
||||
=> req.handle(call, &dynfo.call(actx, *arg).to_api(&*sys.cted.inst())),
|
||||
AtomReq::Command(cmd@Command(_)) => req.handle(cmd, &match dynfo.command(actx) {
|
||||
Err(e) => Err(errv_to_apiv([e])),
|
||||
Ok(opt) => Ok(match opt {
|
||||
Some(cont) => NextStep::Continue(cont.into_api(&*sys.cted.inst())),
|
||||
None => NextStep::Halt,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
init_replica(rn.clone().map());
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::{fmt, iter};
|
||||
|
||||
use dyn_clone::{clone_box, DynClone};
|
||||
use itertools::Itertools;
|
||||
use orchid_api::error::{GetErrorDetails, ProjErr, ProjErrId, ProjErrOrRef};
|
||||
use orchid_api::error::{GetErrorDetails, ProjErr, ProjErrId};
|
||||
use orchid_api::proto::ExtMsgSet;
|
||||
use orchid_base::boxed_iter::{box_once, BoxedIter};
|
||||
use orchid_base::clone;
|
||||
@@ -274,7 +274,7 @@ impl ProjectError for MultiError {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn err_to_api(err: ProjectErrorObj) -> ProjErr {
|
||||
fn err_to_api(err: ProjectErrorObj) -> ProjErr {
|
||||
ProjErr {
|
||||
description: intern(&*err.description()).marker(),
|
||||
message: Arc::new(err.message()),
|
||||
@@ -282,26 +282,18 @@ pub fn err_to_api(err: ProjectErrorObj) -> ProjErr {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn err_or_ref_to_api(err: ProjectErrorObj) -> ProjErrOrRef {
|
||||
match err.as_any_ref().downcast_ref() {
|
||||
Some(RelayedError { id: Some(id), .. }) => ProjErrOrRef::Known(*id),
|
||||
_ => ProjErrOrRef::New(err_to_api(err)),
|
||||
}
|
||||
pub fn errv_to_apiv(errv: impl IntoIterator<Item = ProjectErrorObj>) -> Vec<ProjErr> {
|
||||
errv.into_iter().flat_map(unpack_err).map(err_to_api).collect_vec()
|
||||
}
|
||||
|
||||
pub fn err_from_api(err: &ProjErr, reqnot: ReqNot<ExtMsgSet>) -> ProjectErrorObj {
|
||||
Arc::new(RelayedError { id: None, reqnot, details: OwnedError::from_api(err).into() })
|
||||
}
|
||||
|
||||
pub(crate) fn err_from_api_or_ref(
|
||||
err: &ProjErrOrRef,
|
||||
reqnot: ReqNot<ExtMsgSet>,
|
||||
pub fn err_from_apiv<'a>(
|
||||
err: impl IntoIterator<Item = &'a ProjErr>,
|
||||
reqnot: &ReqNot<ExtMsgSet>
|
||||
) -> ProjectErrorObj {
|
||||
match err {
|
||||
ProjErrOrRef::Known(id) =>
|
||||
Arc::new(RelayedError { id: Some(*id), reqnot, details: OnceLock::default() }),
|
||||
ProjErrOrRef::New(err) => err_from_api(err, reqnot),
|
||||
}
|
||||
pack_err(err.into_iter().map(|e| {
|
||||
let details: OnceLock<_> = OwnedError::from_api(e).into();
|
||||
Arc::new(RelayedError { id: None, reqnot: reqnot.clone(), details }).into_packed()
|
||||
}))
|
||||
}
|
||||
|
||||
struct RelayedError {
|
||||
|
||||
@@ -9,7 +9,7 @@ use orchid_base::location::Pos;
|
||||
use orchid_base::reqnot::Requester;
|
||||
|
||||
use crate::atom::{AtomFactory, AtomicFeatures, ForeignAtom};
|
||||
use crate::error::{err_from_api, err_to_api, DynProjectError, ProjectErrorObj};
|
||||
use crate::error::{err_from_apiv, errv_to_apiv, DynProjectError, ProjectErrorObj};
|
||||
use crate::system::{DynSystem, SysCtx};
|
||||
|
||||
#[derive(destructure)]
|
||||
@@ -46,7 +46,7 @@ impl OwnedExpr {
|
||||
self.val.get_or_init(|| {
|
||||
Box::new(GenExpr::from_api(
|
||||
self.handle.ctx.reqnot.request(Inspect(self.handle.tk)).expr,
|
||||
self.handle.get_ctx(),
|
||||
&self.handle.ctx,
|
||||
))
|
||||
})
|
||||
}
|
||||
@@ -75,7 +75,7 @@ impl GenExpr {
|
||||
pub fn into_api(self, sys: &dyn DynSystem) -> Expr {
|
||||
Expr { location: self.pos.to_api(), clause: self.clause.into_api(sys) }
|
||||
}
|
||||
pub fn from_api(api: Expr, ctx: SysCtx) -> Self {
|
||||
pub fn from_api(api: Expr, ctx: &SysCtx) -> Self {
|
||||
Self { pos: Pos::from_api(&api.location), clause: GenClause::from_api(api.clause, ctx) }
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ impl GenClause {
|
||||
Self::Lambda(arg, body) => Clause::Lambda(*arg, Box::new(body.to_api(sys))),
|
||||
Self::Arg(arg) => Clause::Arg(*arg),
|
||||
Self::Const(name) => Clause::Const(name.marker()),
|
||||
Self::Bottom(msg) => Clause::Bottom(err_to_api(msg.clone())),
|
||||
Self::Bottom(err) => Clause::Bottom(errv_to_apiv([err.clone()])),
|
||||
Self::NewAtom(fac) => Clause::NewAtom(fac.clone().build(sys)),
|
||||
Self::Atom(tk, atom) => Clause::Atom(*tk, atom.clone()),
|
||||
Self::Slot(_) => panic!("Slot is forbidden in const tree"),
|
||||
@@ -114,34 +114,34 @@ impl GenClause {
|
||||
Self::Arg(arg) => Clause::Arg(arg),
|
||||
Self::Slot(extk) => Clause::Slot(extk.handle.into_tk()),
|
||||
Self::Const(name) => Clause::Const(name.marker()),
|
||||
Self::Bottom(msg) => Clause::Bottom(err_to_api(msg)),
|
||||
Self::Bottom(err) => Clause::Bottom(errv_to_apiv([err])),
|
||||
Self::NewAtom(fac) => Clause::NewAtom(fac.clone().build(sys)),
|
||||
Self::Atom(tk, atom) => Clause::Atom(tk, atom),
|
||||
}
|
||||
}
|
||||
pub fn from_api(api: Clause, ctx: SysCtx) -> Self {
|
||||
pub fn from_api(api: Clause, ctx: &SysCtx) -> Self {
|
||||
match api {
|
||||
Clause::Arg(id) => Self::Arg(id),
|
||||
Clause::Lambda(arg, body) => Self::Lambda(arg, Box::new(GenExpr::from_api(*body, ctx))),
|
||||
Clause::NewAtom(_) => panic!("Clause::NewAtom should never be received, only sent"),
|
||||
Clause::Bottom(s) => Self::Bottom(err_from_api(&s, ctx.reqnot)),
|
||||
Clause::Bottom(s) => Self::Bottom(err_from_apiv(&s, &ctx.reqnot)),
|
||||
Clause::Call(f, x) => Self::Call(
|
||||
Box::new(GenExpr::from_api(*f, ctx.clone())),
|
||||
Box::new(GenExpr::from_api(*f, ctx)),
|
||||
Box::new(GenExpr::from_api(*x, ctx)),
|
||||
),
|
||||
Clause::Seq(a, b) => Self::Seq(
|
||||
Box::new(GenExpr::from_api(*a, ctx.clone())),
|
||||
Box::new(GenExpr::from_api(*a, ctx)),
|
||||
Box::new(GenExpr::from_api(*b, ctx)),
|
||||
),
|
||||
Clause::Const(name) => Self::Const(deintern(name)),
|
||||
Clause::Slot(exi) => Self::Slot(OwnedExpr::new(ExprHandle::from_args(ctx, exi))),
|
||||
Clause::Slot(exi) => Self::Slot(OwnedExpr::new(ExprHandle::from_args(ctx.clone(), exi))),
|
||||
Clause::Atom(tk, atom) => Self::Atom(tk, atom),
|
||||
}
|
||||
}
|
||||
}
|
||||
fn inherit(clause: GenClause) -> GenExpr { GenExpr { pos: Pos::Inherit, clause } }
|
||||
|
||||
pub fn cnst(path: Tok<Vec<Tok<String>>>) -> GenExpr { inherit(GenClause::Const(path)) }
|
||||
pub fn sym_ref(path: Tok<Vec<Tok<String>>>) -> GenExpr { inherit(GenClause::Const(path)) }
|
||||
pub fn atom<A: AtomicFeatures>(atom: A) -> GenExpr { inherit(GenClause::NewAtom(atom.factory())) }
|
||||
|
||||
pub fn seq(ops: impl IntoIterator<Item = GenExpr>) -> GenExpr {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::num::NonZeroU16;
|
||||
use std::num::NonZero;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use orchid_api::error::ProjResult;
|
||||
@@ -19,7 +19,7 @@ impl DeclFs {
|
||||
match self {
|
||||
DeclFs::Lazy(fs) => {
|
||||
let vfsc: u16 = vfses.len().try_into().expect("too many vfses (more than u16::MAX)");
|
||||
let id: VfsId = NonZeroU16::new(vfsc + 1).unwrap();
|
||||
let id = VfsId(NonZero::new(vfsc + 1).unwrap());
|
||||
vfses.insert(id, *fs);
|
||||
EagerVfs::Lazy(id)
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ use dyn_clone::{clone_box, DynClone};
|
||||
use never::Never;
|
||||
use trait_set::trait_set;
|
||||
|
||||
use crate::atom::Atomic;
|
||||
use crate::atom::{Atomic, ReqPck};
|
||||
use crate::atom_owned::{OwnedAtom, OwnedVariant};
|
||||
use crate::conv::{ToExpr, TryFromExpr};
|
||||
use crate::expr::{ExprHandle, GenExpr};
|
||||
@@ -34,7 +34,5 @@ impl OwnedAtom for Fun {
|
||||
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||
fn call_ref(&self, arg: ExprHandle) -> GenExpr { self.clone().call(arg) }
|
||||
fn call(self, arg: ExprHandle) -> GenExpr { (self.0)(arg) }
|
||||
fn handle_req(&self, _ctx: SysCtx, req: Self::Req, _rep: &mut (impl std::io::Write + ?Sized)) {
|
||||
match req {}
|
||||
}
|
||||
fn handle_req(&self, _ctx: SysCtx, pck: impl ReqPck<Self>) { pck.never() }
|
||||
}
|
||||
|
||||
@@ -1,32 +1,46 @@
|
||||
use std::ops::{Range, RangeInclusive};
|
||||
|
||||
use orchid_api::error::ReportError;
|
||||
use orchid_api::parser::{LexId, SubLex};
|
||||
use orchid_api::parser::{ParsId, SubLex};
|
||||
use orchid_api::proto::ExtMsgSet;
|
||||
use orchid_api::system::SysId;
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::reqnot::{ReqNot, Requester};
|
||||
|
||||
use crate::error::{
|
||||
err_from_api_or_ref, err_or_ref_to_api, pack_err, unpack_err, ProjectErrorObj, ProjectResult,
|
||||
ProjectError, ProjectResult
|
||||
};
|
||||
use crate::tree::{OwnedTok, OwnedTokTree};
|
||||
use crate::tree::{GenTok, GenTokTree};
|
||||
|
||||
pub struct CascadingError;
|
||||
impl ProjectError for CascadingError {
|
||||
const DESCRIPTION: &'static str = "An error cascading from a recursive sublexer";
|
||||
fn message(&self) -> String {
|
||||
"This error should not surface. If you are seeing it, something is wrong".to_string()
|
||||
}
|
||||
fn one_position(&self) -> Pos { Pos::None }
|
||||
}
|
||||
|
||||
pub struct NotApplicableLexerError;
|
||||
impl ProjectError for NotApplicableLexerError {
|
||||
const DESCRIPTION: &'static str = "Pseudo-error to communicate that the lexer doesn't apply";
|
||||
fn message(&self) -> String { CascadingError.message() }
|
||||
fn one_position(&self) -> Pos { Pos::None }
|
||||
}
|
||||
|
||||
pub struct LexContext<'a> {
|
||||
pub text: &'a Tok<String>,
|
||||
pub sys: SysId,
|
||||
pub id: LexId,
|
||||
pub id: ParsId,
|
||||
pub pos: u32,
|
||||
pub reqnot: ReqNot<ExtMsgSet>,
|
||||
}
|
||||
impl<'a> LexContext<'a> {
|
||||
pub fn recurse(&self, tail: &'a str) -> ProjectResult<(&'a str, OwnedTokTree)> {
|
||||
pub fn recurse(&self, tail: &'a str) -> ProjectResult<(&'a str, GenTokTree)> {
|
||||
let start = self.pos(tail);
|
||||
self
|
||||
.reqnot
|
||||
.request(SubLex { pos: start, id: self.id })
|
||||
.map_err(|e| pack_err(e.iter().map(|e| err_from_api_or_ref(e, self.reqnot.clone()))))
|
||||
.map(|lx| (&self.text[lx.pos as usize..], OwnedTok::Slot(lx.ticket).at(start..lx.pos)))
|
||||
let lx = (self.reqnot.request(SubLex { pos: start, id: self.id }))
|
||||
.ok_or_else(|| CascadingError.pack())?;
|
||||
Ok((&self.text[lx.pos as usize..], GenTok::Slot(lx.ticket).at(start..lx.pos)))
|
||||
}
|
||||
|
||||
pub fn pos(&self, tail: &'a str) -> u32 { (self.text.len() - tail.len()) as u32 }
|
||||
@@ -34,12 +48,6 @@ impl<'a> LexContext<'a> {
|
||||
pub fn tok_ran(&self, len: u32, tail: &'a str) -> Range<u32> {
|
||||
self.pos(tail) - len..self.pos(tail)
|
||||
}
|
||||
|
||||
pub fn report(&self, e: ProjectErrorObj) {
|
||||
for e in unpack_err(e) {
|
||||
self.reqnot.notify(ReportError(self.sys, err_or_ref_to_api(e)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Lexer: Send + Sync + Sized + Default + 'static {
|
||||
@@ -47,7 +55,7 @@ pub trait Lexer: Send + Sync + Sized + Default + 'static {
|
||||
fn lex<'a>(
|
||||
tail: &'a str,
|
||||
ctx: &'a LexContext<'a>,
|
||||
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>>;
|
||||
) -> ProjectResult<(&'a str, GenTokTree)>;
|
||||
}
|
||||
|
||||
pub trait DynLexer: Send + Sync + 'static {
|
||||
@@ -56,7 +64,7 @@ pub trait DynLexer: Send + Sync + 'static {
|
||||
&self,
|
||||
tail: &'a str,
|
||||
ctx: &'a LexContext<'a>,
|
||||
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>>;
|
||||
) -> ProjectResult<(&'a str, GenTokTree)>;
|
||||
}
|
||||
|
||||
impl<T: Lexer> DynLexer for T {
|
||||
@@ -65,7 +73,7 @@ impl<T: Lexer> DynLexer for T {
|
||||
&self,
|
||||
tail: &'a str,
|
||||
ctx: &'a LexContext<'a>,
|
||||
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>> {
|
||||
) -> ProjectResult<(&'a str, GenTokTree)> {
|
||||
T::lex(tail, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
//! Abstractions for handling various code-related errors under a common trait
|
||||
//! object.
|
||||
|
||||
use std::any::Any;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, iter};
|
||||
|
||||
use dyn_clone::{clone_box, DynClone};
|
||||
use itertools::Itertools;
|
||||
use orchid_api::error::{ProjErr, ProjErrLocation};
|
||||
|
||||
use crate::boxed_iter::{box_once, BoxedIter};
|
||||
use crate::intern::{deintern, intern, Token};
|
||||
use crate::location::{GetSrc, Position};
|
||||
#[allow(unused)] // for doc
|
||||
use crate::virt_fs::CodeNotFound;
|
||||
@@ -1,16 +1,19 @@
|
||||
use std::any::TypeId;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use orchid_api::atom::Atom;
|
||||
use orchid_api::proto::ExtMsgSet;
|
||||
use orchid_api::system::SysId;
|
||||
use orchid_api_traits::Decode;
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::reqnot::ReqNot;
|
||||
|
||||
use crate::atom::{get_info, AtomCard, AtomDynfo, AtomicFeatures, ForeignAtom, TypAtom};
|
||||
use crate::atom::{get_info, AtomCtx, AtomDynfo, AtomicFeatures, ForeignAtom, TypAtom};
|
||||
use crate::fs::DeclFs;
|
||||
use crate::fun::Fun;
|
||||
use crate::lexer::LexerObj;
|
||||
use crate::system_ctor::{CtedObj, SystemCtor};
|
||||
use crate::tree::GenTree;
|
||||
use crate::tree::GenMemberKind;
|
||||
|
||||
/// System as consumed by foreign code
|
||||
pub trait SystemCard: Default + Send + Sync + 'static {
|
||||
@@ -51,6 +54,11 @@ pub fn atom_by_idx(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolv_atom(sys: &(impl DynSystemCard + ?Sized), atom: &Atom) -> &'static dyn AtomDynfo {
|
||||
let tid = u64::decode(&mut &atom.data[..8]);
|
||||
atom_by_idx(sys, tid).expect("Value of nonexistent type found")
|
||||
}
|
||||
|
||||
impl<T: SystemCard> DynSystemCard for T {
|
||||
fn name(&self) -> &'static str { T::Ctor::NAME }
|
||||
fn atoms(&self) -> &'static [Option<&'static dyn AtomDynfo>] { Self::ATOM_DEFS }
|
||||
@@ -58,26 +66,26 @@ impl<T: SystemCard> DynSystemCard for T {
|
||||
|
||||
/// System as defined by author
|
||||
pub trait System: Send + Sync + SystemCard + 'static {
|
||||
fn env() -> GenTree;
|
||||
fn env() -> Vec<(Tok<String>, GenMemberKind)>;
|
||||
fn vfs() -> DeclFs;
|
||||
fn lexers() -> Vec<LexerObj>;
|
||||
}
|
||||
|
||||
pub trait DynSystem: Send + Sync + 'static {
|
||||
fn dyn_env(&self) -> GenTree;
|
||||
pub trait DynSystem: Send + Sync + DynSystemCard + 'static {
|
||||
fn dyn_env(&self) -> HashMap<Tok<String>, GenMemberKind>;
|
||||
fn dyn_vfs(&self) -> DeclFs;
|
||||
fn dyn_lexers(&self) -> Vec<LexerObj>;
|
||||
fn dyn_card(&self) -> &dyn DynSystemCard;
|
||||
}
|
||||
|
||||
impl<T: System> DynSystem for T {
|
||||
fn dyn_env(&self) -> GenTree { Self::env() }
|
||||
fn dyn_env(&self) -> HashMap<Tok<String>, GenMemberKind> { Self::env().into_iter().collect() }
|
||||
fn dyn_vfs(&self) -> DeclFs { Self::vfs() }
|
||||
fn dyn_lexers(&self) -> Vec<LexerObj> { Self::lexers() }
|
||||
fn dyn_card(&self) -> &dyn DynSystemCard { self }
|
||||
}
|
||||
|
||||
pub fn downcast_atom<A: AtomCard>(foreign: ForeignAtom) -> Result<TypAtom<A>, ForeignAtom> {
|
||||
pub fn downcast_atom<A: AtomicFeatures>(foreign: ForeignAtom) -> Result<TypAtom<A>, ForeignAtom> {
|
||||
let mut data = &foreign.atom.data[..];
|
||||
let ctx = foreign.expr.get_ctx();
|
||||
let info_ent = (ctx.cted.deps().find(|s| s.id() == foreign.atom.owner))
|
||||
@@ -86,7 +94,7 @@ pub fn downcast_atom<A: AtomCard>(foreign: ForeignAtom) -> Result<TypAtom<A>, Fo
|
||||
match info_ent {
|
||||
None => Err(foreign),
|
||||
Some((_, info)) => {
|
||||
let val = info.decode(data);
|
||||
let val = info.decode(AtomCtx(data, ctx));
|
||||
let value = *val.downcast::<A::Data>().expect("atom decode returned wrong type");
|
||||
Ok(TypAtom { value, data: foreign })
|
||||
},
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use std::any::Any;
|
||||
use std::num::NonZeroU16;
|
||||
use std::sync::Arc;
|
||||
|
||||
use orchid_api::system::{NewSystem, SysId, SystemDecl};
|
||||
use orchid_api::system::{NewSystem, SysDeclId, SysId, SystemDecl};
|
||||
use orchid_base::boxed_iter::{box_empty, box_once, BoxedIter};
|
||||
use ordered_float::NotNan;
|
||||
|
||||
@@ -67,12 +66,12 @@ pub trait SystemCtor: Send + Sync + 'static {
|
||||
}
|
||||
|
||||
pub trait DynSystemCtor: Send + Sync + 'static {
|
||||
fn decl(&self, id: NonZeroU16) -> SystemDecl;
|
||||
fn decl(&self, id: SysDeclId) -> SystemDecl;
|
||||
fn new_system(&self, new: &NewSystem) -> CtedObj;
|
||||
}
|
||||
|
||||
impl<T: SystemCtor> DynSystemCtor for T {
|
||||
fn decl(&self, id: NonZeroU16) -> SystemDecl {
|
||||
fn decl(&self, id: SysDeclId) -> SystemDecl {
|
||||
// Version is equivalent to priority for all practical purposes
|
||||
let priority = NotNan::new(T::VERSION).unwrap();
|
||||
// aggregate depends names
|
||||
|
||||
@@ -1,31 +1,33 @@
|
||||
use std::iter;
|
||||
use std::num::NonZero;
|
||||
use std::ops::Range;
|
||||
|
||||
use ahash::HashMap;
|
||||
use hashbrown::HashMap;
|
||||
use dyn_clone::{clone_box, DynClone};
|
||||
use itertools::Itertools;
|
||||
use orchid_api::tree::{
|
||||
MacroRule, Paren, PlaceholderKind, Token, TokenTree, Tree, TreeId, TreeModule,
|
||||
TreeTicket,
|
||||
Macro, Paren, PlaceholderKind, Token, TokenTree, Item, TreeId, ItemKind, Member, MemberKind, Module, TreeTicket
|
||||
};
|
||||
use orchid_base::interner::intern;
|
||||
use orchid_base::interner::{intern, Tok};
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::name::VName;
|
||||
use orchid_base::name::{NameLike, Sym, VName};
|
||||
use orchid_base::tokens::OwnedPh;
|
||||
use ordered_float::NotNan;
|
||||
use trait_set::trait_set;
|
||||
|
||||
use crate::atom::AtomFactory;
|
||||
use crate::conv::ToExpr;
|
||||
use crate::error::{err_or_ref_to_api, ProjectErrorObj};
|
||||
use crate::entrypoint::MemberRecord;
|
||||
use crate::error::{errv_to_apiv, ProjectErrorObj};
|
||||
use crate::expr::GenExpr;
|
||||
use crate::system::DynSystem;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OwnedTokTree {
|
||||
pub tok: OwnedTok,
|
||||
pub struct GenTokTree {
|
||||
pub tok: GenTok,
|
||||
pub range: Range<u32>,
|
||||
}
|
||||
impl OwnedTokTree {
|
||||
impl GenTokTree {
|
||||
pub fn into_api(self, sys: &dyn DynSystem) -> TokenTree {
|
||||
TokenTree { token: self.tok.into_api(sys), range: self.range }
|
||||
}
|
||||
@@ -58,120 +60,185 @@ pub fn ph(s: &str) -> OwnedPh {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum OwnedTok {
|
||||
Lambda(Vec<OwnedTokTree>, Vec<OwnedTokTree>),
|
||||
Name(VName),
|
||||
S(Paren, Vec<OwnedTokTree>),
|
||||
pub enum GenTok {
|
||||
Lambda(Vec<GenTokTree>),
|
||||
Name(Tok<String>),
|
||||
NS,
|
||||
BR,
|
||||
S(Paren, Vec<GenTokTree>),
|
||||
Atom(AtomFactory),
|
||||
Slot(TreeTicket),
|
||||
Ph(OwnedPh),
|
||||
Bottom(ProjectErrorObj),
|
||||
}
|
||||
impl OwnedTok {
|
||||
pub fn at(self, range: Range<u32>) -> OwnedTokTree { OwnedTokTree { tok: self, range } }
|
||||
impl GenTok {
|
||||
pub fn at(self, range: Range<u32>) -> GenTokTree { GenTokTree { tok: self, range } }
|
||||
pub fn into_api(self, sys: &dyn DynSystem) -> Token {
|
||||
match self {
|
||||
Self::Lambda(x, body) => Token::Lambda(
|
||||
x.into_iter().map(|tt| tt.into_api(sys)).collect_vec(),
|
||||
body.into_iter().map(|tt| tt.into_api(sys)).collect_vec(),
|
||||
),
|
||||
Self::Name(n) => Token::Name(n.into_iter().map(|t| t.marker()).collect_vec()),
|
||||
Self::Lambda(x) => Token::Lambda(x.into_iter().map(|tt| tt.into_api(sys)).collect()),
|
||||
Self::Name(n) => Token::Name(n.marker()),
|
||||
Self::NS => Token::NS,
|
||||
Self::BR => Token::BR,
|
||||
Self::Ph(ph) => Token::Ph(ph.to_api()),
|
||||
Self::S(p, body) => Token::S(p, body.into_iter().map(|tt| tt.into_api(sys)).collect_vec()),
|
||||
Self::Slot(tk) => Token::Slot(tk),
|
||||
Self::Atom(at) => Token::Atom(at.build(sys)),
|
||||
Self::Bottom(err) => Token::Bottom(err_or_ref_to_api(err)),
|
||||
Self::Bottom(err) => Token::Bottom(errv_to_apiv([err])),
|
||||
}
|
||||
}
|
||||
pub fn vname(name: &VName) -> impl Iterator<Item = GenTok> + '_ {
|
||||
let (head, tail) = name.split_first();
|
||||
iter::once(Self::Name(head)).chain(tail.iter().flat_map(|t| [Self::NS, Self::Name(t)]))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GenMacro {
|
||||
pub pattern: Vec<OwnedTokTree>,
|
||||
pub pattern: Vec<GenTokTree>,
|
||||
pub priority: NotNan<f64>,
|
||||
pub template: Vec<OwnedTokTree>,
|
||||
pub template: Vec<GenTokTree>,
|
||||
}
|
||||
|
||||
pub fn tokv_into_api(
|
||||
tokv: impl IntoIterator<Item = OwnedTokTree>,
|
||||
tokv: impl IntoIterator<Item = GenTokTree>,
|
||||
sys: &dyn DynSystem,
|
||||
) -> Vec<TokenTree> {
|
||||
tokv.into_iter().map(|tok| tok.into_api(sys)).collect_vec()
|
||||
}
|
||||
|
||||
pub fn wrap_tokv(items: Vec<OwnedTokTree>, range: Range<u32>) -> OwnedTokTree {
|
||||
pub fn wrap_tokv(items: Vec<GenTokTree>, range: Range<u32>) -> GenTokTree {
|
||||
match items.len() {
|
||||
1 => items.into_iter().next().unwrap(),
|
||||
_ => OwnedTok::S(Paren::Round, items).at(range),
|
||||
_ => GenTok::S(Paren::Round, items).at(range),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GenTree {
|
||||
pub item: GenItem,
|
||||
pub location: Pos,
|
||||
pub struct GenItem {
|
||||
pub item: GenItemKind,
|
||||
pub pos: Pos,
|
||||
}
|
||||
impl GenTree {
|
||||
pub fn cnst(gc: impl ToExpr) -> Self { GenItem::Const(gc.to_expr()).at(Pos::Inherit) }
|
||||
pub fn module<'a>(entries: impl IntoIterator<Item = (&'a str, GenTree)>) -> Self {
|
||||
GenItem::Mod(entries.into_iter().map(|(k, v)| (k.to_string(), v)).collect()).at(Pos::Inherit)
|
||||
}
|
||||
pub fn rule(
|
||||
prio: f64,
|
||||
pat: impl IntoIterator<Item = OwnedTokTree>,
|
||||
tpl: impl IntoIterator<Item = OwnedTokTree>,
|
||||
) -> Self {
|
||||
GenItem::Rule(GenMacro {
|
||||
pattern: pat.into_iter().collect(),
|
||||
priority: NotNan::new(prio).expect("expected to be static"),
|
||||
template: tpl.into_iter().collect(),
|
||||
})
|
||||
.at(Pos::Inherit)
|
||||
}
|
||||
pub fn into_api(
|
||||
self,
|
||||
sys: &dyn DynSystem,
|
||||
with_lazy: &mut impl FnMut(LazyTreeFactory) -> TreeId,
|
||||
) -> Tree {
|
||||
match self.item {
|
||||
GenItem::Const(gc) => Tree::Const(gc.into_api(sys)),
|
||||
GenItem::Rule(GenMacro { pattern, priority, template }) => Tree::Rule(MacroRule {
|
||||
pattern: tokv_into_api(pattern, sys),
|
||||
impl GenItem {
|
||||
pub fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> Item {
|
||||
let kind = match self.item {
|
||||
GenItemKind::Rule(GenMacro { pattern, priority, template }) => ItemKind::Rule(Macro {
|
||||
pattern: tokv_into_api(pattern, ctx.sys()),
|
||||
priority,
|
||||
template: tokv_into_api(template, sys),
|
||||
template: tokv_into_api(template, ctx.sys()),
|
||||
}),
|
||||
GenItem::Mod(entv) => Tree::Mod(TreeModule {
|
||||
children: entv
|
||||
.into_iter()
|
||||
.map(|(name, tree)| (name.to_string(), tree.into_api(sys, with_lazy)))
|
||||
.collect(),
|
||||
GenItemKind::Raw(item) => ItemKind::Raw(item.into_iter().map(|t| t.into_api(ctx.sys())).collect_vec()),
|
||||
GenItemKind::Member(mem) => ItemKind::Member(mem.into_api(ctx))
|
||||
};
|
||||
Item { location: self.pos.to_api(), kind }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cnst(public: bool, name: &str, value: impl ToExpr) -> GenItem {
|
||||
let kind = GenMemberKind::Const(value.to_expr());
|
||||
GenItemKind::Member(GenMember { public, name: intern(name), kind }).at(Pos::Inherit)
|
||||
}
|
||||
pub fn module(
|
||||
public: bool,
|
||||
name: &str,
|
||||
imports: impl IntoIterator<Item = Sym>,
|
||||
items: impl IntoIterator<Item = GenItem>
|
||||
) -> GenItem {
|
||||
let (name, kind) = root_mod(name, imports, items);
|
||||
GenItemKind::Member(GenMember { public, name, kind }).at(Pos::Inherit)
|
||||
}
|
||||
pub fn root_mod(
|
||||
name: &str,
|
||||
imports: impl IntoIterator<Item = Sym>,
|
||||
items: impl IntoIterator<Item = GenItem>
|
||||
) -> (Tok<String>, GenMemberKind) {
|
||||
let kind = GenMemberKind::Mod {
|
||||
imports: imports.into_iter().collect(),
|
||||
items: items.into_iter().collect()
|
||||
};
|
||||
(intern(name), kind)
|
||||
}
|
||||
pub fn rule(
|
||||
prio: f64,
|
||||
pat: impl IntoIterator<Item = GenTokTree>,
|
||||
tpl: impl IntoIterator<Item = GenTokTree>,
|
||||
) -> GenItem {
|
||||
GenItemKind::Rule(GenMacro {
|
||||
pattern: pat.into_iter().collect(),
|
||||
priority: NotNan::new(prio).expect("expected to be static"),
|
||||
template: tpl.into_iter().collect(),
|
||||
})
|
||||
.at(Pos::Inherit)
|
||||
}
|
||||
|
||||
trait_set! {
|
||||
trait LazyMemberCallback = FnOnce() -> GenMemberKind + Send + Sync + DynClone
|
||||
}
|
||||
pub struct LazyMemberFactory(Box<dyn LazyMemberCallback>);
|
||||
impl LazyMemberFactory {
|
||||
pub fn new(cb: impl FnOnce() -> GenMemberKind + Send + Sync + Clone + 'static) -> Self {
|
||||
Self(Box::new(cb))
|
||||
}
|
||||
pub fn build(self) -> GenMemberKind { (self.0)() }
|
||||
}
|
||||
impl Clone for LazyMemberFactory {
|
||||
fn clone(&self) -> Self { Self(clone_box(&*self.0)) }
|
||||
}
|
||||
|
||||
pub enum GenItemKind {
|
||||
Member(GenMember),
|
||||
Raw(Vec<GenTokTree>),
|
||||
Rule(GenMacro),
|
||||
}
|
||||
impl GenItemKind {
|
||||
pub fn at(self, position: Pos) -> GenItem { GenItem { item: self, pos: position } }
|
||||
}
|
||||
|
||||
pub struct GenMember {
|
||||
public: bool,
|
||||
name: Tok<String>,
|
||||
kind: GenMemberKind,
|
||||
}
|
||||
impl GenMember {
|
||||
pub fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> Member {
|
||||
Member { name: self.name.marker(), public: self.public, kind: self.kind.into_api(ctx) }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum GenMemberKind {
|
||||
Const(GenExpr),
|
||||
Mod{
|
||||
imports: Vec<Sym>,
|
||||
items: Vec<GenItem>,
|
||||
},
|
||||
Lazy(LazyMemberFactory)
|
||||
}
|
||||
impl GenMemberKind {
|
||||
pub fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> MemberKind {
|
||||
match self {
|
||||
Self::Lazy(lazy) => MemberKind::Lazy(ctx.with_lazy(lazy)),
|
||||
Self::Const(c) => MemberKind::Const(c.into_api(ctx.sys())),
|
||||
Self::Mod { imports, items } => MemberKind::Module(Module {
|
||||
imports: imports.into_iter().map(|t| t.tok().marker()).collect(),
|
||||
items: items.into_iter().map(|i| i.into_api(ctx)).collect_vec()
|
||||
}),
|
||||
GenItem::Lazy(cb) => Tree::Lazy(with_lazy(cb)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait_set! {
|
||||
trait LazyTreeCallback = FnMut() -> GenTree + Send + Sync + DynClone
|
||||
}
|
||||
pub struct LazyTreeFactory(Box<dyn LazyTreeCallback>);
|
||||
impl LazyTreeFactory {
|
||||
pub fn new(cb: impl FnMut() -> GenTree + Send + Sync + Clone + 'static) -> Self {
|
||||
Self(Box::new(cb))
|
||||
}
|
||||
pub fn build(&mut self) -> GenTree { (self.0)() }
|
||||
}
|
||||
impl Clone for LazyTreeFactory {
|
||||
fn clone(&self) -> Self { Self(clone_box(&*self.0)) }
|
||||
pub trait TreeIntoApiCtx {
|
||||
fn sys(&self) -> &dyn DynSystem;
|
||||
fn with_lazy(&mut self, fac: LazyMemberFactory) -> TreeId;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum GenItem {
|
||||
Const(GenExpr),
|
||||
Mod(HashMap<String, GenTree>),
|
||||
Rule(GenMacro),
|
||||
Lazy(LazyTreeFactory),
|
||||
pub struct TIACtxImpl<'a> {
|
||||
pub sys: &'a dyn DynSystem,
|
||||
pub lazy: &'a mut HashMap<TreeId, MemberRecord>
|
||||
}
|
||||
impl GenItem {
|
||||
pub fn at(self, position: Pos) -> GenTree { GenTree { item: self, location: position } }
|
||||
|
||||
impl<'a> TreeIntoApiCtx for TIACtxImpl<'a> {
|
||||
fn sys(&self) -> &dyn DynSystem { self.sys }
|
||||
fn with_lazy(&mut self, fac: LazyMemberFactory) -> TreeId {
|
||||
let id = TreeId(NonZero::new((self.lazy.len() + 2) as u64).unwrap());
|
||||
self.lazy.insert(id, MemberRecord::Gen(fac));
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user