forked from Orchid/orchid
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:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -326,6 +326,7 @@ dependencies = [
|
|||||||
"itertools",
|
"itertools",
|
||||||
"konst",
|
"konst",
|
||||||
"never",
|
"never",
|
||||||
|
"once_cell",
|
||||||
"orchid-api",
|
"orchid-api",
|
||||||
"orchid-api-derive",
|
"orchid-api-derive",
|
||||||
"orchid-api-traits",
|
"orchid-api-traits",
|
||||||
@@ -356,6 +357,7 @@ name = "orchid-std"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
|
"once_cell",
|
||||||
"orchid-api",
|
"orchid-api",
|
||||||
"orchid-api-derive",
|
"orchid-api-derive",
|
||||||
"orchid-api-traits",
|
"orchid-api-traits",
|
||||||
|
|||||||
37
notes/crates.md
Normal file
37
notes/crates.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
The role and relations of the crates in this monorepo
|
||||||
|
|
||||||
|
# orcx
|
||||||
|
|
||||||
|
Reference runtime built using [`orchid-host`](#orchid-host)
|
||||||
|
|
||||||
|
# orchid-std
|
||||||
|
|
||||||
|
Standard library and reference extension built using [`orchid-extension`](#orchid-extension)
|
||||||
|
|
||||||
|
# orchid-host
|
||||||
|
|
||||||
|
Interpreter library with extension host. This is built to support embedding in arbitrary host applications for scripting, although it is not security hardened.
|
||||||
|
|
||||||
|
# orchid-extension
|
||||||
|
|
||||||
|
Extension development toolkit. It routes the requests to handlers in a nice object model, and manages resources like `ExprTicket`.
|
||||||
|
|
||||||
|
# orchid-base
|
||||||
|
|
||||||
|
Common items used by both [`orchid-host`](#orchid-host) and [`orchid-extension`](#orchid-extension). Most notably, both sides of the string interner are defined here because it has to be callable from other items defined in this crate through the same set of global functions in both environments.
|
||||||
|
|
||||||
|
# orchid-api
|
||||||
|
|
||||||
|
Definition of the extension API. This crate should not contain any logic, it should hold only serializable message structs, and their relations should represent how they fit into the protocol.
|
||||||
|
|
||||||
|
# orchid-api-derive
|
||||||
|
|
||||||
|
Derive macros for the traits in [`orchid-api-traits`](#orchid-api-traits) to make the definitions in [`orchid-api`](#orchid-api) more concise.
|
||||||
|
|
||||||
|
# orchid-api-traits
|
||||||
|
|
||||||
|
Traits with a semantic meaning with respect to the protocol elements defined in [`orchid-api`](#orchid-api):
|
||||||
|
|
||||||
|
- `Encode`, `Decode` and `Coding` define how types serialize.
|
||||||
|
- `Request` associates requests with their response types.
|
||||||
|
- `InHierarchy`, `Extends` and `UnderRoot` associate requests and notifications with the category hierarchy they belong to.
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
pub trait TBool {}
|
|
||||||
pub struct TTrue;
|
|
||||||
impl TBool for TTrue {}
|
|
||||||
pub struct TFalse;
|
|
||||||
impl TBool for TFalse {}
|
|
||||||
|
|
||||||
/// Implementation picker for a tree node
|
|
||||||
///
|
|
||||||
/// Note: This technically allows for the degenerate case
|
|
||||||
/// ```
|
|
||||||
/// struct MyType;
|
|
||||||
/// impl TreeRolePicker for MyType {
|
|
||||||
/// type IsLeaf = TTrue;
|
|
||||||
/// type IsRoot = TTrue;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
/// This isn't very useful because it describes a one element sealed hierarchy.
|
|
||||||
pub trait TreeRolePicker {
|
|
||||||
type IsLeaf: TBool;
|
|
||||||
type IsRoot: TBool;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Extends: TreeRolePicker<IsRoot = TFalse> {
|
|
||||||
type Parent: TreeRolePicker<IsLeaf = TFalse>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Inherits<T> {}
|
|
||||||
|
|
||||||
// impl<T> Inherits<T, 0> for T {}
|
|
||||||
impl<T: Extends, This> Inherits<T::Parent> for This where This: Inherits<T> {}
|
|
||||||
@@ -1,8 +1,3 @@
|
|||||||
/// [Hierarchy] implementation key. The two implementors of this trait are
|
|
||||||
/// [Base] and [Subtype]. These types are assigned to [InHierarchy::Role] to
|
|
||||||
/// select the implementation of [Hierarchy].
|
|
||||||
pub trait HierarchyRole {}
|
|
||||||
|
|
||||||
/// A type-level boolean suitable to select conditional trait implementations.
|
/// A type-level boolean suitable to select conditional trait implementations.
|
||||||
/// Implementors are [True] and [False]
|
/// Implementors are [True] and [False]
|
||||||
pub trait TLBool {}
|
pub trait TLBool {}
|
||||||
@@ -13,17 +8,6 @@ impl TLBool for TLTrue {}
|
|||||||
pub struct TLFalse;
|
pub struct TLFalse;
|
||||||
impl TLBool for TLFalse {}
|
impl TLBool for TLFalse {}
|
||||||
|
|
||||||
/// Assign this type to [InHierarchy::Role] and implement [Descendant] to create
|
|
||||||
/// a subtype. These types can be upcast to their parent type, conditionally
|
|
||||||
/// downcast from it, and selected for [Descendant::Parent] by other types.
|
|
||||||
pub struct Subtype;
|
|
||||||
impl HierarchyRole for Subtype {}
|
|
||||||
/// Assign this type to [InHierarchy::Role] to create a base type. These types
|
|
||||||
/// are upcast only to themselves, but they can be selected in
|
|
||||||
/// [Descendant::Parent].
|
|
||||||
pub struct Base;
|
|
||||||
impl HierarchyRole for Base {}
|
|
||||||
|
|
||||||
/// A type that implements [Hierarchy]. Used to select implementations of traits
|
/// A type that implements [Hierarchy]. Used to select implementations of traits
|
||||||
/// on the hierarchy
|
/// on the hierarchy
|
||||||
pub trait InHierarchy: Clone {
|
pub trait InHierarchy: Clone {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ mod relations;
|
|||||||
pub use coding::{Coding, Decode, Encode};
|
pub use coding::{Coding, Decode, Encode};
|
||||||
pub use helpers::{encode_enum, read_exact, write_exact};
|
pub use helpers::{encode_enum, read_exact, write_exact};
|
||||||
pub use hierarchy::{
|
pub use hierarchy::{
|
||||||
Base, Extends, HierarchyRole, InHierarchy, Subtype, TLBool, TLFalse, TLTrue, UnderRoot,
|
Extends, InHierarchy, TLBool, TLFalse, TLTrue, UnderRoot,
|
||||||
UnderRootImpl,
|
|
||||||
};
|
};
|
||||||
pub use relations::{Channel, MsgSet, Request};
|
pub use relations::{Channel, MsgSet, Request};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use orchid_api_derive::{Coding, Hierarchy};
|
|||||||
use orchid_api_traits::Request;
|
use orchid_api_traits::Request;
|
||||||
|
|
||||||
use crate::atom::{Atom, LocalAtom};
|
use crate::atom::{Atom, LocalAtom};
|
||||||
|
use crate::error::ProjErr;
|
||||||
use crate::interner::TStrv;
|
use crate::interner::TStrv;
|
||||||
use crate::location::Location;
|
use crate::location::Location;
|
||||||
use crate::proto::{ExtHostNotif, ExtHostReq};
|
use crate::proto::{ExtHostNotif, ExtHostReq};
|
||||||
@@ -83,7 +84,7 @@ pub enum Clause {
|
|||||||
/// A reference to a constant
|
/// A reference to a constant
|
||||||
Const(TStrv),
|
Const(TStrv),
|
||||||
/// A static runtime error.
|
/// A static runtime error.
|
||||||
Bottom(String),
|
Bottom(ProjErr),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Coding)]
|
#[derive(Clone, Debug, Coding)]
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ hashbrown = "0.14.5"
|
|||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
konst = "0.3.9"
|
konst = "0.3.9"
|
||||||
never = "0.1.0"
|
never = "0.1.0"
|
||||||
|
once_cell = "1.19.0"
|
||||||
orchid-api = { version = "0.1.0", path = "../orchid-api" }
|
orchid-api = { version = "0.1.0", path = "../orchid-api" }
|
||||||
orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" }
|
orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" }
|
||||||
orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
|
orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
|
||||||
|
|||||||
@@ -1,75 +1,60 @@
|
|||||||
use std::any::{type_name, Any};
|
use std::any::{type_name, Any};
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::fmt;
|
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::num::NonZeroU64;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use dyn_clone::{clone_box, DynClone};
|
use dyn_clone::{clone_box, DynClone};
|
||||||
use orchid_api::atom::{Atom, Fwd, LocalAtom};
|
use orchid_api::atom::{Atom, Fwd, LocalAtom};
|
||||||
use orchid_api::expr::ExprTicket;
|
use orchid_api::expr::ExprTicket;
|
||||||
use orchid_api::system::SysId;
|
use orchid_api_traits::{Coding, Decode, Request};
|
||||||
use orchid_api_traits::{Coding, Decode, Encode, Request};
|
|
||||||
use orchid_base::id_store::{IdRecord, IdStore};
|
|
||||||
use orchid_base::location::Pos;
|
use orchid_base::location::Pos;
|
||||||
use orchid_base::reqnot::Requester;
|
use orchid_base::reqnot::Requester;
|
||||||
use trait_set::trait_set;
|
use trait_set::trait_set;
|
||||||
use typeid::ConstTypeId;
|
use typeid::ConstTypeId;
|
||||||
|
|
||||||
use crate::expr::{bot, ExprHandle, GenClause};
|
use crate::error::ProjectError;
|
||||||
|
use crate::expr::{ExprHandle, GenExpr};
|
||||||
use crate::system::{atom_info_for, DynSystem, DynSystemCard, SysCtx};
|
use crate::system::{atom_info_for, DynSystem, DynSystemCard, SysCtx};
|
||||||
|
|
||||||
pub trait AtomCard: 'static + Sized {
|
pub trait AtomCard: 'static + Sized {
|
||||||
// type Owner: SystemCard;
|
|
||||||
type Data: Clone + Coding + Sized;
|
type Data: Clone + Coding + Sized;
|
||||||
type Req: Coding;
|
type Req: Coding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait AtomicVariant {}
|
||||||
|
pub trait Atomic: 'static + Sized {
|
||||||
|
type Variant: AtomicVariant;
|
||||||
|
type Data: Clone + Coding + Sized;
|
||||||
|
type Req: Coding;
|
||||||
|
}
|
||||||
|
impl<A: Atomic> AtomCard for A {
|
||||||
|
type Data = <Self as Atomic>::Data;
|
||||||
|
type Req = <Self as Atomic>::Req;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AtomicFeatures: Atomic {
|
||||||
|
fn factory(self) -> AtomFactory;
|
||||||
|
fn info() -> &'static AtomInfo;
|
||||||
|
}
|
||||||
|
pub trait AtomicFeaturesImpl<Variant: AtomicVariant> {
|
||||||
|
fn _factory(self) -> AtomFactory;
|
||||||
|
fn _info() -> &'static AtomInfo;
|
||||||
|
}
|
||||||
|
impl<A: Atomic + AtomicFeaturesImpl<A::Variant>> AtomicFeatures for A {
|
||||||
|
fn factory(self) -> AtomFactory { self._factory() }
|
||||||
|
fn info() -> &'static AtomInfo { Self::_info() }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_info<A: AtomCard>(sys: &(impl DynSystemCard + ?Sized)) -> (u64, &AtomInfo) {
|
pub fn get_info<A: AtomCard>(sys: &(impl DynSystemCard + ?Sized)) -> (u64, &AtomInfo) {
|
||||||
atom_info_for(sys, ConstTypeId::of::<A>()).unwrap_or_else(|| {
|
atom_info_for(sys, ConstTypeId::of::<A>()).unwrap_or_else(|| {
|
||||||
panic!("Atom {} not associated with system {}", type_name::<A>(), sys.name())
|
panic!("Atom {} not associated with system {}", type_name::<A>(), sys.name())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_atom_nodrop<A: AtomCard>(
|
|
||||||
sys: &(impl DynSystemCard + ?Sized),
|
|
||||||
data: &A::Data,
|
|
||||||
) -> LocalAtom {
|
|
||||||
let mut buf = get_info::<A>(sys).0.enc_vec();
|
|
||||||
data.encode(&mut buf);
|
|
||||||
LocalAtom { drop: false, data: buf }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encode_atom_drop<A: AtomCard>(
|
|
||||||
sys_id: SysId,
|
|
||||||
sys: &(impl DynSystemCard + ?Sized),
|
|
||||||
atom_id: u64,
|
|
||||||
data: &A::Data,
|
|
||||||
) -> Atom {
|
|
||||||
let mut buf = get_info::<A>(sys).0.enc_vec();
|
|
||||||
atom_id.encode(&mut buf);
|
|
||||||
data.encode(&mut buf);
|
|
||||||
Atom { owner: sys_id, drop: true, data: buf }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decode_atom<A: AtomCard>(
|
|
||||||
sys: &(impl DynSystemCard + ?Sized),
|
|
||||||
Atom { data, drop: _, owner: _ }: &Atom,
|
|
||||||
) -> Option<A::Data> {
|
|
||||||
let (info_pos, info) = get_info::<A>(sys);
|
|
||||||
let mut data = &data[..];
|
|
||||||
if u64::decode(&mut data) != info_pos {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let val = (info.decode)(data);
|
|
||||||
Some(*val.downcast().expect("The type-id checked out, the decode should've worked"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ForeignAtom {
|
pub struct ForeignAtom {
|
||||||
pub expr: ExprHandle,
|
pub expr: ExprHandle,
|
||||||
pub atom: Atom,
|
pub atom: Atom,
|
||||||
pub position: Pos,
|
pub pos: Pos,
|
||||||
}
|
}
|
||||||
impl ForeignAtom {}
|
impl ForeignAtom {}
|
||||||
|
|
||||||
@@ -93,126 +78,13 @@ impl<A: AtomCard> Deref for TypAtom<A> {
|
|||||||
pub struct AtomInfo {
|
pub struct AtomInfo {
|
||||||
pub tid: ConstTypeId,
|
pub tid: ConstTypeId,
|
||||||
pub decode: fn(&[u8]) -> Box<dyn Any>,
|
pub decode: fn(&[u8]) -> Box<dyn Any>,
|
||||||
pub call: fn(&[u8], SysCtx, ExprTicket) -> GenClause,
|
pub call: fn(&[u8], SysCtx, ExprTicket) -> GenExpr,
|
||||||
pub call_ref: fn(&[u8], SysCtx, ExprTicket) -> GenClause,
|
pub call_ref: fn(&[u8], SysCtx, ExprTicket) -> GenExpr,
|
||||||
pub same: fn(&[u8], SysCtx, &[u8]) -> bool,
|
pub same: fn(&[u8], SysCtx, &[u8]) -> bool,
|
||||||
pub handle_req: fn(&[u8], SysCtx, &mut dyn Read, &mut dyn Write),
|
pub handle_req: fn(&[u8], SysCtx, &mut dyn Read, &mut dyn Write),
|
||||||
pub drop: fn(&[u8], SysCtx),
|
pub drop: fn(&[u8], SysCtx),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ThinAtom: AtomCard<Data = Self> + Coding + fmt::Debug {
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn call(&self, arg: ExprHandle) -> GenClause { bot("This atom is not callable") }
|
|
||||||
#[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>()
|
|
||||||
);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
fn handle_req(&self, ctx: SysCtx, req: Self::Req, rep: &mut (impl Write + ?Sized));
|
|
||||||
fn factory(self) -> AtomFactory {
|
|
||||||
AtomFactory::new(move |sys| encode_atom_nodrop::<Self>(sys.dyn_card(), &self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn thin_atom_info<T: ThinAtom>() -> AtomInfo {
|
|
||||||
AtomInfo {
|
|
||||||
tid: ConstTypeId::of::<T>(),
|
|
||||||
decode: |mut b| Box::new(T::decode(&mut b)),
|
|
||||||
call: |mut b, ctx, extk| T::decode(&mut b).call(ExprHandle::from_args(ctx, extk)),
|
|
||||||
call_ref: |mut b, ctx, extk| T::decode(&mut b).call(ExprHandle::from_args(ctx, extk)),
|
|
||||||
handle_req: |mut b, ctx, req, rep| T::decode(&mut b).handle_req(ctx, Decode::decode(req), rep),
|
|
||||||
same: |mut b1, ctx, mut b2| T::decode(&mut b1).same(ctx, &T::decode(&mut b2)),
|
|
||||||
drop: |mut b1, _| eprintln!("Received drop signal for non-drop atom {:?}", T::decode(&mut b1)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Atoms that have a [Drop]
|
|
||||||
pub trait OwnedAtom: AtomCard + Send + Sync + Any + Clone + 'static {
|
|
||||||
fn val(&self) -> Cow<'_, Self::Data>;
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn call_ref(&self, arg: ExprHandle) -> GenClause { bot("This atom is not callable") }
|
|
||||||
fn call(self, arg: ExprHandle) -> GenClause {
|
|
||||||
let ctx = arg.get_ctx();
|
|
||||||
let gcl = self.call_ref(arg);
|
|
||||||
self.free(ctx);
|
|
||||||
gcl
|
|
||||||
}
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn same(&self, ctx: SysCtx, other: &Self) -> bool {
|
|
||||||
eprintln!(
|
|
||||||
"Override OwnedAtom::same for {} if it can be generated during parsing",
|
|
||||||
type_name::<Self>()
|
|
||||||
);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
fn handle_req(&self, ctx: SysCtx, req: Self::Req, rep: &mut (impl Write + ?Sized));
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn free(self, ctx: SysCtx) {}
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
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();
|
|
||||||
rec.id().encode(&mut data);
|
|
||||||
rec.encode(&mut data);
|
|
||||||
LocalAtom { drop: true, data }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DynOwnedAtom: Send + Sync + 'static {
|
|
||||||
fn atom_tid(&self) -> ConstTypeId;
|
|
||||||
fn as_any_ref(&self) -> &dyn Any;
|
|
||||||
fn encode(&self, buffer: &mut dyn Write);
|
|
||||||
fn dyn_call_ref(&self, ctx: SysCtx, arg: ExprTicket) -> GenClause;
|
|
||||||
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: ExprTicket) -> GenClause;
|
|
||||||
fn dyn_same(&self, ctx: SysCtx, other: &dyn DynOwnedAtom) -> bool;
|
|
||||||
fn dyn_handle_req(&self, ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write);
|
|
||||||
fn dyn_free(self: Box<Self>, ctx: SysCtx);
|
|
||||||
}
|
|
||||||
impl<T: OwnedAtom> DynOwnedAtom for T {
|
|
||||||
fn atom_tid(&self) -> ConstTypeId { ConstTypeId::of::<T>() }
|
|
||||||
fn as_any_ref(&self) -> &dyn Any { self }
|
|
||||||
fn encode(&self, buffer: &mut dyn Write) { self.val().as_ref().encode(buffer) }
|
|
||||||
fn dyn_call_ref(&self, ctx: SysCtx, arg: ExprTicket) -> GenClause {
|
|
||||||
self.call_ref(ExprHandle::from_args(ctx, arg))
|
|
||||||
}
|
|
||||||
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: ExprTicket) -> GenClause {
|
|
||||||
self.call(ExprHandle::from_args(ctx, arg))
|
|
||||||
}
|
|
||||||
fn dyn_same(&self, ctx: SysCtx, other: &dyn DynOwnedAtom) -> bool {
|
|
||||||
if ConstTypeId::of::<Self>() != other.as_any_ref().type_id() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let other_self = other.as_any_ref().downcast_ref().expect("The type_ids are the same");
|
|
||||||
self.same(ctx, other_self)
|
|
||||||
}
|
|
||||||
fn dyn_handle_req(&self, ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write) {
|
|
||||||
self.handle_req(ctx, <Self as AtomCard>::Req::decode(req), rep)
|
|
||||||
}
|
|
||||||
fn dyn_free(self: Box<Self>, ctx: SysCtx) { self.free(ctx) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) static OBJ_STORE: IdStore<Box<dyn DynOwnedAtom>> = IdStore::new();
|
|
||||||
|
|
||||||
pub const fn owned_atom_info<T: OwnedAtom>() -> AtomInfo {
|
|
||||||
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"))
|
|
||||||
}
|
|
||||||
AtomInfo {
|
|
||||||
tid: ConstTypeId::of::<T>(),
|
|
||||||
decode: |mut b| Box::new(T::Data::decode(&mut b)),
|
|
||||||
call: |b, ctx, arg| with_atom(b, |a| a.remove().dyn_call(ctx, arg)),
|
|
||||||
call_ref: |b, ctx, arg| with_atom(b, |a| a.dyn_call_ref(ctx, arg)),
|
|
||||||
same: |b1, ctx, b2| with_atom(b1, |a1| with_atom(b2, |a2| a1.dyn_same(ctx, &**a2))),
|
|
||||||
handle_req: |b, ctx, req, rep| with_atom(b, |a| a.dyn_handle_req(ctx, req, rep)),
|
|
||||||
drop: |b, ctx| with_atom(b, |a| a.remove().dyn_free(ctx)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait_set! {
|
trait_set! {
|
||||||
pub trait AtomFactoryFn = FnOnce(&dyn DynSystem) -> LocalAtom + DynClone;
|
pub trait AtomFactoryFn = FnOnce(&dyn DynSystem) -> LocalAtom + DynClone;
|
||||||
}
|
}
|
||||||
@@ -226,3 +98,8 @@ impl AtomFactory {
|
|||||||
impl Clone for AtomFactory {
|
impl Clone for AtomFactory {
|
||||||
fn clone(&self) -> Self { AtomFactory(clone_box(&*self.0)) }
|
fn clone(&self) -> Self { AtomFactory(clone_box(&*self.0)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ErrorNotCallable;
|
||||||
|
impl ProjectError for ErrorNotCallable {
|
||||||
|
const DESCRIPTION: &'static str = "This atom is not callable";
|
||||||
|
}
|
||||||
96
orchid-extension/src/atom_owned.rs
Normal file
96
orchid-extension/src/atom_owned.rs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
use std::{any::{type_name, Any}, borrow::Cow, io::{Read, Write}, num::NonZeroU64};
|
||||||
|
|
||||||
|
use orchid_api::{atom::LocalAtom, expr::ExprTicket};
|
||||||
|
use orchid_api_traits::{Decode, Encode};
|
||||||
|
use orchid_base::id_store::{IdRecord, IdStore};
|
||||||
|
use typeid::ConstTypeId;
|
||||||
|
|
||||||
|
use crate::{atom::{AtomCard, AtomFactory, AtomInfo, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrorNotCallable}, expr::{bot, ExprHandle, GenExpr}, system::{atom_info_for, SysCtx}};
|
||||||
|
|
||||||
|
pub struct OwnedVariant;
|
||||||
|
impl AtomicVariant for OwnedVariant {}
|
||||||
|
impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVariant> for A {
|
||||||
|
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();
|
||||||
|
rec.id().encode(&mut data);
|
||||||
|
rec.encode(&mut data);
|
||||||
|
LocalAtom { drop: true, data }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn _info() -> &'static AtomInfo {
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
&const {
|
||||||
|
AtomInfo {
|
||||||
|
tid: ConstTypeId::of::<Self>(),
|
||||||
|
decode: |mut b| Box::new(<Self as Atomic>::Data::decode(&mut b)),
|
||||||
|
call: |b, ctx, arg| with_atom(b, |a| a.remove().dyn_call(ctx, arg)),
|
||||||
|
call_ref: |b, ctx, arg| with_atom(b, |a| a.dyn_call_ref(ctx, arg)),
|
||||||
|
same: |b1, ctx, b2| with_atom(b1, |a1| with_atom(b2, |a2| a1.dyn_same(ctx, &**a2))),
|
||||||
|
handle_req: |b, ctx, req, rep| with_atom(b, |a| a.dyn_handle_req(ctx, req, rep)),
|
||||||
|
drop: |b, ctx| with_atom(b, |a| a.remove().dyn_free(ctx)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Atoms that have a [Drop]
|
||||||
|
pub trait OwnedAtom: AtomCard + 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(self, arg: ExprHandle) -> GenExpr {
|
||||||
|
let ctx = arg.get_ctx();
|
||||||
|
let gcl = self.call_ref(arg);
|
||||||
|
self.free(ctx);
|
||||||
|
gcl
|
||||||
|
}
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn same(&self, ctx: SysCtx, other: &Self) -> bool {
|
||||||
|
eprintln!(
|
||||||
|
"Override OwnedAtom::same for {} if it can be generated during parsing",
|
||||||
|
type_name::<Self>()
|
||||||
|
);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn handle_req(&self, ctx: SysCtx, req: Self::Req, rep: &mut (impl Write + ?Sized));
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn free(self, ctx: SysCtx) {}
|
||||||
|
}
|
||||||
|
pub trait DynOwnedAtom: Send + Sync + 'static {
|
||||||
|
fn atom_tid(&self) -> ConstTypeId;
|
||||||
|
fn as_any_ref(&self) -> &dyn Any;
|
||||||
|
fn encode(&self, buffer: &mut dyn Write);
|
||||||
|
fn dyn_call_ref(&self, ctx: SysCtx, arg: ExprTicket) -> GenExpr;
|
||||||
|
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: ExprTicket) -> GenExpr;
|
||||||
|
fn dyn_same(&self, ctx: SysCtx, other: &dyn DynOwnedAtom) -> bool;
|
||||||
|
fn dyn_handle_req(&self, ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write);
|
||||||
|
fn dyn_free(self: Box<Self>, ctx: SysCtx);
|
||||||
|
}
|
||||||
|
impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||||
|
fn atom_tid(&self) -> ConstTypeId { ConstTypeId::of::<T>() }
|
||||||
|
fn as_any_ref(&self) -> &dyn Any { self }
|
||||||
|
fn encode(&self, buffer: &mut dyn Write) { self.val().as_ref().encode(buffer) }
|
||||||
|
fn dyn_call_ref(&self, ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||||
|
self.call_ref(ExprHandle::from_args(ctx, arg))
|
||||||
|
}
|
||||||
|
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||||
|
self.call(ExprHandle::from_args(ctx, arg))
|
||||||
|
}
|
||||||
|
fn dyn_same(&self, ctx: SysCtx, other: &dyn DynOwnedAtom) -> bool {
|
||||||
|
if ConstTypeId::of::<Self>() != other.as_any_ref().type_id() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let other_self = other.as_any_ref().downcast_ref().expect("The type_ids are the same");
|
||||||
|
self.same(ctx, other_self)
|
||||||
|
}
|
||||||
|
fn dyn_handle_req(&self, ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write) {
|
||||||
|
self.handle_req(ctx, <Self as AtomCard>::Req::decode(req), rep)
|
||||||
|
}
|
||||||
|
fn dyn_free(self: Box<Self>, ctx: SysCtx) { self.free(ctx) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) static OBJ_STORE: IdStore<Box<dyn DynOwnedAtom>> = IdStore::new();
|
||||||
46
orchid-extension/src/atom_thin.rs
Normal file
46
orchid-extension/src/atom_thin.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use std::{any::type_name, fmt, io::Write};
|
||||||
|
|
||||||
|
use orchid_api::atom::LocalAtom;
|
||||||
|
use orchid_api_traits::{Coding, Decode, Encode};
|
||||||
|
use typeid::ConstTypeId;
|
||||||
|
|
||||||
|
use crate::{atom::{get_info, AtomCard, AtomFactory, AtomInfo, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrorNotCallable}, expr::{bot, ExprHandle, GenExpr}, system::SysCtx};
|
||||||
|
|
||||||
|
pub struct ThinVariant;
|
||||||
|
impl AtomicVariant for ThinVariant {}
|
||||||
|
impl<A: ThinAtom + Atomic<Variant = ThinVariant>> AtomicFeaturesImpl<ThinVariant> for A {
|
||||||
|
fn _factory(self) -> AtomFactory {
|
||||||
|
AtomFactory::new(move |sys| {
|
||||||
|
let mut buf = get_info::<A>(sys.dyn_card()).0.enc_vec();
|
||||||
|
self.encode(&mut buf);
|
||||||
|
LocalAtom { drop: false, data: buf }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn _info() -> &'static AtomInfo {
|
||||||
|
&const {
|
||||||
|
AtomInfo {
|
||||||
|
tid: ConstTypeId::of::<Self>(),
|
||||||
|
decode: |mut b| Box::new(Self::decode(&mut b)),
|
||||||
|
call: |mut b, ctx, extk| Self::decode(&mut b).call(ExprHandle::from_args(ctx, extk)),
|
||||||
|
call_ref: |mut b, ctx, extk| Self::decode(&mut b).call(ExprHandle::from_args(ctx, extk)),
|
||||||
|
handle_req: |mut b, ctx, req, rep| Self::decode(&mut b).handle_req(ctx, Decode::decode(req), rep),
|
||||||
|
same: |mut b1, ctx, mut b2| Self::decode(&mut b1).same(ctx, &Self::decode(&mut b2)),
|
||||||
|
drop: |mut b1, _| eprintln!("Received drop signal for non-drop atom {:?}", Self::decode(&mut b1)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ThinAtom: AtomCard<Data = Self> + Coding + fmt::Debug {
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn call(&self, arg: ExprHandle) -> GenExpr { bot(ErrorNotCallable) }
|
||||||
|
#[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>()
|
||||||
|
);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn handle_req(&self, ctx: SysCtx, req: Self::Req, rep: &mut (impl Write + ?Sized));
|
||||||
|
}
|
||||||
55
orchid-extension/src/conv.rs
Normal file
55
orchid-extension/src/conv.rs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
use orchid_base::location::Pos;
|
||||||
|
|
||||||
|
use crate::{atom::{AtomicFeatures, TypAtom}, error::{ProjectError, ProjectResult}, expr::{atom, bot_obj, ExprHandle, GenExpr, OwnedExpr}, system::downcast_atom};
|
||||||
|
|
||||||
|
pub trait TryFromExpr: Sized {
|
||||||
|
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFromExpr for OwnedExpr {
|
||||||
|
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self> { Ok(OwnedExpr::new(expr)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: TryFromExpr, U: TryFromExpr> TryFromExpr for (T, U) {
|
||||||
|
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self> {
|
||||||
|
Ok((T::try_from_expr(expr.clone())?, U::try_from_expr(expr)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ErrorNotAtom(Pos);
|
||||||
|
impl ProjectError for ErrorNotAtom {
|
||||||
|
const DESCRIPTION: &'static str = "Expected an atom";
|
||||||
|
fn one_position(&self) -> Pos { self.0.clone() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ErrorUnexpectedType(Pos);
|
||||||
|
impl ProjectError for ErrorUnexpectedType {
|
||||||
|
const DESCRIPTION: &'static str = "Type error";
|
||||||
|
fn one_position(&self) -> Pos {
|
||||||
|
self.0.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: AtomicFeatures> TryFromExpr for TypAtom<A> {
|
||||||
|
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self> {
|
||||||
|
OwnedExpr::new(expr).foreign_atom().map_err(|ex| ErrorNotAtom(ex.pos.clone()).pack())
|
||||||
|
.and_then(|f| downcast_atom(f).map_err(|f| ErrorUnexpectedType(f.pos).pack()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ToExpr {
|
||||||
|
fn to_expr(self) -> GenExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ToExpr> ToExpr for ProjectResult<T> {
|
||||||
|
fn to_expr(self) -> GenExpr {
|
||||||
|
match self {
|
||||||
|
Err(e) => bot_obj(e),
|
||||||
|
Ok(t) => t.to_expr(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: AtomicFeatures> ToExpr for A {
|
||||||
|
fn to_expr(self) -> GenExpr { atom(self) }
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ use orchid_base::name::PathSlice;
|
|||||||
use orchid_base::reqnot::{ReqNot, Requester};
|
use orchid_base::reqnot::{ReqNot, Requester};
|
||||||
|
|
||||||
use crate::atom::AtomInfo;
|
use crate::atom::AtomInfo;
|
||||||
use crate::error::{err_to_api, unpack_err};
|
use crate::error::{err_or_ref_to_api, unpack_err};
|
||||||
use crate::fs::VirtFS;
|
use crate::fs::VirtFS;
|
||||||
use crate::lexer::LexContext;
|
use crate::lexer::LexContext;
|
||||||
use crate::msg::{recv_parent_msg, send_parent_msg};
|
use crate::msg::{recv_parent_msg, send_parent_msg};
|
||||||
@@ -155,7 +155,7 @@ pub fn extension_main(data: ExtensionData) {
|
|||||||
let data = data.into_api(&*systems_g[&sys].cted.inst());
|
let data = data.into_api(&*systems_g[&sys].cted.inst());
|
||||||
Ok(Lexed { data, pos: (text.len() - s.len()) as u32 })
|
Ok(Lexed { data, pos: (text.len() - s.len()) as u32 })
|
||||||
},
|
},
|
||||||
Err(e) => Err(unpack_err(e).into_iter().map(err_to_api).collect_vec())
|
Err(e) => Err(unpack_err(e).into_iter().map(err_or_ref_to_api).collect_vec())
|
||||||
}))
|
}))
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ pub trait ProjectError: Sized + Send + Sync + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Object-safe version of [ProjectError]. Implement that instead of this.
|
/// Object-safe version of [ProjectError]. Implement that instead of this.
|
||||||
pub trait DynProjectError: Send + Sync {
|
pub trait DynProjectError: Send + Sync + 'static {
|
||||||
/// Access type information about this error
|
/// Access type information about this error
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn as_any_ref(&self) -> &dyn Any;
|
fn as_any_ref(&self) -> &dyn Any;
|
||||||
@@ -274,23 +274,30 @@ impl ProjectError for MultiError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn err_to_api(err: ProjectErrorObj) -> ProjErrOrRef {
|
pub fn err_to_api(err: ProjectErrorObj) -> ProjErr {
|
||||||
match err.as_any_ref().downcast_ref() {
|
ProjErr {
|
||||||
Some(RelayedError { id: Some(id), .. }) => ProjErrOrRef::Known(*id),
|
|
||||||
_ => ProjErrOrRef::New(ProjErr {
|
|
||||||
description: intern(&*err.description()).marker(),
|
description: intern(&*err.description()).marker(),
|
||||||
message: Arc::new(err.message()),
|
message: Arc::new(err.message()),
|
||||||
locations: err.positions().map(|e| e.to_api()).collect_vec(),
|
locations: err.positions().map(|e| e.to_api()).collect_vec(),
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn err_from_api(err: &ProjErrOrRef, reqnot: ReqNot<ExtMsgSet>) -> ProjectErrorObj {
|
pub(crate) fn err_or_ref_to_api(err: ProjectErrorObj) -> ProjErrOrRef {
|
||||||
Arc::new(match err {
|
match err.as_any_ref().downcast_ref() {
|
||||||
ProjErrOrRef::Known(id) => RelayedError { id: Some(*id), reqnot, details: OnceLock::default() },
|
Some(RelayedError { id: Some(id), .. }) => ProjErrOrRef::Known(*id),
|
||||||
ProjErrOrRef::New(err) =>
|
_ => ProjErrOrRef::New(err_to_api(err)),
|
||||||
RelayedError { id: None, reqnot, details: ErrorDetails::from_api(err).into() },
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
pub fn err_from_api(err: &ProjErr, reqnot: ReqNot<ExtMsgSet>) -> ProjectErrorObj {
|
||||||
|
Arc::new(RelayedError { id: None, reqnot, details: ErrorDetails::from_api(err).into() })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn err_from_api_or_ref(err: &ProjErrOrRef, reqnot: ReqNot<ExtMsgSet>) -> ProjectErrorObj {
|
||||||
|
match err {
|
||||||
|
ProjErrOrRef::Known(id) => Arc::new(RelayedError { id: Some(*id), reqnot, details: OnceLock::default() }),
|
||||||
|
ProjErrOrRef::New(err) => err_from_api(err, reqnot),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RelayedError {
|
struct RelayedError {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::OnceLock;
|
use std::sync::{Arc, OnceLock};
|
||||||
|
|
||||||
use derive_destructure::destructure;
|
use derive_destructure::destructure;
|
||||||
use orchid_api::atom::Atom;
|
use orchid_api::atom::Atom;
|
||||||
@@ -8,7 +8,8 @@ use orchid_base::interner::{deintern, Tok};
|
|||||||
use orchid_base::location::Pos;
|
use orchid_base::location::Pos;
|
||||||
use orchid_base::reqnot::Requester;
|
use orchid_base::reqnot::Requester;
|
||||||
|
|
||||||
use crate::atom::{AtomFactory, ForeignAtom, OwnedAtom, ThinAtom};
|
use crate::atom::{AtomFactory, AtomicFeatures, ForeignAtom};
|
||||||
|
use crate::error::{err_from_api, err_to_api, DynProjectError, ProjectErrorObj};
|
||||||
use crate::system::{DynSystem, SysCtx};
|
use crate::system::{DynSystem, SysCtx};
|
||||||
|
|
||||||
#[derive(destructure)]
|
#[derive(destructure)]
|
||||||
@@ -22,7 +23,6 @@ impl ExprHandle {
|
|||||||
let (tk, ..) = self.destructure();
|
let (tk, ..) = self.destructure();
|
||||||
tk
|
tk
|
||||||
}
|
}
|
||||||
pub(crate) fn get_tk(&self) -> ExprTicket { self.tk }
|
|
||||||
pub fn get_ctx(&self) -> SysCtx { self.ctx.clone() }
|
pub fn get_ctx(&self) -> SysCtx { self.ctx.clone() }
|
||||||
}
|
}
|
||||||
impl Clone for ExprHandle {
|
impl Clone for ExprHandle {
|
||||||
@@ -51,9 +51,9 @@ impl OwnedExpr {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn foreign_atom(self) -> Result<ForeignAtom, Self> {
|
pub fn foreign_atom(self) -> Result<ForeignAtom, Self> {
|
||||||
if let GenExpr { clause: GenClause::Atom(_, atom), position } = self.get_data() {
|
if let GenExpr { clause: GenClause::Atom(_, atom), pos: position } = self.get_data() {
|
||||||
let (atom, position) = (atom.clone(), position.clone());
|
let (atom, position) = (atom.clone(), position.clone());
|
||||||
return Ok(ForeignAtom { expr: self.handle, atom, position });
|
return Ok(ForeignAtom { expr: self.handle, atom, pos: position });
|
||||||
}
|
}
|
||||||
Err(self)
|
Err(self)
|
||||||
}
|
}
|
||||||
@@ -65,18 +65,18 @@ impl Deref for OwnedExpr {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct GenExpr {
|
pub struct GenExpr {
|
||||||
pub position: Pos,
|
pub pos: Pos,
|
||||||
pub clause: GenClause,
|
pub clause: GenClause,
|
||||||
}
|
}
|
||||||
impl GenExpr {
|
impl GenExpr {
|
||||||
pub fn to_api(&self, sys: &dyn DynSystem) -> Expr {
|
pub fn to_api(&self, sys: &dyn DynSystem) -> Expr {
|
||||||
Expr { location: self.position.to_api(), clause: self.clause.to_api(sys) }
|
Expr { location: self.pos.to_api(), clause: self.clause.to_api(sys) }
|
||||||
}
|
}
|
||||||
pub fn into_api(self, sys: &dyn DynSystem) -> Expr {
|
pub fn into_api(self, sys: &dyn DynSystem) -> Expr {
|
||||||
Expr { location: self.position.to_api(), clause: self.clause.into_api(sys) }
|
Expr { location: self.pos.to_api(), clause: self.clause.into_api(sys) }
|
||||||
}
|
}
|
||||||
pub fn from_api(api: Expr, ctx: SysCtx) -> Self {
|
pub fn from_api(api: Expr, ctx: SysCtx) -> Self {
|
||||||
Self { position: Pos::from_api(&api.location), clause: GenClause::from_api(api.clause, ctx) }
|
Self { pos: Pos::from_api(&api.location), clause: GenClause::from_api(api.clause, ctx) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ pub enum GenClause {
|
|||||||
Const(Tok<Vec<Tok<String>>>),
|
Const(Tok<Vec<Tok<String>>>),
|
||||||
NewAtom(AtomFactory),
|
NewAtom(AtomFactory),
|
||||||
Atom(ExprTicket, Atom),
|
Atom(ExprTicket, Atom),
|
||||||
Bottom(String),
|
Bottom(ProjectErrorObj),
|
||||||
}
|
}
|
||||||
impl GenClause {
|
impl GenClause {
|
||||||
pub fn to_api(&self, sys: &dyn DynSystem) -> Clause {
|
pub fn to_api(&self, sys: &dyn DynSystem) -> Clause {
|
||||||
@@ -100,7 +100,7 @@ impl GenClause {
|
|||||||
Self::Lambda(arg, body) => Clause::Lambda(*arg, Box::new(body.to_api(sys))),
|
Self::Lambda(arg, body) => Clause::Lambda(*arg, Box::new(body.to_api(sys))),
|
||||||
Self::Arg(arg) => Clause::Arg(*arg),
|
Self::Arg(arg) => Clause::Arg(*arg),
|
||||||
Self::Const(name) => Clause::Const(name.marker()),
|
Self::Const(name) => Clause::Const(name.marker()),
|
||||||
Self::Bottom(msg) => Clause::Bottom(msg.clone()),
|
Self::Bottom(msg) => Clause::Bottom(err_to_api(msg.clone())),
|
||||||
Self::NewAtom(fac) => Clause::NewAtom(fac.clone().build(sys)),
|
Self::NewAtom(fac) => Clause::NewAtom(fac.clone().build(sys)),
|
||||||
Self::Atom(tk, atom) => Clause::Atom(*tk, atom.clone()),
|
Self::Atom(tk, atom) => Clause::Atom(*tk, atom.clone()),
|
||||||
Self::Slot(_) => panic!("Slot is forbidden in const tree"),
|
Self::Slot(_) => panic!("Slot is forbidden in const tree"),
|
||||||
@@ -114,7 +114,7 @@ impl GenClause {
|
|||||||
Self::Arg(arg) => Clause::Arg(arg),
|
Self::Arg(arg) => Clause::Arg(arg),
|
||||||
Self::Slot(extk) => Clause::Slot(extk.handle.into_tk()),
|
Self::Slot(extk) => Clause::Slot(extk.handle.into_tk()),
|
||||||
Self::Const(name) => Clause::Const(name.marker()),
|
Self::Const(name) => Clause::Const(name.marker()),
|
||||||
Self::Bottom(msg) => Clause::Bottom(msg.clone()),
|
Self::Bottom(msg) => Clause::Bottom(err_to_api(msg)),
|
||||||
Self::NewAtom(fac) => Clause::NewAtom(fac.clone().build(sys)),
|
Self::NewAtom(fac) => Clause::NewAtom(fac.clone().build(sys)),
|
||||||
Self::Atom(tk, atom) => Clause::Atom(tk, atom),
|
Self::Atom(tk, atom) => Clause::Atom(tk, atom),
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ impl GenClause {
|
|||||||
Clause::Arg(id) => Self::Arg(id),
|
Clause::Arg(id) => Self::Arg(id),
|
||||||
Clause::Lambda(arg, body) => Self::Lambda(arg, Box::new(GenExpr::from_api(*body, ctx))),
|
Clause::Lambda(arg, body) => Self::Lambda(arg, Box::new(GenExpr::from_api(*body, ctx))),
|
||||||
Clause::NewAtom(_) => panic!("Clause::NewAtom should never be received, only sent"),
|
Clause::NewAtom(_) => panic!("Clause::NewAtom should never be received, only sent"),
|
||||||
Clause::Bottom(s) => Self::Bottom(s),
|
Clause::Bottom(s) => Self::Bottom(err_from_api(&s, ctx.reqnot)),
|
||||||
Clause::Call(f, x) => Self::Call(
|
Clause::Call(f, x) => Self::Call(
|
||||||
Box::new(GenExpr::from_api(*f, ctx.clone())),
|
Box::new(GenExpr::from_api(*f, ctx.clone())),
|
||||||
Box::new(GenExpr::from_api(*x, ctx)),
|
Box::new(GenExpr::from_api(*x, ctx)),
|
||||||
@@ -139,11 +139,10 @@ impl GenClause {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn inherit(clause: GenClause) -> GenExpr { GenExpr { position: Pos::Inherit, clause } }
|
fn inherit(clause: GenClause) -> GenExpr { GenExpr { pos: Pos::Inherit, clause } }
|
||||||
|
|
||||||
pub fn cnst(path: Tok<Vec<Tok<String>>>) -> GenExpr { inherit(GenClause::Const(path)) }
|
pub fn cnst(path: Tok<Vec<Tok<String>>>) -> GenExpr { inherit(GenClause::Const(path)) }
|
||||||
pub fn val<A: ThinAtom>(atom: A) -> GenExpr { inherit(GenClause::NewAtom(atom.factory())) }
|
pub fn atom<A: AtomicFeatures>(atom: A) -> GenExpr { inherit(GenClause::NewAtom(atom.factory())) }
|
||||||
pub fn obj<A: OwnedAtom>(atom: A) -> GenExpr { inherit(GenClause::NewAtom(atom.factory())) }
|
|
||||||
|
|
||||||
pub fn seq(ops: impl IntoIterator<Item = GenExpr>) -> GenExpr {
|
pub fn seq(ops: impl IntoIterator<Item = GenExpr>) -> GenExpr {
|
||||||
fn recur(mut ops: impl Iterator<Item = GenExpr>) -> Option<GenExpr> {
|
fn recur(mut ops: impl Iterator<Item = GenExpr>) -> Option<GenExpr> {
|
||||||
@@ -170,4 +169,5 @@ pub fn call(v: impl IntoIterator<Item = GenExpr>) -> GenExpr {
|
|||||||
.expect("Empty call expression")
|
.expect("Empty call expression")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bot(msg: &str) -> GenClause { GenClause::Bottom(msg.to_string()) }
|
pub fn bot<E: DynProjectError>(msg: E) -> GenExpr { inherit(GenClause::Bottom(Arc::new(msg))) }
|
||||||
|
pub fn bot_obj(e: ProjectErrorObj) -> GenExpr { inherit(GenClause::Bottom(e)) }
|
||||||
|
|||||||
@@ -4,31 +4,34 @@ use dyn_clone::{clone_box, DynClone};
|
|||||||
use never::Never;
|
use never::Never;
|
||||||
use trait_set::trait_set;
|
use trait_set::trait_set;
|
||||||
|
|
||||||
use crate::atom::{AtomCard, OwnedAtom};
|
use crate::atom::Atomic;
|
||||||
use crate::expr::{ExprHandle, GenClause};
|
use crate::atom_owned::{OwnedAtom, OwnedVariant};
|
||||||
|
use crate::expr::{ExprHandle, GenExpr};
|
||||||
use crate::system::SysCtx;
|
use crate::system::SysCtx;
|
||||||
|
use crate::conv::{ToExpr, TryFromExpr};
|
||||||
|
|
||||||
trait_set! {
|
trait_set! {
|
||||||
trait FunCB = FnOnce(ExprHandle) -> GenClause + DynClone + Send + Sync + 'static;
|
trait FunCB = FnOnce(ExprHandle) -> GenExpr + DynClone + Send + Sync + 'static;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Fun(Box<dyn FunCB>);
|
pub struct Fun(Box<dyn FunCB>);
|
||||||
impl Fun {
|
impl Fun {
|
||||||
pub fn new(f: impl FnOnce(ExprHandle) -> GenClause + Clone + Send + Sync + 'static) -> Self {
|
pub fn new<I: TryFromExpr, O: ToExpr>(f: impl FnOnce(I) -> O + Clone + Send + Sync + 'static) -> Self {
|
||||||
Self(Box::new(f))
|
Self(Box::new(|eh| I::try_from_expr(eh).map(f).to_expr()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Clone for Fun {
|
impl Clone for Fun {
|
||||||
fn clone(&self) -> Self { Self(clone_box(&*self.0)) }
|
fn clone(&self) -> Self { Self(clone_box(&*self.0)) }
|
||||||
}
|
}
|
||||||
impl AtomCard for Fun {
|
impl Atomic for Fun {
|
||||||
type Data = ();
|
type Data = ();
|
||||||
type Req = Never;
|
type Req = Never;
|
||||||
|
type Variant = OwnedVariant;
|
||||||
}
|
}
|
||||||
impl OwnedAtom for Fun {
|
impl OwnedAtom for Fun {
|
||||||
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||||
fn call_ref(&self, arg: ExprHandle) -> GenClause { self.clone().call(arg) }
|
fn call_ref(&self, arg: ExprHandle) -> GenExpr { self.clone().call(arg) }
|
||||||
fn call(self, arg: ExprHandle) -> GenClause { (self.0)(arg) }
|
fn call(self, arg: ExprHandle) -> GenExpr { (self.0)(arg) }
|
||||||
fn handle_req(&self, _ctx: SysCtx, req: Self::Req, _rep: &mut (impl std::io::Write + ?Sized)) {
|
fn handle_req(&self, _ctx: SysCtx, req: Self::Req, _rep: &mut (impl std::io::Write + ?Sized)) {
|
||||||
match req {}
|
match req {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use orchid_base::interner::Tok;
|
|||||||
use orchid_base::reqnot::{ReqNot, Requester};
|
use orchid_base::reqnot::{ReqNot, Requester};
|
||||||
|
|
||||||
use crate::error::{
|
use crate::error::{
|
||||||
err_from_api, err_to_api, pack_err, unpack_err, ProjectErrorObj, ProjectResult,
|
err_from_api_or_ref, err_or_ref_to_api, pack_err, unpack_err, ProjectErrorObj, ProjectResult,
|
||||||
};
|
};
|
||||||
use crate::tree::{GenTok, GenTokTree};
|
use crate::tree::{GenTok, GenTokTree};
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ impl<'a> LexContext<'a> {
|
|||||||
self
|
self
|
||||||
.reqnot
|
.reqnot
|
||||||
.request(SubLex { pos: start, id: self.id })
|
.request(SubLex { pos: start, id: self.id })
|
||||||
.map_err(|e| pack_err(e.iter().map(|e| err_from_api(e, self.reqnot.clone()))))
|
.map_err(|e| pack_err(e.iter().map(|e| err_from_api_or_ref(e, self.reqnot.clone()))))
|
||||||
.map(|lx| (&self.text[lx.pos as usize..], GenTok::Slot(lx.ticket).at(start..lx.pos)))
|
.map(|lx| (&self.text[lx.pos as usize..], GenTok::Slot(lx.ticket).at(start..lx.pos)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ impl<'a> LexContext<'a> {
|
|||||||
|
|
||||||
pub fn report(&self, e: ProjectErrorObj) {
|
pub fn report(&self, e: ProjectErrorObj) {
|
||||||
for e in unpack_err(e) {
|
for e in unpack_err(e) {
|
||||||
self.reqnot.notify(ReportError(self.sys, err_to_api(e)))
|
self.reqnot.notify(ReportError(self.sys, err_or_ref_to_api(e)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,4 +10,6 @@ pub mod other_system;
|
|||||||
pub mod system;
|
pub mod system;
|
||||||
pub mod system_ctor;
|
pub mod system_ctor;
|
||||||
pub mod tree;
|
pub mod tree;
|
||||||
pub mod try_from_expr;
|
pub mod conv;
|
||||||
|
pub mod atom_thin;
|
||||||
|
pub mod atom_owned;
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
use orchid_api_traits::Decode;
|
||||||
|
|
||||||
use orchid_api::proto::ExtMsgSet;
|
use orchid_api::proto::ExtMsgSet;
|
||||||
use orchid_api::system::SysId;
|
use orchid_api::system::SysId;
|
||||||
use orchid_base::reqnot::ReqNot;
|
use orchid_base::reqnot::ReqNot;
|
||||||
use typeid::ConstTypeId;
|
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::fs::DeclFs;
|
||||||
use crate::fun::Fun;
|
use crate::fun::Fun;
|
||||||
use crate::lexer::LexerObj;
|
use crate::lexer::LexerObj;
|
||||||
@@ -13,42 +15,44 @@ use crate::tree::GenTree;
|
|||||||
/// System as consumed by foreign code
|
/// System as consumed by foreign code
|
||||||
pub trait SystemCard: Default + Send + Sync + 'static {
|
pub trait SystemCard: Default + Send + Sync + 'static {
|
||||||
type Ctor: SystemCtor;
|
type Ctor: SystemCtor;
|
||||||
const ATOM_DEFS: &'static [Option<AtomInfo>];
|
const ATOM_DEFS: &'static [Option<fn() -> &'static AtomInfo>];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DynSystemCard: Send + Sync + 'static {
|
pub trait DynSystemCard: Send + Sync + 'static {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
/// Atoms explicitly defined by the system card. Do not rely on this for
|
/// Atoms explicitly defined by the system card. Do not rely on this for
|
||||||
/// querying atoms as it doesn't include the general atom types
|
/// 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.
|
/// 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
|
/// 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)
|
/// 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(
|
pub fn atom_info_for(
|
||||||
sys: &(impl DynSystemCard + ?Sized),
|
sys: &(impl DynSystemCard + ?Sized),
|
||||||
tid: ConstTypeId,
|
tid: ConstTypeId,
|
||||||
) -> Option<(u64, &AtomInfo)> {
|
) -> Option<(u64, &AtomInfo)> {
|
||||||
(sys.atoms().iter().enumerate().map(|(i, o)| (i as u64, o)))
|
(sys.atoms().iter().enumerate().map(|(i, o)| (i as u64, o)))
|
||||||
.chain(GENERAL_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)))
|
.filter_map(|(i, o)| o.as_ref().map(|a| (i, a())))
|
||||||
.find(|ent| ent.1.tid == tid)
|
.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 {
|
if (tid >> (u64::BITS - 1)) & 1 == 1 {
|
||||||
GENERAL_ATOMS[!tid as usize].as_ref()
|
general_atoms()[!tid as usize].map(|f| f())
|
||||||
} else {
|
} else {
|
||||||
sys.atoms()[tid as usize].as_ref()
|
sys.atoms()[tid as usize].map(|f| f())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: SystemCard> DynSystemCard for T {
|
impl<T: SystemCard> DynSystemCard for T {
|
||||||
fn name(&self) -> &'static str { T::Ctor::NAME }
|
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
|
/// 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> {
|
pub fn downcast_atom<A: AtomCard>(foreign: ForeignAtom) -> Result<TypAtom<A>, ForeignAtom> {
|
||||||
match (foreign.expr.get_ctx().cted.deps())
|
let mut data = &foreign.atom.data[..];
|
||||||
.find(|s| s.id() == foreign.atom.owner)
|
let ctx = foreign.expr.get_ctx();
|
||||||
.and_then(|sys| decode_atom::<A>(sys.get_card(), &foreign.atom))
|
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),
|
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 })
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use ordered_float::NotNan;
|
|||||||
use trait_set::trait_set;
|
use trait_set::trait_set;
|
||||||
|
|
||||||
use crate::atom::AtomFactory;
|
use crate::atom::AtomFactory;
|
||||||
|
use crate::conv::ToExpr;
|
||||||
use crate::expr::GenExpr;
|
use crate::expr::GenExpr;
|
||||||
use crate::system::DynSystem;
|
use crate::system::DynSystem;
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ pub struct GenTree {
|
|||||||
pub location: Pos,
|
pub location: Pos,
|
||||||
}
|
}
|
||||||
impl GenTree {
|
impl GenTree {
|
||||||
pub fn cnst(gc: GenExpr) -> Self { GenItem::Const(gc).at(Pos::Inherit) }
|
pub fn cnst(gc: impl ToExpr) -> Self { GenItem::Const(gc.to_expr()).at(Pos::Inherit) }
|
||||||
pub fn module<'a>(entries: impl IntoIterator<Item = (&'a str, GenTree)>) -> Self {
|
pub fn module<'a>(entries: impl IntoIterator<Item = (&'a str, GenTree)>) -> Self {
|
||||||
GenItem::Mod(entries.into_iter().map(|(k, v)| (k.to_string(), v)).collect()).at(Pos::Inherit)
|
GenItem::Mod(entries.into_iter().map(|(k, v)| (k.to_string(), v)).collect()).at(Pos::Inherit)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
use crate::error::ProjectResult;
|
|
||||||
use crate::expr::{ExprHandle, OwnedExpr};
|
|
||||||
|
|
||||||
pub trait TryFromExpr: Sized {
|
|
||||||
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFromExpr for OwnedExpr {
|
|
||||||
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self> { Ok(OwnedExpr::new(expr)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: TryFromExpr, U: TryFromExpr> TryFromExpr for (T, U) {
|
|
||||||
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self> {
|
|
||||||
Ok((T::try_from_expr(expr.clone())?, U::try_from_expr(expr)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,7 @@ use hashbrown::HashMap;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use orchid_api::atom::{Atom, AtomDrop, AtomSame, CallRef, FinalCall, Fwd, Fwded};
|
use orchid_api::atom::{Atom, AtomDrop, AtomSame, CallRef, FinalCall, Fwd, Fwded};
|
||||||
use orchid_api::error::{ErrNotif, ProjErr, ProjErrOrRef, ProjResult, ReportError};
|
use orchid_api::error::{ErrNotif, ProjErrOrRef, ProjResult, ReportError};
|
||||||
use orchid_api::expr::{Acquire, Expr, ExprNotif, ExprTicket, Release, Relocate};
|
use orchid_api::expr::{Acquire, Expr, ExprNotif, ExprTicket, Release, Relocate};
|
||||||
use orchid_api::interner::IntReq;
|
use orchid_api::interner::IntReq;
|
||||||
use orchid_api::parser::CharFilter;
|
use orchid_api::parser::CharFilter;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
|
once_cell = "1.19.0"
|
||||||
orchid-api = { version = "0.1.0", path = "../orchid-api" }
|
orchid-api = { version = "0.1.0", path = "../orchid-api" }
|
||||||
orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" }
|
orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" }
|
||||||
orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
|
orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
use orchid_extension::atom::owned_atom_info;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use orchid_extension::atom::AtomicFeatures;
|
||||||
use orchid_extension::fs::DeclFs;
|
use orchid_extension::fs::DeclFs;
|
||||||
|
use orchid_extension::fun::Fun;
|
||||||
use orchid_extension::system::{System, SystemCard};
|
use orchid_extension::system::{System, SystemCard};
|
||||||
use orchid_extension::system_ctor::SystemCtor;
|
use orchid_extension::system_ctor::SystemCtor;
|
||||||
use orchid_extension::tree::GenTree;
|
use orchid_extension::tree::GenTree;
|
||||||
|
|
||||||
use crate::string::str_atom::StringAtom;
|
use crate::string::str_atom::StringAtom;
|
||||||
use crate::string::str_leer::StringLexer;
|
use crate::string::str_leer::StringLexer;
|
||||||
|
use crate::OrcString;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct StdSystem;
|
pub struct StdSystem;
|
||||||
@@ -18,13 +22,16 @@ impl SystemCtor for StdSystem {
|
|||||||
}
|
}
|
||||||
impl SystemCard for StdSystem {
|
impl SystemCard for StdSystem {
|
||||||
type Ctor = Self;
|
type Ctor = Self;
|
||||||
const ATOM_DEFS: &'static [Option<orchid_extension::atom::AtomInfo>] =
|
const ATOM_DEFS: &'static [Option<fn() -> &'static orchid_extension::atom::AtomInfo>] = &[
|
||||||
&[Some(owned_atom_info::<StringAtom>())];
|
Some(StringAtom::info)
|
||||||
|
];
|
||||||
}
|
}
|
||||||
impl System for StdSystem {
|
impl System for StdSystem {
|
||||||
fn lexers() -> Vec<orchid_extension::lexer::LexerObj> { vec![&StringLexer] }
|
fn lexers() -> Vec<orchid_extension::lexer::LexerObj> { vec![&StringLexer] }
|
||||||
fn vfs() -> DeclFs { DeclFs::Mod(&[]) }
|
fn vfs() -> DeclFs { DeclFs::Mod(&[]) }
|
||||||
fn env() -> GenTree {
|
fn env() -> GenTree {
|
||||||
GenTree::module([("std", GenTree::module([("string", GenTree::module([]))]))])
|
GenTree::module([("std", GenTree::module([("string", GenTree::module([
|
||||||
|
("concat", GenTree::cnst(Fun::new(|left: OrcString| Fun::new(move |right: OrcString| StringAtom::new(Arc::new(left.get_string().to_string() + &right.get_string()))))))
|
||||||
|
]))]))])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ use orchid_api_traits::{Encode, Request};
|
|||||||
use orchid_base::id_store::IdStore;
|
use orchid_base::id_store::IdStore;
|
||||||
use orchid_base::interner::{deintern, Tok};
|
use orchid_base::interner::{deintern, Tok};
|
||||||
use orchid_base::location::Pos;
|
use orchid_base::location::Pos;
|
||||||
use orchid_extension::atom::{AtomCard, OwnedAtom, TypAtom};
|
use orchid_extension::atom::{Atomic, TypAtom};
|
||||||
|
use orchid_extension::atom_owned::{OwnedAtom, OwnedVariant};
|
||||||
use orchid_extension::error::{ProjectError, ProjectResult};
|
use orchid_extension::error::{ProjectError, ProjectResult};
|
||||||
use orchid_extension::expr::{ExprHandle, OwnedExpr};
|
use orchid_extension::expr::{ExprHandle, OwnedExpr};
|
||||||
use orchid_extension::system::{downcast_atom, SysCtx};
|
use orchid_extension::system::{downcast_atom, SysCtx};
|
||||||
use orchid_extension::try_from_expr::TryFromExpr;
|
use orchid_extension::conv::TryFromExpr;
|
||||||
|
|
||||||
pub static STR_REPO: IdStore<Arc<String>> = IdStore::new();
|
pub static STR_REPO: IdStore<Arc<String>> = IdStore::new();
|
||||||
|
|
||||||
@@ -31,7 +32,8 @@ pub(crate) enum StringAtom {
|
|||||||
Val(NonZeroU64),
|
Val(NonZeroU64),
|
||||||
Int(Tok<String>),
|
Int(Tok<String>),
|
||||||
}
|
}
|
||||||
impl AtomCard for StringAtom {
|
impl Atomic for StringAtom {
|
||||||
|
type Variant = OwnedVariant;
|
||||||
type Data = StringVal;
|
type Data = StringVal;
|
||||||
type Req = StringGetVal;
|
type Req = StringGetVal;
|
||||||
}
|
}
|
||||||
@@ -72,6 +74,7 @@ impl OwnedAtom for StringAtom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct OrcString(TypAtom<StringAtom>);
|
pub struct OrcString(TypAtom<StringAtom>);
|
||||||
impl OrcString {
|
impl OrcString {
|
||||||
pub fn get_string(&self) -> Arc<String> {
|
pub fn get_string(&self) -> Arc<String> {
|
||||||
@@ -92,9 +95,9 @@ impl ProjectError for NotString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl TryFromExpr for OrcString {
|
impl TryFromExpr for OrcString {
|
||||||
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self> {
|
fn try_from_expr(expr: ExprHandle) -> ProjectResult<OrcString> {
|
||||||
(OwnedExpr::new(expr).foreign_atom().map_err(|expr| expr.position.clone()))
|
(OwnedExpr::new(expr).foreign_atom().map_err(|expr| expr.pos.clone()))
|
||||||
.and_then(|fatom| downcast_atom(fatom).map_err(|f| f.position))
|
.and_then(|fatom| downcast_atom(fatom).map_err(|f| f.pos))
|
||||||
.map_err(|p| NotString(p).pack())
|
.map_err(|p| NotString(p).pack())
|
||||||
.map(OrcString)
|
.map(OrcString)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use orchid_base::interner::intern;
|
|||||||
use orchid_base::location::Pos;
|
use orchid_base::location::Pos;
|
||||||
use orchid_base::name::VName;
|
use orchid_base::name::VName;
|
||||||
use orchid_base::vname;
|
use orchid_base::vname;
|
||||||
use orchid_extension::atom::OwnedAtom;
|
use orchid_extension::atom::AtomicFeatures;
|
||||||
use orchid_extension::error::{ErrorSansOrigin, ProjectErrorObj, ProjectResult};
|
use orchid_extension::error::{ErrorSansOrigin, ProjectErrorObj, ProjectResult};
|
||||||
use orchid_extension::lexer::{LexContext, Lexer};
|
use orchid_extension::lexer::{LexContext, Lexer};
|
||||||
use orchid_extension::tree::{wrap_tokv, GenTok, GenTokTree};
|
use orchid_extension::tree::{wrap_tokv, GenTok, GenTokTree};
|
||||||
|
|||||||
Reference in New Issue
Block a user