Backup commit

My backspace key started ghosting. Nothing works atm.
This commit is contained in:
2024-01-27 14:50:33 +00:00
parent f77e4fd90a
commit a8887227e5
236 changed files with 10946 additions and 8977 deletions

View File

@@ -1,47 +1,16 @@
use std::any::{Any, TypeId};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::sync::Arc;
use super::atom::StrictEq;
use super::{
Atomic, AtomicResult, AtomicReturn, ExternError, ExternFn, XfnResult,
};
use crate::ddispatch::Responder;
use crate::interpreted::{Clause, ExprInst, TryFromExprInst};
use crate::interpreter::{run, Context, Return};
use crate::systems::codegen::{opt, res};
use crate::OrcString;
/// A trait for things that are infallibly convertible to [Clause]. These types
/// can be returned by callbacks passed to the [super::xfn_1ary] family of
/// functions.
pub trait ToClause: Clone {
/// Convert the type to a [Clause].
fn to_clause(self) -> Clause;
/// Convert to an expression instance via [ToClause].
fn to_exi(self) -> ExprInst { self.to_clause().wrap() }
}
impl<T: Atomic + Clone> ToClause for T {
fn to_clause(self) -> Clause { self.atom_cls() }
}
impl ToClause for Clause {
fn to_clause(self) -> Clause { self }
}
impl ToClause for ExprInst {
fn to_clause(self) -> Clause { self.expr_val().clause }
}
impl ToClause for String {
fn to_clause(self) -> Clause { OrcString::from(self).atom_cls() }
}
impl<T: ToClause> ToClause for Option<T> {
fn to_clause(self) -> Clause { opt(self.map(|t| t.to_clause().wrap())) }
}
impl<T: ToClause, U: ToClause> ToClause for Result<T, U> {
fn to_clause(self) -> Clause {
res(self.map(|t| t.to_clause().wrap()).map_err(|u| u.to_clause().wrap()))
}
}
use super::atom::{Atomic, AtomicResult, AtomicReturn};
use super::error::ExternResult;
use super::to_clause::ToClause;
use super::try_from_expr::TryFromExpr;
use crate::interpreter::apply::CallData;
use crate::interpreter::context::Halt;
use crate::interpreter::nort::{Clause, ClauseInst, Expr};
use crate::interpreter::run::{run, RunData};
use crate::utils::ddispatch::Responder;
/// Return a unary lambda wrapped in this struct to take an additional argument
/// in a function passed to Orchid through a member of the [super::xfn_1ary]
@@ -51,6 +20,11 @@ impl<T: ToClause, U: ToClause> ToClause for Result<T, U> {
/// type. Rust functions are never overloaded, but inexplicably the [Fn] traits
/// take the argument tuple as a generic parameter which means that it cannot
/// be a unique dispatch target.
///
/// If the function takes an instance of [Lazy], it will contain the expression
/// the function was applied to without any specific normalization. If it takes
/// any other type, the argument will be fully normalized and cast using the
/// type's [TryFromExpr] impl.
pub struct Param<T, U, F> {
data: F,
_t: PhantomData<T>,
@@ -60,9 +34,7 @@ unsafe impl<T, U, F: Send> Send for Param<T, U, F> {}
impl<T, U, F> Param<T, U, F> {
/// Wrap a new function in a parametric struct
pub fn new(f: F) -> Self
where
F: FnOnce(T) -> Result<U, Arc<dyn ExternError>>,
{
where F: FnOnce(T) -> U {
Self { data: f, _t: PhantomData, _u: PhantomData }
}
/// Take out the function
@@ -74,75 +46,91 @@ impl<T, U, F: Clone> Clone for Param<T, U, F> {
}
}
impl<
T: 'static + TryFromExprInst,
U: 'static + ToClause,
F: 'static + Clone + Send + FnOnce(T) -> Result<U, Arc<dyn ExternError>>,
> ToClause for Param<T, U, F>
{
fn to_clause(self) -> Clause { self.xfn_cls() }
/// A marker struct that gets assigned an expression without normalizing it.
/// This behaviour cannot be replicated in usercode, it's implemented with an
/// explicit runtime [TypeId] check invoked by [Param].
#[derive(Debug, Clone)]
pub struct Thunk(pub Expr);
impl TryFromExpr for Thunk {
fn from_expr(expr: Expr) -> ExternResult<Self> { Ok(Thunk(expr)) }
}
struct FnMiddleStage<T, U, F> {
argument: ExprInst,
arg: Expr,
f: Param<T, U, F>,
}
impl<T, U, F> StrictEq for FnMiddleStage<T, U, F> {
fn strict_eq(&self, _other: &dyn std::any::Any) -> bool {
unimplemented!("This should never be able to appear in a pattern")
}
}
impl<T, U, F: Clone> Clone for FnMiddleStage<T, U, F> {
fn clone(&self) -> Self {
Self { argument: self.argument.clone(), f: self.f.clone() }
}
fn clone(&self) -> Self { Self { arg: self.arg.clone(), f: self.f.clone() } }
}
impl<T, U, F> Debug for FnMiddleStage<T, U, F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FnMiddleStage")
.field("argument", &self.argument)
.field("argument", &self.arg)
.finish_non_exhaustive()
}
}
impl<T, U, F> Responder for FnMiddleStage<T, U, F> {}
impl<
T: 'static + TryFromExprInst,
T: 'static + TryFromExpr,
U: 'static + ToClause,
F: 'static + Clone + FnOnce(T) -> Result<U, Arc<dyn ExternError>> + Send,
F: 'static + Clone + FnOnce(T) -> U + Any + Send,
> Atomic for FnMiddleStage<T, U, F>
{
fn as_any(self: Box<Self>) -> Box<dyn std::any::Any> { self }
fn as_any_ref(&self) -> &dyn std::any::Any { self }
fn run(self: Box<Self>, ctx: Context) -> AtomicResult {
let Return { gas, inert, state } = run(self.argument, ctx)?;
let clause = match inert {
false => state.expr_val().clause,
true => (self.f.data)(state.downcast()?)?.to_clause(),
};
Ok(AtomicReturn { gas, inert: false, clause })
fn redirect(&mut self) -> Option<&mut ClauseInst> {
// this should be ctfe'd
(TypeId::of::<T>() != TypeId::of::<Thunk>()).then(|| &mut self.arg.clause)
}
fn run(self: Box<Self>, r: RunData) -> AtomicResult {
let Self { arg, f: Param { data: f, .. } } = *self;
let clause = f(arg.downcast()?).to_clause(r.location);
Ok(AtomicReturn { gas: r.ctx.gas, inert: false, clause })
}
fn apply_ref(&self, _: CallData) -> ExternResult<Clause> {
panic!("Atom should have decayed")
}
}
impl<T, U, F> Responder for Param<T, U, F> {}
impl<T, U, F> Debug for Param<T, U, F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Param")
}
}
impl<
T: 'static + TryFromExprInst,
T: 'static + TryFromExpr + Clone,
U: 'static + ToClause,
F: 'static + Clone + Send + FnOnce(T) -> Result<U, Arc<dyn ExternError>>,
> ExternFn for Param<T, U, F>
F: 'static + Clone + Send + FnOnce(T) -> U,
> Atomic for Param<T, U, F>
{
fn name(&self) -> &str { "anonymous Rust function" }
fn apply(self: Box<Self>, arg: ExprInst, _: Context) -> XfnResult<Clause> {
Ok(FnMiddleStage { argument: arg, f: *self }.atom_cls())
fn as_any(self: Box<Self>) -> Box<dyn std::any::Any> { self }
fn as_any_ref(&self) -> &dyn std::any::Any { self }
fn redirect(&mut self) -> Option<&mut ClauseInst> { None }
fn run(self: Box<Self>, r: RunData) -> AtomicResult {
AtomicReturn::inert(*self, r.ctx)
}
fn apply_ref(&self, call: CallData) -> ExternResult<Clause> {
Ok(FnMiddleStage { arg: call.arg, f: self.clone() }.atom_cls())
}
fn apply(self: Box<Self>, call: CallData) -> ExternResult<Clause> {
Ok(FnMiddleStage { arg: call.arg, f: *self }.atom_cls())
}
}
/// Conversion functions from [Fn] traits into [Atomic]. Since Rust's type
/// system allows overloaded [Fn] implementations, we must specify the arity and
/// argument types for this process. Arities are only defined up to 9, but the
/// function can always return another call to `xfn_`N`ary` to consume more
/// arguments.
pub mod constructors {
use std::sync::Arc;
use super::super::atom::Atomic;
use super::super::try_from_expr::TryFromExpr;
#[allow(unused)] // for doc
use super::Thunk;
use super::{Param, ToClause};
use crate::foreign::{ExternError, ExternFn};
use crate::interpreted::TryFromExprInst;
macro_rules! xfn_variant {
(
@@ -154,18 +142,21 @@ pub mod constructors {
#[doc = "Convert a function of " $number " argument(s) into a curried"
" Orchid function. See also Constraints summarized:\n\n"
"- the callback must live as long as `'static`\n"
"- All arguments must implement [TryFromExprInst]\n"
"- All arguments must implement [TryFromExpr]\n"
"- all but the last argument must implement [Clone] and [Send]\n"
"- the return type must implement [ToClause].\n\n"
]
#[doc = "Take [Lazy] to take the argument as-is,\n"
"without normalization\n\n"
]
#[doc = "Other arities: " $( "[xfn_" $alt "ary], " )+ ]
pub fn [< xfn_ $number ary >] <
$( $t : TryFromExprInst + Clone + Send + 'static, )*
TLast: TryFromExprInst + 'static,
$( $t : TryFromExpr + Clone + Send + 'static, )*
TLast: TryFromExpr + Clone + 'static,
TReturn: ToClause + Send + 'static,
TFunction: FnOnce( $( $t , )* TLast )
-> Result<TReturn, Arc<dyn ExternError>> + Clone + Send + 'static
>(function: TFunction) -> impl ExternFn {
-> TReturn + Clone + Send + 'static
>(function: TFunction) -> impl Atomic + Clone {
xfn_variant!(@BODY_LOOP function
( $( ( $t [< $t:lower >] ) )* )
( $( [< $t:lower >] )* )
@@ -178,7 +169,7 @@ pub mod constructors {
$( ( $T:ident $t:ident ) )*
) $full:tt) => {
Param::new(|$next : $Next| {
Ok(xfn_variant!(@BODY_LOOP $function ( $( ( $T $t ) )* ) $full))
xfn_variant!(@BODY_LOOP $function ( $( ( $T $t ) )* ) $full)
})
};
(@BODY_LOOP $function:ident () ( $( $t:ident )* )) => {