1
0

Remove reference counted thread lock from map type

This commit is contained in:
Jeff 2024-01-03 13:15:19 -05:00
parent 4b22221322
commit 7f7772e654
29 changed files with 173 additions and 184 deletions

View File

@ -19,7 +19,7 @@ pub enum AssignmentOperator {
} }
impl AbstractTree for Assignment { impl AbstractTree for Assignment {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "assignment", node)?; Error::expect_syntax_node(source, "assignment", node)?;
let child_count = node.child_count(); let child_count = node.child_count();
@ -57,13 +57,13 @@ impl AbstractTree for Assignment {
let variable_key = identifier.inner().clone(); let variable_key = identifier.inner().clone();
let variable_type = if let Some(definition) = &type_definition { let variable_type = if let Some(definition) = &type_definition {
definition.inner().clone() definition.inner().clone()
} else if let Some((_, r#type)) = context.variables()?.get(identifier.inner()) { } else if let Some((_, r#type)) = context.variables().get(identifier.inner()) {
r#type.clone() r#type.clone()
} else { } else {
statement.expected_type(context)? statement.expected_type(context)?
}; };
context.set(variable_key, Value::none(), Some(variable_type))?; context.set(variable_key, Value::none(), Some(variable_type));
Ok(Assignment { Ok(Assignment {
identifier, identifier,
@ -107,13 +107,13 @@ impl AbstractTree for Assignment {
Ok(()) Ok(())
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let key = self.identifier.inner(); let key = self.identifier.inner();
let value = self.statement.run(source, context)?; let value = self.statement.run(source, context)?;
let new_value = match self.operator { let new_value = match self.operator {
AssignmentOperator::PlusEqual => { AssignmentOperator::PlusEqual => {
if let Some((mut previous_value, _)) = context.variables()?.get(key).cloned() { if let Some((mut previous_value, _)) = context.variables().get(key).cloned() {
previous_value += value; previous_value += value;
previous_value previous_value
} else { } else {
@ -121,7 +121,7 @@ impl AbstractTree for Assignment {
} }
} }
AssignmentOperator::MinusEqual => { AssignmentOperator::MinusEqual => {
if let Some((mut previous_value, _)) = context.variables()?.get(key).cloned() { if let Some((mut previous_value, _)) = context.variables().get(key).cloned() {
previous_value -= value; previous_value -= value;
previous_value previous_value
} else { } else {
@ -132,9 +132,9 @@ impl AbstractTree for Assignment {
}; };
if let Some(type_defintion) = &self.type_definition { if let Some(type_defintion) = &self.type_definition {
context.set(key.clone(), new_value, Some(type_defintion.inner().clone()))?; context.set(key.clone(), new_value, Some(type_defintion.inner().clone()));
} else { } else {
context.set(key.clone(), new_value, None)?; context.set(key.clone(), new_value, None);
} }
Ok(Value::none()) Ok(Value::none())

View File

@ -21,7 +21,7 @@ pub struct Block {
} }
impl AbstractTree for Block { impl AbstractTree for Block {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "block", node)?; Error::expect_syntax_node(source, "block", node)?;
let first_child = node.child(0).unwrap(); let first_child = node.child(0).unwrap();
@ -62,16 +62,22 @@ impl AbstractTree for Block {
Ok(()) Ok(())
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
if self.is_async { if self.is_async {
let statements = &self.statements; let statements = &self.statements;
let context = RwLock::new(context);
let final_result = RwLock::new(Ok(Value::none())); let final_result = RwLock::new(Ok(Value::none()));
statements statements
.into_par_iter() .into_par_iter()
.enumerate() .enumerate()
.find_map_first(|(index, statement)| { .find_map_first(|(index, statement)| {
let result = statement.run(source, context); let mut context = match context.write() {
Ok(context) => context,
Err(error) => return Some(Err(error.into())),
};
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
@ -82,9 +88,7 @@ impl AbstractTree for Block {
if is_return_statement || result.is_err() { if is_return_statement || result.is_err() {
Some(result) Some(result)
} else if is_last_statement { } else if is_last_statement {
let get_write_lock = final_result.write(); match final_result.write() {
match get_write_lock {
Ok(mut final_result) => { Ok(mut final_result) => {
*final_result = result; *final_result = result;
None None

View File

@ -51,39 +51,33 @@ impl BuiltInValue {
&Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual)) &Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual))
} }
BuiltInValue::Fs => FS.get_or_init(|| { BuiltInValue::Fs => FS.get_or_init(|| {
let fs_context = Map::new(); let mut fs_context = Map::new();
fs_context fs_context.set(
.set(
"read".to_string(), "read".to_string(),
Value::Function(Function::BuiltIn(BuiltInFunction::FsRead)), Value::Function(Function::BuiltIn(BuiltInFunction::FsRead)),
None, None,
) );
.unwrap();
Value::Map(fs_context) Value::Map(fs_context)
}), }),
BuiltInValue::Json => JSON.get_or_init(|| { BuiltInValue::Json => JSON.get_or_init(|| {
let json_context = Map::new(); let mut json_context = Map::new();
json_context json_context.set(
.set(
"parse".to_string(), "parse".to_string(),
Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)), Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)),
None, None,
) );
.unwrap();
Value::Map(json_context) Value::Map(json_context)
}), }),
BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)), BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)), BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
BuiltInValue::Random => RANDOM.get_or_init(|| { BuiltInValue::Random => RANDOM.get_or_init(|| {
let random_context = Map::new(); let mut random_context = Map::new();
{ {
let mut variables = random_context.variables_mut().unwrap();
for built_in_function in [ for built_in_function in [
BuiltInFunction::RandomBoolean, BuiltInFunction::RandomBoolean,
BuiltInFunction::RandomFloat, BuiltInFunction::RandomFloat,
@ -94,18 +88,16 @@ impl BuiltInValue {
let value = Value::Function(Function::BuiltIn(built_in_function)); let value = Value::Function(Function::BuiltIn(built_in_function));
let r#type = built_in_function.r#type(); let r#type = built_in_function.r#type();
variables.insert(key, (value, r#type)); random_context.set(key, value, Some(r#type));
} }
} }
Value::Map(random_context) Value::Map(random_context)
}), }),
BuiltInValue::String => STRING.get_or_init(|| { BuiltInValue::String => STRING.get_or_init(|| {
let string_context = Map::new(); let mut string_context = Map::new();
{ {
let mut variables = string_context.variables_mut().unwrap();
for string_function in string_functions() { for string_function in string_functions() {
let key = string_function.name().to_string(); let key = string_function.name().to_string();
let value = Value::Function(Function::BuiltIn(BuiltInFunction::String( let value = Value::Function(Function::BuiltIn(BuiltInFunction::String(
@ -113,7 +105,7 @@ impl BuiltInValue {
))); )));
let r#type = string_function.r#type(); let r#type = string_function.r#type();
variables.insert(key, (value, r#type)); string_context.set(key, value, Some(r#type));
} }
} }
@ -124,7 +116,7 @@ impl BuiltInValue {
} }
impl AbstractTree for BuiltInValue { impl AbstractTree for BuiltInValue {
fn from_syntax_node(_source: &str, node: Node, _context: &Map) -> Result<Self> { fn from_syntax_node(_source: &str, node: Node, _context: &mut Map) -> Result<Self> {
let built_in_value = match node.kind() { let built_in_value = match node.kind() {
"args" => BuiltInValue::Args, "args" => BuiltInValue::Args,
"assert_equal" => BuiltInValue::AssertEqual, "assert_equal" => BuiltInValue::AssertEqual,
@ -144,7 +136,7 @@ impl AbstractTree for BuiltInValue {
Ok(()) Ok(())
} }
fn run(&self, _source: &str, _context: &Map) -> Result<Value> { fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> {
Ok(self.get().clone()) Ok(self.get().clone())
} }

View File

@ -24,7 +24,7 @@ pub enum Expression {
} }
impl AbstractTree for Expression { impl AbstractTree for Expression {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "expression", node)?; Error::expect_syntax_node(source, "expression", node)?;
let child = if node.child(0).unwrap().is_named() { let child = if node.child(0).unwrap().is_named() {
@ -65,7 +65,7 @@ impl AbstractTree for Expression {
Ok(expression) Ok(expression)
} }
fn run(&self, _source: &str, _context: &Map) -> Result<Value> { fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> {
match self { match self {
Expression::Value(value_node) => value_node.run(_source, _context), Expression::Value(value_node) => value_node.run(_source, _context),
Expression::Identifier(identifier) => identifier.run(_source, _context), Expression::Identifier(identifier) => identifier.run(_source, _context),

View File

@ -14,7 +14,7 @@ pub struct For {
} }
impl AbstractTree for For { impl AbstractTree for For {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "for", node)?; Error::expect_syntax_node(source, "for", node)?;
let for_node = node.child(0).unwrap(); let for_node = node.child(0).unwrap();
@ -48,26 +48,26 @@ impl AbstractTree for For {
}) })
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let expression_run = self.collection.run(source, context)?; let expression_run = self.collection.run(source, context)?;
let values = expression_run.as_list()?.items(); let values = expression_run.as_list()?.items();
let key = self.item_id.inner(); let key = self.item_id.inner();
if self.is_async { if self.is_async {
values.par_iter().try_for_each(|value| { values.par_iter().try_for_each(|value| {
let iter_context = Map::clone_from(context)?; let mut iter_context = Map::clone_from(context)?;
iter_context.set(key.clone(), value.clone(), None)?; iter_context.set(key.clone(), value.clone(), None);
self.block.run(source, &iter_context).map(|_value| ()) self.block.run(source, &mut iter_context).map(|_value| ())
})?; })?;
} else { } else {
let loop_context = Map::clone_from(context)?; let mut loop_context = Map::clone_from(context)?;
for value in values.iter() { for value in values.iter() {
loop_context.set(key.clone(), value.clone(), None)?; loop_context.set(key.clone(), value.clone(), None);
self.block.run(source, &loop_context)?; self.block.run(source, &mut loop_context)?;
} }
} }

View File

@ -19,7 +19,7 @@ impl FunctionCall {
} }
impl AbstractTree for FunctionCall { impl AbstractTree for FunctionCall {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "function_call", node)?; Error::expect_syntax_node(source, "function_call", node)?;
let function_node = node.child(0).unwrap(); let function_node = node.child(0).unwrap();
@ -80,11 +80,11 @@ impl AbstractTree for FunctionCall {
Ok(()) Ok(())
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let (name, value) = match &self.function_expression { let (name, value) = match &self.function_expression {
FunctionExpression::Identifier(identifier) => { FunctionExpression::Identifier(identifier) => {
let key = identifier.inner(); let key = identifier.inner();
let variables = context.variables()?; let variables = context.variables();
if let Some((value, _)) = variables.get(key) { if let Some((value, _)) = variables.get(key) {
(Some(key.clone()), value.clone()) (Some(key.clone()), value.clone())
@ -111,7 +111,7 @@ impl AbstractTree for FunctionCall {
} }
if let Some(name) = &name { if let Some(name) = &name {
context.set(name.to_string(), value.clone(), None)?; context.set(name.to_string(), value.clone(), None);
} }
value value

View File

@ -16,7 +16,7 @@ pub enum FunctionExpression {
} }
impl AbstractTree for FunctionExpression { impl AbstractTree for FunctionExpression {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "function_expression", node)?; Error::expect_syntax_node(source, "function_expression", node)?;
let first_child = node.child(0).unwrap(); let first_child = node.child(0).unwrap();
@ -54,7 +54,7 @@ impl AbstractTree for FunctionExpression {
Ok(function_expression) Ok(function_expression)
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
match self { match self {
FunctionExpression::Identifier(identifier) => identifier.run(source, context), FunctionExpression::Identifier(identifier) => identifier.run(source, context),
FunctionExpression::FunctionCall(function_call) => function_call.run(source, context), FunctionExpression::FunctionCall(function_call) => function_call.run(source, context),

View File

@ -25,7 +25,7 @@ impl Identifier {
} }
impl AbstractTree for Identifier { impl AbstractTree for Identifier {
fn from_syntax_node(source: &str, node: Node, _context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, _context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "identifier", node)?; Error::expect_syntax_node(source, "identifier", node)?;
let text = &source[node.byte_range()]; let text = &source[node.byte_range()];
@ -35,8 +35,8 @@ impl AbstractTree for Identifier {
Ok(Identifier(text.to_string())) Ok(Identifier(text.to_string()))
} }
fn run(&self, _source: &str, context: &Map) -> Result<Value> { fn run(&self, _source: &str, context: &mut Map) -> Result<Value> {
if let Some((value, _)) = context.variables()?.get(&self.0) { if let Some((value, _)) = context.variables().get(&self.0) {
Ok(value.clone()) Ok(value.clone())
} else { } else {
Err(Error::VariableIdentifierNotFound(self.inner().clone())) Err(Error::VariableIdentifierNotFound(self.inner().clone()))
@ -48,7 +48,7 @@ impl AbstractTree for Identifier {
} }
fn expected_type(&self, context: &Map) -> Result<Type> { fn expected_type(&self, context: &Map) -> Result<Type> {
if let Some((_value, r#type)) = context.variables()?.get(&self.0) { if let Some((_value, r#type)) = context.variables().get(&self.0) {
Ok(r#type.clone()) Ok(r#type.clone())
} else { } else {
Ok(Type::None) Ok(Type::None)

View File

@ -13,7 +13,7 @@ pub struct IfElse {
} }
impl AbstractTree for IfElse { impl AbstractTree for IfElse {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
let if_expression_node = node.child(0).unwrap().child(1).unwrap(); let if_expression_node = node.child(0).unwrap().child(1).unwrap();
let if_expression = Expression::from_syntax_node(source, if_expression_node, context)?; let if_expression = Expression::from_syntax_node(source, if_expression_node, context)?;
@ -55,7 +55,7 @@ impl AbstractTree for IfElse {
}) })
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let if_boolean = self.if_expression.run(source, context)?.as_boolean()?; let if_boolean = self.if_expression.run(source, context)?.as_boolean()?;
if if_boolean { if if_boolean {

View File

@ -14,7 +14,7 @@ pub struct Index {
} }
impl AbstractTree for Index { impl AbstractTree for Index {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "index", node)?; Error::expect_syntax_node(source, "index", node)?;
let collection_node = node.child(0).unwrap(); let collection_node = node.child(0).unwrap();
@ -41,7 +41,7 @@ impl AbstractTree for Index {
}) })
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let collection = self.collection.run(source, context)?; let collection = self.collection.run(source, context)?;
match collection { match collection {
@ -63,7 +63,7 @@ impl AbstractTree for Index {
let value = if let IndexExpression::Identifier(identifier) = &self.index { let value = if let IndexExpression::Identifier(identifier) = &self.index {
let key = identifier.inner(); let key = identifier.inner();
map.variables()? map.variables()
.get(key) .get(key)
.map(|(value, _)| value.clone()) .map(|(value, _)| value.clone())
.unwrap_or_default() .unwrap_or_default()
@ -71,7 +71,7 @@ impl AbstractTree for Index {
let value = self.index.run(source, context)?; let value = self.index.run(source, context)?;
let key = value.as_string()?; let key = value.as_string()?;
map.variables()? map.variables()
.get(key.as_str()) .get(key.as_str())
.map(|(value, _)| value.clone()) .map(|(value, _)| value.clone())
.unwrap_or_default() .unwrap_or_default()

View File

@ -18,7 +18,7 @@ pub enum AssignmentOperator {
} }
impl AbstractTree for IndexAssignment { impl AbstractTree for IndexAssignment {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "index_assignment", node)?; Error::expect_syntax_node(source, "index_assignment", node)?;
let index_node = node.child(0).unwrap(); let index_node = node.child(0).unwrap();
@ -49,9 +49,16 @@ impl AbstractTree for IndexAssignment {
}) })
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let index_collection = self.index.collection.run(source, context)?; let index_collection = self.index.collection.run(source, context)?;
let index_context = index_collection.as_map().unwrap_or(context); let value = self.statement.run(source, context)?;
let mut index_context = if let Value::Map(map) = index_collection {
map
} else {
return Err(Error::ExpectedCollection {
actual: index_collection,
});
};
let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index { let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index {
identifier.inner() identifier.inner()
} else { } else {
@ -60,12 +67,10 @@ impl AbstractTree for IndexAssignment {
)); ));
}; };
let value = self.statement.run(source, context)?;
let new_value = match self.operator { let new_value = match self.operator {
AssignmentOperator::PlusEqual => { AssignmentOperator::PlusEqual => {
if let Some((mut previous_value, _)) = if let Some((mut previous_value, _)) =
index_context.variables()?.get(index_key).cloned() index_context.variables().get(index_key).cloned()
{ {
previous_value += value; previous_value += value;
previous_value previous_value
@ -75,7 +80,7 @@ impl AbstractTree for IndexAssignment {
} }
AssignmentOperator::MinusEqual => { AssignmentOperator::MinusEqual => {
if let Some((mut previous_value, _)) = if let Some((mut previous_value, _)) =
index_context.variables()?.get(index_key).cloned() index_context.variables().get(index_key).cloned()
{ {
previous_value -= value; previous_value -= value;
previous_value previous_value
@ -86,7 +91,7 @@ impl AbstractTree for IndexAssignment {
AssignmentOperator::Equal => value, AssignmentOperator::Equal => value,
}; };
index_context.set(index_key.clone(), new_value, None)?; index_context.set(index_key.clone(), new_value, None);
Ok(Value::none()) Ok(Value::none())
} }

View File

@ -14,7 +14,7 @@ pub enum IndexExpression {
} }
impl AbstractTree for IndexExpression { impl AbstractTree for IndexExpression {
fn from_syntax_node(source: &str, node: tree_sitter::Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: tree_sitter::Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "index_expression", node)?; Error::expect_syntax_node(source, "index_expression", node)?;
let first_child = node.child(0).unwrap(); let first_child = node.child(0).unwrap();
@ -52,7 +52,7 @@ impl AbstractTree for IndexExpression {
Ok(()) Ok(())
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
match self { match self {
IndexExpression::Value(value_node) => value_node.run(source, context), IndexExpression::Value(value_node) => value_node.run(source, context),
IndexExpression::Identifier(identifier) => identifier.run(source, context), IndexExpression::Identifier(identifier) => identifier.run(source, context),

View File

@ -12,7 +12,7 @@ pub struct Logic {
} }
impl AbstractTree for Logic { impl AbstractTree for Logic {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "logic", node)?; Error::expect_syntax_node(source, "logic", node)?;
let first_node = node.child(0).unwrap(); let first_node = node.child(0).unwrap();
@ -59,7 +59,7 @@ impl AbstractTree for Logic {
}) })
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let left = self.left.run(source, context)?; let left = self.left.run(source, context)?;
let right = self.right.run(source, context)?; let right = self.right.run(source, context)?;
let result = match self.operator { let result = match self.operator {

View File

@ -17,7 +17,7 @@ pub struct Match {
} }
impl AbstractTree for Match { impl AbstractTree for Match {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "match", node)?; Error::expect_syntax_node(source, "match", node)?;
let matcher_node = node.child(1).unwrap(); let matcher_node = node.child(1).unwrap();
@ -58,7 +58,7 @@ impl AbstractTree for Match {
}) })
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let matcher_value = self.matcher.run(source, context)?; let matcher_value = self.matcher.run(source, context)?;
for (expression, statement) in &self.options { for (expression, statement) in &self.options {

View File

@ -15,7 +15,7 @@ pub struct Math {
} }
impl AbstractTree for Math { impl AbstractTree for Math {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "math", node)?; Error::expect_syntax_node(source, "math", node)?;
let left_node = node.child(0).unwrap(); let left_node = node.child(0).unwrap();
@ -48,7 +48,7 @@ impl AbstractTree for Math {
}) })
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let left = self.left.run(source, context)?; let left = self.left.run(source, context)?;
let right = self.right.run(source, context)?; let right = self.right.run(source, context)?;
let value = match self.operator { let value = match self.operator {

View File

@ -43,7 +43,7 @@ pub struct Root {
} }
impl AbstractTree for Root { impl AbstractTree for Root {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "root", node)?; Error::expect_syntax_node(source, "root", node)?;
let statement_count = node.child_count(); let statement_count = node.child_count();
@ -71,7 +71,7 @@ impl AbstractTree for Root {
Ok(()) Ok(())
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let mut value = Value::none(); let mut value = Value::none();
for statement in &self.statements { for statement in &self.statements {
@ -102,10 +102,10 @@ pub trait AbstractTree: Sized {
/// ///
/// If necessary, the source code can be accessed directly by getting the /// If necessary, the source code can be accessed directly by getting the
/// node's byte range. /// node's byte range.
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self>; fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self>;
/// Execute dust code by traversing the tree. /// Execute dust code by traversing the tree.
fn run(&self, source: &str, context: &Map) -> Result<Value>; fn run(&self, source: &str, context: &mut Map) -> Result<Value>;
/// Verify the type compatibility of this node. /// Verify the type compatibility of this node.
fn check_type(&self, _source: &str, _context: &Map) -> Result<()>; fn check_type(&self, _source: &str, _context: &Map) -> Result<()>;

View File

@ -21,7 +21,7 @@ pub enum Statement {
} }
impl AbstractTree for Statement { impl AbstractTree for Statement {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "statement", node)?; Error::expect_syntax_node(source, "statement", node)?;
let child = node.child(0).unwrap(); let child = node.child(0).unwrap();
@ -66,7 +66,7 @@ impl AbstractTree for Statement {
} }
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
match self { match self {
Statement::Assignment(assignment) => assignment.run(source, context), Statement::Assignment(assignment) => assignment.run(source, context),
Statement::Expression(expression) => expression.run(source, context), Statement::Expression(expression) => expression.run(source, context),

View File

@ -25,7 +25,7 @@ impl TypeDefinition {
} }
impl AbstractTree for TypeDefinition { impl AbstractTree for TypeDefinition {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "type_definition", node)?; Error::expect_syntax_node(source, "type_definition", node)?;
let type_node = node.child(1).unwrap(); let type_node = node.child(1).unwrap();
@ -34,7 +34,7 @@ impl AbstractTree for TypeDefinition {
Ok(TypeDefinition { r#type }) Ok(TypeDefinition { r#type })
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
self.r#type.run(source, context) self.r#type.run(source, context)
} }
@ -176,7 +176,7 @@ impl Type {
} }
impl AbstractTree for Type { impl AbstractTree for Type {
fn from_syntax_node(source: &str, node: Node, _context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, _context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "type", node)?; Error::expect_syntax_node(source, "type", node)?;
let type_node = node.child(0).unwrap(); let type_node = node.child(0).unwrap();
@ -247,7 +247,7 @@ impl AbstractTree for Type {
Ok(()) Ok(())
} }
fn run(&self, _source: &str, _context: &Map) -> Result<Value> { fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> {
Ok(Value::none()) Ok(Value::none())
} }

View File

@ -17,12 +17,12 @@ pub enum ValueNode {
String(String), String(String),
List(Vec<Expression>), List(Vec<Expression>),
Option(Option<Box<Expression>>), Option(Option<Box<Expression>>),
Map(BTreeMap<String, (Statement, Option<Type>)>), Map(BTreeMap<Identifier, (Statement, Option<TypeDefinition>)>),
BuiltInValue(BuiltInValue), BuiltInValue(BuiltInValue),
} }
impl AbstractTree for ValueNode { impl AbstractTree for ValueNode {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "value", node)?; Error::expect_syntax_node(source, "value", node)?;
let child = node.child(0).unwrap(); let child = node.child(0).unwrap();
@ -53,31 +53,37 @@ impl AbstractTree for ValueNode {
} }
"map" => { "map" => {
let mut child_nodes = BTreeMap::new(); let mut child_nodes = BTreeMap::new();
let mut current_key = "".to_string(); let mut current_identifier = None;
let mut current_type = None; let mut current_type = None;
for index in 0..child.child_count() - 1 { for index in 0..child.child_count() - 1 {
let child_syntax_node = child.child(index).unwrap(); let child_syntax_node = child.child(index).unwrap();
if child_syntax_node.kind() == "identifier" { if child_syntax_node.kind() == "identifier" {
current_key = current_identifier = Some(Identifier::from_syntax_node(
Identifier::from_syntax_node(source, child_syntax_node, context)? source,
.take_inner(); child_syntax_node,
context,
)?);
current_type = None; current_type = None;
} }
if child_syntax_node.kind() == "type_definition" { if child_syntax_node.kind() == "type_definition" {
current_type = Some( current_type = Some(TypeDefinition::from_syntax_node(
TypeDefinition::from_syntax_node(source, child_syntax_node, context)? source,
.take_inner(), child_syntax_node,
); context,
)?);
} }
if child_syntax_node.kind() == "statement" { if child_syntax_node.kind() == "statement" {
let statement = let statement =
Statement::from_syntax_node(source, child_syntax_node, context)?; Statement::from_syntax_node(source, child_syntax_node, context)?;
child_nodes.insert(current_key.clone(), (statement, current_type.clone())); if let Some(identifier) = &current_identifier {
child_nodes
.insert(identifier.clone(), (statement, current_type.clone()));
}
} }
} }
@ -133,7 +139,9 @@ impl AbstractTree for ValueNode {
for (_, (statement, r#type)) in map { for (_, (statement, r#type)) in map {
statement.check_type(_source, context)?; statement.check_type(_source, context)?;
if let Some(r#type) = r#type { if let Some(type_definition) = r#type {
let r#type = type_definition.inner();
r#type.check_type(_source, context)?; r#type.check_type(_source, context)?;
r#type.check(&statement.expected_type(context)?)?; r#type.check(&statement.expected_type(context)?)?;
} }
@ -150,7 +158,7 @@ impl AbstractTree for ValueNode {
Ok(()) Ok(())
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value = match self { let value = match self {
ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()), ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()),
ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()), ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()),
@ -177,14 +185,17 @@ impl AbstractTree for ValueNode {
Value::Option(option_value) Value::Option(option_value)
} }
ValueNode::Map(key_statement_pairs) => { ValueNode::Map(map_node) => {
let map = Map::new(); let mut map = Map::new();
{ {
for (key, (statement, r#type)) in key_statement_pairs { for (identifier, (statement, type_definition_option)) in map_node.iter() {
let value = statement.run(source, context)?; let value = statement.run(source, context)?;
let type_option = type_definition_option
.as_ref()
.map(|definition| definition.inner().clone());
map.set(key.clone(), value, r#type.clone())?; map.set(identifier.inner().clone(), value, type_option);
} }
} }

View File

@ -13,7 +13,7 @@ pub struct While {
} }
impl AbstractTree for While { impl AbstractTree for While {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> crate::Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> crate::Result<Self> {
Error::expect_syntax_node(source, "while", node)?; Error::expect_syntax_node(source, "while", node)?;
let expression_node = node.child(1).unwrap(); let expression_node = node.child(1).unwrap();
@ -30,7 +30,7 @@ impl AbstractTree for While {
self.block.check_type(_source, _context) self.block.check_type(_source, _context)
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
while self.expression.run(source, context)?.as_boolean()? { while self.expression.run(source, context)?.as_boolean()? {
self.block.run(source, context)?; self.block.run(source, context)?;
} }

View File

@ -15,7 +15,7 @@ pub struct Yield {
} }
impl AbstractTree for Yield { impl AbstractTree for Yield {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "yield", node)?; Error::expect_syntax_node(source, "yield", node)?;
let input_node = node.child(0).unwrap(); let input_node = node.child(0).unwrap();
@ -48,7 +48,7 @@ impl AbstractTree for Yield {
self.call.check_type(_source, _context) self.call.check_type(_source, _context)
} }
fn run(&self, source: &str, context: &Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
self.call.run(source, context) self.call.run(source, context)
} }

View File

@ -171,7 +171,7 @@ fn display_value(value: &Value, ui: &mut egui::Ui) {
}); });
}) })
.body(|mut body| { .body(|mut body| {
for (key, (value, _)) in map.variables().unwrap().iter() { for (key, (value, _)) in map.variables().iter() {
body.row(20.0, |mut row| { body.row(20.0, |mut row| {
row.col(|ui| { row.col(|ui| {
ui.label(key); ui.label(key);

View File

@ -87,7 +87,7 @@ impl BuiltInFunction {
let length = if let Ok(list) = value.as_list() { let length = if let Ok(list) = value.as_list() {
list.items().len() list.items().len()
} else if let Ok(map) = value.as_map() { } else if let Ok(map) = value.as_map() {
map.variables()?.len() map.variables().len()
} else if let Ok(str) = value.as_string() { } else if let Ok(str) = value.as_string() {
str.chars().count() str.chars().count()
} else { } else {

View File

@ -27,7 +27,7 @@ pub fn interpret(source: &str) -> Result<Value> {
/// ///
/// ```rust /// ```rust
/// # use dust_lang::*; /// # use dust_lang::*;
/// let context = Map::new(); /// let mut context = Map::new();
/// ///
/// context.set("one".into(), 1.into(), None); /// context.set("one".into(), 1.into(), None);
/// context.set("two".into(), 2.into(), None); /// context.set("two".into(), 2.into(), None);
@ -108,7 +108,7 @@ impl Interpreter {
Some(Root::from_syntax_node( Some(Root::from_syntax_node(
source, source,
syntax_tree.root_node(), syntax_tree.root_node(),
&self.context, &mut self.context,
)?) )?)
} else { } else {
return Err(Error::ParserCancelled); return Err(Error::ParserCancelled);
@ -116,7 +116,7 @@ impl Interpreter {
if let Some(abstract_tree) = &self.abstract_tree { if let Some(abstract_tree) = &self.abstract_tree {
abstract_tree.check_type(source, &self.context)?; abstract_tree.check_type(source, &self.context)?;
abstract_tree.run(source, &self.context) abstract_tree.run(source, &mut self.context)
} else { } else {
Ok(Value::none()) Ok(Value::none())
} }

View File

@ -53,7 +53,7 @@ fn main() {
"".to_string() "".to_string()
}; };
let context = Map::new(); let mut context = Map::new();
if let Some(input) = args.input { if let Some(input) = args.input {
context context

View File

@ -54,7 +54,7 @@ impl Function {
} }
impl AbstractTree for Function { impl AbstractTree for Function {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &mut Map) -> Result<Self> {
Error::expect_syntax_node(source, "function", node)?; Error::expect_syntax_node(source, "function", node)?;
let child_count = node.child_count(); let child_count = node.child_count();
@ -77,21 +77,21 @@ impl AbstractTree for Function {
} }
} }
let function_context = Map::clone_from(context)?; let mut function_context = Map::clone_from(context)?;
for (parameter_name, parameter_type) in parameters.iter().zip(parameter_types.iter()) { for (parameter_name, parameter_type) in parameters.iter().zip(parameter_types.iter()) {
function_context.set( function_context.set(
parameter_name.inner().clone(), parameter_name.inner().clone(),
Value::none(), Value::none(),
Some(parameter_type.clone()), Some(parameter_type.clone()),
)?; );
} }
let return_type_node = node.child(child_count - 2).unwrap(); let return_type_node = node.child(child_count - 2).unwrap();
let return_type = TypeDefinition::from_syntax_node(source, return_type_node, context)?; let return_type = TypeDefinition::from_syntax_node(source, return_type_node, context)?;
let body_node = node.child(child_count - 1).unwrap(); let body_node = node.child(child_count - 1).unwrap();
let body = Block::from_syntax_node(source, body_node, &function_context)?; let body = Block::from_syntax_node(source, body_node, &mut function_context)?;
let r#type = Type::function(parameter_types, return_type.take_inner()); let r#type = Type::function(parameter_types, return_type.take_inner());
@ -113,7 +113,7 @@ impl AbstractTree for Function {
Ok(()) Ok(())
} }
fn run(&self, _source: &str, _context: &Map) -> Result<Value> { fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> {
Ok(Value::Function(self.clone())) Ok(Value::Function(self.clone()))
} }
@ -171,12 +171,12 @@ impl ContextDefinedFunction {
outer_context: &Map, outer_context: &Map,
) -> Result<Value> { ) -> Result<Value> {
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter()); let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
let function_context = Map::clone_from(outer_context)?; let mut function_context = Map::clone_from(outer_context)?;
for (identifier, value) in parameter_argument_pairs { for (identifier, value) in parameter_argument_pairs {
let key = identifier.inner().clone(); let key = identifier.inner().clone();
function_context.set(key, value.clone(), None)?; function_context.set(key, value.clone(), None);
} }
if let Some(name) = name { if let Some(name) = name {
@ -184,10 +184,10 @@ impl ContextDefinedFunction {
name, name,
Value::Function(Function::ContextDefined(self.clone())), Value::Function(Function::ContextDefined(self.clone())),
None, None,
)?; );
} }
let return_value = self.body.run(source, &function_context)?; let return_value = self.body.run(source, &mut function_context)?;
Ok(return_value) Ok(return_value)
} }

View File

@ -8,7 +8,6 @@ use std::{
collections::BTreeMap, collections::BTreeMap,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
marker::PhantomData, marker::PhantomData,
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
}; };
use crate::{value::Value, Result, Type}; use crate::{value::Value, Result, Type};
@ -19,62 +18,52 @@ use crate::{value::Value, Result, Type};
/// to one another. /// to one another.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Map { pub struct Map {
variables: Arc<RwLock<BTreeMap<String, (Value, Type)>>>, variables: BTreeMap<String, (Value, Type)>,
} }
impl Map { impl Map {
/// Creates a new instace. /// Creates a new instace.
pub fn new() -> Self { pub fn new() -> Self {
Map { Map {
variables: Arc::new(RwLock::new(BTreeMap::new())), variables: BTreeMap::new(),
} }
} }
pub fn clone_from(other: &Self) -> Result<Self> { pub fn clone_from(other: &Self) -> Result<Self> {
let mut new_map = BTreeMap::new(); let mut variables = BTreeMap::new();
for (key, (value, r#type)) in other.variables()?.iter() { for (key, (value, r#type)) in other.variables() {
new_map.insert(key.clone(), (value.clone(), r#type.clone())); variables.insert(key.clone(), (value.clone(), r#type.clone()));
} }
Ok(Map { Ok(Map { variables })
variables: Arc::new(RwLock::new(new_map)),
})
} }
pub fn variables(&self) -> Result<RwLockReadGuard<BTreeMap<String, (Value, Type)>>> { pub fn variables(&self) -> &BTreeMap<String, (Value, Type)> {
Ok(self.variables.read()?) &self.variables
}
pub fn variables_mut(&self) -> Result<RwLockWriteGuard<BTreeMap<String, (Value, Type)>>> {
Ok(self.variables.write()?)
} }
pub fn set( pub fn set(
&self, &mut self,
key: String, key: String,
value: Value, value: Value,
r#type: Option<Type>, r#type: Option<Type>,
) -> Result<Option<(Value, Type)>> { ) -> Option<(Value, Type)> {
let value_type = r#type.unwrap_or(value.r#type()); let value_type = r#type.unwrap_or(value.r#type());
let previous = self
.variables
.write()?
.insert(key, (value, value_type.clone()));
Ok(previous) self.variables.insert(key, (value, value_type.clone()))
} }
pub fn unset_all(&self) -> Result<()> { pub fn unset_all(&mut self) -> Result<()> {
for (_key, (value, r#_type)) in self.variables.write()?.iter_mut() { for (_key, (value, r#_type)) in self.variables.iter_mut() {
*value = Value::none(); *value = Value::none();
} }
Ok(()) Ok(())
} }
pub fn clear(&self) -> Result<()> { pub fn clear(&mut self) -> Result<()> {
self.variables.write()?.clear(); self.variables.clear();
Ok(()) Ok(())
} }
@ -90,19 +79,13 @@ impl Eq for Map {}
impl PartialEq for Map { impl PartialEq for Map {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
let left = self.variables.read().unwrap().clone().into_iter(); self.variables.eq(&other.variables)
let right = other.variables.read().unwrap().clone().into_iter();
left.eq(right)
} }
} }
impl Ord for Map { impl Ord for Map {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
let left = self.variables.read().unwrap().clone().into_iter(); self.variables.cmp(&other.variables)
let right = other.variables.read().unwrap().clone().into_iter();
left.cmp(right)
} }
} }
@ -116,9 +99,7 @@ impl Display for Map {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln!(f, "{{")?; writeln!(f, "{{")?;
let variables = self.variables.read().unwrap().clone().into_iter(); for (key, (value, _)) in &self.variables {
for (key, (value, _)) in variables {
writeln!(f, " {key} = {value}")?; writeln!(f, " {key} = {value}")?;
} }
write!(f, "}}") write!(f, "}}")
@ -130,11 +111,10 @@ impl Serialize for Map {
where where
S: serde::Serializer, S: serde::Serializer,
{ {
let variables = self.variables.read().unwrap(); let mut map = serializer.serialize_map(Some(self.variables.len()))?;
let mut map = serializer.serialize_map(Some(variables.len()))?;
for (key, (value, _type)) in variables.iter() { for (key, (value, _type)) in &self.variables {
map.serialize_entry(key, value)?; map.serialize_entry(&key, &value)?;
} }
map.end() map.end()
@ -157,14 +137,14 @@ impl<'de> Visitor<'de> for MapVisitor {
type Value = Map; type Value = Map;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("Any valid whale data.") formatter.write_str("Valid map data.")
} }
fn visit_map<M>(self, mut access: M) -> std::result::Result<Map, M::Error> fn visit_map<M>(self, mut access: M) -> std::result::Result<Map, M::Error>
where where
M: MapAccess<'de>, M: MapAccess<'de>,
{ {
let map = Map::new(); let mut map = Map::new();
{ {
while let Some((key, value)) = access.next_entry::<String, Value>()? { while let Some((key, value)) = access.next_entry::<String, Value>()? {

View File

@ -226,7 +226,7 @@ impl Value {
} }
} }
/// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if `self` is not a `Value::Map`. /// Borrows the value stored in `self` as `&Map`, or returns `Err` if `self` is not a `Value::Map`.
pub fn as_map(&self) -> Result<&Map> { pub fn as_map(&self) -> Result<&Map> {
match self { match self {
Value::Map(map) => Ok(map), Value::Map(map) => Ok(map),
@ -236,7 +236,7 @@ impl Value {
} }
} }
/// Borrows the value stored in `self` as `Function`, or returns `Err` if /// Borrows the value stored in `self` as `&Function`, or returns `Err` if
/// `self` is not a `Value::Function`. /// `self` is not a `Value::Function`.
pub fn as_function(&self) -> Result<&Function> { pub fn as_function(&self) -> Result<&Function> {
match self { match self {
@ -841,10 +841,10 @@ impl<'de> Visitor<'de> for ValueVisitor {
where where
M: MapAccess<'de>, M: MapAccess<'de>,
{ {
let map = Map::new(); let mut map = Map::new();
while let Some((key, value)) = access.next_entry::<String, Value>()? { while let Some((key, value)) = access.next_entry::<String, Value>()? {
map.set(key, value, None).unwrap(); map.set(key, value, None);
} }
Ok(Value::Map(map)) Ok(Value::Map(map))

View File

@ -140,27 +140,24 @@ mod value {
#[test] #[test]
fn map() { fn map() {
let map = Map::new(); let mut map = Map::new();
map.set("x".to_string(), Value::Integer(1), None).unwrap(); map.set("x".to_string(), Value::Integer(1), None);
map.set("foo".to_string(), Value::string("bar".to_string()), None) map.set("foo".to_string(), Value::string("bar".to_string()), None);
.unwrap();
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map))); assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
} }
#[test] #[test]
fn map_types() { fn map_types() {
let map = Map::new(); let mut map = Map::new();
map.set("x".to_string(), Value::Integer(1), Some(Type::Integer)) map.set("x".to_string(), Value::Integer(1), Some(Type::Integer));
.unwrap();
map.set( map.set(
"foo".to_string(), "foo".to_string(),
Value::string("bar".to_string()), Value::string("bar".to_string()),
Some(Type::String), Some(Type::String),
) );
.unwrap();
assert_eq!( assert_eq!(
interpret("{ x <int> = 1, foo <str> = 'bar' }"), interpret("{ x <int> = 1, foo <str> = 'bar' }"),