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, function_expression: FunctionExpression,
arguments: Vec<Expression>, arguments: Vec<Expression>,
syntax_position: SourcePosition, syntax_position: SourcePosition,
#[serde(skip)]
context: Context,
} }
impl FunctionCall { impl FunctionCall {
@ -20,11 +23,13 @@ impl FunctionCall {
function_expression: FunctionExpression, function_expression: FunctionExpression,
arguments: Vec<Expression>, arguments: Vec<Expression>,
syntax_position: SourcePosition, syntax_position: SourcePosition,
context: Context,
) -> Self { ) -> Self {
Self { Self {
function_expression, function_expression,
arguments, arguments,
syntax_position, syntax_position,
context,
} }
} }
} }
@ -52,6 +57,7 @@ impl AbstractTree for FunctionCall {
function_expression, function_expression,
arguments, arguments,
syntax_position: node.range().into(), 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::Value(value_node) => value_node.run(source, context)?,
FunctionExpression::Index(index) => index.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 (identifier, expression) in parameter_expression_pairs {
for expression in &self.arguments {
let value = expression.run(source, context)?; 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, body: Block,
r#type: Type, r#type: Type,
syntax_position: SourcePosition, syntax_position: SourcePosition,
#[serde(skip)]
context: Context,
} }
impl FunctionNode { impl FunctionNode {
@ -31,7 +28,6 @@ impl FunctionNode {
body, body,
r#type, r#type,
syntax_position, syntax_position,
context: Context::new(),
} }
} }
@ -61,21 +57,8 @@ impl FunctionNode {
} }
} }
pub fn call( pub fn call(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
&self, let return_value = self.body.run(source, context)?;
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)?;
Ok(return_value) Ok(return_value)
} }
@ -108,15 +91,9 @@ impl AbstractTree for FunctionNode {
let return_type_node = node.child(child_count - 2).unwrap(); let return_type_node = node.child(child_count - 2).unwrap();
let return_type = TypeSpecification::from_syntax(return_type_node, source, context)?; 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_node = node.child(child_count - 1).unwrap();
let body = Block::from_syntax(body_node, source, &context)?; 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 r#type = Type::function(parameter_types, return_type.take_inner());
let syntax_position = node.range().into(); let syntax_position = node.range().into();
@ -125,7 +102,6 @@ impl AbstractTree for FunctionNode {
body, body,
r#type, r#type,
syntax_position, syntax_position,
context: function_context,
}) })
} }

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
built_in_functions::Callable, error::RuntimeError, BuiltInFunction, Context, Format, 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)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
@ -24,9 +24,7 @@ impl Function {
Function::BuiltIn(built_in_function) => { Function::BuiltIn(built_in_function) => {
built_in_function.call(arguments, source, outer_context) built_in_function.call(arguments, source, outer_context)
} }
Function::ContextDefined(function_node) => { Function::ContextDefined(function_node) => function_node.call(source, outer_context),
function_node.call(arguments, 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 { impl Format for Function {