forked from Orchid/orchid
Massive feature drop
- pattern matching seems to be correct - dynamic dispatch works with the to_string example - template strings as a last-minute addition - interpreter revamp, virtual stack for abort safety
This commit is contained in:
@@ -5,35 +5,27 @@ use std::sync::{Arc, Mutex};
|
||||
use never::Never;
|
||||
|
||||
use super::error::{ExternError, ExternResult};
|
||||
use crate::interpreter::apply::CallData;
|
||||
use crate::interpreter::context::RunContext;
|
||||
use crate::interpreter::error::RunError;
|
||||
use crate::interpreter::nort;
|
||||
use crate::interpreter::run::RunData;
|
||||
use crate::location::{CodeLocation, SourceRange};
|
||||
use crate::name::NameLike;
|
||||
use crate::parse::parsed;
|
||||
use crate::utils::ddispatch::{request, Request, Responder};
|
||||
|
||||
/// Information returned by [Atomic::run]. This mirrors
|
||||
/// [crate::interpreter::Return] but with a clause instead of an Expr.
|
||||
pub struct AtomicReturn {
|
||||
/// The next form of the expression
|
||||
pub clause: nort::Clause,
|
||||
/// Remaining gas
|
||||
pub gas: Option<usize>,
|
||||
/// Whether further normalization is possible by repeated calls to
|
||||
/// [Atomic::run]
|
||||
pub inert: bool,
|
||||
/// Information returned by [Atomic::run].
|
||||
pub enum AtomicReturn {
|
||||
/// No work was done. If the atom takes an argument, it can be provided now
|
||||
Inert(nort::Clause),
|
||||
/// Work was done, returns new clause and consumed gas. 1 gas is already
|
||||
/// consumed by the virtual call, so nonzero values indicate expensive
|
||||
/// operations.
|
||||
Change(usize, nort::Clause),
|
||||
}
|
||||
impl AtomicReturn {
|
||||
/// Report indicating that the value is inert
|
||||
pub fn inert<T: Atomic, E>(this: T, ctx: RunContext) -> Result<Self, E> {
|
||||
Ok(Self { clause: this.atom_cls(), gas: ctx.gas, inert: true })
|
||||
}
|
||||
/// Report indicating that the value has been processed
|
||||
pub fn run<E>(clause: nort::Clause, run: RunData) -> Result<Self, E> {
|
||||
Ok(Self { clause, gas: run.ctx.gas, inert: false })
|
||||
pub fn inert<T: Atomic, E>(this: T) -> Result<Self, E> {
|
||||
Ok(Self::Inert(this.atom_cls()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +43,25 @@ impl Display for NotAFunction {
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about a function call presented to an external function
|
||||
pub struct CallData<'a> {
|
||||
/// Location of the function expression
|
||||
pub location: CodeLocation,
|
||||
/// The argument the function was called on. Functions are curried
|
||||
pub arg: nort::Expr,
|
||||
/// Information relating to this interpreter run
|
||||
pub ctx: RunContext<'a>,
|
||||
}
|
||||
|
||||
/// Information about a normalization run presented to an atom
|
||||
#[derive(Clone)]
|
||||
pub struct RunData<'a> {
|
||||
/// Location of the atom
|
||||
pub location: CodeLocation,
|
||||
/// Information about the execution
|
||||
pub ctx: RunContext<'a>,
|
||||
}
|
||||
|
||||
/// Functionality the interpreter needs to handle a value
|
||||
///
|
||||
/// # Lifecycle methods
|
||||
@@ -91,7 +102,7 @@ where Self: 'static
|
||||
|
||||
/// Returns a reference to a possible expression held inside the atom which
|
||||
/// can be reduced. For an overview of the lifecycle see [Atomic]
|
||||
fn redirect(&mut self) -> Option<&mut nort::ClauseInst>;
|
||||
fn redirect(&mut self) -> Option<&mut nort::Expr>;
|
||||
|
||||
/// Attempt to normalize this value. If it wraps a value, this should report
|
||||
/// inert. If it wraps a computation, it should execute one logical step of
|
||||
@@ -172,7 +183,7 @@ impl AtomGenerator {
|
||||
}
|
||||
impl Debug for AtomGenerator {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("AtomGenerator").finish_non_exhaustive()
|
||||
write!(f, "{:?}", self.run())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +250,7 @@ impl Responder for Never {
|
||||
impl Atomic for Never {
|
||||
fn as_any(self: Box<Self>) -> Box<dyn Any> { match *self {} }
|
||||
fn as_any_ref(&self) -> &dyn Any { match *self {} }
|
||||
fn redirect(&mut self) -> Option<&mut nort::ClauseInst> { match *self {} }
|
||||
fn redirect(&mut self) -> Option<&mut nort::Expr> { match *self {} }
|
||||
fn run(self: Box<Self>, _: RunData) -> AtomicResult { match *self {} }
|
||||
fn apply_ref(&self, _: CallData) -> ExternResult<nort::Clause> {
|
||||
match *self {}
|
||||
|
||||
@@ -4,11 +4,11 @@ use std::fmt::Debug;
|
||||
|
||||
use trait_set::trait_set;
|
||||
|
||||
use super::atom::{Atomic, AtomicResult, AtomicReturn, NotAFunction};
|
||||
use super::atom::{
|
||||
Atomic, AtomicResult, AtomicReturn, CallData, NotAFunction, RunData,
|
||||
};
|
||||
use super::error::{ExternError, ExternResult};
|
||||
use crate::interpreter::apply::CallData;
|
||||
use crate::interpreter::nort::{Clause, ClauseInst, Expr};
|
||||
use crate::interpreter::run::RunData;
|
||||
use crate::interpreter::nort::{Clause, Expr};
|
||||
use crate::location::CodeLocation;
|
||||
use crate::utils::ddispatch::{Request, Responder};
|
||||
use crate::utils::pure_seq::pushed_ref;
|
||||
@@ -78,9 +78,9 @@ impl<T: CPSPayload> Atomic for CPSBox<T> {
|
||||
fn as_any(self: Box<Self>) -> Box<dyn std::any::Any> { self }
|
||||
fn as_any_ref(&self) -> &dyn std::any::Any { self }
|
||||
fn parser_eq(&self, _: &dyn std::any::Any) -> bool { false }
|
||||
fn redirect(&mut self) -> Option<&mut ClauseInst> { None }
|
||||
fn run(self: Box<Self>, run: RunData) -> AtomicResult {
|
||||
AtomicReturn::inert(*self, run.ctx)
|
||||
fn redirect(&mut self) -> Option<&mut Expr> { None }
|
||||
fn run(self: Box<Self>, _: RunData) -> AtomicResult {
|
||||
AtomicReturn::inert(*self)
|
||||
}
|
||||
fn apply(mut self: Box<Self>, call: CallData) -> ExternResult<Clause> {
|
||||
self.assert_applicable(&call.location)?;
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::location::CodeLocation;
|
||||
pub trait ExternError: Display + Send + Sync + DynClone {
|
||||
/// Convert into trait object
|
||||
#[must_use]
|
||||
fn rc(self) -> Arc<dyn ExternError>
|
||||
fn rc(self) -> ExternErrorObj
|
||||
where Self: 'static + Sized {
|
||||
Arc::new(self)
|
||||
}
|
||||
@@ -25,7 +25,10 @@ impl Debug for dyn ExternError {
|
||||
impl Error for dyn ExternError {}
|
||||
|
||||
/// An error produced by Rust code called form Orchid. The error is type-erased.
|
||||
pub type ExternResult<T> = Result<T, Arc<dyn ExternError>>;
|
||||
pub type ExternErrorObj = Arc<dyn ExternError>;
|
||||
|
||||
/// A result produced by Rust code called from Orchid.
|
||||
pub type ExternResult<T> = Result<T, ExternErrorObj>;
|
||||
|
||||
/// Some expectation (usually about the argument types of a function) did not
|
||||
/// hold.
|
||||
@@ -52,7 +55,7 @@ impl AssertionError {
|
||||
location: CodeLocation,
|
||||
message: &'static str,
|
||||
details: String,
|
||||
) -> Arc<dyn ExternError> {
|
||||
) -> ExternErrorObj {
|
||||
Self { location, message, details }.rc()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
use std::any::{Any, TypeId};
|
||||
use std::fmt::Debug;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use super::atom::{Atomic, AtomicResult, AtomicReturn};
|
||||
use intern_all::{i, Tok};
|
||||
|
||||
use super::atom::{Atomic, AtomicResult, AtomicReturn, CallData, RunData};
|
||||
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::interpreter::nort::{Clause, Expr};
|
||||
use crate::utils::ddispatch::Responder;
|
||||
|
||||
/// Return a unary lambda wrapped in this struct to take an additional argument
|
||||
@@ -27,22 +26,31 @@ use crate::utils::ddispatch::Responder;
|
||||
/// type's [TryFromExpr] impl.
|
||||
pub struct Param<T, U, F> {
|
||||
data: F,
|
||||
name: Tok<String>,
|
||||
_t: PhantomData<T>,
|
||||
_u: PhantomData<U>,
|
||||
}
|
||||
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
|
||||
pub fn new(name: Tok<String>, f: F) -> Self
|
||||
where F: FnOnce(T) -> U {
|
||||
Self { data: f, _t: PhantomData, _u: PhantomData }
|
||||
Self { name, data: f, _t: PhantomData, _u: PhantomData }
|
||||
}
|
||||
/// Take out the function
|
||||
pub fn get(self) -> F { self.data }
|
||||
}
|
||||
impl<T, U, F: Clone> Clone for Param<T, U, F> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { data: self.data.clone(), _t: PhantomData, _u: PhantomData }
|
||||
Self { name: self.name.clone(), data: self.data.clone(), _t: PhantomData, _u: PhantomData }
|
||||
}
|
||||
}
|
||||
impl<T, U, F> Display for Param<T, U, F> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(&self.name) }
|
||||
}
|
||||
impl<T, U, F> Debug for Param<T, U, F> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("Param").field(&*self.name).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,9 +73,7 @@ impl<T, U, F: Clone> Clone for FnMiddleStage<T, U, F> {
|
||||
}
|
||||
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.arg)
|
||||
.finish_non_exhaustive()
|
||||
write!(f, "FnMiddleStage({} {})", self.f, self.arg)
|
||||
}
|
||||
}
|
||||
impl<T, U, F> Responder for FnMiddleStage<T, U, F> {}
|
||||
@@ -79,26 +85,18 @@ impl<
|
||||
{
|
||||
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> {
|
||||
fn redirect(&mut self) -> Option<&mut Expr> {
|
||||
// this should be ctfe'd
|
||||
(TypeId::of::<T>() != TypeId::of::<Thunk>()).then(|| &mut self.arg.clause)
|
||||
(TypeId::of::<T>() != TypeId::of::<Thunk>()).then_some(&mut self.arg)
|
||||
}
|
||||
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")
|
||||
Ok(AtomicReturn::Change(0, f(arg.downcast()?).to_clause(r.location)))
|
||||
}
|
||||
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 + TryFromExpr + Clone,
|
||||
@@ -108,10 +106,8 @@ impl<
|
||||
{
|
||||
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 redirect(&mut self) -> Option<&mut Expr> { None }
|
||||
fn run(self: Box<Self>, _: RunData) -> AtomicResult { AtomicReturn::inert(*self) }
|
||||
fn apply_ref(&self, call: CallData) -> ExternResult<Clause> {
|
||||
Ok(FnMiddleStage { arg: call.arg, f: self.clone() }.atom_cls())
|
||||
}
|
||||
@@ -120,17 +116,42 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a Rust function to Orchid. If you can, register your Rust functions
|
||||
/// statically with functions in [crate::gen::tree].
|
||||
pub fn xfn<const N: usize, Argv, Ret>(
|
||||
name: &str,
|
||||
x: impl Xfn<N, Argv, Ret>,
|
||||
) -> impl Atomic + Clone {
|
||||
x.to_atomic(i(name))
|
||||
}
|
||||
|
||||
/// Trait for functions that can be directly passed to Orchid. Constraints in a
|
||||
/// nutshell:
|
||||
///
|
||||
/// - the function must live as long as ['static]
|
||||
/// - All arguments must implement [TryFromExpr]
|
||||
/// - all but the last argument must implement [Clone] and [Send]
|
||||
/// - the return type must implement [ToClause]
|
||||
///
|
||||
/// Take [Thunk] to consume the argument as-is, without normalization.
|
||||
pub trait Xfn<const N: usize, Argv, Ret>: Clone + 'static {
|
||||
/// Convert Rust type to Orchid function, given a name for logging
|
||||
fn to_atomic(self, name: Tok<String>) -> impl Atomic + Clone;
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
pub mod xfn_impls {
|
||||
use intern_all::{i, Tok};
|
||||
|
||||
use super::super::atom::Atomic;
|
||||
use super::super::try_from_expr::TryFromExpr;
|
||||
#[allow(unused)] // for doc
|
||||
use super::Thunk;
|
||||
use super::{Param, ToClause};
|
||||
use super::{Param, ToClause, Xfn};
|
||||
|
||||
macro_rules! xfn_variant {
|
||||
(
|
||||
@@ -139,42 +160,40 @@ pub mod constructors {
|
||||
($($alt:expr)*)
|
||||
) => {
|
||||
paste::paste!{
|
||||
#[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 [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 >] <
|
||||
impl<
|
||||
$( $t : TryFromExpr + Clone + Send + 'static, )*
|
||||
TLast: TryFromExpr + Clone + 'static,
|
||||
TReturn: ToClause + Send + 'static,
|
||||
TFunction: FnOnce( $( $t , )* TLast )
|
||||
-> TReturn + Clone + Send + 'static
|
||||
>(function: TFunction) -> impl Atomic + Clone {
|
||||
xfn_variant!(@BODY_LOOP function
|
||||
( $( ( $t [< $t:lower >] ) )* )
|
||||
( $( [< $t:lower >] )* )
|
||||
)
|
||||
> Xfn<$number, ($($t,)* TLast,), TReturn> for TFunction {
|
||||
fn to_atomic(self, name: Tok<String>) -> impl Atomic + Clone {
|
||||
#[allow(unused_variables)]
|
||||
let argc = 0;
|
||||
let stage_n = name.clone();
|
||||
xfn_variant!(@BODY_LOOP self name stage_n argc
|
||||
( $( ( $t [< $t:lower >] ) )* )
|
||||
( $( [< $t:lower >] )* )
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
(@BODY_LOOP $function:ident (
|
||||
(@BODY_LOOP $function:ident $name:ident $stage_n:ident $argc:ident (
|
||||
( $Next:ident $next:ident )
|
||||
$( ( $T:ident $t:ident ) )*
|
||||
) $full:tt) => {
|
||||
Param::new(|$next : $Next| {
|
||||
xfn_variant!(@BODY_LOOP $function ( $( ( $T $t ) )* ) $full)
|
||||
) $full:tt) => {{
|
||||
Param::new($stage_n, move |$next : $Next| {
|
||||
let $argc = $argc + 1;
|
||||
let $stage_n = i(&format!("{}/{}", $name, $argc));
|
||||
xfn_variant!(@BODY_LOOP $function $name $stage_n $argc ( $( ( $T $t ) )* ) $full)
|
||||
})
|
||||
};
|
||||
(@BODY_LOOP $function:ident () ( $( $t:ident )* )) => {
|
||||
Param::new(|last: TLast| $function ( $( $t , )* last ))
|
||||
};
|
||||
}};
|
||||
(@BODY_LOOP $function:ident $name:ident $stage_n:ident $argc:ident (
|
||||
|
||||
) ( $( $t:ident )* )) => {{
|
||||
Param::new($stage_n, |last: TLast| $function ( $( $t , )* last ))
|
||||
}};
|
||||
}
|
||||
|
||||
xfn_variant!(1, () (2 3 4 5 6 7 8 9 10 11 12 13 14 15 16));
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
use std::any::Any;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::atom::{Atom, Atomic, AtomicResult};
|
||||
use super::error::{ExternError, ExternResult};
|
||||
use super::atom::{Atom, Atomic, AtomicResult, CallData, RunData};
|
||||
use super::error::{ExternErrorObj, ExternResult};
|
||||
use super::process::Unstable;
|
||||
use super::to_clause::ToClause;
|
||||
use crate::gen::tpl;
|
||||
use crate::gen::traits::Gen;
|
||||
use crate::interpreter::apply::CallData;
|
||||
use crate::interpreter::error::RunError;
|
||||
use crate::interpreter::gen_nort::nort_gen;
|
||||
use crate::interpreter::nort::{Clause, ClauseInst};
|
||||
use crate::interpreter::run::RunData;
|
||||
use crate::interpreter::nort::{Clause, Expr};
|
||||
use crate::location::CodeLocation;
|
||||
use crate::utils::clonable_iter::Clonable;
|
||||
use crate::utils::ddispatch::Responder;
|
||||
@@ -40,7 +37,7 @@ impl<T: ToClause, U: ToClause> ToClause for Result<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
struct PendingError(Arc<dyn ExternError>);
|
||||
struct PendingError(ExternErrorObj);
|
||||
impl Responder for PendingError {}
|
||||
impl Debug for PendingError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@@ -50,7 +47,7 @@ impl Debug for PendingError {
|
||||
impl Atomic for PendingError {
|
||||
fn as_any(self: Box<Self>) -> Box<dyn Any> { self }
|
||||
fn as_any_ref(&self) -> &dyn Any { self }
|
||||
fn redirect(&mut self) -> Option<&mut ClauseInst> { None }
|
||||
fn redirect(&mut self) -> Option<&mut Expr> { None }
|
||||
fn run(self: Box<Self>, _: RunData) -> AtomicResult {
|
||||
Err(RunError::Extern(self.0))
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ use std::ops::{Deref, DerefMut};
|
||||
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use super::atom::{Atom, Atomic, AtomicResult, AtomicReturn, NotAFunction};
|
||||
use super::atom::{
|
||||
Atom, Atomic, AtomicResult, AtomicReturn, CallData, NotAFunction, RunData,
|
||||
};
|
||||
use super::error::{ExternError, ExternResult};
|
||||
use super::try_from_expr::TryFromExpr;
|
||||
use crate::foreign::error::AssertionError;
|
||||
use crate::interpreter::apply::CallData;
|
||||
use crate::interpreter::nort::{Clause, ClauseInst, Expr};
|
||||
use crate::interpreter::run::RunData;
|
||||
use crate::interpreter::nort::{Clause, Expr};
|
||||
use crate::libs::std::number::Numeric;
|
||||
use crate::libs::std::string::OrcString;
|
||||
use crate::utils::ddispatch::{Request, Responder};
|
||||
@@ -72,9 +72,9 @@ impl<T: InertPayload> Atomic for Inert<T> {
|
||||
fn as_any(self: Box<Self>) -> Box<dyn Any> { self }
|
||||
fn as_any_ref(&self) -> &dyn Any { self }
|
||||
|
||||
fn redirect(&mut self) -> Option<&mut ClauseInst> { None }
|
||||
fn run(self: Box<Self>, run: RunData) -> AtomicResult {
|
||||
AtomicReturn::inert(*self, run.ctx)
|
||||
fn redirect(&mut self) -> Option<&mut Expr> { None }
|
||||
fn run(self: Box<Self>, _: RunData) -> AtomicResult {
|
||||
AtomicReturn::inert(*self)
|
||||
}
|
||||
fn apply_ref(&self, call: CallData) -> ExternResult<Clause> {
|
||||
Err(NotAFunction(self.clone().atom_expr(call.location)).rc())
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::atom::{Atomic, AtomicReturn};
|
||||
use super::atom::{Atomic, AtomicReturn, CallData, RunData};
|
||||
use super::error::ExternResult;
|
||||
use super::to_clause::ToClause;
|
||||
use crate::interpreter::apply::CallData;
|
||||
use crate::interpreter::nort::{Clause, ClauseInst};
|
||||
use crate::interpreter::run::RunData;
|
||||
use crate::interpreter::nort::{Clause, Expr};
|
||||
use crate::utils::ddispatch::Responder;
|
||||
|
||||
/// An atom that immediately decays to the result of the function when
|
||||
@@ -33,7 +31,7 @@ impl<F: FnOnce(RunData) -> R + Send + 'static, R: ToClause> Atomic
|
||||
}
|
||||
fn run(self: Box<Self>, run: RunData) -> super::atom::AtomicResult {
|
||||
let clause = self.0(run.clone()).to_clause(run.location.clone());
|
||||
AtomicReturn::run(clause, run)
|
||||
Ok(AtomicReturn::Change(0, clause))
|
||||
}
|
||||
fn redirect(&mut self) -> Option<&mut ClauseInst> { None }
|
||||
fn redirect(&mut self) -> Option<&mut Expr> { None }
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ impl TryFromExpr for Expr {
|
||||
}
|
||||
|
||||
impl TryFromExpr for ClauseInst {
|
||||
fn from_expr(expr: Expr) -> ExternResult<Self> { Ok(expr.clause.clone()) }
|
||||
fn from_expr(expr: Expr) -> ExternResult<Self> { Ok(expr.clsi()) }
|
||||
}
|
||||
|
||||
/// Request a value of a particular type and also return its location for
|
||||
|
||||
Reference in New Issue
Block a user