Fix function call bug
This commit is contained in:
parent
af20dab0d2
commit
64ce3d56e4
@ -42,6 +42,8 @@ impl Expression {
|
||||
|
||||
impl AbstractNode for Expression {
|
||||
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||
log::trace!("Defining types for expression at {}", self.position());
|
||||
|
||||
match self {
|
||||
Expression::As(inner) => inner.node.define_types(_context),
|
||||
Expression::BuiltIn(inner) => inner.node.define_types(_context),
|
||||
@ -56,6 +58,8 @@ impl AbstractNode for Expression {
|
||||
}
|
||||
|
||||
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||
log::trace!("Validating expression at {}", self.position());
|
||||
|
||||
match self {
|
||||
Expression::As(r#as) => r#as.node.validate(context, manage_memory),
|
||||
Expression::BuiltIn(built_in_function_call) => {
|
||||
@ -89,6 +93,8 @@ impl AbstractNode for Expression {
|
||||
context: &Context,
|
||||
manage_memory: bool,
|
||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||
log::trace!("Evaluating expression at {}", self.position());
|
||||
|
||||
match self {
|
||||
Expression::As(r#as) => r#as.node.evaluate(context, manage_memory),
|
||||
Expression::FunctionCall(function_call) => {
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
@ -10,14 +8,11 @@ use crate::{
|
||||
|
||||
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct FunctionCall {
|
||||
function_expression: Box<Expression>,
|
||||
type_arguments: Option<Vec<TypeConstructor>>,
|
||||
value_arguments: Option<Vec<Expression>>,
|
||||
|
||||
#[serde(skip)]
|
||||
context: Context,
|
||||
}
|
||||
|
||||
impl FunctionCall {
|
||||
@ -30,7 +25,6 @@ impl FunctionCall {
|
||||
function_expression: Box::new(function_expression),
|
||||
type_arguments,
|
||||
value_arguments,
|
||||
context: Context::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,34 +37,9 @@ impl AbstractNode for FunctionCall {
|
||||
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||
self.function_expression.define_types(context)?;
|
||||
|
||||
let (type_parameters, value_parameters) =
|
||||
if let Some(r#type) = self.function_expression.expected_type(context)? {
|
||||
if let Type::Function {
|
||||
type_parameters,
|
||||
value_parameters,
|
||||
..
|
||||
} = r#type
|
||||
{
|
||||
(type_parameters, value_parameters)
|
||||
} else {
|
||||
return Err(ValidationError::ExpectedFunction {
|
||||
actual: r#type,
|
||||
position: self.function_expression.position(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
todo!("Create an error for this occurence");
|
||||
};
|
||||
|
||||
if let (Some(type_parameters), Some(type_arguments)) =
|
||||
(type_parameters, &self.type_arguments)
|
||||
{
|
||||
for (identifier, constructor) in
|
||||
type_parameters.into_iter().zip(type_arguments.into_iter())
|
||||
{
|
||||
let r#type = constructor.construct(context)?;
|
||||
|
||||
self.context.set_type(identifier, r#type)?;
|
||||
if let Some(expressions) = &self.value_arguments {
|
||||
for expression in expressions {
|
||||
expression.define_types(context)?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,12 +94,10 @@ impl AbstractNode for FunctionCall {
|
||||
fn evaluate(
|
||||
self,
|
||||
context: &Context,
|
||||
clear_variables: bool,
|
||||
manage_memory: bool,
|
||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||
let function_position = self.function_expression.position();
|
||||
let evaluation = self
|
||||
.function_expression
|
||||
.evaluate(context, clear_variables)?;
|
||||
let evaluation = self.function_expression.evaluate(context, manage_memory)?;
|
||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||
value
|
||||
} else {
|
||||
@ -149,50 +116,34 @@ impl AbstractNode for FunctionCall {
|
||||
));
|
||||
};
|
||||
|
||||
match (function.type_parameters(), self.type_arguments) {
|
||||
(Some(type_parameters), Some(type_arguments)) => {
|
||||
for (parameter, constructor) in
|
||||
type_parameters.into_iter().zip(type_arguments.into_iter())
|
||||
{
|
||||
let r#type = constructor.construct(context)?;
|
||||
function.populate_context_template()?;
|
||||
|
||||
self.context.set_type(parameter.clone(), r#type)?;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let function_context = function.context_template().create_child();
|
||||
|
||||
if let (Some(value_parameters), Some(value_arguments)) =
|
||||
if let (Some(parameters), Some(arguments)) =
|
||||
(function.value_parameters(), self.value_arguments)
|
||||
{
|
||||
for ((identifier, _), expression) in
|
||||
value_parameters.into_iter().zip(value_arguments.iter())
|
||||
{
|
||||
let expression_position = expression.position();
|
||||
let evaluation = expression.clone().evaluate(context, clear_variables)?;
|
||||
for ((identifier, _), expression) in parameters.into_iter().zip(arguments.into_iter()) {
|
||||
let position = expression.position();
|
||||
let evaluation = expression.evaluate(context, manage_memory)?;
|
||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||
value
|
||||
} else {
|
||||
return Err(RuntimeError::ValidationFailure(
|
||||
ValidationError::ExpectedExpression(expression_position),
|
||||
ValidationError::ExpectedValue(position),
|
||||
));
|
||||
};
|
||||
|
||||
self.context.set_value(identifier.clone(), value)?;
|
||||
function_context.set_value(identifier.clone(), value)?;
|
||||
}
|
||||
}
|
||||
|
||||
function.clone().call(&self.context, clear_variables)
|
||||
function.call(&function_context, manage_memory)
|
||||
}
|
||||
|
||||
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||
let return_type = if let Some(r#type) = self.function_expression.expected_type(context)? {
|
||||
if let Type::Function {
|
||||
type_parameters,
|
||||
value_parameters,
|
||||
return_type,
|
||||
} = r#type
|
||||
{
|
||||
if let Type::Function { return_type, .. } = r#type {
|
||||
return_type
|
||||
} else {
|
||||
return Err(ValidationError::ExpectedFunction {
|
||||
@ -211,37 +162,3 @@ impl AbstractNode for FunctionCall {
|
||||
Ok(return_type)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FunctionCall {}
|
||||
|
||||
impl PartialEq for FunctionCall {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.function_expression == other.function_expression
|
||||
&& self.type_arguments == other.type_arguments
|
||||
&& self.value_arguments == other.value_arguments
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for FunctionCall {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for FunctionCall {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
let function_cmp = self.function_expression.cmp(&other.function_expression);
|
||||
|
||||
if function_cmp.is_eq() {
|
||||
let type_arg_cmp = self.type_arguments.cmp(&other.type_arguments);
|
||||
|
||||
if type_arg_cmp.is_eq() {
|
||||
self.value_arguments.cmp(&other.value_arguments)
|
||||
} else {
|
||||
type_arg_cmp
|
||||
}
|
||||
} else {
|
||||
function_cmp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,11 @@ pub mod type_constructor;
|
||||
pub mod value_node;
|
||||
pub mod r#while;
|
||||
|
||||
use std::{cmp::Ordering, ops::Index};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
fmt::{self, Display, Formatter},
|
||||
ops::Index,
|
||||
};
|
||||
|
||||
use chumsky::span::{SimpleSpan, Span};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -77,6 +81,12 @@ impl<T> WithPos for T {}
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct SourcePosition(pub usize, pub usize);
|
||||
|
||||
impl Display for SourcePosition {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "({}, {})", self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SimpleSpan> for SourcePosition {
|
||||
fn from(span: SimpleSpan) -> Self {
|
||||
SourcePosition(span.start(), span.end())
|
||||
|
@ -53,6 +53,8 @@ impl Statement {
|
||||
|
||||
impl AbstractNode for Statement {
|
||||
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||
log::trace!("Defining types for statement at {}", self.position());
|
||||
|
||||
match self {
|
||||
Statement::Expression(expression) => expression.define_types(_context),
|
||||
Statement::IfElse(if_else) => if_else.node.define_types(_context),
|
||||
@ -73,6 +75,8 @@ impl AbstractNode for Statement {
|
||||
}
|
||||
|
||||
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||
log::trace!("Validating statement at {}", self.position());
|
||||
|
||||
match self {
|
||||
Statement::Assignment(assignment) => assignment.node.validate(_context, _manage_memory),
|
||||
Statement::AsyncBlock(async_block) => {
|
||||
@ -93,6 +97,8 @@ impl AbstractNode for Statement {
|
||||
context: &Context,
|
||||
manage_memory: bool,
|
||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||
log::trace!("Evaluating statement at {}", self.position());
|
||||
|
||||
let result = match self {
|
||||
Statement::Assignment(assignment) => assignment.node.evaluate(context, manage_memory),
|
||||
Statement::AsyncBlock(async_block) => async_block.node.evaluate(context, manage_memory),
|
||||
|
@ -95,7 +95,7 @@ impl Context {
|
||||
if let Some((VariableData::Value(value), _)) = data.variables.get(identifier) {
|
||||
Ok(Some(value.clone()))
|
||||
} else if let Some(parent) = &data.parent {
|
||||
parent.use_value(identifier)
|
||||
parent.get_value(identifier)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
@ -149,17 +149,22 @@ impl Context {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.data
|
||||
.write()?
|
||||
.variables
|
||||
.retain(|_, (value_data, usage_data)| match value_data {
|
||||
self.data.write()?.variables.retain(
|
||||
|identifier, (value_data, usage_data)| match value_data {
|
||||
VariableData::Type(_) => true,
|
||||
VariableData::Value(_) => {
|
||||
let usage = usage_data.inner().read().unwrap();
|
||||
|
||||
usage.actual < usage.expected
|
||||
if usage.actual < usage.expected {
|
||||
true
|
||||
} else {
|
||||
log::trace!("Removing {identifier}.");
|
||||
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
*self.is_clean.write()? = true;
|
||||
|
||||
|
@ -50,9 +50,8 @@ fn main() {
|
||||
Level::Error => "ERROR".red().bold(),
|
||||
Level::Info => "INFO".white().bold(),
|
||||
};
|
||||
let timestamp = buffer.timestamp_seconds().to_string().dimmed();
|
||||
|
||||
writeln!(buffer, "[{} {}] {}", log_level, timestamp, args)
|
||||
writeln!(buffer, "[{}] {}", log_level, args)
|
||||
})
|
||||
.init();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user