Lexer test mode works
This commit is contained in:
@@ -108,6 +108,7 @@ pub trait AtomDynfo: Send + Sync + 'static {
|
||||
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 print(&self, ctx: AtomCtx<'_>) -> String;
|
||||
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<'_>);
|
||||
@@ -127,8 +128,8 @@ impl Clone for AtomFactory {
|
||||
fn clone(&self) -> Self { AtomFactory(clone_box(&*self.0)) }
|
||||
}
|
||||
|
||||
pub struct ErrorNotCallable;
|
||||
impl ProjectError for ErrorNotCallable {
|
||||
pub struct ErrNotCallable;
|
||||
impl ProjectError for ErrNotCallable {
|
||||
const DESCRIPTION: &'static str = "This atom is not callable";
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,11 @@ use orchid_api_traits::{Decode, Encode};
|
||||
use orchid_base::id_store::{IdRecord, IdStore};
|
||||
|
||||
use crate::atom::{
|
||||
AtomCard, AtomCtx, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant,
|
||||
ErrorNotCallable, ErrorNotCommand, ReqPck, RequestPack,
|
||||
get_info, AtomCard, AtomCtx, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrNotCallable, ErrorNotCommand, ReqPck, RequestPack
|
||||
};
|
||||
use crate::error::ProjectResult;
|
||||
use crate::expr::{bot, ExprHandle, GenExpr};
|
||||
use crate::system::{atom_info_for, SysCtx};
|
||||
use crate::system::SysCtx;
|
||||
|
||||
pub struct OwnedVariant;
|
||||
impl AtomicVariant for OwnedVariant {}
|
||||
@@ -24,7 +23,7 @@ impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVari
|
||||
fn _factory(self) -> AtomFactory {
|
||||
AtomFactory::new(move |sys| {
|
||||
let rec = OBJ_STORE.add(Box::new(self));
|
||||
let mut data = atom_info_for(sys.dyn_card(), rec.atom_tid()).expect("obj exists").0.enc_vec();
|
||||
let mut data = get_info::<A>(sys.dyn_card()).0.enc_vec();
|
||||
rec.id().encode(&mut data);
|
||||
rec.encode(&mut data);
|
||||
LocalAtom { drop: true, data }
|
||||
@@ -35,11 +34,15 @@ impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVari
|
||||
}
|
||||
|
||||
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"))
|
||||
let id = NonZeroU64::decode(&mut b);
|
||||
f(OBJ_STORE.get(id).unwrap_or_else(|| panic!("Received invalid atom ID: {id}")))
|
||||
}
|
||||
|
||||
pub struct OwnedAtomDynfo<T: OwnedAtom>(PhantomData<T>);
|
||||
impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
||||
fn print(&self, AtomCtx(buf, ctx): AtomCtx<'_>) -> String {
|
||||
with_atom(buf, |a| a.dyn_print(ctx))
|
||||
}
|
||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn name(&self) -> &'static str { type_name::<T>() }
|
||||
fn decode(&self, AtomCtx(data, _): AtomCtx) -> Box<dyn Any> {
|
||||
@@ -67,7 +70,7 @@ impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
||||
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) }
|
||||
fn call_ref(&self, arg: ExprHandle) -> GenExpr { bot(ErrNotCallable) }
|
||||
fn call(self, arg: ExprHandle) -> GenExpr {
|
||||
let ctx = arg.get_ctx();
|
||||
let gcl = self.call_ref(arg);
|
||||
@@ -87,6 +90,8 @@ pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Send + Sync + Any + Clone
|
||||
fn command(self, ctx: SysCtx) -> ProjectResult<Option<GenExpr>> { Err(Arc::new(ErrorNotCommand)) }
|
||||
#[allow(unused_variables)]
|
||||
fn free(self, ctx: SysCtx) {}
|
||||
#[allow(unused_variables)]
|
||||
fn print(&self, ctx: SysCtx) -> String { format!("OwnedAtom({})", type_name::<Self>()) }
|
||||
}
|
||||
pub trait DynOwnedAtom: Send + Sync + 'static {
|
||||
fn atom_tid(&self) -> TypeId;
|
||||
@@ -98,6 +103,7 @@ pub trait DynOwnedAtom: Send + Sync + 'static {
|
||||
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);
|
||||
fn dyn_print(&self, ctx: SysCtx) -> String;
|
||||
}
|
||||
impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
fn atom_tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
@@ -123,6 +129,7 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
self.command(ctx)
|
||||
}
|
||||
fn dyn_free(self: Box<Self>, ctx: SysCtx) { self.free(ctx) }
|
||||
fn dyn_print(&self, ctx: SysCtx) -> String { self.print(ctx) }
|
||||
}
|
||||
|
||||
pub(crate) static OBJ_STORE: IdStore<Box<dyn DynOwnedAtom>> = IdStore::new();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use std::any::{type_name, Any, TypeId};
|
||||
use std::fmt;
|
||||
use std::io::Write;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
@@ -10,7 +9,7 @@ use orchid_api_traits::{Coding, Decode, Encode};
|
||||
|
||||
use crate::atom::{
|
||||
get_info, AtomCard, AtomCtx, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant,
|
||||
ErrorNotCallable, ReqPck, RequestPack,
|
||||
ErrNotCallable, ReqPck, RequestPack,
|
||||
};
|
||||
use crate::error::ProjectResult;
|
||||
use crate::expr::{bot, ExprHandle, GenExpr};
|
||||
@@ -32,11 +31,10 @@ impl<A: ThinAtom + Atomic<Variant = ThinVariant>> AtomicFeaturesImpl<ThinVariant
|
||||
|
||||
pub struct ThinAtomDynfo<T: ThinAtom>(PhantomData<T>);
|
||||
impl<T: ThinAtom> AtomDynfo for ThinAtomDynfo<T> {
|
||||
fn print(&self, AtomCtx(buf, ctx): AtomCtx<'_>) -> String { T::decode(&mut &buf[..]).print(ctx) }
|
||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn name(&self) -> &'static str { type_name::<T>() }
|
||||
fn decode(&self, AtomCtx(data, _): AtomCtx) -> Box<dyn Any> {
|
||||
Box::new(T::decode(&mut &data[..]))
|
||||
}
|
||||
fn decode(&self, AtomCtx(buf, _): AtomCtx) -> Box<dyn Any> { Box::new(T::decode(&mut &buf[..])) }
|
||||
fn call(&self, AtomCtx(buf, ctx): AtomCtx, arg: ExprTicket) -> GenExpr {
|
||||
T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg))
|
||||
}
|
||||
@@ -57,25 +55,24 @@ impl<T: ThinAtom> AtomDynfo for ThinAtomDynfo<T> {
|
||||
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[..]))
|
||||
fn drop(&self, AtomCtx(buf, ctx): AtomCtx) {
|
||||
let string_self = T::decode(&mut &buf[..]).print(ctx);
|
||||
eprintln!("Received drop signal for non-drop atom {string_self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ThinAtom: AtomCard<Data = Self> + Coding + fmt::Debug + Send + Sync + 'static {
|
||||
pub trait ThinAtom: AtomCard<Data = Self> + Coding + Send + Sync + 'static {
|
||||
#[allow(unused_variables)]
|
||||
fn call(&self, arg: ExprHandle) -> GenExpr { bot(ErrorNotCallable) }
|
||||
fn call(&self, arg: ExprHandle) -> GenExpr { bot(ErrNotCallable) }
|
||||
#[allow(unused_variables)]
|
||||
fn same(&self, ctx: SysCtx, other: &Self) -> bool {
|
||||
eprintln!(
|
||||
"Override ThinAtom::same for {} if it can be generated during parsing",
|
||||
type_name::<Self>()
|
||||
);
|
||||
let tname = type_name::<Self>();
|
||||
eprintln!("Override ThinAtom::same for {tname} if it can be generated during parsing");
|
||||
false
|
||||
}
|
||||
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))
|
||||
}
|
||||
fn command(&self, ctx: SysCtx) -> ProjectResult<Option<GenExpr>> { Err(Arc::new(ErrNotCallable)) }
|
||||
#[allow(unused_variables)]
|
||||
fn print(&self, ctx: SysCtx) -> String { format!("ThinAtom({})", type_name::<Self>()) }
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use std::io::Write;
|
||||
use std::num::NonZero;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{mem, thread};
|
||||
use std::{mem, process, thread};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use orchid_api::atom::{
|
||||
Atom, AtomDrop, AtomReq, AtomSame, CallRef, Command, FinalCall, Fwded, NextStep,
|
||||
Atom, AtomDrop, AtomPrint, AtomReq, AtomSame, CallRef, Command, FinalCall, Fwded, NextStep
|
||||
};
|
||||
use orchid_api::interner::Sweep;
|
||||
use orchid_api::parser::{CharFilter, LexExpr, LexedExpr, ParserReq};
|
||||
@@ -18,6 +19,7 @@ use orchid_api_traits::{Decode, Encode};
|
||||
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::logging::Logger;
|
||||
use orchid_base::name::PathSlice;
|
||||
use orchid_base::reqnot::{ReqNot, Requester};
|
||||
|
||||
@@ -31,8 +33,17 @@ use crate::system_ctor::{CtedObj, DynSystemCtor};
|
||||
use crate::tree::{LazyMemberFactory, TIACtxImpl};
|
||||
|
||||
pub struct ExtensionData {
|
||||
pub thread_name: &'static str,
|
||||
pub systems: &'static [&'static dyn DynSystemCtor],
|
||||
}
|
||||
impl ExtensionData {
|
||||
pub fn new(thread_name: &'static str, systems: &'static [&'static dyn DynSystemCtor]) -> Self {
|
||||
Self { thread_name, systems }
|
||||
}
|
||||
pub fn main(self) {
|
||||
extension_main(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MemberRecord {
|
||||
Gen(LazyMemberFactory),
|
||||
@@ -60,7 +71,13 @@ pub fn with_atom_record<T>(
|
||||
}
|
||||
|
||||
pub fn extension_main(data: ExtensionData) {
|
||||
HostHeader::decode(&mut &recv_parent_msg().unwrap()[..]);
|
||||
if thread::Builder::new().name(data.thread_name.to_string()).spawn(|| extension_main_logic(data)).unwrap().join().is_err() {
|
||||
process::exit(-1)
|
||||
}
|
||||
}
|
||||
|
||||
fn extension_main_logic(data: ExtensionData) {
|
||||
let HostHeader{ log_strategy } = HostHeader::decode(&mut std::io::stdin().lock());
|
||||
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))
|
||||
@@ -68,21 +85,26 @@ pub fn extension_main(data: ExtensionData) {
|
||||
.collect_vec();
|
||||
let systems = Arc::new(Mutex::new(HashMap::<SysId, SystemRecord>::new()));
|
||||
ExtensionHeader { systems: decls.clone() }.encode(&mut buf);
|
||||
send_parent_msg(&buf).unwrap();
|
||||
std::io::stdout().write_all(&buf).unwrap();
|
||||
std::io::stdout().flush().unwrap();
|
||||
let exiting = Arc::new(AtomicBool::new(false));
|
||||
let logger = Arc::new(Logger::new(log_strategy));
|
||||
let rn = ReqNot::<ExtMsgSet>::new(
|
||||
|a, _| send_parent_msg(a).unwrap(),
|
||||
clone!(systems, exiting; move |n, reqnot| match n {
|
||||
|a, _| {
|
||||
eprintln!("Upsending {:?}", a);
|
||||
send_parent_msg(a).unwrap()
|
||||
},
|
||||
clone!(systems, exiting, logger; move |n, reqnot| match n {
|
||||
HostExtNotif::Exit => exiting.store(true, Ordering::Relaxed),
|
||||
HostExtNotif::SystemDrop(SystemDrop(sys_id)) =>
|
||||
mem::drop(systems.lock().unwrap().remove(&sys_id)),
|
||||
HostExtNotif::AtomDrop(AtomDrop(atom)) => {
|
||||
with_atom_record(&systems, &atom, |rec, cted, data| {
|
||||
rec.drop(AtomCtx(data, SysCtx{ reqnot, id: atom.owner, cted }))
|
||||
rec.drop(AtomCtx(data, SysCtx{ reqnot, logger: logger.clone(), id: atom.owner, cted }))
|
||||
})
|
||||
}
|
||||
}),
|
||||
clone!(systems; move |req| match req.req() {
|
||||
clone!(systems, logger; move |req| match req.req() {
|
||||
HostExtReq::Ping(ping@Ping) => req.handle(ping, &()),
|
||||
HostExtReq::Sweep(sweep@Sweep) => req.handle(sweep, &sweep_replica()),
|
||||
HostExtReq::NewSystem(new_sys) => {
|
||||
@@ -90,7 +112,8 @@ pub fn extension_main(data: ExtensionData) {
|
||||
let cted = data.systems[i].new_system(new_sys);
|
||||
let mut vfses = HashMap::new();
|
||||
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 lxcf = mk_char_filter(lx.char_filter().iter().cloned());
|
||||
char_filter_union(&cf, &lxcf)
|
||||
});
|
||||
let mut lazy_mems = HashMap::new();
|
||||
let const_root = (cted.inst().dyn_env().into_iter())
|
||||
@@ -141,8 +164,8 @@ 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 first_char = text.chars().next().unwrap();
|
||||
for lx in lexers.iter().filter(|l| char_filter_match(l.char_filter(), first_char)) {
|
||||
let trigger_char = text.chars().nth(pos as usize).unwrap();
|
||||
for lx in lexers.iter().filter(|l| char_filter_match(l.char_filter(), trigger_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),
|
||||
@@ -155,6 +178,7 @@ pub fn extension_main(data: ExtensionData) {
|
||||
}
|
||||
}
|
||||
}
|
||||
eprintln!("Got notified about n/a character '{trigger_char}'");
|
||||
req.handle_as(tk, &None)
|
||||
}));
|
||||
},
|
||||
@@ -162,10 +186,16 @@ pub fn extension_main(data: ExtensionData) {
|
||||
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 ctx = SysCtx {
|
||||
cted: sys.cted.clone(),
|
||||
id: atom.owner,
|
||||
logger: logger.clone(),
|
||||
reqnot: req.reqnot()
|
||||
};
|
||||
let dynfo = resolv_atom(&*sys.cted.inst(), atom);
|
||||
let actx = AtomCtx(&atom.data[8..], ctx);
|
||||
match atom_req {
|
||||
AtomReq::AtomPrint(print@AtomPrint(_)) => req.handle(print, &dynfo.print(actx)),
|
||||
AtomReq::AtomSame(same@AtomSame(_, r)) => {
|
||||
// different systems or different type tags
|
||||
if atom.owner != r.owner || atom.data[..8] != r.data[..8] {
|
||||
@@ -195,6 +225,8 @@ pub fn extension_main(data: ExtensionData) {
|
||||
);
|
||||
init_replica(rn.clone().map());
|
||||
while !exiting.load(Ordering::Relaxed) {
|
||||
rn.receive(recv_parent_msg().unwrap())
|
||||
let rcvd = recv_parent_msg().unwrap();
|
||||
// eprintln!("Downsent {rcvd:?}");
|
||||
rn.receive(rcvd)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::any::TypeId;
|
||||
use std::sync::Arc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use orchid_api::atom::Atom;
|
||||
@@ -6,6 +7,7 @@ use orchid_api::proto::ExtMsgSet;
|
||||
use orchid_api::system::SysId;
|
||||
use orchid_api_traits::Decode;
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::logging::Logger;
|
||||
use orchid_base::reqnot::ReqNot;
|
||||
|
||||
use crate::atom::{get_info, AtomCtx, AtomDynfo, AtomicFeatures, ForeignAtom, TypAtom};
|
||||
@@ -106,4 +108,5 @@ pub struct SysCtx {
|
||||
pub reqnot: ReqNot<ExtMsgSet>,
|
||||
pub id: SysId,
|
||||
pub cted: CtedObj,
|
||||
pub logger: Arc<Logger>,
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ pub fn ph(s: &str) -> OwnedPh {
|
||||
if konst::string::starts_with(name, "_") {
|
||||
panic!("Names starting with an underscore indicate a single-name scalar placeholder")
|
||||
}
|
||||
OwnedPh { name: intern(name), kind: PlaceholderKind::Vector { nonzero, priority } }
|
||||
OwnedPh { name: intern(name), kind: PlaceholderKind::Vector { nz: nonzero, prio: priority } }
|
||||
},
|
||||
None => match konst::string::strip_prefix(s, "$_") {
|
||||
Some(name) => OwnedPh { name: intern(name), kind: PlaceholderKind::Name },
|
||||
|
||||
Reference in New Issue
Block a user