From 6bdefd0698ae92d85dd3e422d1e99ff69fa876e8 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 22 Jun 2024 13:55:43 -0400 Subject: [PATCH] Continue major refactoring --- dust-lang/src/abstract_tree/assignment.rs | 5 +- dust-lang/src/abstract_tree/expression.rs | 34 ++++- dust-lang/src/abstract_tree/function_call.rs | 40 +++--- dust-lang/src/abstract_tree/list_index.rs | 2 +- dust-lang/src/abstract_tree/value_node.rs | 137 ++++++++++++------- dust-lang/src/context.rs | 21 ++- dust-lang/src/parser/mod.rs | 4 +- dust-lang/src/parser/tests.rs | 38 ++--- dust-lang/src/value.rs | 65 +++++++-- dust-lang/tests/variables.rs | 4 +- 10 files changed, 223 insertions(+), 127 deletions(-) diff --git a/dust-lang/src/abstract_tree/assignment.rs b/dust-lang/src/abstract_tree/assignment.rs index 5b4bed4..bd14127 100644 --- a/dust-lang/src/abstract_tree/assignment.rs +++ b/dust-lang/src/abstract_tree/assignment.rs @@ -128,7 +128,10 @@ impl AbstractNode for Assignment { (&self.constructor, relevant_statement) { let declared_type = constructor.clone().construct(context)?; - let function_type = function_call.node.function().expected_type(context)?; + let function_type = function_call + .node + .function_expression() + .expected_type(context)?; if let Some(Type::Function { return_type, diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index a344b2a..33d5a77 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -4,6 +4,7 @@ use crate::{ context::Context, error::{RuntimeError, ValidationError}, identifier::Identifier, + value::ValueInner, }; use super::{ @@ -46,7 +47,24 @@ impl AbstractNode for Expression { Expression::As(inner) => inner.node.define_types(_context), Expression::BuiltInFunctionCall(inner) => inner.node.define_types(_context), Expression::FunctionCall(inner) => inner.node.define_types(_context), - Expression::Identifier(_) => Ok(()), + Expression::Identifier(identifier) => { + let found = _context.get_value(&identifier.node)?; + + if let Some(value) = &found { + if let ValueInner::Function(function) = value.inner().as_ref() { + function.body().define_types(_context)?; + } + } + + if found.is_some() { + Ok(()) + } else { + Err(ValidationError::VariableNotFound { + identifier: identifier.node.clone(), + position: identifier.position, + }) + } + } Expression::MapIndex(inner) => inner.node.define_types(_context), Expression::ListIndex(inner) => inner.node.define_types(_context), Expression::Logic(inner) => inner.node.define_types(_context), @@ -65,13 +83,15 @@ impl AbstractNode for Expression { function_call.node.validate(context, manage_memory) } Expression::Identifier(identifier) => { - let found = if manage_memory { - context.add_expected_use(&identifier.node)? - } else { - context.contains(&identifier.node)? - }; + let found = context.get_value(&identifier.node)?; - if found { + if let Some(value) = &found { + if let ValueInner::Function(function) = value.inner().as_ref() { + function.body().validate(context, manage_memory)?; + } + } + + if found.is_some() { Ok(()) } else { Err(ValidationError::VariableNotFound { diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index 0704322..3d61b3c 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -37,7 +37,7 @@ impl FunctionCall { } } - pub fn function(&self) -> &Box { + pub fn function_expression(&self) -> &Box { &self.function_expression } } @@ -126,22 +126,6 @@ impl AbstractNode for FunctionCall { }, )); }; - let mut arguments = Vec::with_capacity(self.value_arguments.len()); - - for expression in self.value_arguments { - let expression_position = expression.position(); - let evaluation = expression.evaluate(context, clear_variables)?; - let value = if let Some(Evaluation::Return(value)) = evaluation { - value - } else { - return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(expression_position), - )); - }; - - arguments.push(value); - } - let function_context = if let Some(context) = self.context.lock()?.clone() { context } else { @@ -161,9 +145,25 @@ impl AbstractNode for FunctionCall { _ => {} } - function - .clone() - .call(arguments, &function_context, clear_variables) + for ((identifier, _), expression) in function + .value_parameters() + .into_iter() + .zip(self.value_arguments.iter()) + { + let expression_position = expression.position(); + let evaluation = expression.clone().evaluate(context, clear_variables)?; + let value = if let Some(Evaluation::Return(value)) = evaluation { + value + } else { + return Err(RuntimeError::ValidationFailure( + ValidationError::ExpectedExpression(expression_position), + )); + }; + + function_context.set_value(identifier.clone(), value)?; + } + + function.clone().call(&function_context, clear_variables) } fn expected_type(&self, context: &Context) -> Result, ValidationError> { diff --git a/dust-lang/src/abstract_tree/list_index.rs b/dust-lang/src/abstract_tree/list_index.rs index 407bb55..464d5ab 100644 --- a/dust-lang/src/abstract_tree/list_index.rs +++ b/dust-lang/src/abstract_tree/list_index.rs @@ -32,7 +32,7 @@ impl AbstractNode for ListIndex { self.collection.validate(context, _manage_memory)?; self.index.validate(context, _manage_memory)?; - let collection_type = if let Some(r#type) = self.index.expected_type(context)? { + let collection_type = if let Some(r#type) = self.collection.expected_type(context)? { r#type } else { return Err(ValidationError::ExpectedExpression( diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index b324c2f..8c6c1ac 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -31,12 +31,23 @@ pub enum ValueNode { name: WithPosition, fields: Vec<(WithPosition, Expression)>, }, - Function { + Function(FunctionNode), +} +impl ValueNode { + pub fn function( type_parameters: Option>, value_parameters: Vec<(Identifier, TypeConstructor)>, return_type: Option, body: WithPosition, - }, + ) -> Self { + ValueNode::Function(FunctionNode { + type_parameters, + value_parameters, + return_type, + body, + context_template: Context::new(None), + }) + } } impl AbstractNode for ValueNode { @@ -64,7 +75,31 @@ impl AbstractNode for ValueNode { expression.define_types(_context)?; } } - ValueNode::Function { body, .. } => { + ValueNode::Function(FunctionNode { + body, + type_parameters, + value_parameters, + context_template, + .. + }) => { + if let Some(type_parameters) = type_parameters { + for identifier in type_parameters { + context_template.set_type( + identifier.clone(), + Type::Generic { + identifier: identifier.clone(), + concrete_type: None, + }, + )?; + } + } + + for (identifier, type_constructor) in value_parameters { + let r#type = type_constructor.clone().construct(&context_template)?; + + context_template.set_type(identifier.clone(), r#type)?; + } + body.node.define_types(_context)?; } _ => {} @@ -122,37 +157,17 @@ impl AbstractNode for ValueNode { return Ok(()); } - if let ValueNode::Function { - type_parameters, - value_parameters, + if let ValueNode::Function(FunctionNode { return_type, body, - } = self + context_template, + .. + }) = self { - let mut function_context = context.create_child(); - - if let Some(type_parameters) = type_parameters { - for identifier in type_parameters { - function_context.set_type( - identifier.clone(), - Type::Generic { - identifier: identifier.clone(), - concrete_type: None, - }, - )?; - } - } - - for (identifier, type_constructor) in value_parameters { - let r#type = type_constructor.clone().construct(&function_context)?; - - function_context.set_type(identifier.clone(), r#type)?; - } - - body.node.validate(&mut function_context, _manage_memory)?; + body.node.validate(&context_template, _manage_memory)?; let ((expected_return, expected_position), actual_return) = - match (return_type, body.node.expected_type(context)?) { + match (return_type, body.node.expected_type(&context_template)?) { (Some(constructor), Some(r#type)) => ( (constructor.construct(context)?, constructor.position()), r#type, @@ -289,26 +304,15 @@ impl AbstractNode for ValueNode { } ValueNode::Range(range) => Value::range(range), ValueNode::String(string) => Value::string(string), - ValueNode::Function { + ValueNode::Function(FunctionNode { type_parameters, value_parameters: constructors, return_type, body, - } => { - let function_context = context.create_child(); - - if let Some(identifiers) = &type_parameters { - for identifier in identifiers { - function_context.set_type( - identifier.clone(), - Type::Generic { - identifier: identifier.clone(), - concrete_type: None, - }, - )?; - } - } - + context_template, + }) => { + let outer_context = context; + let function_context = context_template.create_child(); let mut value_parameters = Vec::with_capacity(constructors.len()); for (identifier, constructor) in constructors { @@ -318,12 +322,18 @@ impl AbstractNode for ValueNode { } let return_type = if let Some(constructor) = return_type { - Some(constructor.construct(&function_context)?) + Some(constructor.construct(&outer_context)?) } else { None }; - Value::function(type_parameters, value_parameters, return_type, body.node) + Value::function( + type_parameters, + value_parameters, + return_type, + body.node, + context_template, + ) } ValueNode::Structure { name, @@ -383,12 +393,12 @@ impl AbstractNode for ValueNode { ValueNode::Map(_) => Type::Map, ValueNode::Range(_) => Type::Range, ValueNode::String(_) => Type::String, - ValueNode::Function { + ValueNode::Function(FunctionNode { type_parameters, value_parameters, return_type, .. - } => { + }) => { let mut value_parameter_types = Vec::with_capacity(value_parameters.len()); for (_, type_constructor) in value_parameters { @@ -511,18 +521,20 @@ impl Ord for ValueNode { } (EnumInstance { .. }, _) => Ordering::Greater, ( - Function { + Function(FunctionNode { type_parameters: left_type_arguments, value_parameters: left_parameters, return_type: left_return, body: left_body, - }, - Function { + .. + }), + Function(FunctionNode { type_parameters: right_type_arguments, value_parameters: right_parameters, return_type: right_return, body: right_body, - }, + .. + }), ) => { let parameter_cmp = left_parameters.cmp(right_parameters); @@ -567,3 +579,22 @@ impl Ord for ValueNode { } } } + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct FunctionNode { + type_parameters: Option>, + value_parameters: Vec<(Identifier, TypeConstructor)>, + return_type: Option, + body: WithPosition, + #[serde(skip)] + context_template: Context, +} + +impl PartialEq for FunctionNode { + fn eq(&self, other: &Self) -> bool { + self.type_parameters == other.type_parameters + && self.value_parameters == other.value_parameters + && self.return_type == other.return_type + && self.body == other.body + } +} diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index def8209..4735596 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -152,19 +152,12 @@ impl Context { self.data .write()? .variables - .retain(|identifier, (value_data, usage_data)| { - if let VariableData::Value(_) = value_data { + .retain(|_, (value_data, usage_data)| match value_data { + VariableData::Type(_) => true, + VariableData::Value(_) => { let usage = usage_data.inner().read().unwrap(); - if usage.actual < usage.expected { - true - } else { - log::trace!("Removing variable {identifier}."); - - false - } - } else { - false + usage.actual < usage.expected } }); @@ -178,6 +171,12 @@ impl Context { } } +impl Default for Context { + fn default() -> Self { + Context::new(None) + } +} + #[derive(Clone, Debug, PartialEq)] pub enum VariableData { Type(Type), diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index 763057e..bd3751b 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -291,12 +291,12 @@ pub fn parser<'src>( .map_with( |(((type_parameters, value_parameters), return_type), body), state| { Expression::Value( - ValueNode::Function { + ValueNode::function( type_parameters, value_parameters, return_type, body, - } + ) .with_position(state.span()), ) }, diff --git a/dust-lang/src/parser/tests.rs b/dust-lang/src/parser/tests.rs index 43914a3..71c4d5a 100644 --- a/dust-lang/src/parser/tests.rs +++ b/dust-lang/src/parser/tests.rs @@ -528,17 +528,17 @@ fn function() { assert_eq!( parse(&lex("fn () -> int { 0 }").unwrap()).unwrap()[0], Statement::Expression(Expression::Value( - ValueNode::Function { - type_parameters: None, - value_parameters: vec![], - return_type: Some(TypeConstructor::Raw( + ValueNode::function( + None, + vec![], + Some(TypeConstructor::Raw( RawTypeConstructor::Integer.with_position((9, 12)) )), - body: Block::new(vec![Statement::Expression(Expression::Value( + Block::new(vec![Statement::Expression(Expression::Value( ValueNode::Integer(0).with_position((15, 16)) ))]) - .with_position((13, 18)) - } + .with_position((13, 18)), + ) .with_position((0, 18)) ),) ); @@ -546,20 +546,20 @@ fn function() { assert_eq!( parse(&lex("fn (x: int) -> int { x }").unwrap()).unwrap()[0], Statement::Expression(Expression::Value( - ValueNode::Function { - type_parameters: None, - value_parameters: vec![( + ValueNode::function( + None, + vec![( Identifier::new("x"), TypeConstructor::Raw(RawTypeConstructor::Integer.with_position((7, 10))) )], - return_type: Some(TypeConstructor::Raw( + Some(TypeConstructor::Raw( RawTypeConstructor::Integer.with_position((15, 18)) )), - body: Block::new(vec![Statement::Expression(Expression::Identifier( + Block::new(vec![Statement::Expression(Expression::Identifier( Identifier::new("x").with_position((21, 22)) ))]) .with_position((19, 24)), - } + ) .with_position((0, 24)) ),) ); @@ -570,9 +570,9 @@ fn function_with_type_arguments() { assert_eq!( parse(&lex("fn |T, U| (x: T, y: U) -> T { x }").unwrap()).unwrap()[0], Statement::Expression(Expression::Value( - ValueNode::Function { - type_parameters: Some(vec![Identifier::new("T"), Identifier::new("U"),]), - value_parameters: vec![ + ValueNode::function( + Some(vec![Identifier::new("T"), Identifier::new("U"),]), + vec![ ( Identifier::new("x"), TypeConstructor::Invokation(TypeInvokationConstructor { @@ -588,15 +588,15 @@ fn function_with_type_arguments() { }) ) ], - return_type: Some(TypeConstructor::Invokation(TypeInvokationConstructor { + Some(TypeConstructor::Invokation(TypeInvokationConstructor { identifier: Identifier::new("T").with_position((26, 27)), type_arguments: None, })), - body: Block::new(vec![Statement::Expression(Expression::Identifier( + Block::new(vec![Statement::Expression(Expression::Identifier( Identifier::new("x").with_position((30, 31)) ))]) .with_position((28, 33)), - } + ) .with_position((0, 33)) )) ) diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index b589286..fe2ca4d 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -16,7 +16,7 @@ use serde::{ use crate::{ abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition}, context::Context, - error::{RuntimeError, ValidationError}, + error::{PoisonError, RuntimeError, ValidationError}, identifier::Identifier, }; @@ -73,12 +73,14 @@ impl Value { value_parameters: Vec<(Identifier, Type)>, return_type: Option, body: Block, + context_template: Context, ) -> Self { Value(Arc::new(ValueInner::Function(Function { type_parameters, value_parameters, return_type, body, + context_template, }))) } @@ -167,6 +169,7 @@ impl Display for Value { value_parameters: parameters, return_type, body, + .. }) => { if let Some(type_parameters) = type_parameters { write!(f, "(")?; @@ -249,6 +252,7 @@ impl Serialize for Value { value_parameters, return_type, body, + .. }) => { let mut struct_ser = serializer.serialize_struct("Function", 4)?; @@ -541,7 +545,7 @@ impl<'de> Deserialize<'de> for Value { } } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] pub enum ValueInner { Boolean(bool), EnumInstance { @@ -707,15 +711,20 @@ impl Ord for ValueInner { } } -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +#[derive(Clone, Debug)] pub struct Function { type_parameters: Option>, value_parameters: Vec<(Identifier, Type)>, return_type: Option, body: Block, + context_template: Context, } impl Function { + pub fn context_template(&self) -> &Context { + &self.context_template + } + pub fn type_parameters(&self) -> &Option> { &self.type_parameters } @@ -730,18 +739,50 @@ impl Function { pub fn call( self, - value_arguments: Vec, context: &Context, manage_memory: bool, ) -> Result, RuntimeError> { - for ((identifier, _), value) in self - .value_parameters - .into_iter() - .zip(value_arguments.into_iter()) - { - context.set_value(identifier.clone(), value)?; - } - self.body.evaluate(context, manage_memory) } + + pub fn populate_context_template(&self) -> Result<(), PoisonError> { + if let Some(type_parameters) = &self.type_parameters { + for identifier in type_parameters { + self.context_template.set_type( + identifier.clone(), + Type::Generic { + identifier: identifier.clone(), + concrete_type: None, + }, + )?; + } + } + + for (identifier, r#type) in &self.value_parameters { + self.context_template + .set_type(identifier.clone(), r#type.clone())?; + } + + Ok(()) + } +} + +impl Eq for Function {} + +impl PartialEq for Function { + fn eq(&self, other: &Self) -> bool { + todo!() + } +} + +impl PartialOrd for Function { + fn partial_cmp(&self, other: &Self) -> Option { + todo!() + } +} + +impl Ord for Function { + fn cmp(&self, other: &Self) -> Ordering { + todo!() + } } diff --git a/dust-lang/tests/variables.rs b/dust-lang/tests/variables.rs index f252b70..5ce1cae 100644 --- a/dust-lang/tests/variables.rs +++ b/dust-lang/tests/variables.rs @@ -1,5 +1,6 @@ use dust_lang::{ abstract_tree::{Block, Expression, Statement, Type, WithPos}, + context::Context, error::{DustError, TypeConflict, ValidationError}, identifier::Identifier, *, @@ -51,7 +52,8 @@ fn function_variable() { Some(Type::Integer), Block::new(vec![Statement::Expression(Expression::Identifier( Identifier::new("x").with_position((30, 31)) - ))]) + ))]), + Context::new(None) ))) ); }