1
0

Move block contexts to loops and function

This commit is contained in:
Jeff 2024-02-12 16:51:06 -05:00
parent 1e665a6f13
commit daf78919da
5 changed files with 48 additions and 80 deletions

View File

@ -23,15 +23,6 @@ use crate::{
pub struct Block { pub struct Block {
is_async: bool, is_async: bool,
statements: Vec<Statement>, statements: Vec<Statement>,
#[serde(skip)]
context: Context,
}
impl Block {
pub fn context(&self) -> &Context {
&self.context
}
} }
impl AbstractTree for Block { impl AbstractTree for Block {
@ -62,23 +53,18 @@ impl AbstractTree for Block {
Ok(Block { Ok(Block {
is_async, is_async,
statements, statements,
context: block_context,
}) })
} }
fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> {
self.context.inherit_from(_context)?;
for statement in &self.statements { for statement in &self.statements {
statement.validate(_source, &self.context)?; statement.validate(_source, _context)?;
} }
Ok(()) Ok(())
} }
fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> { fn run(&self, _source: &str, _context: &Context) -> Result<Value, RuntimeError> {
self.context.inherit_from(context)?;
if self.is_async { if self.is_async {
let statements = &self.statements; let statements = &self.statements;
let final_result = RwLock::new(Ok(Value::none())); let final_result = RwLock::new(Ok(Value::none()));
@ -87,7 +73,7 @@ impl AbstractTree for Block {
.into_par_iter() .into_par_iter()
.enumerate() .enumerate()
.find_map_first(|(index, statement)| { .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_last_statement = index == statements.len() - 1;
let is_return_statement = if let Statement::Return(_) = statement { let is_return_statement = if let Statement::Return(_) = statement {
true true
@ -117,10 +103,10 @@ impl AbstractTree for Block {
for statement in &self.statements { for statement in &self.statements {
if let Statement::Return(inner_statement) = statement { 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())) prev_result.unwrap_or(Ok(Value::none()))
@ -135,9 +121,9 @@ impl AbstractTree for Block {
false false
} }
}) { }) {
statement.expected_type(&self.context) statement.expected_type(_context)
} else if let Some(statement) = self.statements.last() { } else if let Some(statement) = self.statements.last() {
statement.expected_type(&self.context) statement.expected_type(_context)
} else { } else {
Ok(Type::None) Ok(Type::None)
} }

View File

@ -15,6 +15,9 @@ pub struct For {
collection: Expression, collection: Expression,
block: Block, block: Block,
source_position: SourcePosition, source_position: SourcePosition,
#[serde(skip)]
context: Context,
} }
impl AbstractTree for For { impl AbstractTree for For {
@ -41,6 +44,8 @@ impl AbstractTree for For {
let expression_node = node.child(3).unwrap(); let expression_node = node.child(3).unwrap();
let expression = Expression::from_syntax(expression_node, source, context)?; 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_node = node.child(4).unwrap();
let item = Block::from_syntax(item_node, source, context)?; let item = Block::from_syntax(item_node, source, context)?;
@ -50,6 +55,7 @@ impl AbstractTree for For {
collection: expression, collection: expression,
block: item, block: item,
source_position: SourcePosition::from(node.range()), source_position: SourcePosition::from(node.range()),
context: loop_context,
}) })
} }
@ -72,8 +78,8 @@ impl AbstractTree for For {
}; };
let key = self.item_id.inner().clone(); let key = self.item_id.inner().clone();
self.block.context().set_type(key, item_type)?; self.context.set_type(key, item_type)?;
self.block.validate(_source, context) self.block.validate(_source, &self.context)
} }
fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> { fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
@ -83,17 +89,14 @@ impl AbstractTree for For {
if let Value::Range(range) = expression_run { if let Value::Range(range) = expression_run {
if self.is_async { if self.is_async {
range.into_par_iter().try_for_each(|integer| { range.into_par_iter().try_for_each(|integer| {
self.block self.context
.context()
.set_value(key.clone(), Value::Integer(integer))?; .set_value(key.clone(), Value::Integer(integer))?;
self.block.run(source, context).map(|_value| ()) self.block.run(source, &self.context).map(|_value| ())
})?; })?;
} else { } else {
for i in range { for i in range {
self.block self.context.set_value(key.clone(), Value::Integer(i))?;
.context() self.block.run(source, &self.context)?;
.set_value(key.clone(), Value::Integer(i))?;
self.block.run(source, context)?;
} }
} }
@ -103,20 +106,17 @@ impl AbstractTree for For {
if let Value::List(list) = &expression_run { if let Value::List(list) = &expression_run {
if self.is_async { if self.is_async {
list.items().par_iter().try_for_each(|value| { list.items().par_iter().try_for_each(|value| {
self.block.context().set_value(key.clone(), value.clone())?; self.context.set_value(key.clone(), value.clone())?;
self.block.run(source, context).map(|_value| ()) self.block.run(source, &self.context).map(|_value| ())
})?; })?;
} else { } else {
for value in list.items().iter() { for value in list.items().iter() {
self.block.context().set_value(key.clone(), value.clone())?; self.context.set_value(key.clone(), value.clone())?;
self.block.run(source, context)?; self.block.run(source, &self.context)?;
} }
} }
} }
self.block.context().unset(&key)?;
context.inherit_from(self.block.context())?;
Ok(Value::none()) Ok(Value::none())
} }
} }

View File

@ -14,6 +14,9 @@ pub struct FunctionNode {
body: Block, body: Block,
r#type: Type, r#type: Type,
syntax_position: SourcePosition, syntax_position: SourcePosition,
#[serde(skip)]
context: Context,
} }
impl FunctionNode { impl FunctionNode {
@ -28,6 +31,7 @@ impl FunctionNode {
body, body,
r#type, r#type,
syntax_position, syntax_position,
context: Context::new(),
} }
} }
@ -61,28 +65,24 @@ impl FunctionNode {
&self, &self,
arguments: &[Value], arguments: &[Value],
source: &str, source: &str,
outer_context: &Context, _context: &Context,
) -> Result<Value, RuntimeError> { ) -> Result<Value, RuntimeError> {
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter()); let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
for (identifier, value) in parameter_argument_pairs { for (identifier, value) in parameter_argument_pairs {
let key = identifier.inner().clone(); 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) Ok(return_value)
} }
} }
impl AbstractTree for FunctionNode { impl AbstractTree for FunctionNode {
fn from_syntax( fn from_syntax(node: SyntaxNode, source: &str, context: &Context) -> Result<Self, SyntaxError> {
node: SyntaxNode,
source: &str,
outer_context: &Context,
) -> Result<Self, SyntaxError> {
SyntaxError::expect_syntax_node(source, "function", node)?; SyntaxError::expect_syntax_node(source, "function", node)?;
let child_count = node.child_count(); let child_count = node.child_count();
@ -93,28 +93,28 @@ impl AbstractTree for FunctionNode {
let child = node.child(index).unwrap(); let child = node.child(index).unwrap();
if child.kind() == "identifier" { if child.kind() == "identifier" {
let identifier = Identifier::from_syntax(child, source, outer_context)?; let identifier = Identifier::from_syntax(child, source, context)?;
parameters.push(identifier); parameters.push(identifier);
} }
if child.kind() == "type_specification" { if child.kind() == "type_specification" {
let type_specification = let type_specification = TypeSpecification::from_syntax(child, source, context)?;
TypeSpecification::from_syntax(child, source, outer_context)?;
parameter_types.push(type_specification.take_inner()); parameter_types.push(type_specification.take_inner());
} }
} }
let return_type_node = node.child(child_count - 2).unwrap(); 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_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()) { for (parameter, parameter_type) in parameters.iter().zip(parameter_types.iter()) {
body.context() function_context.set_type(parameter.inner().clone(), parameter_type.clone())?;
.set_type(parameter.inner().clone(), parameter_type.clone())?;
} }
let r#type = Type::function(parameter_types, return_type.take_inner()); let r#type = Type::function(parameter_types, return_type.take_inner());
@ -125,6 +125,7 @@ impl AbstractTree for FunctionNode {
body, body,
r#type, r#type,
syntax_position, syntax_position,
context: function_context,
}) })
} }

View File

@ -38,7 +38,13 @@ impl Context {
let mut self_variables = self.inner.write()?; let mut self_variables = self.inner.write()?;
for (identifier, value_data) in other.inner.read()?.iter() { 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(()) Ok(())

View File

@ -74,7 +74,7 @@ fn modify_map() {
} }
#[test] #[test]
fn modify_list_values() { fn do_not_modify_list_values() {
let result = interpret( let result = interpret(
" "
list = [1 2 3] list = [1 2 3]
@ -85,39 +85,14 @@ fn modify_list_values() {
assert_eq!( assert_eq!(
Ok(Value::List(List::with_items(vec![ Ok(Value::List(List::with_items(vec![
Value::Integer(1),
Value::Integer(2), Value::Integer(2),
Value::Integer(3), Value::Integer(3),
Value::Integer(4),
]))), ]))),
result 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] #[test]
fn r#break() { fn r#break() {
let result = interpret( let result = interpret(