use std::cell::RefCell;
use std::io::{self, Read};
use std::rc::Rc;
use radix_fmt::radix;
use rand::Rng;
use crate::utils::num::{to_u32, Num};
use crate::utils::{self, env::Environment, tokens::Node, types::*};
use crate::{FLOAT_PRECISION, MATCHES};
lazy_static! {
static ref DEFAULT: Node = Node::String(String::new());
static ref USCORE: String = String::from("_");
}
fn grab_block_from_fold(fold: &Node, mut block: Option<Node>) -> (Option<Node>, Node) {
match fold {
Node::Op(n, l, r) => {
let mut r = r.clone();
let end = r.len() - 1;
let inter = grab_block_from_fold(&r[end], block);
block = inter.0;
r[end] = inter.1;
(block, Node::Op(n.clone(), l.clone(), r))
}
Node::Block(_, _) => (Some(fold.clone()), Node::Variable("_".to_string())),
_ => (block, fold.clone()),
}
}
pub fn parse_op(env: Env, op: &str, left: &[Node], right: &[Node]) -> Dynamic {
match op {
":=" => {
let name = format!("{}", left[0]);
let right = right[0].clone();
env.borrow_mut().define([name.trim()], move |env, arg| {
let child = Rc::new(env.as_ref().clone());
child.borrow_mut().define_var("_", arg);
parse_node(Rc::clone(&child), &right)
});
Dynamic::from(false)
}
"." => {
let v = format!("{}", right[0]);
let arg = parse_node(Rc::clone(&env), &left[0]);
env.borrow().attempt_call(v.trim(), &env, arg)
}
"^" => {
let left = parse_node(Rc::clone(&env), &left[0]);
if left.is_string() {
left.mutate_string(|s| s.repeat(to_u32(&env, &right[0]) as usize))
} else {
let mut left = left.literal_num();
let o = left.clone();
let right = to_u32(&env, &right[0]);
for _ in 1..right {
left *= o.clone();
}
Dynamic::from(left)
}
}
"<>" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let right = parse_node(Rc::clone(&env), &right[0]);
Dynamic::from([left, right])
}
"*" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let right = parse_node(Rc::clone(&env), &right[0]).literal_num();
left.mutate_num(|n| n * right)
}
"/" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let right = parse_node(Rc::clone(&env), &right[0]).literal_num();
left.mutate_num(|n| n / right)
}
"%" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let right = parse_node(Rc::clone(&env), &right[0]).literal_num();
left.mutate_num(|n| n % right)
}
":|" => {
let mut left = parse_node(Rc::clone(&env), &left[0]).literal_array();
left.set_env(Rc::clone(&env));
Dynamic::from(
left.map(|dy| format!("{}", dy))
.collect::<Vec<String>>()
.join(&parse_node(Rc::clone(&env), &right[0]).literal_string()),
)
}
":!" => {
let left = parse_node(Rc::clone(&env), &left[0]).literal_string();
let right = parse_node(Rc::clone(&env), &right[0]).literal_string();
Dynamic::from(
left.split(&right)
.map(str::to_owned)
.collect::<Vec<String>>(),
)
}
"+" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let right = parse_node(Rc::clone(&env), &right[0]).literal_num();
left.mutate_num(|n| n + right)
}
"-" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let right = parse_node(Rc::clone(&env), &right[0]).literal_num();
left.mutate_num(|n| n - right)
}
".$" => {
let mut left = parse_node(Rc::clone(&env), &left[0]).literal_array();
let i = to_u32(&env, &right[0]) as usize;
left.set_env(Rc::clone(&env));
let seq = left.collect::<Vec<Dynamic>>();
let (l, r) = seq.split_at(i);
Dynamic::from([l, r])
}
".~" => {
let end = to_u32(&env, &left[0]) as usize;
Dynamic::from(
(1..=end)
.rev()
.map(|n| Dynamic::from(Num::with_val(*FLOAT_PRECISION, n)))
.collect::<Vec<_>>(),
)
}
"=>" => {
let left = to_u32(&env, &left[0]) as usize;
let right = to_u32(&env, &right[0]) as usize;
Dynamic::new(
Val::Array(Box::new(Sequence::from_iter(
(left..=right).map(|n| Dynamic::from(Num::with_val(*FLOAT_PRECISION, n))),
Node::Block(vec![], None),
Some(right - left + 1),
))),
4,
)
}
"->" => {
let left = to_u32(&env, &left[0]) as usize;
let right = to_u32(&env, &right[0]) as usize;
Dynamic::new(
Val::Array(Box::new(Sequence::from_iter(
(left..right).map(|n| Dynamic::from(Num::with_val(*FLOAT_PRECISION, n))),
Node::Block(vec![], None),
Some(right - left),
))),
4,
)
}
"~" => {
let right = to_u32(&env, &right[0]) as usize;
Dynamic::new(
Val::Array(Box::new(Sequence::from_iter(
(1..=right).map(|n| Dynamic::from(Num::with_val(*FLOAT_PRECISION, n))),
Node::Block(vec![], None),
Some(right),
))),
4,
)
}
"#" => Dynamic::from(Num::with_val(
*FLOAT_PRECISION,
parse_node(Rc::clone(&env), &left[0])
.literal_array()
.len()
.expect("Cannot take length of infinite sequence"),
)),
";" => {
let ops = if env.borrow().vals.get(&right[0].to_string()).is_none() {
right[0].to_string()
} else {
parse_node(Rc::clone(&env), &right[0]).to_string()
};
let chars = ops.trim().trim_matches('"').chars();
let mut cur = parse_node(Rc::clone(&env), &left[0]);
cur = if cur.clone().to_string().matches('\n').count() > 0 {
let temp = cur
.to_string()
.trim()
.split('\n')
.map(str::to_owned)
.collect::<Vec<_>>();
if chars
.clone()
.next()
.map_or(true, |c| c != 'H' && c != 'O' && c != 'B')
{
Dynamic::from(temp)
} else {
Dynamic::from(temp.join(""))
}
} else {
cur.into_string()
};
let mut num = String::new();
for char in chars.chain("\u{2192}".chars()) {
if !num.is_empty() && !char.is_numeric() {
cur = Dynamic::from(utils::nbase_padded(cur, |cur| {
radix(
cur.parse::<i128>().expect("Invalid base10 number"),
num.parse().unwrap(),
)
.to_string()
}));
num.clear();
}
cur = match char {
'b' => Dynamic::from(utils::nbase_padded(cur, |cur| {
radix(cur.parse::<i128>().expect("Invalid base10 number"), 2).to_string()
})),
'o' => Dynamic::from(utils::nbase_padded(cur, |cur| {
radix(cur.parse::<i128>().expect("Invalid base10 number"), 8).to_string()
})),
'h' => Dynamic::from(utils::nbase_padded(cur, |cur| {
radix(cur.parse::<i128>().expect("Invalid base10 number"), 16).to_string()
})),
'B' => Dynamic::from(
i128::from_str_radix(&cur.literal_string(), 2)
.expect("Invalid base2 number")
.to_string(),
),
'O' => Dynamic::from(
i128::from_str_radix(&cur.literal_string(), 8)
.expect("Invalid base8 number")
.to_string(),
),
'H' => Dynamic::from(
i128::from_str_radix(&cur.literal_string(), 16)
.expect("Invalid base16 number")
.to_string(),
),
'0'..='9' => {
num.push(char);
cur
}
'\u{2192}' => cur,
_ => panic!("Unrecognized base conversion char {}", char),
}
}
Dynamic::from(cur)
}
":_" => {
let orig = parse_node(Rc::clone(&env), &left[0]).literal_array();
if !orig.is_finite() {
panic!("Cannot flatten infinite sequence");
}
let mut new = Vec::with_capacity(
orig.len().unwrap()
* orig
.clone()
.next()
.unwrap()
.literal_array()
.len()
.expect("Cannot flatten sequence of inifnite sequences"),
);
for dy in orig {
if dy.is_array() {
for n in parse_node(Rc::clone(&env), &dy.into_node()).literal_array() {
new.push(n);
}
} else {
new.push(dy.clone());
}
}
Dynamic::from(new)
}
":%" => {
let mut parent = parse_node(Rc::clone(&env), &left[0]).literal_array();
parent.set_env(Rc::clone(&env));
let mut pre = Vec::new();
for item in parent {
pre.push(item.literal_array());
}
Dynamic::from(
vec![
0;
pre.iter()
.cloned()
.max_by(|l, r| l.clone().count().cmp(&r.clone().count()))
.unwrap_or_else(|| Sequence::from_vec_dyn(
&[],
Node::String(String::new()),
Some(0)
))
.count()
]
.iter()
.enumerate()
.map(|(i, _)| {
pre.iter()
.filter_map(|array| array.clone().nth(i))
.collect()
})
.collect::<Vec<Vec<Dynamic>>>(),
)
}
".|" => {
let left = parse_node(Rc::clone(&env), &left[0]);
left.mutate_num(Num::abs)
}
".<" => Dynamic::from(
parse_node(Rc::clone(&env), &left[0])
.literal_array()
.rev()
.collect::<Vec<Dynamic>>(),
),
".." | ".=" => {
let mut left = parse_node(Rc::clone(&env), &left[0]).literal_array();
left.set_env(Rc::clone(&env));
let left: Vec<u32> = left
.map(|n| {
n.literal_num()
.to_u32_saturating_round(rug::float::Round::Down)
.unwrap()
})
.collect();
#[allow(clippy::range_plus_one)]
let range = if op == ".." {
left[0]..left[1]
} else {
left[0]..left[1] + 1
};
Dynamic::new(
Val::Array(Box::new(Sequence::from_iter(
range
.clone()
.map(|n| Dynamic::from(Num::with_val(*FLOAT_PRECISION, n))),
Node::Block(vec![], None),
Some(range.count()),
))),
4,
)
}
":n" => Dynamic::from(
parse_node(Rc::clone(&env), &left[0])
.literal_string()
.split('\n')
.map(str::to_owned)
.collect::<Vec<_>>(),
),
":s" => Dynamic::from(
parse_node(Rc::clone(&env), &left[0])
.literal_string()
.split(' ')
.map(str::to_owned)
.collect::<Vec<_>>(),
),
":}" => {
let mut seq = parse_node(Rc::clone(&env), &left[0]).literal_array();
seq.set_env(Rc::clone(&env));
seq.last()
.expect("Cannot take last element of infinite sequence")
}
":{" => {
let mut seq = parse_node(Rc::clone(&env), &left[0]).literal_array();
seq.set_env(Rc::clone(&env));
seq.next().unwrap()
}
".{" => {
let mut seq = parse_node(Rc::clone(&env), &left[0]).literal_array();
seq.set_env(Rc::clone(&env));
Dynamic::from(seq.collect::<Vec<Dynamic>>()[1..].to_owned())
}
".}" => {
let mut seq = parse_node(Rc::clone(&env), &left[0]).literal_array();
seq.set_env(Rc::clone(&env));
Dynamic::from(seq.clone().collect::<Vec<Dynamic>>()[..seq.count() - 1].to_owned())
}
":@" => {
let mut arr = parse_node(Rc::clone(&env), &left[0]).literal_array();
arr.set_env(Rc::clone(&env));
let arr = arr.collect::<Vec<Dynamic>>();
Dynamic::from(arr.iter().fold(Vec::new(), |mut acc, val| {
if acc.is_empty() {
vec![vec![val.clone()]]
} else {
let filter = acc.iter().filter(|e| e[0].clone() == val.clone());
if filter.clone().count() > 0 {
let filter = filter.cloned().collect::<Vec<_>>();
let pos = acc.iter().cloned().position(|e| e == filter[0]).unwrap();
acc[pos].push(val.clone());
acc
} else {
acc.push(vec![val.clone()]);
acc
}
}
}))
}
"^*" => {
let left = parse_node(Rc::clone(&env), &left[0]).literal_num();
Dynamic::from(left.sqrt().is_integer())
}
"&." => {
let mut loop_arg = parse_node(Rc::clone(&env), &right[1]);
let count = parse_node(Rc::clone(&env), &right[2])
.literal_num()
.to_u32_saturating_round(rug::float::Round::Down)
.unwrap();
let child_env = Rc::new(env.as_ref().clone());
for _ in 0..count {
if let Node::Block(_, name) = &right[0] {
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), loop_arg)
} else {
child_env.borrow_mut().define_var("_", loop_arg);
}
loop_arg = parse_node_uniq(Rc::clone(&child_env), &right[0]);
}
loop_arg
}
":i" => {
let mut seq = parse_node(Rc::clone(&env), &left[0]).literal_array();
let val = parse_node(Rc::clone(&env), &right[0]);
seq.set_env(Rc::clone(&env));
Dynamic::from(Num::with_val(
*FLOAT_PRECISION,
seq.position(|e| e == val).map_or(-1, |v| v as i128),
))
}
"!" => Dynamic::from(!parse_node(Rc::clone(&env), &right[0]).literal_bool()),
"$" | "$:" => {
let mut seq = parse_node(Rc::clone(&env), &right[1]).literal_array();
seq.set_env(Rc::clone(&env));
let child_env = Rc::new(env.as_ref().clone());
let filter = seq
.filter(|v| {
if let Node::Block(_, name) = &right[0] {
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), v.clone())
} else {
child_env.borrow_mut().define_var("_", v.clone());
}
parse_node_uniq(Rc::clone(&child_env), &right[0]).literal_bool()
})
.collect::<Vec<_>>();
if op == "$" {
Dynamic::from(filter)
} else {
Dynamic::from(!filter.is_empty())
}
}
"\\" | ":\\" => {
let seq = Box::new(
parse_node(Rc::clone(&env), &right[0])
.literal_array()
.set_env_self(Rc::clone(&env)),
);
let (block, rest) = grab_block_from_fold(&left[0], None);
let res = Box::new(if let Some(Node::Block(_, name)) = block.clone() {
let child_env = Rc::new(env.as_ref().clone());
let block = block.unwrap();
seq.map(|val| {
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), val);
parse_node_uniq(Rc::clone(&child_env), &block)
})
.collect::<Vec<_>>()
} else {
seq.collect::<Vec<_>>()
});
if rest == Node::Variable("_".to_string()) {
Dynamic::from(res.as_ref().clone())
} else if op == "\\" {
let constructed = format!("{}", rest);
let seperator = constructed.trim().trim_matches('_');
let program = res
.iter()
.cloned()
.map(|n| format!("{}", n.into_node()))
.collect::<Vec<_>>()
.join(seperator);
let val = crate::build_ast(&program);
parse_node(Rc::clone(&env), &val[0])
} else {
let constructed = format!("{}", rest);
let seperator = constructed.trim().trim_matches('_');
let mut v = res.as_ref().clone();
for i in 1..v.len() {
v[i] = parse_node(
Rc::clone(&env),
&crate::build_ast(&format!(
"{} {} {}",
v[i - 1].clone().into_node(),
seperator,
v[i].clone().into_node()
))[0],
)
}
Dynamic::from(v)
}
}
":v" => {
let right = parse_node(Rc::clone(&env), &right[0]);
if right.is_string() {
right.mutate_string(|s| s.to_ascii_lowercase())
} else {
right.mutate_num(Num::floor)
}
}
":^" => {
let right = parse_node(Rc::clone(&env), &right[0]);
if right.is_string() {
right.mutate_string(|s| s.to_ascii_uppercase())
} else {
right.mutate_num(Num::ceil)
}
}
"++" => {
if let Node::Variable(name) = &right[0] {
let mut val = env.borrow().get_var(name);
val = val.mutate_num(|n| n + 1);
env.borrow_mut().define_var(name, val.clone());
val
} else {
let right = parse_node(Rc::clone(&env), &right[0]);
right.mutate_num(|n| n + 1)
}
}
"--" => {
if let Node::Variable(name) = &right[0] {
let mut val = env.borrow().get_var(name);
val = val.mutate_num(|n| n - 1);
env.borrow_mut().define_var(name, val.clone());
val
} else {
let right = parse_node(Rc::clone(&env), &right[0]);
right.mutate_num(|n| n - 1)
}
}
":*" => parse_node(Rc::clone(&env), &right[0]).mutate_num(Num::square),
":/" => parse_node(Rc::clone(&env), &right[0]).mutate_num(Num::sqrt),
":+" => parse_node(Rc::clone(&env), &right[0]).mutate_num(|n| n * 2),
":-" => parse_node(Rc::clone(&env), &right[0]).mutate_num(|n| n / 2),
":>" => {
let mut seq = parse_node(Rc::clone(&env), &right[0]).literal_array();
seq.set_env(Rc::clone(&env));
let mut seq = seq.collect::<Vec<_>>();
seq.sort_by(|a, b| b.partial_cmp(a).unwrap());
Dynamic::from(seq)
}
":<" => {
let mut seq = parse_node(Rc::clone(&env), &right[0]).literal_array();
seq.set_env(Rc::clone(&env));
let mut seq = seq.collect::<Vec<_>>();
seq.sort_by(|a, b| a.partial_cmp(b).unwrap());
Dynamic::from(seq)
}
"|:" => {
let string = parse_node(Rc::clone(&env), &right[0]).literal_string();
let mid = string.len() / 2;
Dynamic::from([
string[..mid].to_owned(),
string[mid..].to_owned().chars().rev().collect(),
])
}
"?." => {
let mut seq = parse_node(Rc::clone(&env), &right[0]).literal_array();
seq.set_env(Rc::clone(&env));
let seq = seq.collect::<Vec<_>>();
let mut rng = rand::thread_rng();
seq[(rng.gen::<f64>() * seq.len() as f64).floor() as usize].clone()
}
"#." => {
let num = to_u32(&env, &right[0]) as usize;
let sieve = primal::Primes::all()
.take_while(|n| *n <= num)
.map(|n| Num::with_val(*FLOAT_PRECISION, n))
.collect::<Vec<_>>();
Dynamic::new(
Val::Array(Box::new(Sequence::from_vec(
&sieve,
Node::Block(vec![], None),
Some(sieve.len()),
))),
4,
)
}
"*." => {
let num = to_u32(&env, &right[0]) as usize;
let mut fac = Vec::new();
let mut i = 1;
let mut ind = 0;
while i <= (num as f64).sqrt().floor() as usize {
if num % i == 0 {
fac.insert(ind, Num::with_val(*FLOAT_PRECISION, i));
if i != num / i {
fac.insert(fac.len() - ind, Num::with_val(*FLOAT_PRECISION, num / i));
}
ind += 1;
}
i += 1;
}
let len = fac.len();
let temp = fac[len - 1].clone();
fac[len - 1] = fac[0].clone();
fac[0] = temp;
Dynamic::from(fac)
}
"$." => {
let mut seq = parse_node(Rc::clone(&env), &right[0]).literal_array();
seq.set_env(Rc::clone(&env));
let seq = seq.collect::<Vec<_>>();
Dynamic::from([
seq[..seq.len() / 2].to_owned(),
seq[seq.len() / 2..].to_owned(),
])
}
"!." => {
let program = parse_node(Rc::clone(&env), &right[0]).literal_string();
parse_node(Rc::clone(&env), &crate::build_ast(&program)[0])
}
"z" => {
let left = parse_node(Rc::clone(&env), &left[0])
.literal_array()
.set_env_self(Rc::clone(&env))
.collect::<Vec<_>>();
let right = parse_node(Rc::clone(&env), &right[0])
.literal_array()
.set_env_self(Rc::clone(&env))
.collect::<Vec<_>>();
let mut output = Vec::with_capacity(left.len());
for i in 0..left.len() {
output.push([left[i].clone(), right[i].clone()]);
}
Dynamic::from(output)
}
"#>" => {
let mut hash = std::collections::HashSet::new();
let mut result = Vec::new();
let array = parse_node(Rc::clone(&env), &right[0])
.literal_array()
.set_env_self(Rc::clone(&env));
for item in array {
if hash.get(&item).is_none() {
hash.insert(item.clone());
result.push(item);
}
}
Dynamic::from(result)
}
"#:" => {
let mut hash = std::collections::HashSet::new();
let mut result = Vec::new();
let array = parse_node(Rc::clone(&env), &right[0])
.literal_array()
.set_env_self(Rc::clone(&env));
for item in array {
if hash.get(&item).is_none() {
result.push(Num::with_val(*FLOAT_PRECISION, 1));
hash.insert(item);
} else {
result.push(Num::new(*FLOAT_PRECISION));
}
}
Dynamic::from(result)
}
"?" => {
let mut left = parse_node(Rc::clone(&env), &left[0])
.literal_array()
.set_env_self(Rc::clone(&env));
let index = to_u32(&env, &right[0]) as usize;
left.nth(index).unwrap()
}
"|" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let right = parse_node(Rc::clone(&env), &right[0]);
if left.is_array() {
let mut left = left
.literal_array()
.set_env_self(Rc::clone(&env))
.collect::<Vec<_>>();
if right.is_array() {
Dynamic::from(
[
left,
right
.literal_array()
.set_env_self(Rc::clone(&env))
.collect::<Vec<_>>(),
]
.concat(),
)
} else {
left.push(right);
Dynamic::from(left)
}
} else if right.is_array() {
let mut right = right
.literal_array()
.set_env_self(Rc::clone(&env))
.collect::<Vec<_>>();
right.insert(0, left);
Dynamic::from(right)
} else {
let mut left = left.literal_string();
left.push_str(&right.literal_string());
Dynamic::from(left)
}
}
"=" => Dynamic::from(
parse_node(Rc::clone(&env), &left[0]) == parse_node(Rc::clone(&env), &right[0]),
),
"!=" => Dynamic::from(
parse_node(Rc::clone(&env), &left[0]) != parse_node(Rc::clone(&env), &right[0]),
),
"<" => Dynamic::from(
parse_node(Rc::clone(&env), &left[0]).literal_num()
< parse_node(Rc::clone(&env), &right[0]).literal_num(),
),
"<=" => Dynamic::from(
parse_node(Rc::clone(&env), &left[0]).literal_num()
<= parse_node(Rc::clone(&env), &right[0]).literal_num(),
),
">" => Dynamic::from(
parse_node(Rc::clone(&env), &left[0]).literal_num()
> parse_node(Rc::clone(&env), &right[0]).literal_num(),
),
">=" => Dynamic::from(
parse_node(Rc::clone(&env), &left[0]).literal_num()
>= parse_node(Rc::clone(&env), &right[0]).literal_num(),
),
"&&" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let right = parse_node(Rc::clone(&env), &right[0]);
if left.is_bool() {
if right.is_bool() {
Dynamic::from(left.literal_bool() && right.literal_bool())
} else if left.clone().literal_bool() && right.clone().literal_bool() {
right
} else {
left
}
} else if right.is_bool() {
Dynamic::from(left.literal_bool() && right.literal_bool())
} else if left.clone().literal_bool() && right.clone().literal_bool() {
right
} else {
left
}
}
"||" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let right = parse_node(Rc::clone(&env), &right[0]);
if left.clone().literal_bool() {
left
} else {
right
}
}
":" => {
let child_env = Rc::new(env.as_ref().clone());
if let Node::Block(_, name) = &left[0] {
let val = child_env.borrow().get_var("_");
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), val)
}
let mut block = parse_node_uniq(Rc::clone(&child_env), &left[0]);
while {
let child_env = Rc::new(env.as_ref().clone());
if let Node::Block(_, name) = &right[0] {
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), block.clone())
} else {
child_env.borrow_mut().define_var("_", block.clone());
}
parse_node_uniq(Rc::clone(&child_env), &right[0]).literal_bool()
} {
if let Node::Block(_, name) = &left[0] {
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), block.clone())
} else {
child_env.borrow_mut().define_var("_", block.clone());
}
block = parse_node_uniq(Rc::clone(&child_env), &left[0]);
}
block
}
"::" => {
let mut groups = Vec::new();
let orig = parse_node(Rc::clone(&env), &left[0])
.literal_array()
.set_env_self(Rc::clone(&env));
for node in orig {
if groups.last().is_none() {
groups.push(vec![node]);
} else {
let mut vals = vec![
groups.last().unwrap().last().unwrap().clone().into_node(),
node.clone().into_node(),
];
let block = utils::traverse_replace(&mut vals, right[0].clone());
if parse_node(Rc::clone(&env), &block).literal_bool() {
groups.last_mut().unwrap().push(node);
} else {
groups.push(vec![node]);
}
}
}
Dynamic::from(groups)
}
"??" => {
let val = parse_node(Rc::clone(&env), &left[0]);
let condition = parse_node(Rc::clone(&env), &right[0]).literal_bool();
let child_env = Rc::new(env.as_ref().clone());
if condition {
if let Node::Block(_, name) = &right[1] {
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), val.clone())
} else {
child_env.borrow_mut().define_var("_", val.clone());
}
parse_node(Rc::clone(&child_env), &right[1])
} else {
val
}
}
"@" => {
let seq = parse_node(Rc::clone(&env), &left[0])
.literal_array()
.set_env_self(Rc::clone(&env));
let child_env = Rc::new(env.as_ref().clone());
Dynamic::from(
seq.map(|val| {
if let Node::Block(_, name) = &right[0] {
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), val)
} else {
child_env.borrow_mut().define_var("_", val);
}
parse_node_uniq(Rc::clone(&child_env), &right[0])
})
.collect::<Vec<_>>(),
)
}
"&" => {
let left = parse_node(Rc::clone(&env), &left[0]);
let child_env = Rc::new(env.as_ref().clone());
if let Node::Block(_, name) = &right[0] {
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), left)
} else {
child_env.borrow_mut().define_var("_", left);
}
parse_node_uniq(Rc::clone(&child_env), &right[0])
}
"/:" => {
let array = parse_node(Rc::clone(&env), &right[1])
.literal_array()
.set_env_self(Rc::clone(&env));
let child_env = Rc::new(env.as_ref().clone());
Dynamic::from(Num::with_val(
*FLOAT_PRECISION,
array
.filter(|val| {
if let Node::Block(_, name) = &right[0] {
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), val.clone())
} else {
child_env.borrow_mut().define_var("_", val.clone());
}
parse_node_uniq(Rc::clone(&child_env), &right[0]).literal_bool()
})
.count(),
))
}
_ => unimplemented!(),
}
}
fn parse_node_uniq(env: Env, block: &Node) -> Dynamic {
match block {
Node::Block(block, _) => {
for node in &block[..block.len() - 1] {
parse_node(Rc::clone(&env), node);
}
parse_node(Rc::clone(&env), block.last().unwrap_or(&DEFAULT))
}
_ => parse_node(env, block),
}
}
pub fn parse_node(env: Env, node: &Node) -> Dynamic {
match node {
Node::Op(op, left, right) => parse_op(env, op, left, right),
Node::String(v) => Dynamic::from(v.clone()),
Node::CmpString(v, chr) => Dynamic::from(utils::dict::decompress(v, *chr == '\'')),
Node::Number(v) => Dynamic::from(v.clone()),
Node::Variable(v) => env
.borrow()
.attempt_call(v, &env, env.borrow().get_var("_")),
Node::Group(body) => {
for node in &body[..body.len() - 1] {
parse_node(Rc::clone(&env), node);
}
parse_node(Rc::clone(&env), body.last().unwrap_or(&DEFAULT))
}
Node::Block(body, name) => {
let child_env = Rc::new(env.as_ref().clone());
let val = child_env.borrow().get_var("_");
child_env
.borrow_mut()
.define_var(name.as_ref().unwrap_or(&USCORE), val);
for node in &body[..body.len() - 1] {
parse_node(Rc::clone(&child_env), node);
}
parse_node(Rc::clone(&child_env), body.last().unwrap_or(&DEFAULT))
}
Node::Sequence(arr, block, len) => {
let mut seq = Sequence::from_vec_dyn(
&arr.iter()
.map(|n| parse_node(Rc::clone(&env), n))
.collect::<Vec<Dynamic>>(),
block.as_ref().clone(),
len.as_ref().map(|n| to_u32(&env, n.as_ref()) as usize),
);
seq.set_env(Rc::clone(&env));
Dynamic::new(Val::Array(Box::new(seq)), 4)
}
}
}
macro_rules! def_builtins {
($env:ident; $($($name:literal),*: $value:literal);*) => {
$(
$env.define([$($name),*], |e, val| {
let child = Rc::new(e.as_ref().clone());
child.borrow_mut().define_var("_", val);
parse_node(Rc::clone(&child), &crate::build_ast($value)[0])
});
)*
}
}
pub fn parse(ast: &[Node]) {
let mut env = Environment::init();
let mut stdin = if let Some(val) = MATCHES.value_of("input") {
val.to_owned()
} else if atty::is(atty::Stream::Stdin) {
String::from("")
} else {
let mut buffer = String::new();
io::stdin()
.read_to_string(&mut buffer)
.expect("Could not read from stdin");
buffer.trim_end_matches('\n').to_owned()
};
if MATCHES.is_present("one-ten") {
stdin = utils::create_str_range(1, 10);
}
if MATCHES.is_present("one-hundred") {
stdin = utils::create_str_range(1, 100);
}
if MATCHES.is_present("rangeify") {
stdin = utils::create_str_range(
1,
stdin
.parse::<usize>()
.expect("Input was not a valid integer"),
);
}
if MATCHES.is_present("0-range") {
stdin = utils::create_str_range(
0,
stdin
.parse::<usize>()
.expect("Input was not a valid integer")
- 1,
);
}
env.define_var(
"_",
if MATCHES.is_present("eval") {
parse_node(
Rc::new(RefCell::new(env.clone())),
&crate::build_ast(&stdin)[0],
)
} else {
Dynamic::from(stdin.clone())
},
);
env.define_var(
"E",
Num::with_val(
*FLOAT_PRECISION,
Num::parse("2.7182818284590452353602874713527").unwrap(),
),
);
env.define_var(
"pi",
Num::with_val(*FLOAT_PRECISION, rug::float::Constant::Pi),
);
env.define_var(
"phi",
Num::with_val(
*FLOAT_PRECISION,
Num::parse("1.61803398874989484820458683436563811").unwrap(),
),
);
env.define_var("a", Vec::<Dynamic>::new());
env.define_var("c", String::new());
env.define_var("Fi", "Fizz".to_string());
env.define_var("Bu", "Buzz".to_string());
let dummy_env = Rc::new(RefCell::new(Environment::init()));
env.define_var(
"sH",
Sequence::from_vec(
&crate::build_ast("1/2"),
crate::build_ast("/2")[0].clone(),
None,
)
.set_env_self(Rc::clone(&dummy_env)),
);
env.define_var(
"sA",
Sequence::from_vec(
&crate::build_ast("1"),
crate::build_ast("!")[0].clone(),
None,
)
.set_env_self(Rc::clone(&dummy_env)),
);
env.define_var(
"sE",
Sequence::from_vec(
&crate::build_ast("2"),
crate::build_ast("+2")[0].clone(),
None,
)
.set_env_self(Rc::clone(&dummy_env)),
);
env.define_var(
"sO",
Sequence::from_vec(
&crate::build_ast("1"),
crate::build_ast("+2")[0].clone(),
None,
)
.set_env_self(Rc::clone(&dummy_env)),
);
env.define_var(
"sF",
Sequence::from_vec(
&crate::build_ast("1 1"),
crate::build_ast("+")[0].clone(),
None,
)
.set_env_self(Rc::clone(&dummy_env)),
);
if MATCHES.is_present("input-left") {
let orig = env.get_var("_");
let as_vec = orig.literal_array().collect::<Vec<_>>();
env.define_var("_", as_vec[0].clone());
env.define_var("a", as_vec[1..].iter().cloned().collect::<Vec<_>>());
} else if MATCHES.is_present("input-right") {
let orig = env.get_var("_");
let as_vec = orig.literal_array().collect::<Vec<_>>();
env.define_var("_", as_vec[1..].iter().cloned().collect::<Vec<_>>());
env.define_var("a", as_vec[0].clone());
}
env.define(["ol", "outl"], |_, d| {
println!("{}", d);
d
});
env.define(["o", "out"], |_, d| {
print!("{}", d);
d
});
def_builtins! {env;
"f", "fact": r#"~||[1]&*\"#;
"me", "mean": r#"(+\)/(#"#;
"ma", "max": r#":>&:{"#;
"mo", "mode": r#":@&ma:{"#;
"mi", "min": r#":<&:{"#;
"med", "median": r#"(:-#&%2=0)&&:-(((:<)?(--:-#))+((:<)?:-#))||(:<)?:v:-#"#;
"sdev": r#":/((@v{:*(v-me)).me"#;
"crt", "cartesian": r#":{@a{:}@a<>}&:_"#;
"eq", "equal": r#":@#=1"#;
"pst", "powerset": r#":<(0->2^(#);2@a{|{+0&&[:}]||[}\a.<z"#
};
let env: Env = Rc::new(RefCell::new(env));
for node in &ast[..ast.len() - 1] {
parse_node(Rc::clone(&env), node);
}
let mut result = parse_node(Rc::clone(&env), ast.last().unwrap_or(&DEFAULT));
if MATCHES.is_present("first") {
result = result
.literal_array()
.set_env_self(Rc::clone(&env))
.collect::<Vec<_>>()
.first()
.unwrap()
.clone();
}
if MATCHES.is_present("last") {
result = result
.literal_array()
.set_env_self(Rc::clone(&env))
.collect::<Vec<_>>()
.last()
.unwrap()
.clone();
}
if MATCHES.is_present("index") {
result = result
.literal_array()
.set_env_self(Rc::clone(&env))
.nth(stdin.parse::<usize>().unwrap())
.unwrap();
}
if MATCHES.is_present("sum") {
result = Dynamic::from(
result
.literal_array()
.set_env_self(Rc::clone(&env))
.map(|n| n.literal_num())
.fold(Num::new(*FLOAT_PRECISION), |acc, val| acc + val),
);
}
if MATCHES.is_present("size") {
result = Dynamic::from(Num::with_val(
*FLOAT_PRECISION,
result.literal_array().set_env_self(Rc::clone(&env)).count(),
));
}
if MATCHES.is_present("not") {
result = Dynamic::from(!result.literal_bool())
}
println!("{}", result);
}