This commit is contained in:
2024-07-18 16:07:36 +02:00
parent 949b3758fd
commit cc3699bbe7
31 changed files with 1021 additions and 312 deletions

View File

@@ -22,4 +22,3 @@ ordered-float = "4.2.0"
paste = "1.0.15"
substack = "1.1.0"
trait-set = "0.3.0"
typeid = "1.0.0"

View File

@@ -1,4 +1,4 @@
use std::any::{type_name, Any};
use std::any::{type_name, Any, TypeId};
use std::io::{Read, Write};
use std::ops::Deref;
@@ -9,7 +9,6 @@ use orchid_api_traits::{Coding, Decode, Request};
use orchid_base::location::Pos;
use orchid_base::reqnot::Requester;
use trait_set::trait_set;
use typeid::ConstTypeId;
use crate::error::ProjectError;
use crate::expr::{ExprHandle, GenExpr};
@@ -33,19 +32,22 @@ impl<A: Atomic> AtomCard for A {
pub trait AtomicFeatures: Atomic {
fn factory(self) -> AtomFactory;
fn info() -> &'static AtomInfo;
type Info: AtomDynfo;
const INFO: &'static Self::Info;
}
pub trait AtomicFeaturesImpl<Variant: AtomicVariant> {
fn _factory(self) -> AtomFactory;
fn _info() -> &'static AtomInfo;
type _Info: AtomDynfo;
const _INFO: &'static Self::_Info;
}
impl<A: Atomic + AtomicFeaturesImpl<A::Variant>> AtomicFeatures for A {
fn factory(self) -> AtomFactory { self._factory() }
fn info() -> &'static AtomInfo { Self::_info() }
type Info = <Self as AtomicFeaturesImpl<A::Variant>>::_Info;
const INFO: &'static Self::Info = Self::_INFO;
}
pub fn get_info<A: AtomCard>(sys: &(impl DynSystemCard + ?Sized)) -> (u64, &AtomInfo) {
atom_info_for(sys, ConstTypeId::of::<A>()).unwrap_or_else(|| {
pub fn get_info<A: AtomCard>(sys: &(impl DynSystemCard + ?Sized)) -> (u64, &'static dyn AtomDynfo) {
atom_info_for(sys, TypeId::of::<A>()).unwrap_or_else(|| {
panic!("Atom {} not associated with system {}", type_name::<A>(), sys.name())
})
}
@@ -75,14 +77,14 @@ impl<A: AtomCard> Deref for TypAtom<A> {
fn deref(&self) -> &Self::Target { &self.value }
}
pub struct AtomInfo {
pub tid: ConstTypeId,
pub decode: fn(&[u8]) -> Box<dyn Any>,
pub call: fn(&[u8], SysCtx, ExprTicket) -> GenExpr,
pub call_ref: fn(&[u8], SysCtx, ExprTicket) -> GenExpr,
pub same: fn(&[u8], SysCtx, &[u8]) -> bool,
pub handle_req: fn(&[u8], SysCtx, &mut dyn Read, &mut dyn Write),
pub drop: fn(&[u8], 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);
}
trait_set! {
@@ -102,4 +104,4 @@ impl Clone for AtomFactory {
pub struct ErrorNotCallable;
impl ProjectError for ErrorNotCallable {
const DESCRIPTION: &'static str = "This atom is not callable";
}
}

View File

@@ -1,11 +1,19 @@
use std::{any::{type_name, Any}, borrow::Cow, io::{Read, Write}, num::NonZeroU64};
use std::any::{type_name, Any, TypeId};
use std::borrow::Cow;
use std::io::{Read, Write};
use std::marker::PhantomData;
use std::num::NonZeroU64;
use orchid_api::{atom::LocalAtom, expr::ExprTicket};
use orchid_api::atom::LocalAtom;
use orchid_api::expr::ExprTicket;
use orchid_api_traits::{Decode, Encode};
use orchid_base::id_store::{IdRecord, IdStore};
use typeid::ConstTypeId;
use crate::{atom::{AtomCard, AtomFactory, AtomInfo, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrorNotCallable}, expr::{bot, ExprHandle, GenExpr}, system::{atom_info_for, SysCtx}};
use crate::atom::{
AtomCard, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrorNotCallable,
};
use crate::expr::{bot, ExprHandle, GenExpr};
use crate::system::{atom_info_for, SysCtx};
pub struct OwnedVariant;
impl AtomicVariant for OwnedVariant {}
@@ -19,26 +27,37 @@ impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVari
LocalAtom { drop: true, data }
})
}
fn _info() -> &'static AtomInfo {
fn with_atom<U>(mut b: &[u8], f: impl FnOnce(IdRecord<'_, Box<dyn DynOwnedAtom>>) -> U) -> U {
f(OBJ_STORE.get(NonZeroU64::decode(&mut b)).expect("Received invalid atom ID"))
}
&const {
AtomInfo {
tid: ConstTypeId::of::<Self>(),
decode: |mut b| Box::new(<Self as Atomic>::Data::decode(&mut b)),
call: |b, ctx, arg| with_atom(b, |a| a.remove().dyn_call(ctx, arg)),
call_ref: |b, ctx, arg| with_atom(b, |a| a.dyn_call_ref(ctx, arg)),
same: |b1, ctx, b2| with_atom(b1, |a1| with_atom(b2, |a2| a1.dyn_same(ctx, &**a2))),
handle_req: |b, ctx, req, rep| with_atom(b, |a| a.dyn_handle_req(ctx, req, rep)),
drop: |b, ctx| with_atom(b, |a| a.remove().dyn_free(ctx)),
}
}
type _Info = OwnedAtomDynfo<A>;
const _INFO: &'static Self::_Info = &OwnedAtomDynfo(PhantomData);
}
fn with_atom<U>(mut b: &[u8], f: impl FnOnce(IdRecord<'_, Box<dyn DynOwnedAtom>>) -> U) -> U {
f(OBJ_STORE.get(NonZeroU64::decode(&mut b)).expect("Received invalid atom ID"))
}
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> {
Box::new(<T as AtomCard>::Data::decode(&mut &data[..]))
}
fn call(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
with_atom(buf, |a| a.remove().dyn_call(ctx, arg))
}
fn call_ref(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
with_atom(buf, |a| a.dyn_call_ref(ctx, arg))
}
fn same(&self, buf: &[u8], ctx: SysCtx, 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) {
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)) }
}
/// Atoms that have a [Drop]
pub trait OwnedAtom: AtomCard + Send + Sync + Any + Clone + 'static {
pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Send + Sync + Any + Clone + 'static {
fn val(&self) -> Cow<'_, Self::Data>;
#[allow(unused_variables)]
fn call_ref(&self, arg: ExprHandle) -> GenExpr { bot(ErrorNotCallable) }
@@ -61,7 +80,7 @@ pub trait OwnedAtom: AtomCard + Send + Sync + Any + Clone + 'static {
fn free(self, ctx: SysCtx) {}
}
pub trait DynOwnedAtom: Send + Sync + 'static {
fn atom_tid(&self) -> ConstTypeId;
fn atom_tid(&self) -> TypeId;
fn as_any_ref(&self) -> &dyn Any;
fn encode(&self, buffer: &mut dyn Write);
fn dyn_call_ref(&self, ctx: SysCtx, arg: ExprTicket) -> GenExpr;
@@ -71,7 +90,7 @@ pub trait DynOwnedAtom: Send + Sync + 'static {
fn dyn_free(self: Box<Self>, ctx: SysCtx);
}
impl<T: OwnedAtom> DynOwnedAtom for T {
fn atom_tid(&self) -> ConstTypeId { ConstTypeId::of::<T>() }
fn atom_tid(&self) -> TypeId { TypeId::of::<T>() }
fn as_any_ref(&self) -> &dyn Any { self }
fn encode(&self, buffer: &mut dyn Write) { self.val().as_ref().encode(buffer) }
fn dyn_call_ref(&self, ctx: SysCtx, arg: ExprTicket) -> GenExpr {
@@ -81,7 +100,7 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
self.call(ExprHandle::from_args(ctx, arg))
}
fn dyn_same(&self, ctx: SysCtx, other: &dyn DynOwnedAtom) -> bool {
if ConstTypeId::of::<Self>() != other.as_any_ref().type_id() {
if TypeId::of::<Self>() != other.as_any_ref().type_id() {
return false;
}
let other_self = other.as_any_ref().downcast_ref().expect("The type_ids are the same");
@@ -93,4 +112,4 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
fn dyn_free(self: Box<Self>, ctx: SysCtx) { self.free(ctx) }
}
pub(crate) static OBJ_STORE: IdStore<Box<dyn DynOwnedAtom>> = IdStore::new();
pub(crate) static OBJ_STORE: IdStore<Box<dyn DynOwnedAtom>> = IdStore::new();

View File

@@ -1,10 +1,18 @@
use std::{any::type_name, fmt, io::Write};
use std::any::{type_name, Any, TypeId};
use std::fmt;
use std::io::Write;
use std::marker::PhantomData;
use orchid_api::atom::LocalAtom;
use orchid_api::expr::ExprTicket;
use orchid_api_traits::{Coding, Decode, Encode};
use typeid::ConstTypeId;
use crate::{atom::{get_info, AtomCard, AtomFactory, AtomInfo, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrorNotCallable}, expr::{bot, ExprHandle, GenExpr}, system::SysCtx};
use crate::atom::{
get_info, AtomCard, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant,
ErrorNotCallable,
};
use crate::expr::{bot, ExprHandle, GenExpr};
use crate::system::SysCtx;
pub struct ThinVariant;
impl AtomicVariant for ThinVariant {}
@@ -16,22 +24,32 @@ impl<A: ThinAtom + Atomic<Variant = ThinVariant>> AtomicFeaturesImpl<ThinVariant
LocalAtom { drop: false, data: buf }
})
}
fn _info() -> &'static AtomInfo {
&const {
AtomInfo {
tid: ConstTypeId::of::<Self>(),
decode: |mut b| Box::new(Self::decode(&mut b)),
call: |mut b, ctx, extk| Self::decode(&mut b).call(ExprHandle::from_args(ctx, extk)),
call_ref: |mut b, ctx, extk| Self::decode(&mut b).call(ExprHandle::from_args(ctx, extk)),
handle_req: |mut b, ctx, req, rep| Self::decode(&mut b).handle_req(ctx, Decode::decode(req), rep),
same: |mut b1, ctx, mut b2| Self::decode(&mut b1).same(ctx, &Self::decode(&mut b2)),
drop: |mut b1, _| eprintln!("Received drop signal for non-drop atom {:?}", Self::decode(&mut b1)),
}
}
type _Info = ThinAtomDynfo<Self>;
const _INFO: &'static Self::_Info = &ThinAtomDynfo(PhantomData);
}
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 {
T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg))
}
fn call_ref(&self, buf: &[u8], ctx: SysCtx, 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 same(&self, buf: &[u8], ctx: SysCtx, buf2: &[u8]) -> bool {
T::decode(&mut &buf[..]).same(ctx, &T::decode(&mut &buf2[..]))
}
fn drop(&self, buf: &[u8], _ctx: SysCtx) {
eprintln!("Received drop signal for non-drop atom {:?}", T::decode(&mut &buf[..]))
}
}
pub trait ThinAtom: AtomCard<Data = Self> + Coding + fmt::Debug {
pub trait ThinAtom: AtomCard<Data = Self> + Coding + fmt::Debug + Send + Sync + 'static {
#[allow(unused_variables)]
fn call(&self, arg: ExprHandle) -> GenExpr { bot(ErrorNotCallable) }
#[allow(unused_variables)]

View File

@@ -1,6 +1,9 @@
use orchid_base::location::Pos;
use crate::{atom::{AtomicFeatures, TypAtom}, error::{ProjectError, ProjectResult}, expr::{atom, bot_obj, ExprHandle, GenExpr, OwnedExpr}, system::downcast_atom};
use crate::atom::{AtomicFeatures, TypAtom};
use crate::error::{ProjectError, ProjectResult};
use crate::expr::{atom, bot_obj, ExprHandle, GenExpr, OwnedExpr};
use crate::system::downcast_atom;
pub trait TryFromExpr: Sized {
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self>;
@@ -25,14 +28,14 @@ impl ProjectError for ErrorNotAtom {
pub struct ErrorUnexpectedType(Pos);
impl ProjectError for ErrorUnexpectedType {
const DESCRIPTION: &'static str = "Type error";
fn one_position(&self) -> Pos {
self.0.clone()
}
fn one_position(&self) -> Pos { self.0.clone() }
}
impl<A: AtomicFeatures> TryFromExpr for TypAtom<A> {
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self> {
OwnedExpr::new(expr).foreign_atom().map_err(|ex| ErrorNotAtom(ex.pos.clone()).pack())
OwnedExpr::new(expr)
.foreign_atom()
.map_err(|ex| ErrorNotAtom(ex.pos.clone()).pack())
.and_then(|f| downcast_atom(f).map_err(|f| ErrorUnexpectedType(f.pos).pack()))
}
}
@@ -43,13 +46,13 @@ pub trait ToExpr {
impl<T: ToExpr> ToExpr for ProjectResult<T> {
fn to_expr(self) -> GenExpr {
match self {
Err(e) => bot_obj(e),
Ok(t) => t.to_expr(),
}
match self {
Err(e) => bot_obj(e),
Ok(t) => t.to_expr(),
}
}
}
impl<A: AtomicFeatures> ToExpr for A {
fn to_expr(self) -> GenExpr { atom(self) }
}
}

View File

@@ -19,7 +19,7 @@ use orchid_base::interner::{deintern, init_replica, sweep_replica};
use orchid_base::name::PathSlice;
use orchid_base::reqnot::{ReqNot, Requester};
use crate::atom::AtomInfo;
use crate::atom::AtomDynfo;
use crate::error::{err_or_ref_to_api, unpack_err};
use crate::fs::VirtFS;
use crate::lexer::LexContext;
@@ -48,7 +48,7 @@ pub struct SystemRecord {
pub fn with_atom_record<T>(
systems: &Mutex<HashMap<SysId, SystemRecord>>,
atom: &Atom,
cb: impl FnOnce(&AtomInfo, CtedObj, &[u8]) -> T,
cb: impl FnOnce(&'static dyn AtomDynfo, CtedObj, &[u8]) -> T,
) -> T {
let mut data = &atom.data[..];
let systems_g = systems.lock().unwrap();
@@ -77,7 +77,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(data, SysCtx{ reqnot, id: atom.owner, cted })
})
}
}),

View File

@@ -10,7 +10,7 @@ use orchid_api::error::{GetErrorDetails, ProjErr, ProjErrId, ProjErrOrRef};
use orchid_api::proto::ExtMsgSet;
use orchid_base::boxed_iter::{box_once, BoxedIter};
use orchid_base::clone;
use orchid_base::error::{ErrorDetails, ErrorPosition};
use orchid_base::error::{ErrorPosition, OwnedError};
use orchid_base::interner::{deintern, intern};
use orchid_base::location::{GetSrc, Pos};
use orchid_base::reqnot::{ReqNot, Requester};
@@ -290,12 +290,16 @@ pub(crate) fn err_or_ref_to_api(err: ProjectErrorObj) -> ProjErrOrRef {
}
pub fn err_from_api(err: &ProjErr, reqnot: ReqNot<ExtMsgSet>) -> ProjectErrorObj {
Arc::new(RelayedError { id: None, reqnot, details: ErrorDetails::from_api(err).into() })
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>) -> ProjectErrorObj {
pub(crate) fn err_from_api_or_ref(
err: &ProjErrOrRef,
reqnot: ReqNot<ExtMsgSet>,
) -> ProjectErrorObj {
match err {
ProjErrOrRef::Known(id) => Arc::new(RelayedError { id: Some(*id), reqnot, details: OnceLock::default() }),
ProjErrOrRef::Known(id) =>
Arc::new(RelayedError { id: Some(*id), reqnot, details: OnceLock::default() }),
ProjErrOrRef::New(err) => err_from_api(err, reqnot),
}
}
@@ -303,18 +307,18 @@ pub(crate) fn err_from_api_or_ref(err: &ProjErrOrRef, reqnot: ReqNot<ExtMsgSet>)
struct RelayedError {
pub id: Option<ProjErrId>,
pub reqnot: ReqNot<ExtMsgSet>,
pub details: OnceLock<ErrorDetails>,
pub details: OnceLock<OwnedError>,
}
impl RelayedError {
fn details(&self) -> &ErrorDetails {
fn details(&self) -> &OwnedError {
let Self { id, reqnot, details: data } = self;
data.get_or_init(clone!(reqnot; move || {
let id = id.expect("Either data or ID must be initialized");
let projerr = reqnot.request(GetErrorDetails(id));
ErrorDetails {
OwnedError {
description: deintern(projerr.description),
message: projerr.message,
locations: projerr.locations.iter().map(ErrorPosition::from_api).collect_vec(),
positions: projerr.locations.iter().map(ErrorPosition::from_api).collect_vec(),
}
}))
}
@@ -325,6 +329,6 @@ impl DynProjectError for RelayedError {
fn as_any_ref(&self) -> &dyn std::any::Any { self }
fn into_packed(self: Arc<Self>) -> ProjectErrorObj { self }
fn positions(&self) -> BoxedIter<'_, ErrorPosition> {
Box::new(self.details().locations.iter().cloned())
Box::new(self.details().positions.iter().cloned())
}
}

View File

@@ -6,9 +6,9 @@ use trait_set::trait_set;
use crate::atom::Atomic;
use crate::atom_owned::{OwnedAtom, OwnedVariant};
use crate::conv::{ToExpr, TryFromExpr};
use crate::expr::{ExprHandle, GenExpr};
use crate::system::SysCtx;
use crate::conv::{ToExpr, TryFromExpr};
trait_set! {
trait FunCB = FnOnce(ExprHandle) -> GenExpr + DynClone + Send + Sync + 'static;
@@ -16,7 +16,9 @@ trait_set! {
pub struct Fun(Box<dyn FunCB>);
impl Fun {
pub fn new<I: TryFromExpr, O: ToExpr>(f: impl FnOnce(I) -> O + Clone + Send + Sync + 'static) -> Self {
pub fn new<I: TryFromExpr, O: ToExpr>(
f: impl FnOnce(I) -> O + Clone + Send + Sync + 'static,
) -> Self {
Self(Box::new(|eh| I::try_from_expr(eh).map(f).to_expr()))
}
}

View File

@@ -10,7 +10,7 @@ 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,
};
use crate::tree::{GenTok, GenTokTree};
use crate::tree::{OwnedTok, OwnedTokTree};
pub struct LexContext<'a> {
pub text: &'a Tok<String>,
@@ -20,13 +20,13 @@ pub struct LexContext<'a> {
pub reqnot: ReqNot<ExtMsgSet>,
}
impl<'a> LexContext<'a> {
pub fn recurse(&self, tail: &'a str) -> ProjectResult<(&'a str, GenTokTree)> {
pub fn recurse(&self, tail: &'a str) -> ProjectResult<(&'a str, OwnedTokTree)> {
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..], GenTok::Slot(lx.ticket).at(start..lx.pos)))
.map(|lx| (&self.text[lx.pos as usize..], OwnedTok::Slot(lx.ticket).at(start..lx.pos)))
}
pub fn pos(&self, tail: &'a str) -> u32 { (self.text.len() - tail.len()) as u32 }
@@ -47,7 +47,7 @@ pub trait Lexer: Send + Sync + Sized + Default + 'static {
fn lex<'a>(
tail: &'a str,
ctx: &'a LexContext<'a>,
) -> Option<ProjectResult<(&'a str, GenTokTree)>>;
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>>;
}
pub trait DynLexer: Send + Sync + 'static {
@@ -56,7 +56,7 @@ pub trait DynLexer: Send + Sync + 'static {
&self,
tail: &'a str,
ctx: &'a LexContext<'a>,
) -> Option<ProjectResult<(&'a str, GenTokTree)>>;
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>>;
}
impl<T: Lexer> DynLexer for T {
@@ -65,7 +65,7 @@ impl<T: Lexer> DynLexer for T {
&self,
tail: &'a str,
ctx: &'a LexContext<'a>,
) -> Option<ProjectResult<(&'a str, GenTokTree)>> {
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>> {
T::lex(tail, ctx)
}
}

View File

@@ -1,4 +1,7 @@
pub mod atom;
pub mod atom_owned;
pub mod atom_thin;
pub mod conv;
pub mod entrypoint;
pub mod error;
pub mod expr;
@@ -10,6 +13,3 @@ pub mod other_system;
pub mod system;
pub mod system_ctor;
pub mod tree;
pub mod conv;
pub mod atom_thin;
pub mod atom_owned;

View File

@@ -1,11 +1,11 @@
use orchid_api_traits::Decode;
use std::any::TypeId;
use orchid_api::proto::ExtMsgSet;
use orchid_api::system::SysId;
use orchid_api_traits::Decode;
use orchid_base::reqnot::ReqNot;
use typeid::ConstTypeId;
use crate::atom::{get_info, AtomCard, AtomInfo, AtomicFeatures, ForeignAtom, TypAtom};
use crate::atom::{get_info, AtomCard, AtomDynfo, AtomicFeatures, ForeignAtom, TypAtom};
use crate::fs::DeclFs;
use crate::fun::Fun;
use crate::lexer::LexerObj;
@@ -15,44 +15,45 @@ use crate::tree::GenTree;
/// System as consumed by foreign code
pub trait SystemCard: Default + Send + Sync + 'static {
type Ctor: SystemCtor;
const ATOM_DEFS: &'static [Option<fn() -> &'static AtomInfo>];
const ATOM_DEFS: &'static [Option<&'static dyn AtomDynfo>];
}
pub trait DynSystemCard: Send + Sync + 'static {
fn name(&self) -> &'static str;
/// Atoms explicitly defined by the system card. Do not rely on this for
/// querying atoms as it doesn't include the general atom types
fn atoms(&self) -> &'static [Option<fn() -> &'static AtomInfo>];
fn atoms(&self) -> &'static [Option<&'static dyn AtomDynfo>];
}
/// Atoms supported by this package which may appear in all extensions.
/// The indices of these are bitwise negated, such that the MSB of an atom index
/// marks whether it belongs to this package (0) or the importer (1)
fn general_atoms() -> &'static [Option<fn () -> &'static AtomInfo>] {
&[Some(Fun::info)]
}
fn general_atoms() -> &'static [Option<&'static dyn AtomDynfo>] { &[Some(Fun::INFO)] }
pub fn atom_info_for(
sys: &(impl DynSystemCard + ?Sized),
tid: ConstTypeId,
) -> Option<(u64, &AtomInfo)> {
tid: TypeId,
) -> Option<(u64, &'static dyn AtomDynfo)> {
(sys.atoms().iter().enumerate().map(|(i, o)| (i as u64, o)))
.chain(general_atoms().iter().enumerate().map(|(i, o)| (!(i as u64), o)))
.filter_map(|(i, o)| o.as_ref().map(|a| (i, a())))
.find(|ent| ent.1.tid == tid)
.filter_map(|(i, o)| o.as_ref().map(|a| (i, *a)))
.find(|ent| ent.1.tid() == tid)
}
pub fn atom_by_idx(sys: &(impl DynSystemCard + ?Sized), tid: u64) -> Option<&'static AtomInfo> {
pub fn atom_by_idx(
sys: &(impl DynSystemCard + ?Sized),
tid: u64,
) -> Option<&'static dyn AtomDynfo> {
if (tid >> (u64::BITS - 1)) & 1 == 1 {
general_atoms()[!tid as usize].map(|f| f())
general_atoms()[!tid as usize]
} else {
sys.atoms()[tid as usize].map(|f| f())
sys.atoms()[tid as usize]
}
}
impl<T: SystemCard> DynSystemCard for T {
fn name(&self) -> &'static str { T::Ctor::NAME }
fn atoms(&self) -> &'static [Option<fn() -> &'static AtomInfo>] { Self::ATOM_DEFS }
fn atoms(&self) -> &'static [Option<&'static dyn AtomDynfo>] { Self::ATOM_DEFS }
}
/// System as defined by author
@@ -85,7 +86,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(data);
let value = *val.downcast::<A::Data>().expect("atom decode returned wrong type");
Ok(TypAtom { value, data: foreign })
},

