diff --git a/examples/list.ds b/examples/list.ds index c27f974..9fbfb88 100644 --- a/examples/list.ds +++ b/examples/list.ds @@ -4,4 +4,4 @@ x = numbers.0 y = numbers.1 z = numbers.2 -assert_equal +(assert_equal x + y, z) diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 9d13c15..f4acf2d 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -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(); - 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 }) @@ -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(); diff --git a/src/abstract_tree/tool.rs b/src/abstract_tree/tool.rs index 55df2b1..e7d8ea3 100644 --- a/src/abstract_tree/tool.rs +++ b/src/abstract_tree/tool.rs @@ -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 { + pub fn run(&self, values: &[Value]) -> Result { 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) } diff --git a/src/error.rs b/src/error.rs index 45cad4c..61d1694 100644 --- a/src/error.rs +++ b/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 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, diff --git a/tree-sitter-dust b/tree-sitter-dust index a207087..c6ec1ff 160000 --- a/tree-sitter-dust +++ b/tree-sitter-dust @@ -1 +1 @@ -Subproject commit a207087ccafb71764b007db88580b35d5e37dae3 +Subproject commit c6ec1ff6ea51ce28ee465f9c230e2580fab4c437