use std::ops::{Deref, DerefMut};
use crate::{lang::SError, Library, SDoc, SNum, SVal};
#[derive(Default, Debug)]
pub struct TupleLibrary;
impl TupleLibrary {
pub fn operate(&self, pid: &str, doc: &mut SDoc, name: &str, tup: &mut Vec<SVal>, parameters: &mut Vec<SVal>) -> Result<SVal, SError> {
match name {
"len" => {
Ok(SVal::Number(SNum::I64(tup.len() as i64)))
},
"at" => {
if parameters.len() < 1 {
return Err(SError::tup(pid, &doc, "at", "invalid arguments - index not found"));
}
let index = parameters.pop().unwrap().unbox();
match index {
SVal::Number(index) => {
let index = index.int() as usize;
if let Some(val) = tup.get(index) {
return Ok(val.clone());
}
Err(SError::tup(pid, &doc, "at", "index out of bounds"))
},
SVal::Boxed(val) => {
let val = val.lock().unwrap();
let val = val.deref();
match val {
SVal::Number(index) => {
let index = index.int() as usize;
if let Some(val) = tup.get(index) {
return Ok(val.clone());
}
Err(SError::tup(pid, &doc, "at", "index out of bounds"))
},
_ => {
Err(SError::tup(pid, &doc, "at", "non-numerical index not supported"))
}
}
},
_ => {
Err(SError::tup(pid, &doc, "at", "non-numerical index not supported"))
}
}
},
_ => {
Err(SError::tup(pid, &doc, "NotFound", &format!("{} is not a function in the Tuple Library", name)))
}
}
}
}
impl Library for TupleLibrary {
fn scope(&self) -> String {
"Tuple".to_string()
}
fn call(&self, pid: &str, doc: &mut SDoc, name: &str, parameters: &mut Vec<SVal>) -> Result<SVal, SError> {
if parameters.len() > 0 {
match name {
"toString" => {
return Ok(SVal::String(parameters[0].print(doc)));
},
"or" => {
for param in parameters.drain(..) {
if !param.is_empty() {
return Ok(param);
}
}
return Ok(SVal::Null);
},
_ => {}
}
let mut params;
if parameters.len() > 1 {
params = parameters.drain(1..).collect();
} else {
params = Vec::new();
}
match &mut parameters[0] {
SVal::Tuple(tup) => {
return self.operate(pid, doc, name, tup, &mut params);
},
SVal::Boxed(val) => {
let mut val = val.lock().unwrap();
let val = val.deref_mut();
match val {
SVal::Tuple(tup) => {
return self.operate(pid, doc, name, tup, &mut params);
},
_ => {
return Err(SError::tup(pid, &doc, "InvalidArgument", "tuple argument not found"));
}
}
},
_ => {
return Err(SError::tup(pid, &doc, "InvalidArgument", "tuple argument not found"));
}
}
} else {
return Err(SError::tup(pid, &doc, "InvalidArgument", "tuple argument not found"));
}
}
}