bug fixes and performance improvements

This commit is contained in:
2023-05-07 22:35:38 +01:00
parent f3ce910f66
commit a604e40bad
167 changed files with 5965 additions and 4229 deletions

View File

@@ -2,21 +2,21 @@ use std::rc::Rc;
use std::fmt::Display;
use crate::foreign::ExternError;
use crate::representations::interpreted::Clause;
use crate::representations::interpreted::ExprInst;
#[derive(Clone)]
pub struct AssertionError{
pub value: Clause,
pub value: ExprInst,
pub assertion: &'static str,
}
impl AssertionError {
pub fn fail(value: Clause, assertion: &'static str) -> Result<!, Rc<dyn ExternError>> {
pub fn fail(value: ExprInst, assertion: &'static str) -> Result<!, Rc<dyn ExternError>> {
return Err(Self { value, assertion }.into_extern())
}
pub fn ext(value: Clause, assertion: &'static str) -> Rc<dyn ExternError> {
pub fn ext(value: ExprInst, assertion: &'static str) -> Rc<dyn ExternError> {
return Self { value, assertion }.into_extern()
}
}

View File

@@ -1,5 +1,6 @@
use crate::{atomic_inert, representations::{interpreted::Clause, Primitive}, foreign::Atom};
use crate::foreign::Atom;
use crate::representations::{interpreted::{Clause, ExprInst}, Primitive};
use crate::atomic_inert;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Boolean(pub bool);
@@ -7,11 +8,12 @@ atomic_inert!(Boolean);
impl From<bool> for Boolean { fn from(value: bool) -> Self { Self(value) } }
impl<'a> TryFrom<&'a Clause> for Boolean {
impl TryFrom<ExprInst> for Boolean {
type Error = ();
fn try_from(value: &'a Clause) -> Result<Self, Self::Error> {
if let Clause::P(Primitive::Atom(Atom(a))) = value {
fn try_from(value: ExprInst) -> Result<Self, Self::Error> {
let expr = value.expr();
if let Clause::P(Primitive::Atom(Atom(a))) = &expr.clause {
if let Some(b) = a.as_any().downcast_ref::<Boolean>() {
return Ok(*b)
}

View File

@@ -1,10 +1,8 @@
use std::fmt::Debug;
use std::hash::Hash;
use crate::external::litconv::with_lit;
use crate::representations::{interpreted::ExprInst, Literal};
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::foreign::Atom;
use crate::representations::{Primitive, Literal};
use crate::representations::interpreted::Clause;
use super::super::assertion_error::AssertionError;
use super::boolean::Boolean;
@@ -15,38 +13,34 @@ use super::boolean::Boolean;
#[derive(Clone)]
pub struct Equals2;
externfn_impl!(Equals2, |_: &Self, c: Clause| {Ok(Equals1{c})});
externfn_impl!(Equals2, |_: &Self, x: ExprInst| {Ok(Equals1{x})});
/// Partially applied Equals function
///
/// Prev state: [Equals2]; Next state: [Equals0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Equals1{ c: Clause }
atomic_redirect!(Equals1, c);
#[derive(Debug, Clone)]
pub struct Equals1{ x: ExprInst }
atomic_redirect!(Equals1, x);
atomic_impl!(Equals1);
externfn_impl!(Equals1, |this: &Self, c: Clause| {
let a: Literal = this.c.clone().try_into()
.map_err(|_| AssertionError::ext(this.c.clone(), "a primitive"))?;
Ok(Equals0{ a, c })
externfn_impl!(Equals1, |this: &Self, x: ExprInst| {
with_lit(&this.x, |l| Ok(Equals0{ a: l.clone(), x }))
});
/// Fully applied Equals function.
///
/// Prev state: [Equals1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Equals0 { a: Literal, c: Clause }
atomic_redirect!(Equals0, c);
atomic_impl!(Equals0, |Self{ a, c }: &Self| {
let b: Literal = c.clone().try_into()
.map_err(|_| AssertionError::ext(c.clone(), "a literal value"))?;
let eqls = match (a, b) {
(Literal::Char(c1), Literal::Char(c2)) => *c1 == c2,
(Literal::Num(n1), Literal::Num(n2)) => *n1 == n2,
(Literal::Str(s1), Literal::Str(s2)) => *s1 == s2,
(Literal::Uint(i1), Literal::Uint(i2)) => *i1 == i2,
(_, _) => AssertionError::fail(c.clone(), "the expected type")?,
};
Ok(Clause::P(Primitive::Atom(Atom::new(Boolean::from(eqls)))))
#[derive(Debug, Clone)]
pub struct Equals0 { a: Literal, x: ExprInst }
atomic_redirect!(Equals0, x);
atomic_impl!(Equals0, |Self{ a, x }: &Self| {
let eqls = with_lit(x, |l| Ok(match (a, l) {
(Literal::Char(c1), Literal::Char(c2)) => c1 == c2,
(Literal::Num(n1), Literal::Num(n2)) => n1 == n2,
(Literal::Str(s1), Literal::Str(s2)) => s1 == s2,
(Literal::Uint(i1), Literal::Uint(i2)) => i1 == i2,
(_, _) => AssertionError::fail(x.clone(), "the expected type")?,
}))?;
Ok(Boolean::from(eqls).to_atom_cls())
});

View File

@@ -1,11 +1,9 @@
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use crate::external::assertion_error::AssertionError;
use crate::representations::PathSet;
use crate::representations::{PathSet, interpreted::{Clause, ExprInst}};
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::interpreted::Clause;
use super::Boolean;
@@ -15,29 +13,29 @@ use super::Boolean;
#[derive(Clone)]
pub struct IfThenElse1;
externfn_impl!(IfThenElse1, |_: &Self, c: Clause| {Ok(IfThenElse0{c})});
externfn_impl!(IfThenElse1, |_: &Self, x: ExprInst| {Ok(IfThenElse0{x})});
/// Partially applied IfThenElse function
///
/// Prev state: [IfThenElse1]; Next state: [IfThenElse0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct IfThenElse0{ c: Clause }
atomic_redirect!(IfThenElse0, c);
#[derive(Debug, Clone)]
pub struct IfThenElse0{ x: ExprInst }
atomic_redirect!(IfThenElse0, x);
atomic_impl!(IfThenElse0, |this: &Self| {
let Boolean(b) = (&this.c).try_into()
.map_err(|_| AssertionError::ext(this.c.clone(), "a boolean"))?;
let Boolean(b) = this.x.clone().try_into()
.map_err(|_| AssertionError::ext(this.x.clone(), "a boolean"))?;
Ok(if b { Clause::Lambda {
args: Some(PathSet { steps: Rc::new(vec![]), next: None }),
body: Rc::new(Clause::Lambda {
body: Clause::Lambda {
args: None,
body: Rc::new(Clause::LambdaArg)
})
body: Clause::LambdaArg.wrap()
}.wrap()
}} else { Clause::Lambda {
args: None,
body: Rc::new(Clause::Lambda {
body: Clause::Lambda {
args: Some(PathSet { steps: Rc::new(vec![]), next: None }),
body: Rc::new(Clause::LambdaArg)
})
body: Clause::LambdaArg.wrap()
}.wrap()
}})
});

View File

@@ -3,11 +3,12 @@ mod boolean;
mod ifthenelse;
pub use boolean::Boolean;
use crate::project::{Loader, extlib_loader};
use crate::{pipeline::ConstTree, interner::Interner};
pub fn bool() -> impl Loader {
extlib_loader(vec![
("ifthenelse", Box::new(ifthenelse::IfThenElse1)),
("equals", Box::new(equals::Equals2))
pub fn bool(i: &Interner) -> ConstTree {
ConstTree::tree([
(i.i("ifthenelse"), ConstTree::xfn(ifthenelse::IfThenElse1)),
(i.i("equals"), ConstTree::xfn(equals::Equals2))
])
}

View File

@@ -1,13 +1,13 @@
use crate::project::{extlib_loader, Loader};
use crate::{interner::Interner, pipeline::ConstTree};
mod to_string;
mod parse_float;
mod parse_uint;
pub fn conv() -> impl Loader {
extlib_loader(vec![
("parse_float", Box::new(parse_float::ParseFloat1)),
("parse_uint", Box::new(parse_uint::ParseUint1)),
("to_string", Box::new(to_string::ToString1))
pub fn conv(i: &Interner) -> ConstTree {
ConstTree::tree([
(i.i("parse_float"), ConstTree::xfn(parse_float::ParseFloat1)),
(i.i("parse_uint"), ConstTree::xfn(parse_uint::ParseUint1)),
(i.i("to_string"), ConstTree::xfn(to_string::ToString1))
])
}

View File

@@ -2,14 +2,12 @@
use chumsky::Parser;
use std::fmt::Debug;
use std::hash::Hash;
use super::super::assertion_error::AssertionError;
use crate::external::litconv::with_lit;
use crate::parse::float_parser;
use crate::representations::{interpreted::ExprInst, Literal};
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::foreign::ExternError;
use crate::representations::{Primitive, Literal};
use crate::representations::interpreted::Clause;
/// ParseFloat a number
///
@@ -17,30 +15,27 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct ParseFloat1;
externfn_impl!(ParseFloat1, |_: &Self, c: Clause| {Ok(ParseFloat0{c})});
externfn_impl!(ParseFloat1, |_: &Self, x: ExprInst| {Ok(ParseFloat0{x})});
/// Applied to_string function
///
/// Prev state: [ParseFloat1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct ParseFloat0{ c: Clause }
atomic_redirect!(ParseFloat0, c);
atomic_impl!(ParseFloat0, |Self{ c }: &Self| {
let literal: &Literal = c.try_into()
.map_err(|_| AssertionError::ext(c.clone(), "a literal value"))?;
let number = match literal {
#[derive(Debug, Clone)]
pub struct ParseFloat0{ x: ExprInst }
atomic_redirect!(ParseFloat0, x);
atomic_impl!(ParseFloat0, |Self{ x }: &Self| {
let number = with_lit(x, |l| Ok(match l {
Literal::Str(s) => {
let parser = float_parser();
parser.parse(s.as_str()).map_err(|_| AssertionError{
value: c.clone(), assertion: "cannot be parsed into a float"
}.into_extern())?
parser.parse(s.as_str())
.map_err(|_| AssertionError::ext(x.clone(), "cannot be parsed into a float"))?
}
Literal::Num(n) => *n,
Literal::Uint(i) => (*i as u32).into(),
Literal::Char(char) => char.to_digit(10).ok_or(AssertionError{
value: c.clone(), assertion: "is not a decimal digit"
}.into_extern())?.into()
};
Ok(Clause::P(Primitive::Literal(Literal::Num(number))))
Literal::Char(char) => char.to_digit(10)
.ok_or(AssertionError::ext(x.clone(), "is not a decimal digit"))?
.into()
}))?;
Ok(number.into())
});

View File

@@ -2,14 +2,11 @@
use chumsky::Parser;
use std::fmt::Debug;
use std::hash::Hash;
use super::super::assertion_error::AssertionError;
use crate::parse::int_parser;
use crate::external::{litconv::with_lit, assertion_error::AssertionError};
use crate::representations::{interpreted::ExprInst, Literal};
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::foreign::ExternError;
use crate::representations::{Primitive, Literal};
use crate::representations::interpreted::Clause;
use crate::parse::int_parser;
/// Parse a number
///
@@ -17,30 +14,27 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct ParseUint1;
externfn_impl!(ParseUint1, |_: &Self, c: Clause| {Ok(ParseUint0{c})});
externfn_impl!(ParseUint1, |_: &Self, x: ExprInst| {Ok(ParseUint0{x})});
/// Applied ParseUint function
///
/// Prev state: [ParseUint1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct ParseUint0{ c: Clause }
atomic_redirect!(ParseUint0, c);
atomic_impl!(ParseUint0, |Self{ c }: &Self| {
let literal: &Literal = c.try_into()
.map_err(|_| AssertionError::ext(c.clone(), "a literal value"))?;
let uint = match literal {
#[derive(Debug, Clone)]
pub struct ParseUint0{ x: ExprInst }
atomic_redirect!(ParseUint0, x);
atomic_impl!(ParseUint0, |Self{ x }: &Self| {
let uint = with_lit(x, |l| Ok(match l {
Literal::Str(s) => {
let parser = int_parser();
parser.parse(s.as_str()).map_err(|_| AssertionError{
value: c.clone(), assertion: "cannot be parsed into an unsigned int"
}.into_extern())?
parser.parse(s.as_str())
.map_err(|_| AssertionError::ext(x.clone(), "cannot be parsed into an unsigned int"))?
}
Literal::Num(n) => n.floor() as u64,
Literal::Uint(i) => *i,
Literal::Char(char) => char.to_digit(10).ok_or(AssertionError{
value: c.clone(), assertion: "is not a decimal digit"
}.into_extern())? as u64
};
Ok(Clause::P(Primitive::Literal(Literal::Uint(uint))))
Literal::Char(char) => char.to_digit(10)
.ok_or(AssertionError::ext(x.clone(), "is not a decimal digit"))?
.into()
}))?;
Ok(uint.into())
});

View File

@@ -1,11 +1,9 @@
use std::fmt::Debug;
use std::hash::Hash;
use crate::external::assertion_error::AssertionError;
use crate::external::litconv::with_lit;
use crate::representations::{interpreted::ExprInst, Literal};
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::{Primitive, Literal};
use crate::representations::interpreted::Clause;
/// ToString a clause
///
@@ -13,23 +11,21 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct ToString1;
externfn_impl!(ToString1, |_: &Self, c: Clause| {Ok(ToString0{c})});
externfn_impl!(ToString1, |_: &Self, x: ExprInst| {Ok(ToString0{x})});
/// Applied ToString function
///
/// Prev state: [ToString1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct ToString0{ c: Clause }
atomic_redirect!(ToString0, c);
atomic_impl!(ToString0, |Self{ c }: &Self| {
let literal: &Literal = c.try_into()
.map_err(|_| AssertionError::ext(c.clone(), "a literal value"))?;
let string = match literal {
#[derive(Debug, Clone)]
pub struct ToString0{ x: ExprInst }
atomic_redirect!(ToString0, x);
atomic_impl!(ToString0, |Self{ x }: &Self| {
let string = with_lit(x, |l| Ok(match l {
Literal::Char(c) => c.to_string(),
Literal::Uint(i) => i.to_string(),
Literal::Num(n) => n.to_string(),
Literal::Str(s) => s.clone()
};
Ok(Clause::P(Primitive::Literal(Literal::Str(string))))
}))?;
Ok(string.into())
});

View File

@@ -1,11 +1,11 @@
use crate::project::{Loader, extlib_loader};
use crate::{interner::Interner, pipeline::ConstTree};
mod print;
mod readline;
pub fn cpsio() -> impl Loader {
extlib_loader(vec![
("print", Box::new(print::Print2)),
("readline", Box::new(readline::Readln2))
pub fn cpsio(i: &Interner) -> ConstTree {
ConstTree::tree([
(i.i("print"), ConstTree::xfn(print::Print2)),
(i.i("readline"), ConstTree::xfn(readline::Readln2))
])
}

View File

@@ -1,11 +1,10 @@
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use crate::external::str::cls2str;
use crate::external::litconv::with_str;
use crate::representations::PathSet;
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::interpreted::Clause;
use crate::representations::interpreted::{Clause, ExprInst};
/// Print function
///
@@ -13,20 +12,21 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct Print2;
externfn_impl!(Print2, |_: &Self, c: Clause| {Ok(Print1{c})});
externfn_impl!(Print2, |_: &Self, x: ExprInst| {Ok(Print1{x})});
/// Partially applied Print function
///
/// Prev state: [Print2]; Next state: [Print0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Print1{ c: Clause }
atomic_redirect!(Print1, c);
atomic_impl!(Print1, |Self{ c }: &Self| {
let message = cls2str(&c)?;
print!("{}", message);
Ok(Clause::Lambda {
args: Some(PathSet{ steps: Rc::new(vec![]), next: None }),
body: Rc::new(Clause::LambdaArg)
#[derive(Debug, Clone)]
pub struct Print1{ x: ExprInst }
atomic_redirect!(Print1, x);
atomic_impl!(Print1, |Self{ x }: &Self| {
with_str(x, |s| {
print!("{}", s);
Ok(Clause::Lambda {
args: Some(PathSet{ steps: Rc::new(vec![]), next: None }),
body: Clause::LambdaArg.wrap()
})
})
});

View File

@@ -1,12 +1,10 @@
use std::fmt::Debug;
use std::io::stdin;
use std::rc::Rc;
use std::hash::Hash;
use crate::external::runtime_error::RuntimeError;
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::{Primitive, Literal};
use crate::representations::interpreted::Clause;
use crate::representations::interpreted::{Clause, ExprInst};
/// Readln function
///
@@ -14,22 +12,21 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct Readln2;
externfn_impl!(Readln2, |_: &Self, c: Clause| {Ok(Readln1{c})});
externfn_impl!(Readln2, |_: &Self, x: ExprInst| {Ok(Readln1{x})});
/// Partially applied Readln function
///
/// Prev state: [Readln2]; Next state: [Readln0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Readln1{ c: Clause }
atomic_redirect!(Readln1, c);
atomic_impl!(Readln1, |Self{ c }: &Self| {
#[derive(Debug, Clone)]
pub struct Readln1{ x: ExprInst }
atomic_redirect!(Readln1, x);
atomic_impl!(Readln1, |Self{ x }: &Self| {
let mut buf = String::new();
stdin().read_line(&mut buf).map_err(|e| RuntimeError::ext(e.to_string(), "reading from stdin"))?;
buf.pop();
Ok(Clause::Apply {
f: Rc::new(c.clone()),
x: Rc::new(Clause::P(Primitive::Literal(Literal::Str(buf)))),
id: 0
f: x.clone(),
x: Clause::P(Primitive::Literal(Literal::Str(buf))).wrap()
})
});

34
src/external/litconv.rs vendored Normal file
View File

@@ -0,0 +1,34 @@
use std::rc::Rc;
use crate::foreign::ExternError;
use crate::external::assertion_error::AssertionError;
use crate::representations::interpreted::ExprInst;
use crate::representations::Literal;
pub fn with_lit<T>(x: &ExprInst,
predicate: impl FnOnce(&Literal) -> Result<T, Rc<dyn ExternError>>
) -> Result<T, Rc<dyn ExternError>> {
x.with_literal(predicate)
.map_err(|()| AssertionError::ext(x.clone(), "a literal value"))
.and_then(|r| r)
}
pub fn with_str<T>(x: &ExprInst,
predicate: impl FnOnce(&String) -> Result<T, Rc<dyn ExternError>>
) -> Result<T, Rc<dyn ExternError>> {
with_lit(x, |l| {
if let Literal::Str(s) = l {predicate(&s)} else {
AssertionError::fail(x.clone(), "a string")?
}
})
}
pub fn with_uint<T>(x: &ExprInst,
predicate: impl FnOnce(u64) -> Result<T, Rc<dyn ExternError>>
) -> Result<T, Rc<dyn ExternError>> {
with_lit(x, |l| {
if let Literal::Uint(u) = l {predicate(*u)} else {
AssertionError::fail(x.clone(), "an uint")?
}
})
}

1
src/external/mod.rs vendored
View File

@@ -6,3 +6,4 @@ mod str;
mod cpsio;
mod runtime_error;
mod bool;
mod litconv;

View File

@@ -2,14 +2,14 @@ mod numeric;
pub mod operators;
pub use numeric::Numeric;
use crate::project::{extlib_loader, Loader};
use crate::{interner::Interner, pipeline::ConstTree};
pub fn num() -> impl Loader {
extlib_loader(vec![
("add", Box::new(operators::add::Add2)),
("subtract", Box::new(operators::subtract::Subtract2)),
("multiply", Box::new(operators::multiply::Multiply2)),
("divide", Box::new(operators::divide::Divide2)),
("remainder", Box::new(operators::remainder::Remainder2))
pub fn num(i: &Interner) -> ConstTree {
ConstTree::tree([
(i.i("add"), ConstTree::xfn(operators::add::Add2)),
(i.i("subtract"), ConstTree::xfn(operators::subtract::Subtract2)),
(i.i("multiply"), ConstTree::xfn(operators::multiply::Multiply2)),
(i.i("divide"), ConstTree::xfn(operators::divide::Divide2)),
(i.i("remainder"), ConstTree::xfn(operators::remainder::Remainder2))
])
}

View File

@@ -4,9 +4,11 @@ use std::rc::Rc;
use ordered_float::NotNan;
use crate::external::assertion_error::AssertionError;
use crate::external::litconv::with_lit;
use crate::foreign::ExternError;
use crate::representations::{Primitive, Literal};
use crate::representations::interpreted::Clause;
use crate::representations::Literal;
use crate::representations::Primitive;
use crate::representations::interpreted::{Clause, ExprInst};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Numeric {
@@ -93,17 +95,14 @@ impl Rem for Numeric {
}
}
impl TryFrom<Clause> for Numeric {
impl TryFrom<ExprInst> for Numeric {
type Error = Rc<dyn ExternError>;
fn try_from(value: Clause) -> Result<Self, Self::Error> {
let l = if let Clause::P(Primitive::Literal(l)) = value.clone() {l} else {
AssertionError::fail(value, "a literal value")?
};
match l {
Literal::Uint(i) => Ok(Numeric::Uint(i)),
Literal::Num(n) => Ok(Numeric::Num(n)),
fn try_from(value: ExprInst) -> Result<Self, Self::Error> {
with_lit(&value.clone(), |l| match l {
Literal::Uint(i) => Ok(Numeric::Uint(*i)),
Literal::Num(n) => Ok(Numeric::Num(*n)),
_ => AssertionError::fail(value, "an integer or number")?
}
})
}
}

View File

@@ -2,10 +2,9 @@
use super::super::Numeric;
use std::fmt::Debug;
use std::hash::Hash;
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::interpreted::Clause;
use crate::representations::interpreted::ExprInst;
/// Add function
///
@@ -13,29 +12,29 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct Add2;
externfn_impl!(Add2, |_: &Self, c: Clause| {Ok(Add1{c})});
externfn_impl!(Add2, |_: &Self, x: ExprInst| {Ok(Add1{x})});
/// Partially applied Add function
///
/// Prev state: [Add2]; Next state: [Add0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Add1{ c: Clause }
atomic_redirect!(Add1, c);
#[derive(Debug, Clone)]
pub struct Add1{ x: ExprInst }
atomic_redirect!(Add1, x);
atomic_impl!(Add1);
externfn_impl!(Add1, |this: &Self, c: Clause| {
let a: Numeric = this.c.clone().try_into()?;
Ok(Add0{ a, c })
externfn_impl!(Add1, |this: &Self, x: ExprInst| {
let a: Numeric = this.x.clone().try_into()?;
Ok(Add0{ a, x })
});
/// Fully applied Add function.
///
/// Prev state: [Add1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Add0 { a: Numeric, c: Clause }
atomic_redirect!(Add0, c);
atomic_impl!(Add0, |Self{ a, c }: &Self| {
let b: Numeric = c.clone().try_into()?;
#[derive(Debug, Clone)]
pub struct Add0 { a: Numeric, x: ExprInst }
atomic_redirect!(Add0, x);
atomic_impl!(Add0, |Self{ a, x }: &Self| {
let b: Numeric = x.clone().try_into()?;
Ok((*a + b).into())
});

View File

@@ -2,10 +2,9 @@
use super::super::Numeric;
use std::fmt::Debug;
use std::hash::Hash;
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::interpreted::Clause;
use crate::representations::interpreted::ExprInst;
/// Divide function
///
@@ -13,29 +12,29 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct Divide2;
externfn_impl!(Divide2, |_: &Self, c: Clause| {Ok(Divide1{c})});
externfn_impl!(Divide2, |_: &Self, x: ExprInst| {Ok(Divide1{x})});
/// Partially applied Divide function
///
/// Prev state: [Divide2]; Next state: [Divide0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Divide1{ c: Clause }
atomic_redirect!(Divide1, c);
#[derive(Debug, Clone)]
pub struct Divide1{ x: ExprInst }
atomic_redirect!(Divide1, x);
atomic_impl!(Divide1);
externfn_impl!(Divide1, |this: &Self, c: Clause| {
let a: Numeric = this.c.clone().try_into()?;
Ok(Divide0{ a, c })
externfn_impl!(Divide1, |this: &Self, x: ExprInst| {
let a: Numeric = this.x.clone().try_into()?;
Ok(Divide0{ a, x })
});
/// Fully applied Divide function.
///
/// Prev state: [Divide1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Divide0 { a: Numeric, c: Clause }
atomic_redirect!(Divide0, c);
atomic_impl!(Divide0, |Self{ a, c }: &Self| {
let b: Numeric = c.clone().try_into()?;
#[derive(Debug, Clone)]
pub struct Divide0 { a: Numeric, x: ExprInst }
atomic_redirect!(Divide0, x);
atomic_impl!(Divide0, |Self{ a, x }: &Self| {
let b: Numeric = x.clone().try_into()?;
Ok((*a / b).into())
});

View File

@@ -2,10 +2,9 @@
use super::super::Numeric;
use std::fmt::Debug;
use std::hash::Hash;
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::interpreted::Clause;
use crate::representations::interpreted::ExprInst;
/// Multiply function
///
@@ -13,29 +12,29 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct Multiply2;
externfn_impl!(Multiply2, |_: &Self, c: Clause| {Ok(Multiply1{c})});
externfn_impl!(Multiply2, |_: &Self, x: ExprInst| {Ok(Multiply1{x})});
/// Partially applied Multiply function
///
/// Prev state: [Multiply2]; Next state: [Multiply0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Multiply1{ c: Clause }
atomic_redirect!(Multiply1, c);
#[derive(Debug, Clone)]
pub struct Multiply1{ x: ExprInst }
atomic_redirect!(Multiply1, x);
atomic_impl!(Multiply1);
externfn_impl!(Multiply1, |this: &Self, c: Clause| {
let a: Numeric = this.c.clone().try_into()?;
Ok(Multiply0{ a, c })
externfn_impl!(Multiply1, |this: &Self, x: ExprInst| {
let a: Numeric = this.x.clone().try_into()?;
Ok(Multiply0{ a, x })
});
/// 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()?;
#[derive(Debug, Clone)]
pub struct Multiply0 { a: Numeric, x: ExprInst }
atomic_redirect!(Multiply0, x);
atomic_impl!(Multiply0, |Self{ a, x }: &Self| {
let b: Numeric = x.clone().try_into()?;
Ok((*a * b).into())
});

View File

@@ -2,10 +2,9 @@
use super::super::Numeric;
use std::fmt::Debug;
use std::hash::Hash;
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::interpreted::Clause;
use crate::representations::interpreted::ExprInst;
/// Remainder function
///
@@ -13,29 +12,29 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct Remainder2;
externfn_impl!(Remainder2, |_: &Self, c: Clause| {Ok(Remainder1{c})});
externfn_impl!(Remainder2, |_: &Self, x: ExprInst| {Ok(Remainder1{x})});
/// Partially applied Remainder function
///
/// Prev state: [Remainder2]; Next state: [Remainder0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Remainder1{ c: Clause }
atomic_redirect!(Remainder1, c);
#[derive(Debug, Clone)]
pub struct Remainder1{ x: ExprInst }
atomic_redirect!(Remainder1, x);
atomic_impl!(Remainder1);
externfn_impl!(Remainder1, |this: &Self, c: Clause| {
let a: Numeric = this.c.clone().try_into()?;
Ok(Remainder0{ a, c })
externfn_impl!(Remainder1, |this: &Self, x: ExprInst| {
let a: Numeric = this.x.clone().try_into()?;
Ok(Remainder0{ a, x })
});
/// Fully applied Remainder function.
///
/// Prev state: [Remainder1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Remainder0 { a: Numeric, c: Clause }
atomic_redirect!(Remainder0, c);
atomic_impl!(Remainder0, |Self{ a, c }: &Self| {
let b: Numeric = c.clone().try_into()?;
#[derive(Debug, Clone)]
pub struct Remainder0 { a: Numeric, x: ExprInst }
atomic_redirect!(Remainder0, x);
atomic_impl!(Remainder0, |Self{ a, x }: &Self| {
let b: Numeric = x.clone().try_into()?;
Ok((*a % b).into())
});

View File

@@ -2,10 +2,9 @@
use super::super::Numeric;
use std::fmt::Debug;
use std::hash::Hash;
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::interpreted::{Clause};
use crate::representations::interpreted::ExprInst;
/// Subtract function
///
@@ -13,29 +12,29 @@ use crate::representations::interpreted::{Clause};
#[derive(Clone)]
pub struct Subtract2;
externfn_impl!(Subtract2, |_: &Self, c: Clause| {Ok(Subtract1{c})});
externfn_impl!(Subtract2, |_: &Self, x: ExprInst| {Ok(Subtract1{x})});
/// Partially applied Subtract function
///
/// Prev state: [Subtract2]; Next state: [Subtract0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Subtract1{ c: Clause }
atomic_redirect!(Subtract1, c);
#[derive(Debug, Clone)]
pub struct Subtract1{ x: ExprInst }
atomic_redirect!(Subtract1, x);
atomic_impl!(Subtract1);
externfn_impl!(Subtract1, |this: &Self, c: Clause| {
let a: Numeric = this.c.clone().try_into()?;
Ok(Subtract0{ a, c })
externfn_impl!(Subtract1, |this: &Self, x: ExprInst| {
let a: Numeric = this.x.clone().try_into()?;
Ok(Subtract0{ a, x })
});
/// Fully applied Subtract function.
///
/// Prev state: [Subtract1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Subtract0 { a: Numeric, c: Clause }
atomic_redirect!(Subtract0, c);
atomic_impl!(Subtract0, |Self{ a, c }: &Self| {
let b: Numeric = c.clone().try_into()?;
#[derive(Debug, Clone)]
pub struct Subtract0 { a: Numeric, x: ExprInst }
atomic_redirect!(Subtract0, x);
atomic_impl!(Subtract0, |Self{ a, x }: &Self| {
let b: Numeric = x.clone().try_into()?;
Ok((*a - b).into())
});

19
src/external/std.rs vendored
View File

@@ -1,6 +1,5 @@
use std::collections::HashMap;
use crate::project::{map_loader, Loader};
use crate::pipeline::ConstTree;
use crate::interner::Interner;
use super::bool::bool;
use super::cpsio::cpsio;
@@ -8,12 +7,10 @@ use super::conv::conv;
use super::str::str;
use super::num::num;
pub fn std() -> impl Loader {
map_loader(HashMap::from([
("cpsio", cpsio().boxed()),
("conv", conv().boxed()),
("bool", bool().boxed()),
("str", str().boxed()),
("num", num().boxed()),
]))
pub fn std(i: &Interner) -> ConstTree {
cpsio(i)
+ conv(i)
+ bool(i)
+ str(i)
+ num(i)
}

View File

@@ -1,11 +1,10 @@
use std::fmt::Debug;
use std::hash::Hash;
use crate::external::assertion_error::AssertionError;
use crate::external::litconv::{with_str, with_uint};
use crate::external::runtime_error::RuntimeError;
use crate::representations::{Literal, Primitive};
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::interpreted::Clause;
use crate::representations::interpreted::{Clause, ExprInst};
/// CharAt function
///
@@ -13,35 +12,31 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct CharAt2;
externfn_impl!(CharAt2, |_: &Self, c: Clause| {Ok(CharAt1{c})});
externfn_impl!(CharAt2, |_: &Self, x: ExprInst| {Ok(CharAt1{x})});
/// Partially applied CharAt function
///
/// Prev state: [CharAt2]; Next state: [CharAt0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct CharAt1{ c: Clause }
atomic_redirect!(CharAt1, c);
#[derive(Debug, Clone)]
pub struct CharAt1{ x: ExprInst }
atomic_redirect!(CharAt1, x);
atomic_impl!(CharAt1);
externfn_impl!(CharAt1, |this: &Self, c: Clause| {
let s = if let Ok(Literal::Str(s)) = this.c.clone().try_into() {s}
else {AssertionError::fail(this.c.clone(), "a string")?};
Ok(CharAt0{ s, c })
externfn_impl!(CharAt1, |this: &Self, x: ExprInst| {
with_str(&this.x, |s| Ok(CharAt0{ s: s.clone(), x }))
});
/// Fully applied CharAt function.
///
/// Prev state: [CharAt1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct CharAt0 { s: String, c: Clause }
atomic_redirect!(CharAt0, c);
atomic_impl!(CharAt0, |Self{ s, c }: &Self| {
let i = if let Ok(Literal::Uint(i)) = c.clone().try_into() {i}
else {AssertionError::fail(c.clone(), "an uint")?};
if let Some(c) = s.chars().nth(i as usize) {
#[derive(Debug, Clone)]
pub struct CharAt0 { s: String, x: ExprInst }
atomic_redirect!(CharAt0, x);
atomic_impl!(CharAt0, |Self{ s, x }: &Self| {
with_uint(x, |i| if let Some(c) = s.chars().nth(i as usize) {
Ok(Clause::P(Primitive::Literal(Literal::Char(c))))
} else {
RuntimeError::fail("Character index out of bounds".to_string(), "indexing string")?
}
})
});

View File

@@ -1,13 +0,0 @@
use std::rc::Rc;
use crate::foreign::ExternError;
use crate::external::assertion_error::AssertionError;
use crate::representations::{interpreted::Clause, Literal};
pub fn cls2str(c: &Clause) -> Result<&String, Rc<dyn ExternError>> {
let literal: &Literal = c.try_into()
.map_err(|_| AssertionError::ext(c.clone(), "a literal value"))?;
if let Literal::Str(s) = literal {Ok(s)} else {
AssertionError::fail(c.clone(), "a string")?
}
}

View File

@@ -1,11 +1,9 @@
use super::cls2str;
use std::fmt::Debug;
use std::hash::Hash;
use crate::external::litconv::with_str;
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::representations::{Primitive, Literal};
use crate::representations::interpreted::Clause;
use crate::representations::interpreted::{Clause, ExprInst};
/// Concatenate function
///
@@ -13,29 +11,29 @@ use crate::representations::interpreted::Clause;
#[derive(Clone)]
pub struct Concatenate2;
externfn_impl!(Concatenate2, |_: &Self, c: Clause| {Ok(Concatenate1{c})});
externfn_impl!(Concatenate2, |_: &Self, c: ExprInst| {Ok(Concatenate1{c})});
/// Partially applied Concatenate function
///
/// Prev state: [Concatenate2]; Next state: [Concatenate0]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Concatenate1{ c: Clause }
#[derive(Debug, Clone)]
pub struct Concatenate1{ c: ExprInst }
atomic_redirect!(Concatenate1, c);
atomic_impl!(Concatenate1);
externfn_impl!(Concatenate1, |this: &Self, c: Clause| {
let a: String = cls2str(&this.c)?.clone();
Ok(Concatenate0{ a, c })
externfn_impl!(Concatenate1, |this: &Self, c: ExprInst| {
with_str(&this.c, |a| Ok(Concatenate0{ a: a.clone(), c }))
});
/// Fully applied Concatenate function.
///
/// Prev state: [Concatenate1]
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct Concatenate0 { a: String, c: Clause }
#[derive(Debug, Clone)]
pub struct Concatenate0 { a: String, c: ExprInst }
atomic_redirect!(Concatenate0, c);
atomic_impl!(Concatenate0, |Self{ a, c }: &Self| {
let b: &String = cls2str(c)?;
Ok(Clause::P(Primitive::Literal(Literal::Str(a.to_owned() + b))))
with_str(c, |b| Ok(Clause::P(Primitive::Literal(
Literal::Str(a.to_owned() + b)
))))
});

View File

@@ -1,11 +1,10 @@
mod concatenate;
mod cls2str;
mod char_at;
pub use cls2str::cls2str;
use crate::project::{Loader, extlib_loader};
pub fn str() -> impl Loader {
extlib_loader(vec![
("concatenate", Box::new(concatenate::Concatenate2))
use crate::{pipeline::ConstTree, interner::Interner};
pub fn str(i: &Interner) -> ConstTree {
ConstTree::tree([
(i.i("concatenate"), ConstTree::xfn(concatenate::Concatenate2))
])
}