finish base, I think
This commit is contained in:
parent
5e10a87cbc
commit
13c14fd38f
|
@ -11,3 +11,4 @@ chumsky = { git = "https://github.com/zesterer/chumsky", features = ["label"] }
|
||||||
imbl = "3.0.0"
|
imbl = "3.0.0"
|
||||||
struct_scalpel = "0.1.1"
|
struct_scalpel = "0.1.1"
|
||||||
tailcall = "1.0.1"
|
tailcall = "1.0.1"
|
||||||
|
ran = "2.0.1"
|
||||||
|
|
309
src/base.rs
309
src/base.rs
|
@ -1,9 +1,11 @@
|
||||||
use crate::value::*;
|
use crate::value::*;
|
||||||
use imbl::*;
|
use imbl::*;
|
||||||
|
use ran::ran_f64;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Base<'src> {
|
pub enum Base<'src> {
|
||||||
|
Nullary(fn() -> Value<'src>),
|
||||||
Unary(fn(&Value<'src>) -> Value<'src>),
|
Unary(fn(&Value<'src>) -> Value<'src>),
|
||||||
Binary(fn(&Value<'src>, &Value<'src>) -> Value<'src>),
|
Binary(fn(&Value<'src>, &Value<'src>) -> Value<'src>),
|
||||||
Ternary(fn(&Value<'src>, &Value<'src>, &Value<'src>) -> Value<'src>),
|
Ternary(fn(&Value<'src>, &Value<'src>, &Value<'src>) -> Value<'src>),
|
||||||
|
@ -384,72 +386,262 @@ pub fn r#type<'src>(x: &Value<'src>) -> Value<'src> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn split<'src>(source: &Value<'src>, splitter: &Value) -> Value<'src> {
|
||||||
|
match (source, splitter) {
|
||||||
|
(Value::AllocatedString(source), Value::AllocatedString(splitter)) => {
|
||||||
|
let parts = source.split_terminator(splitter.as_str());
|
||||||
|
let mut list = vector![];
|
||||||
|
for part in parts {
|
||||||
|
list.push_back(Value::AllocatedString(Rc::new(part.to_string())));
|
||||||
|
}
|
||||||
|
Value::List(list)
|
||||||
|
}
|
||||||
|
(Value::AllocatedString(source), Value::InternedString(splitter)) => {
|
||||||
|
let parts = source.split_terminator(splitter);
|
||||||
|
let mut list = vector![];
|
||||||
|
for part in parts {
|
||||||
|
list.push_back(Value::AllocatedString(Rc::new(part.to_string())));
|
||||||
|
}
|
||||||
|
Value::List(list)
|
||||||
|
}
|
||||||
|
(Value::InternedString(source), Value::AllocatedString(splitter)) => {
|
||||||
|
let parts = source.split_terminator(splitter.as_str());
|
||||||
|
let mut list = vector![];
|
||||||
|
for part in parts {
|
||||||
|
list.push_back(Value::AllocatedString(Rc::new(part.to_string())));
|
||||||
|
}
|
||||||
|
Value::List(list)
|
||||||
|
}
|
||||||
|
(Value::InternedString(source), Value::InternedString(splitter)) => {
|
||||||
|
let parts = source.split_terminator(splitter);
|
||||||
|
let mut list = vector![];
|
||||||
|
for part in parts {
|
||||||
|
list.push_back(Value::AllocatedString(Rc::new(part.to_string())));
|
||||||
|
}
|
||||||
|
Value::List(list)
|
||||||
|
}
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn upcase<'src>(string: &Value<'src>) -> Value<'src> {
|
||||||
|
match string {
|
||||||
|
Value::AllocatedString(string) => Value::AllocatedString(Rc::new(string.to_uppercase())),
|
||||||
|
Value::InternedString(string) => Value::AllocatedString(Rc::new(string.to_uppercase())),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn downcase<'src>(string: &Value<'src>) -> Value<'src> {
|
||||||
|
match string {
|
||||||
|
Value::AllocatedString(string) => Value::AllocatedString(Rc::new(string.to_lowercase())),
|
||||||
|
Value::InternedString(string) => Value::AllocatedString(Rc::new(string.to_lowercase())),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trim<'src>(string: &Value<'src>) -> Value<'src> {
|
||||||
|
match string {
|
||||||
|
Value::AllocatedString(string) => {
|
||||||
|
Value::AllocatedString(Rc::new(string.trim().to_string()))
|
||||||
|
}
|
||||||
|
Value::InternedString(string) => Value::AllocatedString(Rc::new(string.trim().to_string())),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn triml<'src>(string: &Value<'src>) -> Value<'src> {
|
||||||
|
match string {
|
||||||
|
Value::AllocatedString(string) => {
|
||||||
|
Value::AllocatedString(Rc::new(string.trim_start().to_string()))
|
||||||
|
}
|
||||||
|
Value::InternedString(string) => {
|
||||||
|
Value::AllocatedString(Rc::new(string.trim_start().to_string()))
|
||||||
|
}
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trimr<'src>(string: &Value<'src>) -> Value<'src> {
|
||||||
|
match string {
|
||||||
|
Value::AllocatedString(string) => {
|
||||||
|
Value::AllocatedString(Rc::new(string.trim_end().to_string()))
|
||||||
|
}
|
||||||
|
Value::InternedString(string) => {
|
||||||
|
Value::AllocatedString(Rc::new(string.trim_end().to_string()))
|
||||||
|
}
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn atan_2<'src>(x: &Value, y: &Value) -> Value<'src> {
|
||||||
|
match (x, y) {
|
||||||
|
(Value::Number(x), Value::Number(y)) => Value::Number(x.atan2(*y)),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ceil<'src>(x: &Value) -> Value<'src> {
|
||||||
|
match x {
|
||||||
|
Value::Number(x) => Value::Number(x.ceil()),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cos<'src>(x: &Value) -> Value<'src> {
|
||||||
|
match x {
|
||||||
|
Value::Number(x) => Value::Number(x.cos()),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn floor<'src>(x: &Value) -> Value<'src> {
|
||||||
|
match x {
|
||||||
|
Value::Number(x) => Value::Number(x.floor()),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn random<'src>() -> Value<'src> {
|
||||||
|
Value::Number(ran_f64())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn round<'src>(x: &Value) -> Value<'src> {
|
||||||
|
match x {
|
||||||
|
Value::Number(x) => Value::Number(x.round()),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sin<'src>(x: &Value) -> Value<'src> {
|
||||||
|
match x {
|
||||||
|
Value::Number(x) => Value::Number(x.sin()),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sqrt<'src>(x: &Value) -> Value<'src> {
|
||||||
|
match x {
|
||||||
|
Value::Number(x) => Value::Number(x.sqrt()),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tan<'src>(x: &Value) -> Value<'src> {
|
||||||
|
match x {
|
||||||
|
Value::Number(x) => Value::Number(x.tan()),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gt<'src>(x: &Value, y: &Value) -> Value<'src> {
|
||||||
|
match (x, y) {
|
||||||
|
(Value::Number(x), Value::Number(y)) => Value::Boolean(x > y),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gte<'src>(x: &Value, y: &Value) -> Value<'src> {
|
||||||
|
match (x, y) {
|
||||||
|
(Value::Number(x), Value::Number(y)) => Value::Boolean(x >= y),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lt<'src>(x: &Value, y: &Value) -> Value<'src> {
|
||||||
|
match (x, y) {
|
||||||
|
(Value::Number(x), Value::Number(y)) => Value::Boolean(x < y),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lte<'src>(x: &Value, y: &Value) -> Value<'src> {
|
||||||
|
match (x, y) {
|
||||||
|
(Value::Number(x), Value::Number(y)) => Value::Boolean(x <= y),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn r#mod<'src>(x: &Value, y: &Value) -> Value<'src> {
|
||||||
|
match (x, y) {
|
||||||
|
(Value::Number(x), Value::Number(y)) => Value::Number(x % y),
|
||||||
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn base<'src>() -> Vec<(&'src str, Value<'src>)> {
|
pub fn base<'src>() -> Vec<(&'src str, Value<'src>)> {
|
||||||
vec![
|
vec![
|
||||||
("eq?", Value::Base(Base::Binary(eq))),
|
|
||||||
("add", Value::Base(Base::Binary(add))),
|
("add", Value::Base(Base::Binary(add))),
|
||||||
("sub", Value::Base(Base::Binary(sub))),
|
|
||||||
("unbox", Value::Base(Base::Unary(unbox))),
|
|
||||||
("store!", Value::Base(Base::Binary(store))),
|
|
||||||
("doc!", Value::Base(Base::Unary(doc))),
|
|
||||||
("and", Value::Base(Base::Binary(and))),
|
("and", Value::Base(Base::Binary(and))),
|
||||||
|
("append", Value::Base(Base::Binary(append))),
|
||||||
("assoc", Value::Base(Base::Ternary(assoc))),
|
("assoc", Value::Base(Base::Ternary(assoc))),
|
||||||
|
("at", Value::Base(Base::Binary(at))),
|
||||||
|
("atan_2", Value::Base(Base::Binary(atan_2))),
|
||||||
("bool", Value::Base(Base::Unary(r#bool))),
|
("bool", Value::Base(Base::Unary(r#bool))),
|
||||||
|
("ceil", Value::Base(Base::Unary(ceil))),
|
||||||
("chars", Value::Base(Base::Unary(chars))),
|
("chars", Value::Base(Base::Unary(chars))),
|
||||||
("concat", Value::Base(Base::Binary(concat))),
|
("concat", Value::Base(Base::Binary(concat))),
|
||||||
("append", Value::Base(Base::Binary(append))),
|
("cos", Value::Base(Base::Unary(cos))),
|
||||||
("dec", Value::Base(Base::Unary(dec))),
|
|
||||||
("inc", Value::Base(Base::Unary(inc))),
|
|
||||||
("div", Value::Base(Base::Binary(div))),
|
|
||||||
("mult", Value::Base(Base::Binary(mult))),
|
|
||||||
("dissoc", Value::Base(Base::Binary(dissoc))),
|
|
||||||
("first", Value::Base(Base::Unary(first))),
|
|
||||||
("at", Value::Base(Base::Binary(at))),
|
|
||||||
("get", Value::Base(Base::Binary(get))),
|
|
||||||
("last", Value::Base(Base::Unary(last))),
|
|
||||||
("or", Value::Base(Base::Binary(or))),
|
|
||||||
("print!", Value::Base(Base::Unary(print))),
|
|
||||||
("show", Value::Base(Base::Unary(show))),
|
|
||||||
("rest", Value::Base(Base::Unary(rest))),
|
|
||||||
("count", Value::Base(Base::Unary(count))),
|
("count", Value::Base(Base::Unary(count))),
|
||||||
("range", Value::Base(Base::Binary(range))),
|
("dec", Value::Base(Base::Unary(dec))),
|
||||||
("slice", Value::Base(Base::Ternary(slice))),
|
("dissoc", Value::Base(Base::Binary(dissoc))),
|
||||||
|
("div", Value::Base(Base::Binary(div))),
|
||||||
|
("doc!", Value::Base(Base::Unary(doc))),
|
||||||
|
("downcase", Value::Base(Base::Unary(downcase))),
|
||||||
|
("eq?", Value::Base(Base::Binary(eq))),
|
||||||
|
("first", Value::Base(Base::Unary(first))),
|
||||||
|
("floor", Value::Base(Base::Unary(floor))),
|
||||||
|
("get", Value::Base(Base::Binary(get))),
|
||||||
|
("gt?", Value::Base(Base::Binary(gt))),
|
||||||
|
("gte?", Value::Base(Base::Binary(gte))),
|
||||||
|
("inc", Value::Base(Base::Unary(inc))),
|
||||||
|
("last", Value::Base(Base::Unary(last))),
|
||||||
("list", Value::Base(Base::Unary(list))),
|
("list", Value::Base(Base::Unary(list))),
|
||||||
|
("lt?", Value::Base(Base::Binary(lt))),
|
||||||
|
("lte?", Value::Base(Base::Binary(lte))),
|
||||||
|
("mod", Value::Base(Base::Binary(r#mod))),
|
||||||
|
("mult", Value::Base(Base::Binary(mult))),
|
||||||
("number", Value::Base(Base::Unary(number))),
|
("number", Value::Base(Base::Unary(number))),
|
||||||
|
("or", Value::Base(Base::Binary(or))),
|
||||||
|
("pi", Value::Number(std::f64::consts::PI)),
|
||||||
|
("print!", Value::Base(Base::Unary(print))),
|
||||||
|
("random", Value::Base(Base::Nullary(random))),
|
||||||
|
("range", Value::Base(Base::Binary(range))),
|
||||||
|
("rest", Value::Base(Base::Unary(rest))),
|
||||||
|
("round", Value::Base(Base::Unary(round))),
|
||||||
|
("show", Value::Base(Base::Unary(show))),
|
||||||
|
("sin", Value::Base(Base::Unary(sin))),
|
||||||
|
("slice", Value::Base(Base::Ternary(slice))),
|
||||||
|
("split", Value::Base(Base::Binary(split))),
|
||||||
|
("sqrt", Value::Base(Base::Unary(sqrt))),
|
||||||
|
("sqrt_2", Value::Number(std::f64::consts::SQRT_2)),
|
||||||
|
("store!", Value::Base(Base::Binary(store))),
|
||||||
|
("sub", Value::Base(Base::Binary(sub))),
|
||||||
|
("tan", Value::Base(Base::Unary(tan))),
|
||||||
|
("trim", Value::Base(Base::Unary(trim))),
|
||||||
|
("triml", Value::Base(Base::Unary(triml))),
|
||||||
|
("trimr", Value::Base(Base::Unary(trimr))),
|
||||||
("type", Value::Base(Base::Unary(r#type))),
|
("type", Value::Base(Base::Unary(r#type))),
|
||||||
|
("unbox", Value::Base(Base::Unary(unbox))),
|
||||||
|
("upcase", Value::Base(Base::Unary(upcase))),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// * [ ] atan_2 (x) -> number
|
// * [x] atan_2 (x) -> number
|
||||||
// * [ ] ceil (x) -> number
|
// * [x] ceil (x) -> number
|
||||||
// * [ ] cos (x) -> number
|
// * [x] cos (x) -> number
|
||||||
// * [x] count (x) -> number
|
// * [x] floor (x) -> number
|
||||||
// * [~] disj (x) -> set
|
// * [x] gt (x, y) -> bool
|
||||||
// * [ ] downcase (x) -> string
|
// * [x] gte! (x, y) -> bool
|
||||||
// * [ ] floor (x) -> number
|
// * [x] lt (x) -> bool
|
||||||
// * [ ] gt (x, y) -> bool
|
// * [x] lte (x) -> bool
|
||||||
// * [ ] gte! (x, y) -> bool
|
// * [x] mod (x, y) -> number
|
||||||
// * [ ] lt (x) -> bool
|
// * [x] pi
|
||||||
// * [ ] lte (x) -> bool
|
// * [x] random () -> number
|
||||||
// * [ ] mod (x, y) -> number
|
// * [x] round (x) -> number
|
||||||
// * [ ] pi
|
// * [x] sin (x) -> number
|
||||||
// * [ ] random () -> number
|
// * [x] sqrt (x) -> number
|
||||||
// * [x] range () -> list
|
// * [x] tan (x) -> number
|
||||||
// * [ ] round (x) -> number
|
|
||||||
// * [ ] sin (x) -> number
|
|
||||||
// * [x] slice (x, y, z) -> list
|
|
||||||
// * [ ] split (x, y) -> list(string)
|
|
||||||
// * [ ] sqrt (x) -> number
|
|
||||||
// * [x] ~str_slice (x, y, z) -> string~
|
|
||||||
// * [x] ~stringify (x) -> string~
|
|
||||||
// * [ ] tan (x) -> number
|
|
||||||
// * [x] to_list (x) -> list
|
|
||||||
// * [ ] to_number (x) -> number
|
|
||||||
// * [ ] trim (x) -> string
|
|
||||||
// * [ ] triml (x) -> string
|
|
||||||
// * [ ] trimr (x) -> string
|
|
||||||
// * [ ] type (x) -> keyword
|
|
||||||
// * [ ] upcase (x) -> string
|
|
||||||
// * [x] add (x, y) -> number
|
// * [x] add (x, y) -> number
|
||||||
// * [x] and (x, y) -> value
|
// * [x] and (x, y) -> value
|
||||||
// * [x] append (x, y) -> list
|
// * [x] append (x, y) -> list
|
||||||
|
@ -457,10 +649,12 @@ pub fn base<'src>() -> Vec<(&'src str, Value<'src>)> {
|
||||||
// * [x] bool (x) -> bool
|
// * [x] bool (x) -> bool
|
||||||
// * [x] chars (x) -> list
|
// * [x] chars (x) -> list
|
||||||
// * [x] concat (x, y) -> value
|
// * [x] concat (x, y) -> value
|
||||||
|
// * [x] count (x) -> number
|
||||||
// * [x] dec (x) -> number
|
// * [x] dec (x) -> number
|
||||||
// * [x] dissoc (x, y) -> dict
|
// * [x] dissoc (x, y) -> dict
|
||||||
// * [x] div (x, y) -> number
|
// * [x] div (x, y) -> number
|
||||||
// * [x] doc (x) -> string
|
// * [x] doc (x) -> string
|
||||||
|
// * [x] downcase (x) -> string
|
||||||
// * [x] eq (x, y) -> bool
|
// * [x] eq (x, y) -> bool
|
||||||
// * [x] first (x) -> value
|
// * [x] first (x) -> value
|
||||||
// * [x] get (x, y) -> value
|
// * [x] get (x, y) -> value
|
||||||
|
@ -468,10 +662,23 @@ pub fn base<'src>() -> Vec<(&'src str, Value<'src>)> {
|
||||||
// * [x] last (x) -> value
|
// * [x] last (x) -> value
|
||||||
// * [x] or (x, y) -> value
|
// * [x] or (x, y) -> value
|
||||||
// * [x] print! (x) -> :ok
|
// * [x] print! (x) -> :ok
|
||||||
|
// * [x] range () -> list
|
||||||
// * [x] rest (x) -> coll
|
// * [x] rest (x) -> coll
|
||||||
// * [x] show (x) -> string
|
// * [x] show (x) -> string
|
||||||
|
// * [x] slice (x, y, z) -> list
|
||||||
|
// * [x] split (x, y) -> list(string)
|
||||||
// * [x] store! (x, y) -> value
|
// * [x] store! (x, y) -> value
|
||||||
// * [x] sub (x, y) -> number
|
// * [x] sub (x, y) -> number
|
||||||
|
// * [x] to_list (x) -> list
|
||||||
|
// * [x] to_number (x) -> number
|
||||||
|
// * [x] trim (x) -> string
|
||||||
|
// * [x] triml (x) -> string
|
||||||
|
// * [x] trimr (x) -> string
|
||||||
|
// * [x] type (x) -> keyword
|
||||||
// * [x] unbox (x) -> value
|
// * [x] unbox (x) -> value
|
||||||
|
// * [x] upcase (x) -> string
|
||||||
// * [x] ~prn (x) -> value~
|
// * [x] ~prn (x) -> value~
|
||||||
// * [x] ~push (x) -> list~
|
// * [x] ~push (x) -> list~
|
||||||
|
// * [x] ~str_slice (x, y, z) -> string~
|
||||||
|
// * [x] ~stringify (x) -> string~
|
||||||
|
// * [~] disj (x) -> set
|
||||||
|
|
|
@ -58,8 +58,8 @@ use crate::base::*;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let src = "
|
let src = "
|
||||||
let foo = 42
|
let foo = \" fOobArbaz \"
|
||||||
type (\"{foo}\")
|
trimr (foo)
|
||||||
";
|
";
|
||||||
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
||||||
if !lex_errs.is_empty() {
|
if !lex_errs.is_empty() {
|
||||||
|
|
|
@ -242,6 +242,15 @@ pub fn apply<'src>(
|
||||||
msg: "you may only call a function".to_string(),
|
msg: "you may only call a function".to_string(),
|
||||||
}),
|
}),
|
||||||
(Value::Base(f), Value::Tuple(args)) => match f {
|
(Value::Base(f), Value::Tuple(args)) => match f {
|
||||||
|
Base::Nullary(f) => {
|
||||||
|
if args.len() != 0 {
|
||||||
|
Err(LudusError {
|
||||||
|
msg: "wrong arity: expected 0 arguments".to_string(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(f())
|
||||||
|
}
|
||||||
|
}
|
||||||
Base::Unary(f) => {
|
Base::Unary(f) => {
|
||||||
if args.len() != 1 {
|
if args.len() != 1 {
|
||||||
Err(LudusError {
|
Err(LudusError {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user