2022-09-20 13:06:45 +00:00
|
|
|
pub mod io;
|
2022-09-20 02:59:27 +00:00
|
|
|
pub mod iter;
|
2022-09-20 13:06:45 +00:00
|
|
|
pub mod math;
|
2022-09-20 02:59:27 +00:00
|
|
|
|
2022-09-20 13:06:45 +00:00
|
|
|
use std::{rc::Rc, cmp::Ordering, time::{SystemTime, UNIX_EPOCH}, cell::RefCell};
|
2022-09-09 20:08:40 +00:00
|
|
|
|
2022-09-20 13:06:45 +00:00
|
|
|
use crate::{value::{Value, func::Func}, RuntimeError, env::Environment};
|
2022-09-11 05:01:53 +00:00
|
|
|
|
2022-09-20 02:59:27 +00:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! declare_fn {
|
2022-09-20 13:06:45 +00:00
|
|
|
($env:ident, $name:ident, $arg_count:literal) => {::paste::paste!{{
|
|
|
|
let s: ::std::rc::Rc<str> = ::std::rc::Rc::from(stringify!($name));
|
|
|
|
$env.declare(s.clone(), $crate::value::Value::Func($crate::value::func::Func::Builtin { func: [<fn_ $name>], arg_count: $arg_count, name: s }));
|
2022-09-20 02:59:27 +00:00
|
|
|
}}};
|
|
|
|
($env:ident, $name:literal, $rust_name:ident, $arg_count:literal) => {{
|
2022-09-20 13:06:45 +00:00
|
|
|
let s: ::std::rc::Rc<str> = ::std::rc::Rc::from($name);
|
|
|
|
$env.declare(s.clone(), $crate::value::Value::Func($crate::value::func::Func::Builtin { func: $rust_name, arg_count: $arg_count, name: s }));
|
2022-09-20 02:59:27 +00:00
|
|
|
}};
|
|
|
|
}
|
2022-09-09 20:08:40 +00:00
|
|
|
|
|
|
|
pub fn load(env: &mut Environment) {
|
2022-09-20 02:59:27 +00:00
|
|
|
declare_fn!(env, "type", fn_type, 1);
|
|
|
|
declare_fn!(env, type_eq, 1);
|
|
|
|
declare_fn!(env, str, 1);
|
|
|
|
declare_fn!(env, repr, 1);
|
|
|
|
declare_fn!(env, ord, 1);
|
|
|
|
declare_fn!(env, chr, 1);
|
|
|
|
declare_fn!(env, range, 2);
|
|
|
|
declare_fn!(env, has, 2);
|
|
|
|
declare_fn!(env, len, 1);
|
|
|
|
declare_fn!(env, time, 0);
|
|
|
|
declare_fn!(env, list, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_type(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
|
|
Ok(Value::Type(args[0].get_type()))
|
|
|
|
}
|
|
|
|
|
|
|
|
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-16 20:05:28 +00:00
|
|
|
fn fn_str(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
2022-09-09 20:08:40 +00:00
|
|
|
Ok(Value::String(args[0].to_string()))
|
|
|
|
}
|
|
|
|
|
2022-09-16 20:05:28 +00:00
|
|
|
fn fn_repr(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
2022-09-09 20:08:40 +00:00
|
|
|
Ok(Value::String(args[0].repr()))
|
|
|
|
}
|
|
|
|
|
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-20 13:06:45 +00:00
|
|
|
fn mk_range_inner(start: i64, end: i64, delta: i64) -> Func {
|
|
|
|
let counter = RefCell::new(start);
|
|
|
|
Func::BuiltinClosure {
|
|
|
|
arg_count: 0,
|
|
|
|
func: Rc::new(move |_| {
|
|
|
|
let c_value = *counter.borrow();
|
|
|
|
if delta >= 0 && c_value >= end
|
|
|
|
|| delta <= 0 && c_value <= end {
|
|
|
|
Ok(Value::Nil)
|
|
|
|
} else {
|
|
|
|
let res = *counter.borrow();
|
|
|
|
*counter.borrow_mut() += delta;
|
|
|
|
Ok(Value::Int(res))
|
|
|
|
}
|
|
|
|
})
|
2022-09-16 20:05:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_range(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
2022-09-20 13:06:45 +00:00
|
|
|
let (start, end, delta) = match (&args[0], &args[1]) {
|
|
|
|
(Value::Int(a), Value::Int(b)) => (a, b,
|
|
|
|
match a.cmp(&b) {
|
|
|
|
Ordering::Equal => 0,
|
|
|
|
Ordering::Less => 1,
|
|
|
|
Ordering::Greater => -1,
|
|
|
|
}
|
|
|
|
),
|
2022-09-16 20:05:28 +00:00
|
|
|
_ => return Err("Both arguments to range must be integers".into())
|
|
|
|
};
|
2022-09-20 13:06:45 +00:00
|
|
|
Ok(Value::Func(mk_range_inner(*start, *end, delta)))
|
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_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))
|
|
|
|
}
|