Add context to function call nodes

This commit is contained in:
Jeff 2024-02-12 17:55:45 -05:00
parent daf78919da
commit bbab728ce9
3 changed files with 27 additions and 35 deletions

View File

@ -12,6 +12,9 @@ pub struct FunctionCall {
function_expression: FunctionExpression,
arguments: Vec<Expression>,
syntax_position: SourcePosition,
#[serde(skip)]
context: Context,
}
impl FunctionCall {
@ -20,11 +23,13 @@ impl FunctionCall {
function_expression: FunctionExpression,
arguments: Vec<Expression>,
syntax_position: SourcePosition,
context: Context,
) -> Self {
Self {
function_expression,
arguments,
syntax_position,
context,
}
}
}
@ -52,6 +57,7 @@ impl AbstractTree for FunctionCall {
function_expression,
arguments,
syntax_position: node.range().into(),
context: Context::new(),
})
}
@ -144,16 +150,20 @@ impl AbstractTree for FunctionCall {
FunctionExpression::Value(value_node) => value_node.run(source, context)?,
FunctionExpression::Index(index) => index.run(source, context)?,
};
let function = value.as_function()?;
let parameter_expression_pairs = function
.parameters()
.unwrap()
.iter()
.zip(self.arguments.iter());
let mut arguments = Vec::with_capacity(self.arguments.len());
for expression in &self.arguments {
for (identifier, expression) in parameter_expression_pairs {
let value = expression.run(source, context)?;
arguments.push(value);
self.context.set_value(identifier.inner().clone(), value)?;
}
value.as_function()?.call(&arguments, source, context)
value.as_function()?.call(&[], source, context)
}
}

View File

@ -14,9 +14,6 @@ pub struct FunctionNode {
body: Block,
r#type: Type,
syntax_position: SourcePosition,
#[serde(skip)]
context: Context,
}
impl FunctionNode {
@ -31,7 +28,6 @@ impl FunctionNode {
body,
r#type,
syntax_position,
context: Context::new(),
}
}
@ -61,21 +57,8 @@ impl FunctionNode {
}
}
pub fn call(
&self,
arguments: &[Value],
source: &str,
_context: &Context,
) -> Result<Value, RuntimeError> {
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
for (identifier, value) in parameter_argument_pairs {
let key = identifier.inner().clone();
self.context.set_value(key, value.clone())?;
}
let return_value = self.body.run(source, &self.context)?;
pub fn call(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
let return_value = self.body.run(source, context)?;
Ok(return_value)
}
@ -108,15 +91,9 @@ impl AbstractTree for FunctionNode {
let return_type_node = node.child(child_count - 2).unwrap();
let return_type = TypeSpecification::from_syntax(return_type_node, source, context)?;
let function_context = Context::with_variables_from(context)?;
let body_node = node.child(child_count - 1).unwrap();
let body = Block::from_syntax(body_node, source, &context)?;
for (parameter, parameter_type) in parameters.iter().zip(parameter_types.iter()) {
function_context.set_type(parameter.inner().clone(), parameter_type.clone())?;
}
let r#type = Type::function(parameter_types, return_type.take_inner());
let syntax_position = node.range().into();
@ -125,7 +102,6 @@ impl AbstractTree for FunctionNode {
body,
r#type,
syntax_position,
context: function_context,
})
}

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use crate::{
built_in_functions::Callable, error::RuntimeError, BuiltInFunction, Context, Format,
FunctionNode, Type, Value,
FunctionNode, Identifier, Type, Value,
};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
@ -24,9 +24,7 @@ impl Function {
Function::BuiltIn(built_in_function) => {
built_in_function.call(arguments, source, outer_context)
}
Function::ContextDefined(function_node) => {
function_node.call(arguments, source, outer_context)
}
Function::ContextDefined(function_node) => function_node.call(source, outer_context),
}
}
@ -38,6 +36,14 @@ impl Function {
}
}
}
pub fn parameters(&self) -> Option<&Vec<Identifier>> {
if let Function::ContextDefined(function) = self {
Some(function.parameters())
} else {
None
}
}
}
impl Format for Function {