Cleaned up atoms

- Atoms now use MFBI to distinguish between thin and owned atoms.
- Introduced TryFromExpr and ToExpr (formerly ToClause) from the old FFI
- Standardized on Bottom being a ProjErr, which means that there will be no RTErr
This commit is contained in:
2024-07-02 00:57:11 +02:00
parent fc8441f080
commit 949b3758fd
25 changed files with 383 additions and 297 deletions

View File

@@ -1,9 +1,11 @@
use orchid_api_traits::Decode;
use orchid_api::proto::ExtMsgSet;
use orchid_api::system::SysId;
use orchid_base::reqnot::ReqNot;
use typeid::ConstTypeId;
use crate::atom::{decode_atom, owned_atom_info, AtomCard, AtomInfo, ForeignAtom, TypAtom};
use crate::atom::{get_info, AtomCard, AtomInfo, AtomicFeatures, ForeignAtom, TypAtom};
use crate::fs::DeclFs;
use crate::fun::Fun;
use crate::lexer::LexerObj;
@@ -13,42 +15,44 @@ 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<AtomInfo>];
const ATOM_DEFS: &'static [Option<fn() -> &'static AtomInfo>];
}
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<AtomInfo>];
fn atoms(&self) -> &'static [Option<fn() -> &'static AtomInfo>];
}
/// 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)
const GENERAL_ATOMS: &[Option<AtomInfo>] = &[Some(owned_atom_info::<Fun>())];
fn general_atoms() -> &'static [Option<fn () -> &'static AtomInfo>] {
&[Some(Fun::info)]
}
pub fn atom_info_for(
sys: &(impl DynSystemCard + ?Sized),
tid: ConstTypeId,
) -> Option<(u64, &AtomInfo)> {
(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)))
.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)
}
pub fn atom_by_idx(sys: &(impl DynSystemCard + ?Sized), tid: u64) -> Option<&AtomInfo> {
pub fn atom_by_idx(sys: &(impl DynSystemCard + ?Sized), tid: u64) -> Option<&'static AtomInfo> {
if (tid >> (u64::BITS - 1)) & 1 == 1 {
GENERAL_ATOMS[!tid as usize].as_ref()
general_atoms()[!tid as usize].map(|f| f())
} else {
sys.atoms()[tid as usize].as_ref()
sys.atoms()[tid as usize].map(|f| f())
}
}
impl<T: SystemCard> DynSystemCard for T {
fn name(&self) -> &'static str { T::Ctor::NAME }
fn atoms(&self) -> &'static [Option<AtomInfo>] { Self::ATOM_DEFS }
fn atoms(&self) -> &'static [Option<fn() -> &'static AtomInfo>] { Self::ATOM_DEFS }
}
/// System as defined by author
@@ -73,12 +77,18 @@ impl<T: System> DynSystem for T {
}
pub fn downcast_atom<A: AtomCard>(foreign: ForeignAtom) -> Result<TypAtom<A>, ForeignAtom> {
match (foreign.expr.get_ctx().cted.deps())
.find(|s| s.id() == foreign.atom.owner)
.and_then(|sys| decode_atom::<A>(sys.get_card(), &foreign.atom))
{
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))
.map(|sys| get_info::<A>(sys.get_card()))
.filter(|(pos, _)| u64::decode(&mut data) == *pos);
match info_ent {
None => Err(foreign),
Some(value) => Ok(TypAtom { value, data: foreign }),
Some((_, info)) => {
let val = (info.decode)(data);
let value = *val.downcast::<A::Data>().expect("atom decode returned wrong type");
Ok(TypAtom { value, data: foreign })
},
}
}