rudus/src/base.rs

143 lines
3.5 KiB
Rust
Raw Normal View History

2024-11-15 02:30:42 +00:00
// Solution to the #[derive(Clone)] problem: https://stackoverflow.com/questions/27883509/can-you-clone-a-closure
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)]
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>),
Ternary(
&'src str,
2024-11-15 02:30:42 +00:00
fn(&Value<'src>, &Value<'src>, &Value<'src>) -> LResult<'src>,
),
}
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(),
})
}
}
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-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))));
base
}
2024-11-15 02:30:42 +00:00
// DONE add (x, y) -> number
// 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
// 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
// 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
// upcase (x) -> string