Removed foreign macros

Converted the function integration to use template
metaprogramming instead of macros.
This commit is contained in:
2023-09-22 23:17:54 +01:00
parent 7396078304
commit ba0b155ebd
45 changed files with 854 additions and 1126 deletions

View File

@@ -1,10 +1,8 @@
use std::rc::Rc;
use crate::foreign::InertAtomic;
use crate::foreign::{xfn_1ary, xfn_2ary, InertAtomic, XfnResult};
use crate::interner::Interner;
use crate::representations::interpreted::Clause;
use crate::systems::AssertionError;
use crate::{define_fn, ConstTree, Literal, Location, PathSet};
use crate::{ConstTree, Literal, Location};
/// Booleans exposed to Orchid
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -17,46 +15,38 @@ impl From<bool> for Boolean {
fn from(value: bool) -> Self { Self(value) }
}
define_fn! {
/// Takes a boolean and two branches, runs the first if the bool is true, the
/// second if it's false.
// Even though it's a ternary function, IfThenElse is implemented as an unary
// foreign function, as the rest of the logic can be defined in Orchid.
IfThenElse = |x| x.downcast().map(|Boolean(b)| if b {Clause::Lambda {
args: Some(PathSet { steps: Rc::new(vec![]), next: None }),
body: Clause::Lambda {
args: None,
body: Clause::LambdaArg.wrap()
}.wrap(),
}} else {Clause::Lambda {
args: None,
body: Clause::Lambda {
args: Some(PathSet { steps: Rc::new(vec![]), next: None }),
body: Clause::LambdaArg.wrap(),
}.wrap(),
}});
/// Takes a boolean and two branches, runs the first if the bool is true, the
/// second if it's false.
// Even though it's a ternary function, IfThenElse is implemented as an unary
// foreign function, as the rest of the logic can be defined in Orchid.
pub fn if_then_else(b: Boolean) -> XfnResult<Clause> {
Ok(match b.0 {
true => Clause::pick(Clause::constfn(Clause::LambdaArg)),
false => Clause::constfn(Clause::pick(Clause::LambdaArg)),
})
}
expr=x in
/// Compares the inner values if
///
/// - both are string,
/// - both are either uint or num
Equals { a: Literal, b: Literal } => Ok(Boolean::from(match (a, b) {
/// Compares the inner values if
///
/// - both are string,
/// - both are either uint or num
pub fn equals(a: Literal, b: Literal) -> XfnResult<Boolean> {
Ok(Boolean::from(match (a, b) {
(Literal::Str(s1), Literal::Str(s2)) => s1 == s2,
(Literal::Num(n1), Literal::Num(n2)) => n1 == n2,
(Literal::Uint(i1), Literal::Uint(i2)) => i1 == i2,
(Literal::Num(n1), Literal::Uint(u1)) => *n1 == (u1 as f64),
(Literal::Uint(u1), Literal::Num(n1)) => *n1 == (u1 as f64),
(..) => AssertionError::fail(Location::Unknown, "the expected type")?,
}).atom_cls())
}))
}
pub fn bool(i: &Interner) -> ConstTree {
ConstTree::tree([(
i.i("bool"),
ConstTree::tree([
(i.i("ifthenelse"), ConstTree::xfn(IfThenElse)),
(i.i("equals"), ConstTree::xfn(Equals)),
(i.i("ifthenelse"), ConstTree::xfn(xfn_1ary(if_then_else))),
(i.i("equals"), ConstTree::xfn(xfn_2ary(equals))),
(i.i("true"), ConstTree::atom(Boolean(true))),
(i.i("false"), ConstTree::atom(Boolean(false))),
]),