2024-11-15 02:30:42 +00:00
|
|
|
// Solution to the #[derive(Clone)] problem: https://stackoverflow.com/questions/27883509/can-you-clone-a-closure
|
2024-11-11 22:50:58 +00:00
|
|
|
use crate::value::*;
|
|
|
|
use crate::vm::*;
|
|
|
|
use imbl::*;
|
|
|
|
use std::fmt;
|
|
|
|
|
2024-11-15 02:30:42 +00:00
|
|
|
type LResult<'src> = Result<Value<'src>, LudusError>;
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
2024-11-11 22:50:58 +00:00
|
|
|
pub enum Base<'src> {
|
2024-11-15 02:30:42 +00:00
|
|
|
Unary(&'src str, fn(&Value<'src>) -> LResult<'src>),
|
|
|
|
Binary(&'src str, fn(&Value<'src>, &Value<'src>) -> LResult<'src>),
|
2024-11-11 22:50:58 +00:00
|
|
|
Ternary(
|
|
|
|
&'src str,
|
2024-11-15 02:30:42 +00:00
|
|
|
fn(&Value<'src>, &Value<'src>, &Value<'src>) -> LResult<'src>,
|
2024-11-11 22:50:58 +00:00
|
|
|
),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'src> Base<'src> {
|
|
|
|
pub fn name(&self) -> &'src str {
|
|
|
|
match self {
|
|
|
|
Base::Unary(name, _) => name,
|
|
|
|
Base::Binary(name, _) => name,
|
|
|
|
Base::Ternary(name, _) => name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-15 02:30:42 +00:00
|
|
|
pub fn eq<'src>(x: &Value<'src>, y: &Value<'src>) -> LResult<'src> {
|
|
|
|
Ok(Value::Boolean(x == y))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add<'src>(x: &Value<'src>, y: &Value<'src>) -> LResult<'src> {
|
|
|
|
match (x, y) {
|
|
|
|
(Value::Number(x), Value::Number(y)) => Ok(Value::Number(x + y)),
|
|
|
|
_ => Err(LudusError {
|
|
|
|
msg: "add takes two numbers".to_string(),
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sub<'src>(x: &Value<'src>, y: &Value<'src>) -> LResult<'src> {
|
|
|
|
match (x, y) {
|
|
|
|
(Value::Number(x), Value::Number(y)) => Ok(Value::Number(x - y)),
|
|
|
|
_ => Err(LudusError {
|
|
|
|
msg: "sub takes two numbers".to_string(),
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unbox<'src>(x: &Value<'src>) -> LResult<'src> {
|
|
|
|
match x {
|
|
|
|
Value::Box(_, cell) => Ok(cell.borrow().clone()),
|
|
|
|
_ => Err(LudusError {
|
|
|
|
msg: "only boxes may be unboxed".to_string(),
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn store<'src>(b: &Value<'src>, val: &Value<'src>) -> LResult<'src> {
|
|
|
|
if let Value::Box(_, cell) = b {
|
|
|
|
cell.replace(val.clone());
|
|
|
|
Ok(val.clone())
|
|
|
|
} else {
|
|
|
|
Err(LudusError {
|
|
|
|
msg: "only boxes may store values".to_string(),
|
|
|
|
})
|
2024-11-11 22:50:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn base<'src>() -> Vec<(&'src str, Value<'src>)> {
|
|
|
|
let mut base = vec![];
|
|
|
|
|
2024-11-15 02:30:42 +00:00
|
|
|
let eq = Base::Binary("eq", eq);
|
|
|
|
base.push(("eq", Value::Base(eq)));
|
2024-11-11 22:50:58 +00:00
|
|
|
|
2024-11-15 02:30:42 +00:00
|
|
|
let add = Base::Binary("add", add);
|
|
|
|
base.push(("add", Value::Base(add)));
|
|
|
|
|
|
|
|
base.push(("sub", Value::Base(Base::Binary("sub", sub))));
|
|
|
|
|
|
|
|
base.push(("unbox", Value::Base(Base::Unary("unbox", unbox))));
|
|
|
|
|
|
|
|
base.push(("store", Value::Base(Base::Binary("store", store))));
|
2024-11-11 22:50:58 +00:00
|
|
|
|
|
|
|
base
|
|
|
|
}
|
|
|
|
|
2024-11-15 02:30:42 +00:00
|
|
|
// DONE add (x, y) -> number
|
2024-11-11 22:50:58 +00:00
|
|
|
// and (x, y) -> value
|
|
|
|
// assoc (x, y) -> dict
|
|
|
|
// atan_2 (x) -> number
|
|
|
|
// bool (x) -> bool
|
|
|
|
// ceil (x) -> number
|
|
|
|
// chars (x) -> list
|
|
|
|
// concat (x, y) -> value
|
|
|
|
// conj (x, y) -> list
|
|
|
|
// cos (x) -> number
|
|
|
|
// dec (x) -> number
|
|
|
|
// disj (x) -> set
|
|
|
|
// dissoc (x, y) -> dict
|
|
|
|
// div (x, y) -> number
|
|
|
|
// doc (x) -> string
|
|
|
|
// downcase (x) -> string
|
2024-11-15 02:30:42 +00:00
|
|
|
// DONE eq (x, y) -> bool
|
2024-11-11 22:50:58 +00:00
|
|
|
// first (x) -> value
|
|
|
|
// floor (x) -> number
|
|
|
|
// get (x, y) -> value
|
|
|
|
// gt (x, y) -> bool
|
|
|
|
// gte! (x, y) -> bool
|
|
|
|
// inc (x) -> number
|
|
|
|
// last (x) -> value
|
|
|
|
// lt (x) -> bool
|
|
|
|
// lte (x) -> bool
|
|
|
|
// mod (x, y) -> number
|
|
|
|
// or (x, y) -> value
|
|
|
|
// pi
|
|
|
|
// print! (x) -> :ok
|
|
|
|
// prn (x) -> value
|
|
|
|
// push (x) -> list
|
|
|
|
// random () -> number
|
|
|
|
// range () -> list
|
|
|
|
// rest (x) -> coll
|
|
|
|
// round (x) -> number
|
|
|
|
// show (x) -> string
|
|
|
|
// sin (x) -> number
|
|
|
|
// slice (x, y, z) -> list
|
|
|
|
// split (x, y) -> list(string)
|
|
|
|
// sqrt (x) -> number
|
2024-11-15 02:30:42 +00:00
|
|
|
// DONE store! (x, y) -> value
|
2024-11-11 22:50:58 +00:00
|
|
|
// str_slice (x, y, z) -> string
|
|
|
|
// stringify (x) -> string
|
|
|
|
// sub (x, y) -> number
|
|
|
|
// tan (x) -> number
|
|
|
|
// to_list (x) -> list
|
|
|
|
// to_number (x) -> number
|
|
|
|
// trim (x) -> string
|
|
|
|
// triml (x) -> string
|
|
|
|
// trimr (x) -> string
|
|
|
|
// type (x) -> keyword
|
2024-11-15 02:30:42 +00:00
|
|
|
// DONE unbox (x) -> value
|
2024-11-11 22:50:58 +00:00
|
|
|
// upcase (x) -> string
|