Began implementing fully isomorphic macros
Like Rust's Proc macros. Now we have preprocessor recursion to worry about. I also made a cool macro for enums
This commit is contained in:
@@ -3,96 +3,103 @@ use std::num::NonZero;
|
||||
use std::sync::Arc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use orchid_api::AtomId;
|
||||
use orchid_api_traits::Decode;
|
||||
use orchid_api_traits::{Coding, Decode};
|
||||
use orchid_base::boxed_iter::BoxedIter;
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::logging::Logger;
|
||||
use orchid_base::reqnot::ReqNot;
|
||||
use orchid_base::reqnot::{Receipt, ReqNot};
|
||||
|
||||
use crate::api;
|
||||
use crate::atom::{get_info, AtomCtx, AtomDynfo, AtomicFeatures, ForeignAtom, TypAtom};
|
||||
use crate::entrypoint::ExtReq;
|
||||
use crate::fs::DeclFs;
|
||||
// use crate::fun::Fun;
|
||||
use crate::lexer::LexerObj;
|
||||
use crate::parser::ParserObj;
|
||||
use crate::system_ctor::{CtedObj, SystemCtor};
|
||||
use crate::tree::GenMemberKind;
|
||||
use crate::tree::MemKind;
|
||||
|
||||
/// System as consumed by foreign code
|
||||
pub trait SystemCard: Default + Send + Sync + 'static {
|
||||
type Ctor: SystemCtor;
|
||||
const ATOM_DEFS: &'static [Option<&'static dyn AtomDynfo>];
|
||||
type Req: Coding;
|
||||
fn atoms() -> impl IntoIterator<Item = Option<Box<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<&'static dyn AtomDynfo>];
|
||||
fn atoms(&self) -> BoxedIter<Option<Box<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<&'static dyn AtomDynfo>] {
|
||||
&[/*Some(Fun::INFO)*/]
|
||||
fn general_atoms() -> impl Iterator<Item = Option<Box<dyn AtomDynfo>>> {
|
||||
[/*Some(Fun::INFO)*/].into_iter()
|
||||
}
|
||||
|
||||
pub fn atom_info_for(
|
||||
sys: &(impl DynSystemCard + ?Sized),
|
||||
tid: TypeId,
|
||||
) -> Option<(api::AtomId, &'static dyn AtomDynfo)> {
|
||||
(sys.atoms().iter().enumerate().map(|(i, o)| (NonZero::new(i as u64 + 1).unwrap(), o)))
|
||||
.chain(general_atoms().iter().enumerate().map(|(i, o)| (NonZero::new(!(i as u64)).unwrap(), o)))
|
||||
.filter_map(|(i, o)| o.as_ref().map(|a| (api::AtomId(i), *a)))
|
||||
) -> Option<(api::AtomId, Box<dyn AtomDynfo>)> {
|
||||
(sys.atoms().enumerate().map(|(i, o)| (NonZero::new(i as u64 + 1).unwrap(), o)))
|
||||
.chain(general_atoms().enumerate().map(|(i, o)| (NonZero::new(!(i as u64)).unwrap(), o)))
|
||||
.filter_map(|(i, o)| o.map(|a| (api::AtomId(i), a)))
|
||||
.find(|ent| ent.1.tid() == tid)
|
||||
}
|
||||
|
||||
pub fn atom_by_idx(
|
||||
sys: &(impl DynSystemCard + ?Sized),
|
||||
tid: api::AtomId,
|
||||
) -> Option<&'static dyn AtomDynfo> {
|
||||
) -> Option<Box<dyn AtomDynfo>> {
|
||||
if (u64::from(tid.0) >> (u64::BITS - 1)) & 1 == 1 {
|
||||
general_atoms()[!u64::from(tid.0) as usize]
|
||||
general_atoms().nth(!u64::from(tid.0) as usize).unwrap()
|
||||
} else {
|
||||
sys.atoms()[u64::from(tid.0) as usize - 1]
|
||||
sys.atoms().nth(u64::from(tid.0) as usize - 1).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolv_atom(
|
||||
sys: &(impl DynSystemCard + ?Sized),
|
||||
atom: &api::Atom,
|
||||
) -> &'static dyn AtomDynfo {
|
||||
) -> Box<dyn AtomDynfo> {
|
||||
let tid = api::AtomId::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 }
|
||||
fn atoms(&self) -> BoxedIter<Option<Box<dyn AtomDynfo>>> { Box::new(Self::atoms().into_iter()) }
|
||||
}
|
||||
|
||||
/// System as defined by author
|
||||
pub trait System: Send + Sync + SystemCard + 'static {
|
||||
fn env() -> Vec<(Tok<String>, GenMemberKind)>;
|
||||
fn env() -> Vec<(Tok<String>, MemKind)>;
|
||||
fn vfs() -> DeclFs;
|
||||
fn lexers() -> Vec<LexerObj>;
|
||||
fn parsers() -> Vec<ParserObj>;
|
||||
fn request(hand: ExtReq, req: Self::Req) -> Receipt;
|
||||
}
|
||||
|
||||
pub trait DynSystem: Send + Sync + DynSystemCard + 'static {
|
||||
fn dyn_env(&self) -> HashMap<Tok<String>, GenMemberKind>;
|
||||
fn dyn_env(&self) -> HashMap<Tok<String>, MemKind>;
|
||||
fn dyn_vfs(&self) -> DeclFs;
|
||||
fn dyn_lexers(&self) -> Vec<LexerObj>;
|
||||
fn dyn_parsers(&self) -> Vec<ParserObj>;
|
||||
fn dyn_request(&self, hand: ExtReq, req: Vec<u8>) -> Receipt;
|
||||
fn card(&self) -> &dyn DynSystemCard;
|
||||
}
|
||||
|
||||
impl<T: System> DynSystem for T {
|
||||
fn dyn_env(&self) -> HashMap<Tok<String>, GenMemberKind> { Self::env().into_iter().collect() }
|
||||
fn dyn_env(&self) -> HashMap<Tok<String>, MemKind> { Self::env().into_iter().collect() }
|
||||
fn dyn_vfs(&self) -> DeclFs { Self::vfs() }
|
||||
fn dyn_lexers(&self) -> Vec<LexerObj> { Self::lexers() }
|
||||
fn dyn_parsers(&self) -> Vec<ParserObj> { Self::parsers() }
|
||||
fn dyn_request(&self, hand: ExtReq, req: Vec<u8>) -> Receipt {
|
||||
Self::request(hand, <Self as SystemCard>::Req::decode(&mut &req[..]))
|
||||
}
|
||||
fn card(&self) -> &dyn DynSystemCard { self }
|
||||
}
|
||||
|
||||
@@ -101,7 +108,7 @@ pub fn downcast_atom<A: AtomicFeatures>(foreign: ForeignAtom) -> Result<TypAtom<
|
||||
let ctx = foreign.ctx.clone();
|
||||
let info_ent = (ctx.cted.deps().find(|s| s.id() == foreign.atom.owner))
|
||||
.map(|sys| get_info::<A>(sys.get_card()))
|
||||
.filter(|(pos, _)| AtomId::decode(&mut data) == *pos);
|
||||
.filter(|(pos, _)| api::AtomId::decode(&mut data) == *pos);
|
||||
match info_ent {
|
||||
None => Err(foreign),
|
||||
Some((_, info)) => {
|
||||
|
||||
Reference in New Issue
Block a user