Implement function calls

This commit is contained in:
Jeff 2024-03-09 08:10:54 -05:00
parent eba12b13a3
commit e272d99bae
4 changed files with 65 additions and 6 deletions

View File

@ -22,14 +22,34 @@ impl FunctionCall {
impl AbstractTree for FunctionCall {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
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<Action, RuntimeError> {
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)
}
}

View File

@ -48,6 +48,14 @@ pub enum Action {
}
impl Action {
pub fn as_value(self) -> Result<Value, ValidationError> {
match self {
Action::Break(value) => Ok(value),
Action::Return(value) => Ok(value),
Action::None => Err(ValidationError::ExpectedValue),
}
}
pub fn as_return_value(self) -> Result<Value, ValidationError> {
if let Action::Return(value) = self {
Ok(value)

View File

@ -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),

View File

@ -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<Value>> {
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<Value>, context: Context) -> Result<Action, RuntimeError> {
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<Action, RuntimeError> {
pub fn call(&self, arguments: Vec<Value>, _context: &Context) -> Result<Action, RuntimeError> {
match self {
BuiltInFunction::Output => {
println!("{value}");
println!("{}", arguments[0]);
Ok(Action::None)
}