Almost Alpha

Massive improvements across the board.

One day I'll adopt incremental commits.
This commit is contained in:
2024-02-23 23:59:24 +00:00
parent c279301583
commit ed0d64d52e
147 changed files with 4121 additions and 4203 deletions

View File

@@ -1,69 +1,45 @@
use once_cell::sync::Lazy;
use ordered_float::NotNan;
use super::number::Numeric;
use super::protocol::{gen_resolv, Protocol};
use super::string::OrcString;
use crate::foreign::atom::Atomic;
use crate::foreign::error::{AssertionError, ExternResult};
use crate::foreign::error::{AssertionError, RTResult};
use crate::foreign::inert::Inert;
use crate::foreign::try_from_expr::WithLoc;
use crate::gen::tpl;
use crate::gen::traits::Gen;
use crate::gen::tree::{xfn_ent, ConstTree};
use crate::interpreter::gen_nort::nort_gen;
use crate::interpreter::nort::{ClauseInst, Expr};
use crate::gen::tree::{leaf, xfn_ent, ConstTree};
use crate::interpreter::nort::ClauseInst;
use crate::parse::numeric::parse_num;
pub static TO_STRING: Lazy<Protocol> =
Lazy::new(|| Protocol::new("to_string", []));
fn to_numeric(WithLoc(loc, a): WithLoc<ClauseInst>) -> ExternResult<Numeric> {
fn to_numeric(WithLoc(loc, a): WithLoc<ClauseInst>) -> RTResult<Numeric> {
if let Some(n) = a.request::<Numeric>() {
return Ok(n);
}
if let Some(s) = a.request::<OrcString>() {
return parse_num(s.as_str()).map_err(|e| {
AssertionError::ext(loc, "number syntax", format!("{e:?}"))
});
return parse_num(s.as_str())
.map_err(|e| AssertionError::ext(loc, "number syntax", format!("{e:?}")));
}
AssertionError::fail(loc, "string or number", format!("{a}"))
}
/// parse a number. Accepts the same syntax Orchid does.
pub fn to_float(a: WithLoc<ClauseInst>) -> ExternResult<Inert<NotNan<f64>>> {
pub fn to_float(a: WithLoc<ClauseInst>) -> RTResult<Inert<NotNan<f64>>> {
to_numeric(a).map(|n| Inert(n.as_float()))
}
/// Parse an unsigned integer. Accepts the same formats Orchid does. If the
/// input is a number, floors it.
pub fn to_uint(a: WithLoc<ClauseInst>) -> ExternResult<Inert<usize>> {
pub fn to_uint(a: WithLoc<ClauseInst>) -> RTResult<Inert<usize>> {
to_numeric(a).map(|n| match n {
Numeric::Float(f) => Inert(f.floor() as usize),
Numeric::Uint(i) => Inert(i),
})
}
/// Convert a literal to a string using Rust's conversions for floats, chars and
/// uints respectively
pub fn to_string(WithLoc(loc, a): WithLoc<Expr>) -> Expr {
match a.clone().downcast::<Inert<OrcString>>() {
Ok(str) => str.atom_expr(loc),
Err(_) => match a.clause.request::<OrcString>() {
Some(str) => Inert(str).atom_expr(loc),
None => tpl::a2(gen_resolv("std::to_string"), tpl::Slot, tpl::Slot)
.template(nort_gen(loc), [a.clone(), a]),
},
}
}
pub fn conv_lib() -> ConstTree {
ConstTree::ns("std", [ConstTree::tree([
TO_STRING.as_tree_ent([]),
ConstTree::tree_ent("conv", [
xfn_ent("to_float", [to_float]),
xfn_ent("to_uint", [to_uint]),
xfn_ent("to_string", [to_string]),
]),
])])
ConstTree::ns("std", [ConstTree::tree([ConstTree::tree_ent("conv", [
xfn_ent("to_float", [to_float]),
xfn_ent("to_uint", [to_uint]),
// conversion logic moved to the string library
("to_string", leaf(tpl::C("std::string::convert"))),
])])])
}