Add context to function call nodes
This commit is contained in:
parent
daf78919da
commit
bbab728ce9
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user