1
0

Add analyzing built-in function calls

This commit is contained in:
Jeff 2024-08-11 18:11:59 -04:00
parent 3a2dd28efb
commit 7259206c98

View File

@ -22,9 +22,8 @@ use crate::{
/// # use std::collections::HashMap; /// # use std::collections::HashMap;
/// # use dust_lang::*; /// # use dust_lang::*;
/// let input = "x = 1 + false"; /// let input = "x = 1 + false";
/// let abstract_tree = parse(input).unwrap();
/// let mut context = Context::new(); /// let mut context = Context::new();
/// let result = analyze(&abstract_tree, &mut context); /// let result = analyze(input, &mut context);
/// ///
/// assert!(result.is_err()); /// assert!(result.is_err());
/// ``` /// ```
@ -150,7 +149,27 @@ impl<'a> Analyzer<'a> {
self.analyze_node(statement)?; self.analyze_node(statement)?;
} }
} }
Statement::BuiltInFunctionCall { .. } => {} Statement::BuiltInFunctionCall {
function,
value_arguments,
..
} => {
let value_parameters = function.value_parameters();
if let Some(arguments) = value_arguments {
for argument in arguments {
self.analyze_node(argument)?;
}
if arguments.len() != value_parameters.len() {
return Err(AnalyzerError::ExpectedValueArgumentCount {
expected: value_parameters.len(),
actual: arguments.len(),
position: node.position,
});
}
}
}
Statement::Constant(_) => {} Statement::Constant(_) => {}
Statement::FunctionCall { function, .. } => { Statement::FunctionCall { function, .. } => {
if let Statement::Identifier(_) = &function.inner { if let Statement::Identifier(_) = &function.inner {
@ -368,6 +387,11 @@ pub enum AnalyzerError {
actual: Node<Statement>, actual: Node<Statement>,
position: Span, position: Span,
}, },
ExpectedValueArgumentCount {
expected: usize,
actual: usize,
position: Span,
},
UndefinedVariable { UndefinedVariable {
identifier: Node<Statement>, identifier: Node<Statement>,
}, },
@ -393,6 +417,7 @@ impl AnalyzerError {
AnalyzerError::ExpectedIntegerOrFloat { position, .. } => *position, AnalyzerError::ExpectedIntegerOrFloat { position, .. } => *position,
AnalyzerError::ExpectedIntegerFloatOrString { position, .. } => *position, AnalyzerError::ExpectedIntegerFloatOrString { position, .. } => *position,
AnalyzerError::ExpectedString { position, .. } => *position, AnalyzerError::ExpectedString { position, .. } => *position,
AnalyzerError::ExpectedValueArgumentCount { position, .. } => *position,
AnalyzerError::UndefinedVariable { identifier } => identifier.position, AnalyzerError::UndefinedVariable { identifier } => identifier.position,
AnalyzerError::UnexpectedIdentifier { position, .. } => *position, AnalyzerError::UnexpectedIdentifier { position, .. } => *position,
AnalyzerError::UnexectedString { position, .. } => *position, AnalyzerError::UnexectedString { position, .. } => *position,
@ -432,6 +457,9 @@ impl Display for AnalyzerError {
AnalyzerError::ExpectedValue { actual, .. } => { AnalyzerError::ExpectedValue { actual, .. } => {
write!(f, "Expected value, found {}", actual) write!(f, "Expected value, found {}", actual)
} }
AnalyzerError::ExpectedValueArgumentCount {
expected, actual, ..
} => write!(f, "Expected {} value arguments, found {}", expected, actual),
AnalyzerError::UndefinedVariable { identifier } => { AnalyzerError::UndefinedVariable { identifier } => {
write!(f, "Undefined variable {}", identifier) write!(f, "Undefined variable {}", identifier)
} }
@ -452,16 +480,13 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn write_line_wrong_arguments() { fn length_no_arguments() {
let abstract_tree = AbstractSyntaxTree { let abstract_tree = AbstractSyntaxTree {
nodes: [Node::new( nodes: [Node::new(
Statement::BuiltInFunctionCall { Statement::BuiltInFunctionCall {
function: BuiltInFunction::WriteLine, function: BuiltInFunction::Length,
type_arguments: None, type_arguments: None,
value_arguments: Some(vec![Node::new( value_arguments: Some(vec![]),
Statement::Constant(Value::integer(1)),
(0, 1),
)]),
}, },
(0, 1), (0, 1),
)] )]
@ -472,8 +497,9 @@ mod tests {
assert_eq!( assert_eq!(
analyzer.analyze(), analyzer.analyze(),
Err(AnalyzerError::ExpectedString { Err(AnalyzerError::ExpectedValueArgumentCount {
actual: Node::new(Statement::Constant(Value::integer(1)), (0, 1)), expected: 1,
actual: 0,
position: (0, 1) position: (0, 1)
}) })
) )