From e6acb8cbb917587c3046193cbb6fccfc958282b3 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 6 Jan 2024 11:17:08 -0500 Subject: [PATCH] Implement function purity --- src/abstract_tree/function_call.rs | 9 +-------- src/abstract_tree/function_node.rs | 30 ++++++++++++++++++++++-------- src/abstract_tree/identifier.rs | 16 +++++++++++----- src/abstract_tree/value_node.rs | 21 +++++++++++++++++++++ src/value/map.rs | 11 +++++++++++ 5 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 202d816..e3316dd 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -120,14 +120,7 @@ impl AbstractTree for FunctionCall { context.set(name.to_string(), value.clone(), None)?; } - value - .as_function() - .map_err(|error| { - println!("{name:?}"); - - error - })? - .call(name, &arguments, source, context) + value.as_function()?.call(name, &arguments, source, context) } fn expected_type(&self, context: &Map) -> Result { diff --git a/src/abstract_tree/function_node.rs b/src/abstract_tree/function_node.rs index 57bb654..ef1e58f 100644 --- a/src/abstract_tree/function_node.rs +++ b/src/abstract_tree/function_node.rs @@ -14,6 +14,7 @@ pub struct FunctionNode { body: Block, r#type: Type, syntax_position: SyntaxPosition, + context: Map, } impl FunctionNode { @@ -22,12 +23,14 @@ impl FunctionNode { body: Block, r#type: Type, syntax_position: SyntaxPosition, + context: Map, ) -> Self { Self { parameters, body, r#type, syntax_position, + context, } } @@ -61,23 +64,24 @@ impl FunctionNode { outer_context: &Map, ) -> Result { let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter()); - let function_context = Map::clone_from(outer_context)?; + + self.context.clone_complex_values_from(outer_context)?; for (identifier, value) in parameter_argument_pairs { let key = identifier.inner().clone(); - function_context.set(key, value.clone(), None)?; + self.context.set(key, value.clone(), None)?; } if let Some(name) = name { - function_context.set( + self.context.set( name, Value::Function(Function::ContextDefined(self.clone())), None, )?; } - let return_value = self.body.run(source, &function_context)?; + let return_value = self.body.run(source, &self.context)?; Ok(return_value) } @@ -107,7 +111,9 @@ impl AbstractTree for FunctionNode { } } - let function_context = Map::clone_from(context)?; + let function_context = Map::new(); + + function_context.clone_complex_values_from(context)?; for (parameter_name, parameter_type) in parameters.iter().zip(parameter_types.iter()) { function_context.set( @@ -126,14 +132,22 @@ impl AbstractTree for FunctionNode { let r#type = Type::function(parameter_types, return_type.take_inner()); let syntax_position = node.range().into(); - Ok(FunctionNode::new(parameters, body, r#type, syntax_position)) + Ok(FunctionNode::new( + parameters, + body, + r#type, + syntax_position, + function_context, + )) } - fn check_type(&self, source: &str, context: &Map) -> Result<()> { + fn check_type(&self, source: &str, _context: &Map) -> Result<()> { self.return_type() - .check(&self.body.expected_type(context)?) + .check(&self.body.expected_type(&self.context)?) .map_err(|error| error.at_source_position(source, self.syntax_position))?; + self.body.check_type(source, &self.context)?; + Ok(()) } diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index eec38f5..00194fc 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -39,19 +39,25 @@ impl AbstractTree for Identifier { fn run(&self, _source: &str, context: &Map) -> Result { if let Some((value, _)) = context.variables()?.get(&self.0) { - if !value.is_none() { - return Ok(value.clone()); - } + Ok(value.clone()) + } else { + Err(Error::VariableIdentifierNotFound(self.0.clone())) } + } - Err(Error::VariableIdentifierNotFound(self.0.clone())) + fn check_type(&self, _source: &str, context: &Map) -> Result<()> { + if let Some(_) = context.variables()?.get(&self.0) { + Ok(()) + } else { + Err(Error::VariableIdentifierNotFound(self.0.clone())) + } } fn expected_type(&self, context: &Map) -> Result { if let Some((_value, r#type)) = context.variables()?.get(&self.0) { Ok(r#type.clone()) } else { - Ok(Type::None) + Err(Error::VariableIdentifierNotFound(self.0.clone())) } } } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 0c742ff..e474a99 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -188,6 +188,27 @@ impl AbstractTree for ValueNode { Ok(value_node) } + fn check_type(&self, _source: &str, _context: &Map) -> Result<()> { + match self { + ValueNode::Boolean(_) => todo!(), + ValueNode::Float(_) => todo!(), + ValueNode::Function(function) => { + if let Function::ContextDefined(function_node) = function { + function_node.check_type(_source, _context)?; + } + } + ValueNode::Integer(_) => todo!(), + ValueNode::String(_) => todo!(), + ValueNode::List(_) => todo!(), + ValueNode::Option(_) => todo!(), + ValueNode::Map(_) => todo!(), + ValueNode::BuiltInValue(_) => todo!(), + ValueNode::Structure(_) => todo!(), + } + + Ok(()) + } + fn run(&self, source: &str, context: &Map) -> Result { let value = match self { ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()), diff --git a/src/value/map.rs b/src/value/map.rs index 0102fc4..d0577ff 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -45,6 +45,17 @@ impl Map { }) } + pub fn clone_complex_values_from(&self, other: &Self) -> Result<()> { + for (key, (value, r#type)) in other.variables()?.iter() { + if value.is_function() { + self.variables_mut()? + .insert(key.clone(), (value.clone(), r#type.clone())); + } + } + + Ok(()) + } + pub fn variables(&self) -> Result>> { Ok(self.variables.read()?) }