forked from Orchid/orchid
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:
@@ -1,52 +1,53 @@
|
||||
use std::borrow::Cow;
|
||||
use std::io;
|
||||
use std::num::NonZeroU64;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use never::Never;
|
||||
use orchid_api_derive::Coding;
|
||||
use orchid_api_traits::{Encode, Request};
|
||||
use orchid_base::error::{mk_err, OrcRes};
|
||||
use orchid_base::id_store::IdStore;
|
||||
use orchid_base::error::{mk_errv, OrcRes};
|
||||
use orchid_base::intern;
|
||||
use orchid_base::interner::{deintern, intern, Tok};
|
||||
use orchid_extension::atom::{Atomic, ReqPck, TypAtom};
|
||||
use orchid_extension::atom::{AtomMethod, Atomic, MethodSet, Supports, TypAtom};
|
||||
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant};
|
||||
use orchid_extension::conv::TryFromExpr;
|
||||
use orchid_extension::expr::ExprHandle;
|
||||
use orchid_extension::expr::Expr;
|
||||
use orchid_extension::system::SysCtx;
|
||||
|
||||
pub static STR_REPO: IdStore<Arc<String>> = IdStore::new();
|
||||
|
||||
#[derive(Copy, Clone, Coding)]
|
||||
pub struct StringGetVal;
|
||||
impl Request for StringGetVal {
|
||||
type Response = String;
|
||||
type Response = Arc<String>;
|
||||
}
|
||||
impl AtomMethod for StringGetVal {
|
||||
const NAME: &str = "std::string_get_val";
|
||||
}
|
||||
impl Supports<StringGetVal> for StrAtom {
|
||||
fn handle(&self, _: SysCtx, _: StringGetVal) -> <StringGetVal as Request>::Response {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StrAtom(NonZeroU64);
|
||||
#[derive(Clone)]
|
||||
pub struct StrAtom(Arc<String>);
|
||||
impl Atomic for StrAtom {
|
||||
type Variant = OwnedVariant;
|
||||
type Data = NonZeroU64;
|
||||
type Req = StringGetVal;
|
||||
type Data = ();
|
||||
fn reg_reqs() -> MethodSet<Self> { MethodSet::new().handle::<StringGetVal>() }
|
||||
}
|
||||
impl StrAtom {
|
||||
pub fn new(str: Arc<String>) -> Self { Self(STR_REPO.add(str).id()) }
|
||||
pub fn new(str: Arc<String>) -> Self { Self(str) }
|
||||
pub fn value(&self) -> Arc<String> { self.0.clone() }
|
||||
}
|
||||
impl Clone for StrAtom {
|
||||
fn clone(&self) -> Self { Self::new(self.local_value()) }
|
||||
}
|
||||
impl StrAtom {
|
||||
fn try_local_value(&self) -> Option<Arc<String>> { STR_REPO.get(self.0).map(|r| r.clone()) }
|
||||
fn local_value(&self) -> Arc<String> { self.try_local_value().expect("no string found for ID") }
|
||||
impl Deref for StrAtom {
|
||||
type Target = str;
|
||||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
impl OwnedAtom for StrAtom {
|
||||
type Refs = ();
|
||||
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(self.0) }
|
||||
fn same(&self, _: SysCtx, other: &Self) -> bool { self.local_value() == other.local_value() }
|
||||
fn handle_req(&self, pck: impl ReqPck<Self>) { self.local_value().encode(pck.unpack().1) }
|
||||
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||
fn serialize(&self, _: SysCtx, sink: &mut (impl io::Write + ?Sized)) -> Self::Refs {
|
||||
self.local_value().encode(sink)
|
||||
self.deref().encode(sink)
|
||||
}
|
||||
fn deserialize(mut ctx: impl DeserializeCtx, _: Self::Refs) -> Self {
|
||||
Self::new(Arc::new(ctx.read::<String>()))
|
||||
@@ -58,7 +59,7 @@ pub struct IntStrAtom(Tok<String>);
|
||||
impl Atomic for IntStrAtom {
|
||||
type Variant = OwnedVariant;
|
||||
type Data = orchid_api::TStr;
|
||||
type Req = Never;
|
||||
fn reg_reqs() -> MethodSet<Self> { MethodSet::new() }
|
||||
}
|
||||
impl From<Tok<String>> for IntStrAtom {
|
||||
fn from(value: Tok<String>) -> Self { Self(value) }
|
||||
@@ -66,8 +67,7 @@ impl From<Tok<String>> for IntStrAtom {
|
||||
impl OwnedAtom for IntStrAtom {
|
||||
type Refs = ();
|
||||
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(self.0.marker()) }
|
||||
fn handle_req(&self, pck: impl ReqPck<Self>) { pck.never() }
|
||||
fn print(&self, _ctx: SysCtx) -> String { format!("{:?}i", self.0.as_str()) }
|
||||
fn print(&self, _ctx: SysCtx) -> String { format!("{:?}i", *self.0) }
|
||||
fn serialize(&self, _: SysCtx, write: &mut (impl io::Write + ?Sized)) { self.0.encode(write) }
|
||||
fn deserialize(ctx: impl DeserializeCtx, _: ()) -> Self { Self(intern(&ctx.decode::<String>())) }
|
||||
}
|
||||
@@ -81,22 +81,19 @@ impl<'a> OrcString<'a> {
|
||||
pub fn get_string(&self) -> Arc<String> {
|
||||
match &self {
|
||||
Self::Int(tok) => deintern(tok.value).arc(),
|
||||
Self::Val(atom) => match STR_REPO.get(**atom) {
|
||||
Some(rec) => rec.clone(),
|
||||
None => Arc::new(atom.request(StringGetVal)),
|
||||
},
|
||||
Self::Val(atom) => atom.request(StringGetVal),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromExpr for OrcString<'static> {
|
||||
fn try_from_expr(expr: ExprHandle) -> OrcRes<OrcString<'static>> {
|
||||
if let Ok(v) = TypAtom::<StrAtom>::downcast(expr.clone()) {
|
||||
fn try_from_expr(expr: Expr) -> OrcRes<OrcString<'static>> {
|
||||
if let Ok(v) = TypAtom::<StrAtom>::try_from_expr(expr.clone()) {
|
||||
return Ok(OrcString::Val(v));
|
||||
}
|
||||
match TypAtom::<IntStrAtom>::downcast(expr) {
|
||||
match TypAtom::<IntStrAtom>::try_from_expr(expr) {
|
||||
Ok(t) => Ok(OrcString::Int(t)),
|
||||
Err(e) => Err(vec![mk_err(intern!(str: "A string was expected"), "", [e.0.clone().into()])]),
|
||||
Err(e) => Err(mk_errv(intern!(str: "A string was expected"), "", e.pos_iter())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user