From 64ce3d56e4c5edab4e7d489f192a4b0adfc66e72 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 24 Jun 2024 00:38:06 -0400 Subject: [PATCH] Fix function call bug --- dust-lang/src/abstract_tree/expression.rs | 6 + dust-lang/src/abstract_tree/function_call.rs | 115 +++---------------- dust-lang/src/abstract_tree/mod.rs | 12 +- dust-lang/src/abstract_tree/statement.rs | 6 + dust-lang/src/context.rs | 19 +-- dust-shell/src/main.rs | 3 +- 6 files changed, 52 insertions(+), 109 deletions(-) diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index 0efc1ed..13cb0c6 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -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, 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) => { diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index c4c18aa..4e84afe 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -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, type_arguments: Option>, value_arguments: Option>, - - #[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, 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, 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 { - 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 - } - } -} diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index dd66215..be27604 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -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 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 for SourcePosition { fn from(span: SimpleSpan) -> Self { SourcePosition(span.start(), span.end()) diff --git a/dust-lang/src/abstract_tree/statement.rs b/dust-lang/src/abstract_tree/statement.rs index f76372b..eb9f295 100644 --- a/dust-lang/src/abstract_tree/statement.rs +++ b/dust-lang/src/abstract_tree/statement.rs @@ -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, 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), diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index 4735596..4da3bd0 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -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; diff --git a/dust-shell/src/main.rs b/dust-shell/src/main.rs index bdc9af8..a4eb197 100644 --- a/dust-shell/src/main.rs +++ b/dust-shell/src/main.rs @@ -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();