Add assert and assert_equal tools
This commit is contained in:
parent
96c6193799
commit
fc92513246
@ -4,4 +4,4 @@ x = numbers.0
|
||||
y = numbers.1
|
||||
z = numbers.2
|
||||
|
||||
assert_equal <x + y, z>
|
||||
(assert_equal x + y, z)
|
||||
|
@ -30,6 +30,8 @@ impl AbstractTree for FunctionCall {
|
||||
"tool" => {
|
||||
let tool_node = name_node.child(0).unwrap();
|
||||
let tool = match tool_node.kind() {
|
||||
"assert" => Tool::Assert,
|
||||
"assert_equal" => Tool::AssertEqual,
|
||||
"output" => Tool::Output,
|
||||
"read" => Tool::Read,
|
||||
_ => panic!(""),
|
||||
@ -42,14 +44,14 @@ impl AbstractTree for FunctionCall {
|
||||
|
||||
let mut arguments = Vec::new();
|
||||
|
||||
let mut current_index = 2;
|
||||
while current_index < node.child_count() - 1 {
|
||||
let expression_node = node.child(current_index).unwrap();
|
||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||
for index in 2..node.child_count() - 1 {
|
||||
let child = node.child(index).unwrap();
|
||||
|
||||
if child.is_named() {
|
||||
let expression = Expression::from_syntax_node(source, child)?;
|
||||
|
||||
arguments.push(expression);
|
||||
|
||||
current_index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(FunctionCall { name, arguments })
|
||||
@ -59,13 +61,15 @@ impl AbstractTree for FunctionCall {
|
||||
let identifier = match &self.name {
|
||||
FunctionName::Identifier(identifier) => identifier,
|
||||
FunctionName::Tool(tool) => {
|
||||
let value = self
|
||||
.arguments
|
||||
.first()
|
||||
.map(|expression| expression.run(source, context))
|
||||
.unwrap_or(Ok(Value::Empty))?;
|
||||
let mut values = Vec::with_capacity(self.arguments.len());
|
||||
|
||||
return tool.run(&value);
|
||||
for expression in &self.arguments {
|
||||
let value = expression.run(source, context)?;
|
||||
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
return tool.run(&values);
|
||||
}
|
||||
};
|
||||
let key = identifier.inner();
|
||||
|
@ -2,24 +2,78 @@ use std::fs::read_to_string;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Result, Value};
|
||||
use crate::{Error, Result, Value};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum Tool {
|
||||
Assert,
|
||||
AssertEqual,
|
||||
Output,
|
||||
Read,
|
||||
}
|
||||
|
||||
impl Tool {
|
||||
pub fn run(&self, value: &Value) -> Result<Value> {
|
||||
pub fn run(&self, values: &[Value]) -> Result<Value> {
|
||||
let value = match self {
|
||||
Tool::Assert => {
|
||||
if values.len() != 1 {
|
||||
return Err(Error::ExpectedToolArgumentAmount {
|
||||
tool_name: "assert",
|
||||
expected: 1,
|
||||
actual: values.len(),
|
||||
});
|
||||
}
|
||||
|
||||
if values[0].as_boolean()? {
|
||||
Value::Empty
|
||||
} else {
|
||||
return Err(Error::AssertEqualFailed {
|
||||
expected: Value::Boolean(true),
|
||||
actual: values[0].clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Tool::AssertEqual => {
|
||||
if values.len() != 2 {
|
||||
return Err(Error::ExpectedToolArgumentAmount {
|
||||
tool_name: "assert_equal",
|
||||
expected: 2,
|
||||
actual: values.len(),
|
||||
});
|
||||
}
|
||||
|
||||
if values[0] == values[1] {
|
||||
Value::Empty
|
||||
} else {
|
||||
return Err(Error::AssertEqualFailed {
|
||||
expected: values[0].clone(),
|
||||
actual: values[1].clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Tool::Output => {
|
||||
println!("{value}");
|
||||
if values.len() != 1 {
|
||||
return Err(Error::ExpectedToolArgumentAmount {
|
||||
tool_name: "output",
|
||||
expected: 1,
|
||||
actual: values.len(),
|
||||
});
|
||||
}
|
||||
|
||||
println!("{}", values[0]);
|
||||
|
||||
Value::Empty
|
||||
}
|
||||
Tool::Read => {
|
||||
let file_contents = read_to_string(value.as_string()?)?;
|
||||
if values.len() != 1 {
|
||||
return Err(Error::ExpectedToolArgumentAmount {
|
||||
tool_name: "read",
|
||||
expected: 1,
|
||||
actual: values.len(),
|
||||
});
|
||||
}
|
||||
|
||||
let file_contents = read_to_string(values[0].as_string()?)?;
|
||||
|
||||
Value::String(file_contents)
|
||||
}
|
||||
|
42
src/error.rs
42
src/error.rs
@ -47,8 +47,8 @@ pub enum Error {
|
||||
},
|
||||
|
||||
/// A function was called with the wrong amount of arguments.
|
||||
ExpectedFunctionArgumentAmount {
|
||||
identifier: String,
|
||||
ExpectedToolArgumentAmount {
|
||||
tool_name: &'static str,
|
||||
expected: usize,
|
||||
actual: usize,
|
||||
},
|
||||
@ -283,38 +283,6 @@ impl From<toml::de::Error> for Error {
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub(crate) fn _expect_function_argument_amount(
|
||||
identifier: &str,
|
||||
actual: usize,
|
||||
expected: usize,
|
||||
) -> Result<()> {
|
||||
if actual == expected {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::ExpectedFunctionArgumentAmount {
|
||||
identifier: identifier.to_string(),
|
||||
expected,
|
||||
actual,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn _expected_minimum_function_argument_amount(
|
||||
identifier: &str,
|
||||
actual: usize,
|
||||
minimum: usize,
|
||||
) -> Result<()> {
|
||||
if actual >= minimum {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::ExpectedAtLeastFunctionArgumentAmount {
|
||||
identifier: identifier.to_string(),
|
||||
minimum,
|
||||
actual,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_error(actual: Value, expected: &'static [ValueType]) -> Self {
|
||||
Error::TypeError { actual, expected }
|
||||
}
|
||||
@ -414,13 +382,13 @@ impl fmt::Display for Error {
|
||||
"An operator expected {} arguments, but got {}.",
|
||||
expected, actual
|
||||
),
|
||||
ExpectedFunctionArgumentAmount {
|
||||
ExpectedToolArgumentAmount {
|
||||
tool_name,
|
||||
expected,
|
||||
actual,
|
||||
identifier,
|
||||
} => write!(
|
||||
f,
|
||||
"{identifier} expected {expected} arguments, but got {actual}.",
|
||||
"{tool_name} expected {expected} arguments, but got {actual}.",
|
||||
),
|
||||
ExpectedAtLeastFunctionArgumentAmount {
|
||||
minimum,
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit a207087ccafb71764b007db88580b35d5e37dae3
|
||||
Subproject commit c6ec1ff6ea51ce28ee465f9c230e2580fab4c437
|
Loading…
Reference in New Issue
Block a user