bug fixes and performance improvements
This commit is contained in:
8
src/external/assertion_error.rs
vendored
8
src/external/assertion_error.rs
vendored
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
12
src/external/bool/boolean.rs
vendored
12
src/external/bool/boolean.rs
vendored
@@ -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)
|
||||
}
|
||||
|
||||
46
src/external/bool/equals.rs
vendored
46
src/external/bool/equals.rs
vendored
@@ -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())
|
||||
});
|
||||
|
||||
28
src/external/bool/ifthenelse.rs
vendored
28
src/external/bool/ifthenelse.rs
vendored
@@ -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()
|
||||
}})
|
||||
});
|
||||
11
src/external/bool/mod.rs
vendored
11
src/external/bool/mod.rs
vendored
@@ -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))
|
||||
])
|
||||
}
|
||||
12
src/external/conv/mod.rs
vendored
12
src/external/conv/mod.rs
vendored
@@ -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))
|
||||
])
|
||||
}
|
||||
35
src/external/conv/parse_float.rs
vendored
35
src/external/conv/parse_float.rs
vendored
@@ -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())
|
||||
});
|
||||
38
src/external/conv/parse_uint.rs
vendored
38
src/external/conv/parse_uint.rs
vendored
@@ -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())
|
||||
});
|
||||
24
src/external/conv/to_string.rs
vendored
24
src/external/conv/to_string.rs
vendored
@@ -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())
|
||||
});
|
||||
|
||||
10
src/external/cpsio/mod.rs
vendored
10
src/external/cpsio/mod.rs
vendored
@@ -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))
|
||||
])
|
||||
}
|
||||
26
src/external/cpsio/print.rs
vendored
26
src/external/cpsio/print.rs
vendored
@@ -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()
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
19
src/external/cpsio/readline.rs
vendored
19
src/external/cpsio/readline.rs
vendored
@@ -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
34
src/external/litconv.rs
vendored
Normal 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
1
src/external/mod.rs
vendored
@@ -6,3 +6,4 @@ mod str;
|
||||
mod cpsio;
|
||||
mod runtime_error;
|
||||
mod bool;
|
||||
mod litconv;
|
||||
|
||||
16
src/external/num/mod.rs
vendored
16
src/external/num/mod.rs
vendored
@@ -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))
|
||||
])
|
||||
}
|
||||
21
src/external/num/numeric.rs
vendored
21
src/external/num/numeric.rs
vendored
@@ -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")?
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
27
src/external/num/operators/add.rs
vendored
27
src/external/num/operators/add.rs
vendored
@@ -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())
|
||||
});
|
||||
|
||||
27
src/external/num/operators/divide.rs
vendored
27
src/external/num/operators/divide.rs
vendored
@@ -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())
|
||||
});
|
||||
27
src/external/num/operators/multiply.rs
vendored
27
src/external/num/operators/multiply.rs
vendored
@@ -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())
|
||||
});
|
||||
27
src/external/num/operators/remainder.rs
vendored
27
src/external/num/operators/remainder.rs
vendored
@@ -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())
|
||||
});
|
||||
27
src/external/num/operators/subtract.rs
vendored
27
src/external/num/operators/subtract.rs
vendored
@@ -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
19
src/external/std.rs
vendored
@@ -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)
|
||||
}
|
||||
33
src/external/str/char_at.rs
vendored
33
src/external/str/char_at.rs
vendored
@@ -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")?
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
13
src/external/str/cls2str.rs
vendored
13
src/external/str/cls2str.rs
vendored
@@ -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")?
|
||||
}
|
||||
}
|
||||
26
src/external/str/concatenate.rs
vendored
26
src/external/str/concatenate.rs
vendored
@@ -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)
|
||||
))))
|
||||
});
|
||||
|
||||
11
src/external/str/mod.rs
vendored
11
src/external/str/mod.rs
vendored
@@ -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))
|
||||
])
|
||||
}
|
||||
Reference in New Issue
Block a user