diff --git a/src/abstract_tree/block.rs b/src/abstract_tree/block.rs index bbffc1c..32beb98 100644 --- a/src/abstract_tree/block.rs +++ b/src/abstract_tree/block.rs @@ -23,15 +23,6 @@ use crate::{ pub struct Block { is_async: bool, statements: Vec, - - #[serde(skip)] - context: Context, -} - -impl Block { - pub fn context(&self) -> &Context { - &self.context - } } impl AbstractTree for Block { @@ -62,23 +53,18 @@ impl AbstractTree for Block { Ok(Block { is_async, statements, - context: block_context, }) } fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> { - self.context.inherit_from(_context)?; - for statement in &self.statements { - statement.validate(_source, &self.context)?; + statement.validate(_source, _context)?; } Ok(()) } - fn run(&self, source: &str, context: &Context) -> Result { - self.context.inherit_from(context)?; - + fn run(&self, _source: &str, _context: &Context) -> Result { if self.is_async { let statements = &self.statements; let final_result = RwLock::new(Ok(Value::none())); @@ -87,7 +73,7 @@ impl AbstractTree for Block { .into_par_iter() .enumerate() .find_map_first(|(index, statement)| { - let result = statement.run(source, &self.context); + let result = statement.run(_source, _context); let is_last_statement = index == statements.len() - 1; let is_return_statement = if let Statement::Return(_) = statement { true @@ -117,10 +103,10 @@ impl AbstractTree for Block { for statement in &self.statements { if let Statement::Return(inner_statement) = statement { - return inner_statement.run(source, &self.context); + return inner_statement.run(_source, _context); } - prev_result = Some(statement.run(source, &self.context)); + prev_result = Some(statement.run(_source, _context)); } prev_result.unwrap_or(Ok(Value::none())) @@ -135,9 +121,9 @@ impl AbstractTree for Block { false } }) { - statement.expected_type(&self.context) + statement.expected_type(_context) } else if let Some(statement) = self.statements.last() { - statement.expected_type(&self.context) + statement.expected_type(_context) } else { Ok(Type::None) } diff --git a/src/abstract_tree/for.rs b/src/abstract_tree/for.rs index 02d5b91..cdb923d 100644 --- a/src/abstract_tree/for.rs +++ b/src/abstract_tree/for.rs @@ -15,6 +15,9 @@ pub struct For { collection: Expression, block: Block, source_position: SourcePosition, + + #[serde(skip)] + context: Context, } impl AbstractTree for For { @@ -41,6 +44,8 @@ impl AbstractTree for For { let expression_node = node.child(3).unwrap(); let expression = Expression::from_syntax(expression_node, source, context)?; + let loop_context = Context::with_variables_from(context)?; + let item_node = node.child(4).unwrap(); let item = Block::from_syntax(item_node, source, context)?; @@ -50,6 +55,7 @@ impl AbstractTree for For { collection: expression, block: item, source_position: SourcePosition::from(node.range()), + context: loop_context, }) } @@ -72,8 +78,8 @@ impl AbstractTree for For { }; let key = self.item_id.inner().clone(); - self.block.context().set_type(key, item_type)?; - self.block.validate(_source, context) + self.context.set_type(key, item_type)?; + self.block.validate(_source, &self.context) } fn run(&self, source: &str, context: &Context) -> Result { @@ -83,17 +89,14 @@ impl AbstractTree for For { if let Value::Range(range) = expression_run { if self.is_async { range.into_par_iter().try_for_each(|integer| { - self.block - .context() + self.context .set_value(key.clone(), Value::Integer(integer))?; - self.block.run(source, context).map(|_value| ()) + self.block.run(source, &self.context).map(|_value| ()) })?; } else { for i in range { - self.block - .context() - .set_value(key.clone(), Value::Integer(i))?; - self.block.run(source, context)?; + self.context.set_value(key.clone(), Value::Integer(i))?; + self.block.run(source, &self.context)?; } } @@ -103,20 +106,17 @@ impl AbstractTree for For { if let Value::List(list) = &expression_run { if self.is_async { list.items().par_iter().try_for_each(|value| { - self.block.context().set_value(key.clone(), value.clone())?; - self.block.run(source, context).map(|_value| ()) + self.context.set_value(key.clone(), value.clone())?; + self.block.run(source, &self.context).map(|_value| ()) })?; } else { for value in list.items().iter() { - self.block.context().set_value(key.clone(), value.clone())?; - self.block.run(source, context)?; + self.context.set_value(key.clone(), value.clone())?; + self.block.run(source, &self.context)?; } } } - self.block.context().unset(&key)?; - context.inherit_from(self.block.context())?; - Ok(Value::none()) } } diff --git a/src/abstract_tree/function_node.rs b/src/abstract_tree/function_node.rs index 0b579c5..b468dc1 100644 --- a/src/abstract_tree/function_node.rs +++ b/src/abstract_tree/function_node.rs @@ -14,6 +14,9 @@ pub struct FunctionNode { body: Block, r#type: Type, syntax_position: SourcePosition, + + #[serde(skip)] + context: Context, } impl FunctionNode { @@ -28,6 +31,7 @@ impl FunctionNode { body, r#type, syntax_position, + context: Context::new(), } } @@ -61,28 +65,24 @@ impl FunctionNode { &self, arguments: &[Value], source: &str, - outer_context: &Context, + _context: &Context, ) -> Result { let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter()); for (identifier, value) in parameter_argument_pairs { let key = identifier.inner().clone(); - self.body.context().set_value(key, value.clone())?; + self.context.set_value(key, value.clone())?; } - let return_value = self.body.run(source, outer_context)?; + let return_value = self.body.run(source, &self.context)?; Ok(return_value) } } impl AbstractTree for FunctionNode { - fn from_syntax( - node: SyntaxNode, - source: &str, - outer_context: &Context, - ) -> Result { + fn from_syntax(node: SyntaxNode, source: &str, context: &Context) -> Result { SyntaxError::expect_syntax_node(source, "function", node)?; let child_count = node.child_count(); @@ -93,28 +93,28 @@ impl AbstractTree for FunctionNode { let child = node.child(index).unwrap(); if child.kind() == "identifier" { - let identifier = Identifier::from_syntax(child, source, outer_context)?; + let identifier = Identifier::from_syntax(child, source, context)?; parameters.push(identifier); } if child.kind() == "type_specification" { - let type_specification = - TypeSpecification::from_syntax(child, source, outer_context)?; + let type_specification = TypeSpecification::from_syntax(child, source, context)?; parameter_types.push(type_specification.take_inner()); } } let return_type_node = node.child(child_count - 2).unwrap(); - let return_type = TypeSpecification::from_syntax(return_type_node, source, outer_context)?; + let return_type = TypeSpecification::from_syntax(return_type_node, source, context)?; + + let function_context = Context::with_variables_from(context)?; let body_node = node.child(child_count - 1).unwrap(); - let body = Block::from_syntax(body_node, source, &outer_context)?; + let body = Block::from_syntax(body_node, source, &context)?; for (parameter, parameter_type) in parameters.iter().zip(parameter_types.iter()) { - body.context() - .set_type(parameter.inner().clone(), parameter_type.clone())?; + function_context.set_type(parameter.inner().clone(), parameter_type.clone())?; } let r#type = Type::function(parameter_types, return_type.take_inner()); @@ -125,6 +125,7 @@ impl AbstractTree for FunctionNode { body, r#type, syntax_position, + context: function_context, }) } diff --git a/src/context.rs b/src/context.rs index b3db8cf..25418d0 100644 --- a/src/context.rs +++ b/src/context.rs @@ -38,7 +38,13 @@ impl Context { let mut self_variables = self.inner.write()?; for (identifier, value_data) in other.inner.read()?.iter() { - self_variables.insert(identifier.clone(), value_data.clone()); + let existing_data = self_variables.get(identifier); + + if let Some(ValueData::Value { .. }) = existing_data { + continue; + } else { + self_variables.insert(identifier.clone(), value_data.clone()); + } } Ok(()) diff --git a/tests/for_loop.rs b/tests/for_loop.rs index 221d5ea..110fb4d 100644 --- a/tests/for_loop.rs +++ b/tests/for_loop.rs @@ -74,7 +74,7 @@ fn modify_map() { } #[test] -fn modify_list_values() { +fn do_not_modify_list_values() { let result = interpret( " list = [1 2 3] @@ -85,39 +85,14 @@ fn modify_list_values() { assert_eq!( Ok(Value::List(List::with_items(vec![ + Value::Integer(1), Value::Integer(2), Value::Integer(3), - Value::Integer(4), ]))), result ); } -#[test] -fn modify_map_values() { - let result = interpret( - " - map = { - x = 0 - y = 1 - } - - for [key, value] in map { - value += 1 - } - - map - ", - ); - - let map = Map::new(); - - map.set("x".to_string(), Value::Integer(1)).unwrap(); - map.set("y".to_string(), Value::Integer(2)).unwrap(); - - assert_eq!(Ok(Value::Map(map)), result); -} - #[test] fn r#break() { let result = interpret(