Last working state

This commit is contained in:
2023-03-05 19:57:06 +00:00
parent b9d47c3181
commit 35a081162f
2 changed files with 30 additions and 210 deletions

View File

@@ -5,34 +5,40 @@ use std::fmt::Debug;
use std::rc::Rc;
use std::hash::Hash;
use crate::{atomic_impl, atomic_redirect, externfn_impl, xfn_initial, xfn_middle, xfn_last, xfn};
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::foreign::{ExternError, ExternFn, Atom, Atomic};
use crate::representations::Primitive;
use crate::representations::interpreted::{Clause, InternalError};
// xfn_initial!(
// /// Multiply function
// Multiply2, Multiply1
// );
// xfn_middle!(
// /// Partially applied multiply function
// Multiply2, Multiply1, Multiply0, (
// a: Numeric: |c: &Clause| c.clone().try_into()
// )
// );
// xfn_last!(
// /// Fully applied Multiply function.
// Multiply1, Multiply0, (
// b: Numeric: |c: &Clause| c.clone().try_into(),
// a: Numeric: |c: &Clause| c.clone().try_into()
// ), Ok((*a * b).into())
// );
xfn!((
/// Multiply function
a: Numeric: |c: &Clause| c.clone().try_into(),
/// Partially applied multiply function
b: Numeric: |c: &Clause| c.clone().try_into()
), {
///
/// Next state: [Multiply1]
#[derive(Clone)]
pub struct Multiply2;
externfn_impl!(Multiply2, |_: &Self, c: Clause| {Ok(Multiply1{c})});
/// Partially applied Multiply function
///
/// Prev state: [Multiply2]; Next state: [Multiply0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Multiply1{ c: Clause }
atomic_redirect!(Multiply1, c);
atomic_impl!(Multiply1);
externfn_impl!(Multiply1, |this: &Self, c: Clause| {
let a: Numeric = this.c.clone().try_into()?;
Ok(Multiply0{ a, c })
});
/// Fully applied Multiply function.
///
/// Prev state: [Multiply1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Multiply0 { a: Numeric, c: Clause }
atomic_redirect!(Multiply0, c);
atomic_impl!(Multiply0, |Self{ a, c }: &Self| {
let b: Numeric = c.clone().try_into()?;
Ok((*a * b).into())
});

View File

@@ -145,189 +145,3 @@ macro_rules! externfn_impl {
}
};
}
/// Define a new struct and implement [ExternFn] for it so that it combines with an argument into
/// the struct identified by `$next` with a single field called `clause`.
/// Also generates doc comment for the new struct
#[macro_export]
macro_rules! xfn_initial {
(#[$prefix:meta] $name:ident, $next:ident) => {
paste::paste!{
#[$prefix]
#[doc = "\n\nNext state: [" [<$next:camel>] "]"]
#[derive(Clone)]
pub struct [<$name:camel>];
externfn_impl!([<$name:camel>], |_:&Self, clause: Clause| Ok([<$next:camel>]{ clause }));
}
};
}
/// Define a struct with a field `clause: Clause` that forwards atomic reductions to that field and
/// then converts itself to an [ExternFn] which combines with an argument into the struct identified
/// by `$next` with all fields copied over, `$nname` converted via `$ntransform` and the
/// argument assigned to a field called `clause`.
#[macro_export]
macro_rules! xfn_middle {
(#[$prefix:meta] $prev:ident, $name:ident, $next:ident, (
$nname:ident : $ntype:ty
$(, $fname:ident : $ftype:ty)*
), $transform:expr) => {
paste::paste!{
#[$prefix]
#[doc = "\n\nPrev state: [" [<$prev:camel>] "], Next state: [" [<$next:camel>] "]"]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct [<$name:camel>] {
clause: Clause,
$($fname: $ftype),*
}
atomic_redirect!([<$name:camel>], clause);
atomic_impl!([<$name:camel>]);
externfn_impl!([<$name:camel>], |this: &Self, clause: Clause| {
let $nname: $ntype = match ($transform)(&this.clause) {
Ok(a) => a,
Err(e) => return Err(e)
};
Ok([<$next:camel>]{
clause,
$nname,
$($fname: this.$fname.clone()),*
})
});
}
};
}
#[macro_export]
macro_rules! xfn_last {
(#[$prefix:meta] $prev:ident, $name:ident, (
$nname:ident : $ntype:ty
$(, $fname:ident : $ftype:ty)*
), $transform:expr, $operation:expr) => {
paste!{
#[$prefix]
#[doc = "\n\nPrev state: [" [<$prev:camel>] "]" ]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct [<$name:camel>] {
clause: Clause,
$($fname: $ftype),*
}
}
atomic_redirect!([<$name:camel>], clause);
atomic_impl!([<$name:camel>], |this: &Self| {
let $nname: $ntype = match ($ntransform)(&this.clause) {
Ok(a) => a,
Err(e) => return Err(e)
};
$(
let $fname = &this.$fname;
)*
$operation
});
};
}
#[macro_export]
macro_rules! reverse_proplist {
(
#[$nprefix:meta] $nname:ident : $ntype:ty : $ntransform:expr
$(, #[$fprefix:meta] $fname:ident : $ftype:ty : $ftransform:expr)*
) => {
reverse_proplist!($($fname : $ftype : $ftransform),*)
$nname : $ntype : $ntranform
};
}
#[macro_export]
macro_rules! xfn_make_head {
(
#[$cprefix:meta] $nname:ident : $ntype:ty : $ntransform:expr
, #[$nprefix:meta] $cname:ident : $ctype:ty : $ctransform:expr
$(, #[$fprefix:meta] $fname:ident : $ftype:ty : $ftransform:expr)+
) => {
xfn_make_head!(
#[$nprefix] $cname : $ctype : $ctransform
$(, #[$fprefix] $fname : $ftype : $ftransform)+
)
}; // skip through all intermediate rows
(
#[$cprefix:meta] $nname:ident : $ntype:ty : $ntransform:expr
, #[$nprefix:meta] $cname:ident : $ctype:ty : $ctransform:expr
) => {
paste!{
xfn_initial!(#[$cprefix] $cname, $nname)
}
} // process first two rows
}
#[macro_export]
macro_rules! xfn_make_middle {
(
#[$nprefix:meta] $nname:ident : $ntype:ty : $ntransform:expr
, #[$cprefix:meta] $cname:ident : $ctype:ty : $ctransform:expr
, #[$pprefix:meta] $pname:ident : $ptype:ty : $ptransform:expr
$(, #[$fprefix:meta] $fname:ident : $ftype:ty : $ftransform:expr)*
) => {
// repeat on tail
xfn_make_middle!(
#[$cprefix:meta] $cname:ident : $ctype:ty : $ctransform:expr
, #[$pprefix:meta] $pname:ident : $ptype:ty : $ptransform:expr
$(, #[$fprefix:meta] $fname:ident : $ftype:ty : $ftransform:expr)*
)
xfn_middle!(#[$cprefix] $pname, $cname, $nname (
$cname : $ctype
, $pname : $ptype
$(, $fname : $ftype )*
), $ctransform) // note that the "next" row is not included
};
(
#[$nprefix:meta] $nname:ident : $ntype:ty : $ntransform:expr
, #[$cprefix:meta] $cname:ident : $ctype:ty : $ctransform:expr
) => {}; // discard last two rows (xfn_make_head handles those)
}
#[macro_export]
macro_rules! xfn_make_last {
((
#[$cprefix:meta] $cname:ident : $ctype:ty : $ctransform:expr
, #[$pprefix:meta] $pname:ident : $ptype:ty : $ptransform:expr
$(, #[$fprefix:meta] $fname:ident : $ftype:ty : $ftransform:expr)*
), $operation:expr) => {
xfn_last!(
#[$cprefix] $pname, $cname, (
$cname : $ctype
, $pname : $ptype
$(, $fname : $ftype)*
), $ctransform, $operation
)
};
}
#[macro_export]
macro_rules! xfn_reversed {
(
( $(#[$fprefix:meta] $fname:ident : $ftype:ty : $ftransform:expr),* ),
$operation:expr
) => {
xfn_make_head!($(#[$fprefix] $fname : $ftype : $ftransform),*)
xfn_make_middle!(
$(#[$fprefix] $fname : $ftype : $ftransform),*
)
xfn_make_last(
( $(#[$fprefix] $fname : $ftype : $ftransform),* ),
$operation
)
};
}
#[macro_export]
macro_rules! xfn {
(
( $(#[$fprefix:meta] $fname:ident : $ftype:ty : $ftransform:expr),* ),
$operation:expr
) => {
$crate::xfn_reversed!(
reverse_proplist!($(#[$fprefix] $fname : $ftype : $ftransform),*),
$operation
);
};
}