use crate::{
environment::Environment, HostFunction, HostFunctionBinding, HostType, WanderError, WanderValue,
};
use std::rc::Rc;
struct EqFunction {}
impl<T: HostType> HostFunction<T> for EqFunction {
fn run(
&self,
arguments: &[WanderValue<T>],
_bindings: &Environment<T>,
) -> Result<WanderValue<T>, WanderError> {
if let [left, right] = arguments {
Ok(crate::WanderValue::Bool(left == right))
} else {
Err(WanderError(
"`eq` function requires two parameters.".to_owned(),
))
}
}
fn binding(&self) -> HostFunctionBinding {
HostFunctionBinding {
name: "Core.eq".to_owned(),
parameters: vec![("left".to_owned(), None), ("right".to_owned(), None)],
result: None,
doc_string: "Check if two values are equal.".to_owned(),
}
}
}
struct AssertEqFunction {}
impl<T: HostType> HostFunction<T> for AssertEqFunction {
fn run(
&self,
arguments: &[WanderValue<T>],
_bindings: &Environment<T>,
) -> Result<WanderValue<T>, WanderError> {
if let [left, right] = arguments {
if left == right {
Ok(crate::WanderValue::Nothing)
} else {
Err(WanderError("Assertion failed!".to_owned()))
}
} else {
Err(WanderError(
"`assertEq` function requires two parameters.".to_owned(),
))
}
}
fn binding(&self) -> HostFunctionBinding {
HostFunctionBinding {
name: "Assert.assertEq".to_owned(),
parameters: vec![("value".to_owned(), None), ("expected".to_owned(), None)],
result: None,
doc_string: "Assert that two values are equal.".to_owned(),
}
}
}
struct AndFunction {}
impl<T: HostType> HostFunction<T> for AndFunction {
fn run(
&self,
arguments: &[WanderValue<T>],
_bindings: &Environment<T>,
) -> Result<crate::WanderValue<T>, WanderError> {
if let [WanderValue::Bool(left), WanderValue::Bool(right)] = arguments[..] {
Ok(crate::WanderValue::Bool(left && right))
} else {
Err(WanderError(
"`and` function requires two boolean parameters.".to_owned(),
))
}
}
fn binding(&self) -> HostFunctionBinding {
HostFunctionBinding {
name: "Bool.and".to_owned(),
parameters: vec![
("left".to_owned(), None), ("right".to_owned(), None), ],
result: None, doc_string: "Check if two boolean values are both true.".to_owned(),
}
}
}
struct NotFunction {}
impl<T: HostType> HostFunction<T> for NotFunction {
fn run(
&self,
arguments: &[WanderValue<T>],
_bindings: &Environment<T>,
) -> Result<crate::WanderValue<T>, WanderError> {
if let [WanderValue::Bool(value)] = arguments[..] {
Ok(crate::WanderValue::Bool(!value))
} else {
Err(WanderError(
"`not` function requires one boolean parameter.".to_owned(),
))
}
}
fn binding(&self) -> HostFunctionBinding {
HostFunctionBinding {
name: "Bool.not".to_owned(),
parameters: vec![("value".to_owned(), None)], result: None, doc_string: "Return the opposite of the boolean value passed.".to_owned(),
}
}
}
struct AtFunction {}
impl<T: HostType> HostFunction<T> for AtFunction {
fn run(
&self,
arguments: &[WanderValue<T>],
_: &Environment<T>,
) -> Result<WanderValue<T>, WanderError> {
if let [WanderValue::Int(index), WanderValue::List(value)] = arguments {
let index: usize = index.to_owned().try_into().unwrap();
if index < value.len() {
let t: Option<&WanderValue<T>> = value.get(index);
match t {
Some(t) => Ok(t.to_owned()),
None => Err(WanderError("`at` function err.".to_owned())),
}
} else {
Err(WanderError("`at` function err.".to_owned()))
}
} else {
Err(WanderError("`at` function err.".to_owned()))
}
}
fn binding(&self) -> HostFunctionBinding {
HostFunctionBinding {
name: "List.at".to_owned(),
parameters: vec![
("offset".to_owned(), None), ("list".to_owned(), None), ],
result: None,
doc_string: "Get the value at a given location.".to_owned(),
}
}
}
pub fn common<T: HostType>() -> Environment<T> {
let mut bindings = Environment::new();
bindings.bind_host_function(Rc::new(EqFunction {}));
bindings.bind_host_function(Rc::new(AssertEqFunction {}));
bindings.bind_host_function(Rc::new(AndFunction {}));
bindings.bind_host_function(Rc::new(NotFunction {}));
bindings.bind_host_function(Rc::new(AtFunction {}));
bindings
}