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