forked from Orchid/orchid
Added directfs
Added a very rudimentary file I/O system suitable for experimenting with the language further. A better one will be designed when we have sensible error management.
This commit is contained in:
@@ -37,8 +37,10 @@ where
|
||||
/// ```ignore
|
||||
/// fn as_any(self: Box<Self>) -> Box<dyn Any> { self }
|
||||
/// ```
|
||||
#[must_use]
|
||||
fn as_any(self: Box<Self>) -> Box<dyn Any>;
|
||||
/// See [Atomic::as_any], exactly the same but for references
|
||||
#[must_use]
|
||||
fn as_any_ref(&self) -> &dyn Any;
|
||||
|
||||
/// Attempt to normalize this value. If it wraps a value, this should report
|
||||
@@ -47,6 +49,7 @@ where
|
||||
fn run(self: Box<Self>, ctx: Context) -> AtomicResult;
|
||||
|
||||
/// Wrap the atom in a clause to be placed in an [AtomicResult].
|
||||
#[must_use]
|
||||
fn atom_cls(self) -> Clause
|
||||
where
|
||||
Self: Sized,
|
||||
@@ -55,6 +58,7 @@ where
|
||||
}
|
||||
|
||||
/// Wrap the atom in a new expression instance to be placed in a tree
|
||||
#[must_use]
|
||||
fn atom_exi(self) -> ExprInst
|
||||
where
|
||||
Self: Sized,
|
||||
@@ -73,10 +77,12 @@ where
|
||||
pub struct Atom(pub Box<dyn Atomic>);
|
||||
impl Atom {
|
||||
/// Wrap an [Atomic] in a type-erased box
|
||||
#[must_use]
|
||||
pub fn new<T: 'static + Atomic>(data: T) -> Self {
|
||||
Self(Box::new(data) as Box<dyn Atomic>)
|
||||
}
|
||||
/// Get the contained data
|
||||
#[must_use]
|
||||
pub fn data(&self) -> &dyn Atomic { self.0.as_ref() as &dyn Atomic }
|
||||
/// Attempt to downcast contained data to a specific type
|
||||
pub fn try_cast<T: Atomic>(self) -> Result<T, Self> {
|
||||
@@ -86,8 +92,10 @@ impl Atom {
|
||||
}
|
||||
}
|
||||
/// Test the type of the contained data without downcasting
|
||||
#[must_use]
|
||||
pub fn is<T: 'static>(&self) -> bool { self.data().as_any_ref().is::<T>() }
|
||||
/// Downcast contained data, panic if it isn't the specified type
|
||||
#[must_use]
|
||||
pub fn cast<T: 'static>(self) -> T {
|
||||
*self.0.as_any().downcast().expect("Type mismatch on Atom::cast")
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ struct CPSFn<T: CPSPayload> {
|
||||
pub payload: T,
|
||||
}
|
||||
impl<T: CPSPayload> CPSFn<T> {
|
||||
#[must_use]
|
||||
fn new(argc: usize, payload: T) -> Self {
|
||||
debug_assert!(
|
||||
argc > 0,
|
||||
@@ -55,37 +56,25 @@ pub struct CPSBox<T: CPSPayload> {
|
||||
pub continuations: Vec<ExprInst>,
|
||||
}
|
||||
impl<T: CPSPayload> CPSBox<T> {
|
||||
/// Assert that the command was instantiated with the correct number of
|
||||
/// possible continuations. This is decided by the native bindings, not user
|
||||
/// code, therefore this error may be uncovered by usercode but can never be
|
||||
/// produced at will.
|
||||
pub fn assert_count(&self, expect: usize) {
|
||||
let real = self.continuations.len();
|
||||
debug_assert!(
|
||||
real == expect,
|
||||
"Tried to read {expect} argument(s) but {real} were provided for {:?}",
|
||||
self.payload
|
||||
)
|
||||
}
|
||||
/// Unpack the wrapped command and the continuation
|
||||
#[must_use]
|
||||
pub fn unpack1(self) -> (T, ExprInst) {
|
||||
self.assert_count(1);
|
||||
let [cont]: [ExprInst; 1] =
|
||||
self.continuations.try_into().expect("size checked");
|
||||
(self.payload, cont)
|
||||
}
|
||||
/// Unpack the wrapped command and 2 continuations (usually an async and a
|
||||
/// sync)
|
||||
#[must_use]
|
||||
pub fn unpack2(self) -> (T, ExprInst, ExprInst) {
|
||||
self.assert_count(2);
|
||||
let [c1, c2]: [ExprInst; 2] =
|
||||
self.continuations.try_into().expect("size checked");
|
||||
(self.payload, c1, c2)
|
||||
}
|
||||
/// Unpack the wrapped command and 3 continuations (usually an async success,
|
||||
/// an async fail and a sync)
|
||||
#[must_use]
|
||||
pub fn unpack3(self) -> (T, ExprInst, ExprInst, ExprInst) {
|
||||
self.assert_count(3);
|
||||
let [c1, c2, c3]: [ExprInst; 3] =
|
||||
self.continuations.try_into().expect("size checked");
|
||||
(self.payload, c1, c2, c3)
|
||||
@@ -97,6 +86,7 @@ impl<T: CPSPayload> InertAtomic for CPSBox<T> {
|
||||
}
|
||||
|
||||
/// Like [init_cps] but wrapped in a [ConstTree] for init-time usage
|
||||
#[must_use]
|
||||
pub fn const_cps<T: CPSPayload>(argc: usize, payload: T) -> ConstTree {
|
||||
ConstTree::xfn(CPSFn::new(argc, payload))
|
||||
}
|
||||
@@ -106,6 +96,7 @@ pub fn const_cps<T: CPSPayload>(argc: usize, payload: T) -> ConstTree {
|
||||
///
|
||||
/// This function is meant to be used in an external function defined with
|
||||
/// [crate::define_fn]. For usage in a [ConstTree], see [mk_const]
|
||||
#[must_use]
|
||||
pub fn init_cps<T: CPSPayload>(argc: usize, payload: T) -> Clause {
|
||||
CPSFn::new(argc, payload).xfn_cls()
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ pub type XfnResult = Result<Clause, Rc<dyn ExternError>>;
|
||||
/// Errors produced by external code
|
||||
pub trait ExternError: Display {
|
||||
/// Convert into trait object
|
||||
#[must_use]
|
||||
fn into_extern(self) -> Rc<dyn ExternError>
|
||||
where
|
||||
Self: 'static + Sized,
|
||||
@@ -37,6 +38,7 @@ impl Error for dyn ExternError {}
|
||||
/// these are also external functions.
|
||||
pub trait ExternFn: DynClone {
|
||||
/// Display name of the function
|
||||
#[must_use]
|
||||
fn name(&self) -> &str;
|
||||
/// Combine the function with an argument to produce a new clause
|
||||
fn apply(self: Box<Self>, arg: ExprInst, ctx: Context) -> XfnResult;
|
||||
@@ -45,6 +47,7 @@ pub trait ExternFn: DynClone {
|
||||
self.name().hash(&mut state)
|
||||
}
|
||||
/// Wrap this function in a clause to be placed in an [AtomicResult].
|
||||
#[must_use]
|
||||
fn xfn_cls(self) -> Clause
|
||||
where
|
||||
Self: Sized + 'static,
|
||||
|
||||
@@ -19,6 +19,7 @@ use crate::Primitive;
|
||||
/// provided in argument lists.
|
||||
pub trait InertAtomic: Debug + Clone + 'static {
|
||||
/// Typename to be shown in the error when a conversion from [ExprInst] fails
|
||||
#[must_use]
|
||||
fn type_str() -> &'static str;
|
||||
/// Proxies to [Responder] so that you don't have to implmeent it manually if
|
||||
/// you need it, but behaves exactly as the default implementation.
|
||||
|
||||
Reference in New Issue
Block a user