View File

@@ -4,38 +4,34 @@ use ahash::HashMap;
use dyn_clone::{clone_box, DynClone};
use itertools::Itertools;
use orchid_api::tree::{
MacroRule, Paren, Placeholder, PlaceholderKind, Token, TokenTree, Tree, TreeId, TreeModule,
MacroRule, Paren, PlaceholderKind, Token, TokenTree, Tree, TreeId, TreeModule,
TreeTicket,
};
use orchid_base::interner::{intern, Tok};
use orchid_base::interner::intern;
use orchid_base::location::Pos;
use orchid_base::name::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::expr::GenExpr;
use crate::system::DynSystem;
#[derive(Clone)]
pub struct GenPh {
pub name: Tok<String>,
pub kind: PlaceholderKind,
}
#[derive(Clone)]
pub struct GenTokTree {
pub tok: GenTok,
pub struct OwnedTokTree {
pub tok: OwnedTok,
pub range: Range<u32>,
}
impl GenTokTree {
impl OwnedTokTree {
pub fn into_api(self, sys: &dyn DynSystem) -> TokenTree {
TokenTree { token: self.tok.into_api(sys), range: self.range }
}
}
pub fn ph(s: &str) -> GenPh {
pub fn ph(s: &str) -> OwnedPh {
match s.strip_prefix("..") {
Some(v_tail) => {
let (mid, priority) = match v_tail.split_once(':') {
@@ -49,29 +45,30 @@ pub fn ph(s: &str) -> GenPh {
if konst::string::starts_with(name, "_") {
panic!("Names starting with an underscore indicate a single-name scalar placeholder")
}
GenPh { name: intern(name), kind: PlaceholderKind::Vector { nonzero, priority } }
OwnedPh { name: intern(name), kind: PlaceholderKind::Vector { nonzero, priority } }
},
None => match konst::string::strip_prefix(s, "$_") {
Some(name) => GenPh { name: intern(name), kind: PlaceholderKind::Name },
Some(name) => OwnedPh { name: intern(name), kind: PlaceholderKind::Name },
None => match konst::string::strip_prefix(s, "$") {
None => panic!("Invalid placeholder"),
Some(name) => GenPh { name: intern(name), kind: PlaceholderKind::Scalar },
Some(name) => OwnedPh { name: intern(name), kind: PlaceholderKind::Scalar },
},
},
}
}
#[derive(Clone)]
pub enum GenTok {
Lambda(Vec<GenTokTree>, Vec<GenTokTree>),
pub enum OwnedTok {
Lambda(Vec<OwnedTokTree>, Vec<OwnedTokTree>),
Name(VName),
S(Paren, Vec<GenTokTree>),
S(Paren, Vec<OwnedTokTree>),
Atom(AtomFactory),
Slot(TreeTicket),
Ph(GenPh),
Ph(OwnedPh),
Bottom(ProjectErrorObj),
}
impl GenTok {
pub fn at(self, range: Range<u32>) -> GenTokTree { GenTokTree { tok: self, range } }
impl OwnedTok {
pub fn at(self, range: Range<u32>) -> OwnedTokTree { OwnedTokTree { tok: self, range } }
pub fn into_api(self, sys: &dyn DynSystem) -> Token {
match self {
Self::Lambda(x, body) => Token::Lambda(
@@ -79,32 +76,33 @@ impl GenTok {
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::Ph(GenPh { name, kind }) => Token::Ph(Placeholder { name: name.marker(), kind }),
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)),
}
}
}
#[derive(Clone)]
pub struct GenMacro {
pub pattern: Vec<GenTokTree>,
pub pattern: Vec<OwnedTokTree>,
pub priority: NotNan<f64>,
pub template: Vec<GenTokTree>,
pub template: Vec<OwnedTokTree>,
}
pub fn tokv_into_api(
tokv: impl IntoIterator<Item = GenTokTree>,
tokv: impl IntoIterator<Item = OwnedTokTree>,
sys: &dyn DynSystem,
) -> Vec<TokenTree> {
tokv.into_iter().map(|tok| tok.into_api(sys)).collect_vec()
}
pub fn wrap_tokv(items: Vec<GenTokTree>, range: Range<u32>) -> GenTokTree {
pub fn wrap_tokv(items: Vec<OwnedTokTree>, range: Range<u32>) -> OwnedTokTree {
match items.len() {
1 => items.into_iter().next().unwrap(),
_ => GenTok::S(Paren::Round, items).at(range),
_ => OwnedTok::S(Paren::Round, items).at(range),
}
}
@@ -120,8 +118,8 @@ impl GenTree {
}
pub fn rule(
prio: f64,
pat: impl IntoIterator<Item = GenTokTree>,
tpl: impl IntoIterator<Item = GenTokTree>,
pat: impl IntoIterator<Item = OwnedTokTree>,
tpl: impl IntoIterator<Item = OwnedTokTree>,
) -> Self {
GenItem::Rule(GenMacro {
pattern: pat.into_iter().collect(),