1
0

Fix function call bug

This commit is contained in:
Jeff 2024-06-24 00:38:06 -04:00
parent af20dab0d2
commit 64ce3d56e4
6 changed files with 52 additions and 109 deletions

View File

@ -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) => {

View File

@ -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
}
}
}

View File

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

View File

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

View File

@ -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;

View File

@ -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();