complexpr/complexpr/src/stdlib/mod.rs

266 lines
9.4 KiB
Rust
Raw Normal View History

2022-09-16 20:05:28 +00:00
use std::{rc::Rc, io::Write, cmp::Ordering, time::{SystemTime, UNIX_EPOCH}, cell::RefCell};
2022-09-11 05:01:53 +00:00
use num_traits::ToPrimitive;
use crate::{value::{Value, Func, CIterator}, RuntimeError, env::Environment};
pub fn load(env: &mut Environment) {
let mut name: Rc<str>;
name = Rc::from("str");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_str, arg_count: 1, name }));
name = Rc::from("repr");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_repr, arg_count: 1, name }));
name = Rc::from("print");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_print, arg_count: 1, name }));
name = Rc::from("println");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_println, arg_count: 1, name }));
name = Rc::from("input");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_input, arg_count: 0, name }));
2022-09-10 21:19:23 +00:00
name = Rc::from("ord");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_ord, arg_count: 1, name }));
2022-09-10 21:19:23 +00:00
name = Rc::from("chr");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_chr, arg_count: 1, name }));
2022-09-10 21:19:23 +00:00
name = Rc::from("range");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_range, arg_count: 2, name }));
2022-09-15 04:01:57 +00:00
name = Rc::from("has");
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_has, arg_count: 2, name }));
2022-09-10 21:19:23 +00:00
name = Rc::from("len");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_len, arg_count: 1, name }));
2022-09-11 05:01:53 +00:00
name = Rc::from("re");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_re, arg_count: 1, name }));
2022-09-11 05:01:53 +00:00
name = Rc::from("im");
2022-09-14 15:16:53 +00:00
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_im, arg_count: 1, name }));
2022-09-15 04:01:57 +00:00
name = Rc::from("time");
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_time, arg_count: 0, name }));
2022-09-16 20:05:28 +00:00
name = Rc::from("list");
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_list, arg_count: 1, name }));
name = Rc::from("take");
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_take, arg_count: 2, name }));
2022-09-17 23:23:54 +00:00
name = Rc::from("skip");
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_skip, arg_count: 2, name }));
name = Rc::from("forall");
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_forall, arg_count: 2, name }));
name = Rc::from("exists");
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_exists, arg_count: 2, name }));
name = Rc::from("min");
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_min, arg_count: 2, name }));
name = Rc::from("max");
env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_max, arg_count: 2, name }));
}
2022-09-16 20:05:28 +00:00
fn fn_str(args: Vec<Value>) -> Result<Value, RuntimeError> {
Ok(Value::String(args[0].to_string()))
}
2022-09-16 20:05:28 +00:00
fn fn_repr(args: Vec<Value>) -> Result<Value, RuntimeError> {
Ok(Value::String(args[0].repr()))
}
2022-09-16 20:05:28 +00:00
fn fn_print(args: Vec<Value>) -> Result<Value, RuntimeError> {
print!("{}", args[0].to_string());
std::io::stdout().flush().map_err(|e| e.to_string())?;
Ok(Value::Nil)
}
2022-09-16 20:05:28 +00:00
fn fn_println(args: Vec<Value>) -> Result<Value, RuntimeError> {
println!("{}", args[0].to_string());
Ok(Value::Nil)
}
2022-09-16 20:05:28 +00:00
fn fn_input(_: Vec<Value>) -> Result<Value, RuntimeError> {
let mut buffer = String::new();
let stdin = std::io::stdin();
stdin.read_line(&mut buffer).map_err(|e| e.to_string())?;
2022-09-11 17:02:18 +00:00
if buffer.ends_with('\n') {
2022-09-10 21:19:23 +00:00
buffer.pop();
}
Ok(Value::from(buffer))
2022-09-10 21:19:23 +00:00
}
2022-09-16 20:05:28 +00:00
fn fn_ord(args: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-10 21:19:23 +00:00
if let Value::Char(c) = args[0] {
Ok(Value::from(c as u32))
} else {
Err("Argument to ord must be a char".into())
}
}
2022-09-16 20:05:28 +00:00
fn fn_chr(args: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-10 21:19:23 +00:00
if let Value::Int(i) = args[0] {
if i >= 0 && i < (u32::MAX as i64) {
if let Some(c) = char::from_u32(i as u32) {
return Ok(Value::from(c))
}
}
Err("Out of range".into())
} else {
Err("Argument to chr must be an integer".into())
}
}
2022-09-16 20:05:28 +00:00
fn range_inner(_: Vec<Value>, data: Rc<RefCell<Vec<Value>>>, _: Rc<RefCell<Vec<CIterator>>>) -> Result<Value, RuntimeError> {
const ZERO: Value = Value::Int(0);
let mut d = data.borrow_mut();
2022-09-17 15:17:22 +00:00
if d[2] >= ZERO && d[0] >= d[1]
|| d[2] <= ZERO && d[0] <= d[1] {
2022-09-16 20:05:28 +00:00
Ok(Value::Nil)
} else {
let res = d[0].clone();
d[0] = (&d[0] + &d[2])?;
Ok(res)
}
}
fn fn_range(args: Vec<Value>) -> Result<Value, RuntimeError> {
let start = &args[0];
let end = &args[1];
let delta = match (start, end) {
2022-09-11 17:02:18 +00:00
(Value::Int(a), Value::Int(b)) => match a.cmp(b) {
2022-09-16 20:05:28 +00:00
Ordering::Equal => 0,
Ordering::Less => 1,
Ordering::Greater => -1,
2022-09-10 21:19:23 +00:00
},
2022-09-16 20:05:28 +00:00
_ => return Err("Both arguments to range must be integers".into())
};
2022-09-17 15:17:22 +00:00
Ok(Value::Func(Func::BuiltinClosure {
2022-09-16 20:05:28 +00:00
arg_count: 0,
data: Rc::new(RefCell::new(vec![start.clone(), end.clone(), Value::Int(delta)])),
iter_data: Rc::new(RefCell::new(vec![])),
func: range_inner
}))
2022-09-10 21:19:23 +00:00
}
2022-09-16 20:05:28 +00:00
fn fn_len(args: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-18 06:05:01 +00:00
Ok(Value::Int(args[0].len().map_err(RuntimeError::new_no_pos)? as i64))
2022-09-11 05:01:53 +00:00
}
2022-09-16 20:05:28 +00:00
fn fn_has(args: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-15 04:01:57 +00:00
match &args[0] {
Value::Map(m) => Ok(Value::from(m.borrow().contains_key(&args[1]))),
2022-09-16 20:05:28 +00:00
v => Err(format!("Argument to has must be a map, got {:?} ", v).into())
2022-09-15 04:01:57 +00:00
}
}
2022-09-16 20:05:28 +00:00
fn fn_re(args: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-11 05:01:53 +00:00
match &args[0] {
Value::Int(x) => Ok(Value::Float(*x as f64)),
Value::Float(x) => Ok(Value::Float(*x)),
Value::Rational(x) => Ok(Value::Float(x.to_f64().unwrap())),
Value::Complex(x) => Ok(Value::Float(x.re)),
2022-09-16 20:05:28 +00:00
x => Err(format!("Cannot get real part of {:?}", x).into())
2022-09-11 05:01:53 +00:00
}
}
2022-09-16 20:05:28 +00:00
fn fn_im(args: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-11 05:01:53 +00:00
match &args[0] {
Value::Int(_) | Value::Float(_) | Value::Rational(_)
=> Ok(Value::Float(0.0)),
Value::Complex(x) => Ok(Value::Float(x.im)),
2022-09-16 20:05:28 +00:00
x => Err(format!("Cannot get real part of {:?}", x).into())
2022-09-11 05:01:53 +00:00
}
2022-09-11 17:02:18 +00:00
}
2022-09-15 04:01:57 +00:00
2022-09-16 20:05:28 +00:00
fn fn_time(_: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-15 04:01:57 +00:00
let time = SystemTime::now().duration_since(UNIX_EPOCH).map_err(|e| e.to_string())?;
Ok(Value::from(time.as_secs_f64()))
}
2022-09-16 20:05:28 +00:00
fn fn_list(args: Vec<Value>) -> Result<Value, RuntimeError> {
let a = args[0].iter()?;
let mut res = Vec::new();
for v in a { res.push(v?); }
Ok(Value::from(res))
}
fn take_inner(_: Vec<Value>, data: Rc<RefCell<Vec<Value>>>, iter_data: Rc<RefCell<Vec<CIterator>>>) -> Result<Value, RuntimeError> {
// 0: current index
// 1: target index
let mut d = data.borrow_mut();
if d[0] >= d[1] {
Ok(Value::Nil)
} else {
d[0] = (&d[0] + &Value::Int(1))?;
match iter_data.borrow_mut()[0].next() {
None => Ok(Value::Nil),
Some(x) => x
}
}
}
fn fn_take(args: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-17 15:17:22 +00:00
Ok(Value::Func(Func::BuiltinClosure {
arg_count: 0,
data: Rc::new(RefCell::new(vec![Value::Int(0), args[0].clone()])),
iter_data: Rc::new(RefCell::new(vec![args[1].iter()?])),
func: take_inner
}))
}
2022-09-17 23:23:54 +00:00
fn skip_inner(_: Vec<Value>, data: Rc<RefCell<Vec<Value>>>, iter_data: Rc<RefCell<Vec<CIterator>>>) -> Result<Value, RuntimeError> {
let mut d = if let Value::Int(d) = data.borrow()[0] { d } else {
unreachable!() // checked by fn_skip()
};
while d > 0 {
iter_data.borrow_mut()[0].next();
d -= 1;
}
data.borrow_mut()[0] = Value::Int(d);
match iter_data.borrow_mut()[0].next() {
None => Ok(Value::Nil),
Some(x) => x
}
}
fn fn_skip(args: Vec<Value>) -> Result<Value, RuntimeError> {
let n = match args[0] {
2022-09-18 06:05:01 +00:00
Value::Int(n) if n <= 0 => return Err(RuntimeError::new_no_pos("First argument to skip must be nonnegative")),
2022-09-17 23:23:54 +00:00
Value::Int(n) => n,
2022-09-18 06:05:01 +00:00
_ => return Err(RuntimeError::new_no_pos("First argument to skip must be an integer"))
2022-09-17 23:23:54 +00:00
};
let it = args[1].iter()?;
Ok(Value::Func(Func::BuiltinClosure {
arg_count: 0,
data: Rc::new(RefCell::new(vec![Value::Int(n)])),
iter_data: Rc::new(RefCell::new(vec![it])),
func: skip_inner
}))
}
fn fn_forall(args: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-18 06:05:01 +00:00
let func = &args[0].as_func()?;
2022-09-17 23:23:54 +00:00
for item in args[1].iter()? {
let item = item?;
if !func.call(vec![item])?.truthy() {
return Ok(Value::Bool(false))
}
}
Ok(Value::Bool(true))
}
fn fn_exists(args: Vec<Value>) -> Result<Value, RuntimeError> {
2022-09-18 06:05:01 +00:00
let func = &args[0].as_func()?;
2022-09-17 23:23:54 +00:00
for item in args[1].iter()? {
let item = item?;
if func.call(vec![item])?.truthy() {
return Ok(Value::Bool(true))
}
}
Ok(Value::Bool(false))
}
fn fn_min(args: Vec<Value>) -> Result<Value, RuntimeError> {
match args[0].partial_cmp(&args[1]) {
None => Err("Arguments to min must be comparable".into()),
Some(Ordering::Greater) => Ok(args[1].clone()),
_ => Ok(args[0].clone())
}
}
fn fn_max(args: Vec<Value>) -> Result<Value, RuntimeError> {
match args[0].partial_cmp(&args[1]) {
None => Err("Arguments to max must be comparable".into()),
Some(Ordering::Less) => Ok(args[1].clone()),
_ => Ok(args[0].clone())
}
}