2022-09-23 18:55:18 +00:00
|
|
|
use std::{time::{SystemTime, UNIX_EPOCH}, rc::Rc, cell::RefCell};
|
2022-09-09 20:08:40 +00:00
|
|
|
|
2022-09-25 23:25:13 +00:00
|
|
|
use complexpr::{value::{Value, func::Func, self}, RuntimeError, env::Environment};
|
|
|
|
use try_partialord::TrySort;
|
2022-09-11 05:01:53 +00:00
|
|
|
|
2022-09-23 19:09:22 +00:00
|
|
|
use crate::declare_fn;
|
2022-09-09 20:08:40 +00:00
|
|
|
|
|
|
|
pub fn load(env: &mut Environment) {
|
2022-09-25 23:25:13 +00:00
|
|
|
for ty in value::generate_builtin_types() {
|
|
|
|
env.declare(ty.name.clone(), Value::Type(ty));
|
|
|
|
}
|
2022-09-20 02:59:27 +00:00
|
|
|
declare_fn!(env, "type", fn_type, 1);
|
2022-09-25 23:25:13 +00:00
|
|
|
declare_fn!(env, type_id, 1);
|
|
|
|
declare_fn!(env, type_eq, 2);
|
2022-09-21 01:30:13 +00:00
|
|
|
declare_fn!(env, copy, 1);
|
2022-09-20 02:59:27 +00:00
|
|
|
declare_fn!(env, str, 1);
|
|
|
|
declare_fn!(env, repr, 1);
|
|
|
|
declare_fn!(env, ord, 1);
|
|
|
|
declare_fn!(env, chr, 1);
|
|
|
|
declare_fn!(env, has, 2);
|
|
|
|
declare_fn!(env, len, 1);
|
2022-09-23 18:55:18 +00:00
|
|
|
declare_fn!(env, args, 0);
|
2022-09-20 02:59:27 +00:00
|
|
|
declare_fn!(env, time, 0);
|
2022-09-25 23:25:13 +00:00
|
|
|
declare_fn!(env, assert, 1);
|
2022-09-21 01:30:13 +00:00
|
|
|
declare_fn!(env, list, 1);
|
|
|
|
declare_fn!(env, push, 2);
|
|
|
|
declare_fn!(env, pop, 1);
|
|
|
|
declare_fn!(env, append, 2);
|
|
|
|
declare_fn!(env, insert, 3);
|
|
|
|
declare_fn!(env, remove, 2);
|
2022-09-25 23:25:13 +00:00
|
|
|
declare_fn!(env, rev, 1);
|
|
|
|
declare_fn!(env, sort, 1);
|
|
|
|
declare_fn!(env, sort_by, 2);
|
|
|
|
declare_fn!(env, sort_by_key, 2);
|
2022-09-21 01:30:13 +00:00
|
|
|
|
2022-09-20 02:59:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_type(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
Ok(Value::Type(args[0].get_type()))
|
|
|
|
}
|
|
|
|
|
2022-09-25 23:25:13 +00:00
|
|
|
fn fn_type_id(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
if let Value::Type(ty) = &args[0] {
|
|
|
|
Ok(Value::Int(ty.id as i64))
|
|
|
|
} else {
|
|
|
|
Err("Argument to id must be a type".into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-20 02:59:27 +00:00
|
|
|
fn fn_type_eq(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
Ok(Value::Bool(if args[0].get_type() != args[1].get_type() {
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
args[0] == args[1]
|
|
|
|
}))
|
2022-09-09 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2022-09-21 01:30:13 +00:00
|
|
|
fn fn_copy(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
Ok(match &args[0] {
|
|
|
|
Value::List(l) => Value::from(l.borrow().clone()),
|
|
|
|
Value::Map(m) => Value::from(m.borrow().clone()),
|
|
|
|
// Value::Func(f) => Value::Func(f.make_copy()) // TODO copy functions
|
2022-09-22 12:58:59 +00:00
|
|
|
Value::Struct(_) => todo!(),
|
2022-09-21 01:30:13 +00:00
|
|
|
a => a.clone(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-09-16 20:05:28 +00:00
|
|
|
fn fn_str(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
2022-09-21 23:07:31 +00:00
|
|
|
Ok(Value::from(args[0].to_string()))
|
2022-09-09 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2022-09-16 20:05:28 +00:00
|
|
|
fn fn_repr(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
2022-09-21 23:07:31 +00:00
|
|
|
Ok(Value::from(args[0].repr()))
|
2022-09-09 20:08:40 +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 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-23 18:55:18 +00:00
|
|
|
fn fn_args(_: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
let mut args = std::env::args();
|
|
|
|
args.next();
|
|
|
|
let args = RefCell::new(args);
|
|
|
|
Ok(Value::Func(Func::BuiltinClosure {
|
|
|
|
arg_count: 0,
|
|
|
|
func: Rc::new(move |_| {
|
|
|
|
match args.borrow_mut().next() {
|
|
|
|
Some(s) => Ok(Value::from(s)),
|
|
|
|
None => Ok(Value::Nil)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2022-09-25 23:25:13 +00:00
|
|
|
fn fn_assert(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
if args[0].truthy() {
|
|
|
|
Ok(Value::Nil)
|
|
|
|
} else {
|
|
|
|
Err("Assertion failed".into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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))
|
|
|
|
}
|
2022-09-21 01:30:13 +00:00
|
|
|
|
|
|
|
fn fn_push(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
if let Value::List(l) = &args[0] {
|
|
|
|
l.as_ref().borrow_mut().push(args[1].clone());
|
|
|
|
Ok(Value::Nil)
|
|
|
|
} else{
|
|
|
|
Err("First argument to push must be a list".into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_pop(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
if let Value::List(l) = &args[0] {
|
2022-09-23 18:55:18 +00:00
|
|
|
l.as_ref().borrow_mut().pop().ok_or_else(|| "Pop on empty list".into())
|
2022-09-21 01:30:13 +00:00
|
|
|
} else{
|
|
|
|
Err("First argument to pop must be a list".into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_append(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
match (&args[0], &args[1]) {
|
|
|
|
(Value::List(a), Value::List(b)) => {
|
|
|
|
let mut newvals = b.borrow().clone();
|
|
|
|
a.borrow_mut().append(&mut newvals);
|
|
|
|
Ok(Value::Nil)
|
|
|
|
},
|
|
|
|
_ => Err("Both arguments to append must be lists".into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_insert(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
match (&args[0], &args[1]) {
|
|
|
|
(Value::List(a), Value::Int(i)) => {
|
|
|
|
if *i < 0 {
|
|
|
|
return Err(format!("List index {} cannot be negative", i).into())
|
|
|
|
}
|
|
|
|
if *i > a.borrow().len() as i64 {
|
|
|
|
return Err(format!("List index {} not valid for list of length {}", i, a.borrow().len()).into())
|
|
|
|
}
|
|
|
|
a.borrow_mut().insert(*i as usize, args[2].clone());
|
|
|
|
Ok(Value::Nil)
|
|
|
|
},
|
|
|
|
(Value::Map(a), b) => {
|
|
|
|
Ok(a.borrow_mut().insert(b.clone(), args[3].clone()).unwrap_or(Value::Nil))
|
|
|
|
},
|
|
|
|
(Value::List(_), _) => Err("Second argument to insert must be an integer when the first is a list".into()),
|
|
|
|
_ => Err("First argument to insert must be a list or map".into()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_remove(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
match (&args[0], &args[1]) {
|
|
|
|
(Value::List(a), Value::Int(i)) => {
|
|
|
|
if *i < 0 {
|
|
|
|
return Err(format!("List index {} cannot be negative", i).into())
|
|
|
|
}
|
|
|
|
if *i >= a.borrow().len() as i64 {
|
|
|
|
return Err(format!("List index {} not valid for list of length {}", i, a.borrow().len()).into())
|
|
|
|
}
|
|
|
|
Ok(a.borrow_mut().remove(*i as usize))
|
|
|
|
},
|
|
|
|
(Value::Map(a), b) => {
|
|
|
|
Ok(a.borrow_mut().remove(b).unwrap_or(Value::Nil))
|
|
|
|
},
|
|
|
|
(Value::List(_), _) => Err("Second argument to remove must be an integer when the first is a list".into()),
|
|
|
|
_ => Err("First argument to remove must be a list or map".into()),
|
|
|
|
}
|
|
|
|
}
|
2022-09-25 23:25:13 +00:00
|
|
|
|
|
|
|
fn fn_rev(mut args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
match &args[0] {
|
|
|
|
Value::List(l) => {
|
|
|
|
l.borrow_mut().reverse();
|
|
|
|
Ok(args.swap_remove(0))
|
|
|
|
},
|
|
|
|
Value::String(s) => {
|
|
|
|
let s: String = s.chars().rev().collect();
|
|
|
|
Ok(Value::from(s))
|
|
|
|
},
|
|
|
|
_ => Err(format!("Expected list or string, got {}", args[0]).into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_sort(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
match &args[0] {
|
|
|
|
Value::List(l) => match l.borrow_mut().try_sort() {
|
|
|
|
Ok(_) => Ok(args[0].clone()),
|
|
|
|
Err(_) => Err("List contained incomparable items".into())
|
|
|
|
},
|
|
|
|
_ => Err(format!("Expected list, got {}", args[0]).into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_sort_by(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
let func = match &args[1] {
|
|
|
|
Value::Func(f) => f,
|
|
|
|
x => return Err(format!("Expected function as second argument, got {}", x).into())
|
|
|
|
};
|
|
|
|
let ord = move |a: &Value, b: &Value| {
|
|
|
|
match func.call(vec![a.clone(), b.clone()]) {
|
|
|
|
Ok(Value::Int(n)) => Some(n < 0),
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
};
|
|
|
|
match &args[0] {
|
|
|
|
Value::List(l) => match l.borrow_mut().try_sort_by(ord) {
|
|
|
|
Ok(_) => Ok(args[0].clone()),
|
|
|
|
Err(_) => Err("Error occured in sort comparison function".into())
|
|
|
|
},
|
|
|
|
_ => Err(format!("Expected list as first argument, got {}", args[0]).into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_sort_by_key(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
let func = match &args[1] {
|
|
|
|
Value::Func(f) => f,
|
|
|
|
x => return Err(format!("Expected function as second argument, got {}", x).into())
|
|
|
|
};
|
|
|
|
let ord = move |a: &Value| {
|
|
|
|
func.call(vec![a.clone()]).ok()
|
|
|
|
};
|
|
|
|
match &args[0] {
|
|
|
|
Value::List(l) => match l.borrow_mut().try_sort_by_key(ord) {
|
|
|
|
Ok(_) => Ok(args[0].clone()),
|
|
|
|
Err(_) => Err("Error occured in sort key function".into())
|
|
|
|
},
|
|
|
|
_ => Err(format!("Expected list as first argument, got {}", args[0]).into())
|
|
|
|
}
|
|
|
|
}
|