Files
orchid/orchid-std/src/std/std_system.rs
Lawrence Bethlenfalvy 09cfcb1839 partway towards commands
I got very confused and started mucking about with "spawn" when in fact all I needed was the "inline" extension type in orcx that allows the interpreter to expose custom constants.
2026-03-13 16:48:42 +01:00

161 lines
5.6 KiB
Rust

use std::cell::OnceCell;
use std::rc::Rc;
use futures::future::join_all;
use orchid_api_derive::{Coding, Hierarchy};
use orchid_base::{Receipt, ReqHandle, ReqHandleExt, Sym, es, sym};
use orchid_extension::{AtomOps, AtomicFeatures};
use orchid_extension::conv::ToExpr;
use orchid_extension::expr::Expr;
use orchid_extension::gen_expr::new_atom;
use orchid_extension::lexer::LexerObj;
use orchid_extension::parser::ParserObj;
use orchid_extension::system::{System, SystemCard};
use orchid_extension::system_ctor::SystemCtor;
use orchid_extension::tree::{GenMember, merge_trivial};
use super::number::num_lib::gen_num_lib;
use super::string::str_atom::{IntStrAtom, StrAtom};
use super::string::str_lib::gen_str_lib;
use crate::std::binary::binary_atom::BlobAtom;
use crate::std::binary::binary_lib::gen_binary_lib;
use crate::std::boolean::gen_bool_lib;
use crate::std::future::future_lib::{FutureReq, Scheduler, gen_future_lib};
use crate::std::number::num_atom::{CreateFloat, CreateInt};
use crate::std::number::num_lexer::NumLexer;
use crate::std::ops::gen_ops_lib;
use crate::std::ops::subscript_lexer::SubscriptLexer;
use crate::std::option::{OptAtom, gen_option_lib};
use crate::std::protocol::proto_parser::{AsProtoParser, ProtoParser};
use crate::std::protocol::type_parser::{AsTypeParser, TypeParser};
use crate::std::protocol::types::{CreateTag, Tag, Tagged, gen_protocol_lib};
use crate::std::record::record_atom::{CreateRecord, RecordAtom};
use crate::std::record::record_lib::gen_record_lib;
use crate::std::reflection::sym_atom::{CreateSymAtom, SymAtom, gen_sym_lib};
use crate::std::stream::stream_lib::gen_stream_lib;
use crate::std::string::str_lexer::StringLexer;
use crate::std::time::{CreateDT, gen_time_lib};
use crate::std::tuple::{CreateTuple, Tuple, TupleBuilder, gen_tuple_lib};
use crate::{Float, Int};
#[derive(Clone, Debug, Coding, Hierarchy)]
#[extendable]
#[allow(clippy::enum_variant_names, reason = "For the time being there are only ctor calls")]
pub enum StdReq {
CreateInt(CreateInt),
CreateFloat(CreateFloat),
CreateDT(CreateDT),
CreateTag(CreateTag),
CreateTuple(CreateTuple),
CreateRecord(CreateRecord),
CreateSymAtom(CreateSymAtom),
FutureReq(FutureReq),
}
#[derive(Debug, Default)]
pub struct StdSystem {
pub(crate) sched: OnceCell<Scheduler>,
}
impl SystemCtor for StdSystem {
type Deps = ();
type Instance = Self;
const NAME: &'static str = "orchid::std";
const VERSION: f64 = 0.00_01;
fn inst(&self, _: ()) -> Self::Instance { Self::default() }
}
impl SystemCard for StdSystem {
type Ctor = Self;
type Req = StdReq;
fn atoms() -> impl IntoIterator<Item = Option<Box<dyn AtomOps>>> {
[
Some(BlobAtom::ops()),
Some(Int::ops()),
Some(Float::ops()),
Some(StrAtom::ops()),
Some(IntStrAtom::ops()),
Some(OptAtom::ops()),
Some(RecordAtom::ops()),
Some(Tuple::ops()),
Some(TupleBuilder::ops()),
Some(Tag::ops()),
Some(Tagged::ops()),
]
}
}
impl System for StdSystem {
async fn request<'a>(&self, xreq: Box<dyn ReqHandle<'a> + 'a>, req: Self::Req) -> Receipt<'a> {
match req {
StdReq::FutureReq(req) => {
let sched = self.sched.get_or_init(Scheduler::default);
match req {
FutureReq::AddAsyncWork(req) => xreq.reply(&req, &sched.add(&req).await).await.unwrap(),
FutureReq::FinishAsyncWork(req) =>
xreq.reply(&req, &sched.finish(&req).await).await.unwrap(),
}
},
StdReq::CreateInt(ref req @ CreateInt(int)) =>
xreq.reply(req, &new_atom(int).to_expr().await.serialize().await).await.unwrap(),
StdReq::CreateFloat(ref req @ CreateFloat(float)) =>
xreq.reply(req, &new_atom(float).to_expr().await.serialize().await).await.unwrap(),
StdReq::CreateDT(ref req @ CreateDT(dt)) =>
xreq.reply(req, &new_atom(dt).to_expr().await.serialize().await).await.unwrap(),
StdReq::CreateTuple(ref req @ CreateTuple(ref items)) => {
let tpl = Tuple(Rc::new(join_all(items.iter().copied().map(Expr::deserialize)).await));
let tk = new_atom(tpl).to_expr().await.serialize().await;
xreq.reply(req, &tk).await.unwrap()
},
StdReq::CreateRecord(ref req @ CreateRecord(ref items)) => {
let values =
join_all(items.iter().map(async |(k, v)| (es(*k).await, Expr::deserialize(*v).await)))
.await;
let rec = RecordAtom(Rc::new(values.into_iter().collect()));
let tk = new_atom(rec).to_expr().await.serialize().await;
xreq.reply(req, &tk).await.unwrap()
},
StdReq::CreateSymAtom(ref req @ CreateSymAtom(sym_tok)) => {
let sym_atom = SymAtom(Sym::from_api(sym_tok).await);
xreq.reply(req, &new_atom(sym_atom).to_expr().await.serialize().await).await.unwrap()
},
StdReq::CreateTag(ref req @ CreateTag { name, ref impls }) => {
let tag_atom = Tag {
id: Sym::from_api(name).await,
impls: Rc::new(
join_all(
(impls.iter())
.map(|(k, v)| async { (Sym::from_api(*k).await, Expr::deserialize(*v).await) }),
)
.await
.into_iter()
.collect(),
),
};
xreq.reply(req, &new_atom(tag_atom).to_expr().await.serialize().await).await.unwrap()
},
}
}
fn lexers(&self) -> Vec<LexerObj> { vec![&StringLexer, &NumLexer, &SubscriptLexer] }
fn parsers(&self) -> Vec<ParserObj> {
vec![&AsTypeParser, &TypeParser, &AsProtoParser, &ProtoParser]
}
async fn env(&self) -> Vec<GenMember> {
merge_trivial([
gen_bool_lib(),
gen_num_lib(),
gen_str_lib(),
gen_option_lib(),
gen_record_lib(),
gen_tuple_lib(),
gen_protocol_lib(),
gen_sym_lib().await,
gen_ops_lib(),
gen_binary_lib(),
gen_stream_lib(),
gen_time_lib(),
gen_future_lib(),
])
}
async fn prelude(&self) -> Vec<Sym> {
vec![sym!(std), sym!(std::tuple), sym!(std::option), sym!(std::record), sym!(std::string)]
}
}