diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index bb50c17..af16420 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -22,14 +22,34 @@ impl FunctionCall { impl AbstractTree for FunctionCall { fn expected_type(&self, _context: &Context) -> Result { - todo!() + if let Type::Function { return_type, .. } = self.function.expected_type(_context)? { + Ok(*return_type) + } else { + Err(ValidationError::ExpectedFunction) + } } fn validate(&self, _context: &Context) -> Result<(), ValidationError> { - todo!() + if let Type::Function { .. } = self.function.expected_type(_context)? { + Ok(()) + } else { + Err(ValidationError::ExpectedFunction) + } } fn run(self, _context: &Context) -> Result { - todo!() + let value = self.function.run(_context)?.as_value()?; + let function = value.as_function()?; + let mut arguments = Vec::with_capacity(self.arguments.len()); + + for expression in self.arguments { + let value = expression.run(_context)?.as_value()?; + + arguments.push(value); + } + + let function_context = Context::new(); + + function.call(arguments, function_context) } } diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index 20342af..7017019 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -48,6 +48,14 @@ pub enum Action { } impl Action { + pub fn as_value(self) -> Result { + match self { + Action::Break(value) => Ok(value), + Action::Return(value) => Ok(value), + Action::None => Err(ValidationError::ExpectedValue), + } + } + pub fn as_return_value(self) -> Result { if let Action::Return(value) = self { Ok(value) diff --git a/src/error.rs b/src/error.rs index fd0cd20..b017cf3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -88,6 +88,8 @@ impl Error { ValidationError::CannotIndex(_) => todo!(), ValidationError::CannotIndexWith(_, _) => todo!(), ValidationError::InterpreterExpectedReturn => todo!(), + ValidationError::ExpectedFunction => todo!(), + ValidationError::ExpectedValue => todo!(), } report.finish() @@ -143,7 +145,9 @@ pub enum ValidationError { CannotIndex(Type), CannotIndexWith(Type, Type), ExpectedBoolean, + ExpectedFunction, ExpectedIntegerOrFloat, + ExpectedValue, InterpreterExpectedReturn, RwLockPoison(RwLockPoisonError), TypeCheck(TypeCheckError), diff --git a/src/value.rs b/src/value.rs index 427e92c..ec11588 100644 --- a/src/value.rs +++ b/src/value.rs @@ -13,7 +13,7 @@ use stanza::{ }; use crate::{ - abstract_tree::{Action, Identifier, Statement, Type}, + abstract_tree::{AbstractTree, Action, Identifier, Statement, Type}, context::Context, error::{RuntimeError, ValidationError}, }; @@ -129,6 +129,14 @@ impl Value { Err(ValidationError::ExpectedBoolean) } + pub fn as_function(&self) -> Result<&Function, ValidationError> { + if let ValueInner::Function(function) = self.0.as_ref() { + return Ok(function); + } + + Err(ValidationError::ExpectedFunction) + } + pub fn as_list(&self) -> Option<&Vec> { if let ValueInner::List(list) = self.inner().as_ref() { Some(list) @@ -338,6 +346,25 @@ pub enum Function { BuiltIn(BuiltInFunction), } +impl Function { + pub fn call(&self, arguments: Vec, context: Context) -> Result { + let action = match self { + Function::Parsed(ParsedFunction { + parameters, body, .. + }) => { + for ((identifier, _), value) in parameters.into_iter().zip(arguments.into_iter()) { + context.set_value(identifier.clone(), value)?; + } + + body.clone().run(&context)? + } + Function::BuiltIn(built_in_function) => built_in_function.call(arguments, &context)?, + }; + + Ok(action) + } +} + #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct ParsedFunction { parameters: Vec<(Identifier, Type)>, @@ -368,10 +395,10 @@ impl BuiltInFunction { } } - pub fn call(self, value: Value, _context: &Context) -> Result { + pub fn call(&self, arguments: Vec, _context: &Context) -> Result { match self { BuiltInFunction::Output => { - println!("{value}"); + println!("{}", arguments[0]); Ok(Action::None) }