From 833a830b30ab41bdea4d54a3309b515e2955b435 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 9 Dec 2023 17:15:41 -0500 Subject: [PATCH] Expand type checking to map contexts --- src/abstract_tree/assignment.rs | 42 ++++++++++++++++----------- src/abstract_tree/for.rs | 4 +-- src/abstract_tree/function_call.rs | 2 +- src/abstract_tree/identifier.rs | 4 +-- src/abstract_tree/index.rs | 10 +++++-- src/abstract_tree/index_assignment.rs | 9 ++++-- src/abstract_tree/value_node.rs | 10 +++++-- src/built_in_functions/fs.rs | 13 +++++++-- src/value/function.rs | 5 +++- src/value/map.rs | 31 +++++--------------- src/value/table.rs | 6 ++-- 11 files changed, 75 insertions(+), 61 deletions(-) diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index 5783122..0dd7425 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -74,20 +74,10 @@ impl AbstractTree for Assignment { let identifier_type = identifier.expected_type(context)?; if let Type::List(item_type) = type_definition.inner() { - let item_type_definition = TypeDefinition::new(*item_type.clone()); + println!("{item_type}"); - item_type_definition.inner().check( - &identifier_type, - context, - identifier_node, - source, - )?; - item_type_definition.inner().check( - &statement_type, - context, - statement_node, - source, - )?; + item_type.check(&identifier_type, context, identifier_node, source)?; + item_type.check(&statement_type, context, statement_node, source)?; } else { type_definition.inner().check( &identifier_type, @@ -121,7 +111,7 @@ impl AbstractTree for Assignment { let new_value = match self.operator { 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 } else { @@ -129,7 +119,7 @@ impl AbstractTree for Assignment { } } 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 } else { @@ -138,8 +128,11 @@ impl AbstractTree for Assignment { } AssignmentOperator::Equal => value, }; + let new_value_type = new_value.r#type(context)?; - context.variables_mut()?.insert(key.clone(), new_value); + context + .variables_mut()? + .insert(key.clone(), (new_value, new_value_type)); Ok(Value::Empty) } @@ -151,7 +144,7 @@ impl AbstractTree for Assignment { #[cfg(test)] mod tests { - use crate::{evaluate, List, Value}; + use crate::{evaluate, Error, List, Value}; #[test] fn simple_assignment() { @@ -180,4 +173,19 @@ mod tests { assert_eq!(Value::List(List::with_items(vec![Value::Integer(1)])), test); } + + #[test] + fn list_add_wrong_type() { + let test = evaluate( + " + x <[str]> = [] + x += 1 + ", + ); + + if let Err(Error::TypeCheck { .. }) = test { + } else { + panic!() + } + } } diff --git a/src/abstract_tree/for.rs b/src/abstract_tree/for.rs index 057d2f5..65e7ce5 100644 --- a/src/abstract_tree/for.rs +++ b/src/abstract_tree/for.rs @@ -59,7 +59,7 @@ impl AbstractTree for For { iter_context .variables_mut()? - .insert(key.clone(), value.clone()); + .insert(key.clone(), (value.clone(), value.r#type(context)?)); self.block.run(source, &mut iter_context).map(|_value| ()) })?; @@ -69,7 +69,7 @@ impl AbstractTree for For { for value in values.iter() { loop_context .variables_mut()? - .insert(key.clone(), value.clone()); + .insert(key.clone(), (value.clone(), value.r#type(context)?)); self.block.run(source, &mut loop_context.clone())?; } diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 2444c9b..ea12a62 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -89,7 +89,7 @@ impl AbstractTree for FunctionCall { let variables = context.variables()?; - if let Some(value) = variables.get(key) { + if let Some((value, _)) = variables.get(key) { value.clone() } else { return Err(Error::FunctionIdentifierNotFound(identifier.clone())); diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index 78af224..5145189 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -34,7 +34,7 @@ impl AbstractTree for Identifier { } fn run(&self, _source: &str, context: &Map) -> Result { - if let Some(value) = context.variables()?.get(&self.0) { + if let Some((value, _)) = context.variables()?.get(&self.0) { Ok(value.clone()) } else { Err(Error::VariableIdentifierNotFound(self.inner().clone())) @@ -42,7 +42,7 @@ impl AbstractTree for Identifier { } fn expected_type(&self, context: &Map) -> Result { - if let Some(value) = context.variables()?.get(&self.0) { + if let Some((value, _)) = context.variables()?.get(&self.0) { value.r#type(context) } else { for built_in_function in BUILT_IN_FUNCTIONS { diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index 3e06fc7..e5abd18 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -61,12 +61,18 @@ impl AbstractTree for Index { let value = if let Expression::Identifier(identifier) = &self.index { let key = identifier.inner(); - map.variables()?.get(key).cloned().unwrap_or(Value::Empty) + map.variables()? + .get(key) + .map(|(value, _)| value.clone()) + .unwrap_or_default() } else { let value = self.index.run(source, context)?; let key = value.as_string()?; - map.variables()?.get(key).cloned().unwrap_or(Value::Empty) + map.variables()? + .get(key) + .map(|(value, _)| value.clone()) + .unwrap_or_default() }; Ok(value) diff --git a/src/abstract_tree/index_assignment.rs b/src/abstract_tree/index_assignment.rs index a5588ff..61e7a77 100644 --- a/src/abstract_tree/index_assignment.rs +++ b/src/abstract_tree/index_assignment.rs @@ -64,7 +64,8 @@ impl AbstractTree for IndexAssignment { let new_value = match self.operator { AssignmentOperator::PlusEqual => { - if let Some(mut previous_value) = index_context.variables()?.get(index_key).cloned() + if let Some((mut previous_value, _)) = + index_context.variables()?.get(index_key).cloned() { previous_value += value; previous_value @@ -73,7 +74,8 @@ impl AbstractTree for IndexAssignment { } } AssignmentOperator::MinusEqual => { - if let Some(mut previous_value) = index_context.variables()?.get(index_key).cloned() + if let Some((mut previous_value, _)) = + index_context.variables()?.get(index_key).cloned() { previous_value -= value; previous_value @@ -83,10 +85,11 @@ impl AbstractTree for IndexAssignment { } AssignmentOperator::Equal => value, }; + let new_value_type = new_value.r#type(context)?; index_context .variables_mut()? - .insert(index_key.clone(), new_value); + .insert(index_key.clone(), (new_value, new_value_type)); Ok(Value::Empty) } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 25bce08..e459274 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -132,8 +132,9 @@ impl AbstractTree for ValueNode { for (key, statement) in key_statement_pairs { let value = statement.run(source, context)?; + let value_type = value.r#type(context)?; - variables.insert(key.clone(), value); + variables.insert(key.clone(), (value, value_type)); } } @@ -237,8 +238,11 @@ mod tests { { let mut variables = map.variables_mut().unwrap(); - variables.insert("x".to_string(), Value::Integer(1)); - variables.insert("foo".to_string(), Value::String("bar".to_string())); + variables.insert("x".to_string(), (Value::Integer(1), Type::Integer)); + variables.insert( + "foo".to_string(), + (Value::String("bar".to_string()), Type::String), + ); } assert_eq!(evaluate("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map))); diff --git a/src/built_in_functions/fs.rs b/src/built_in_functions/fs.rs index d14554e..35b95ba 100644 --- a/src/built_in_functions/fs.rs +++ b/src/built_in_functions/fs.rs @@ -31,9 +31,16 @@ impl BuiltInFunction for Read { let created = metadata.created()?.elapsed()?.as_secs() as i64; let modified = metadata.modified()?.elapsed()?.as_secs() as i64; - file_data_variables.insert("name".to_string(), Value::String(name)); - file_data_variables.insert("created".to_string(), Value::Integer(created)); - file_data_variables.insert("modified".to_string(), Value::Integer(modified)); + file_data_variables + .insert("name".to_string(), (Value::String(name), Type::String)); + file_data_variables.insert( + "created".to_string(), + (Value::Integer(created), Type::Integer), + ); + file_data_variables.insert( + "modified".to_string(), + (Value::Integer(modified), Type::Integer), + ); } files.items_mut().push(Value::Map(file_data)); diff --git a/src/value/function.rs b/src/value/function.rs index ec2be97..63cc4ab 100644 --- a/src/value/function.rs +++ b/src/value/function.rs @@ -76,6 +76,7 @@ impl Function { for ((identifier, argument_type), expression) in parameter_argument_pairs { let value = expression.run(source, context)?; + let value_type = value.r#type(context)?; match argument_type { Type::Any => {} @@ -110,7 +111,9 @@ impl Function { let key = identifier.inner().clone(); - function_context.variables_mut()?.insert(key, value); + function_context + .variables_mut()? + .insert(key, (value, value_type)); } let return_value = self.body.run(source, &function_context)?; diff --git a/src/value/map.rs b/src/value/map.rs index 82a972c..1d71bb0 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -6,7 +6,7 @@ use std::{ sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, }; -use crate::{value::Value, List, Result, Table}; +use crate::{value::Value, Result, Type}; /// A collection dust variables comprised of key-value pairs. /// @@ -14,7 +14,7 @@ use crate::{value::Value, List, Result, Table}; /// to one another. #[derive(Clone, Debug)] pub struct Map { - variables: Arc>>, + variables: Arc>>, } impl Map { @@ -28,8 +28,8 @@ impl Map { pub fn clone_from(other: &Self) -> Result { let mut new_map = BTreeMap::new(); - for (key, value) in other.variables()?.iter() { - new_map.insert(key.clone(), value.clone()); + for (key, (value, r#type)) in other.variables()?.iter() { + new_map.insert(key.clone(), (value.clone(), r#type.clone())); } Ok(Map { @@ -37,11 +37,11 @@ impl Map { }) } - pub fn variables(&self) -> Result>> { + pub fn variables(&self) -> Result>> { Ok(self.variables.read()?) } - pub fn variables_mut(&self) -> Result>> { + pub fn variables_mut(&self) -> Result>> { Ok(self.variables.write()?) } } @@ -87,30 +87,13 @@ impl Display for Map { let variables = self.variables.read().unwrap().clone().into_iter(); - for (key, value) in variables { + for (key, (value, _)) in variables { writeln!(f, " {key} = {value}")?; } write!(f, "}}") } } -impl From<&Table> for Result { - fn from(value: &Table) -> Result { - let map = Map::new(); - - for (row_index, row) in value.rows().iter().enumerate() { - map.variables_mut()? - .insert( - row_index.to_string(), - Value::List(List::with_items(row.clone())), - ) - .unwrap(); - } - - Ok(map) - } -} - impl Serialize for Map { fn serialize(&self, serializer: S) -> std::result::Result where diff --git a/src/value/table.rs b/src/value/table.rs index c3a6dff..76cbb4d 100644 --- a/src/value/table.rs +++ b/src/value/table.rs @@ -282,7 +282,7 @@ impl From for Result { fn from(map: Map) -> Self { let variables = map.variables()?; let keys = variables.keys().cloned().collect(); - let values = variables.values().cloned().collect(); + let values = variables.values().map(|(value, _)| value.clone()).collect(); let mut table = Table::new(keys); table.insert(values)?; @@ -295,7 +295,7 @@ impl From<&Map> for Result
{ fn from(map: &Map) -> Self { let variables = map.variables()?; let keys = variables.keys().cloned().collect(); - let values = variables.values().cloned().collect(); + let values = variables.values().map(|(value, _)| value.clone()).collect(); let mut table = Table::new(keys); table.insert(values)?; @@ -308,7 +308,7 @@ impl From<&mut Map> for Result
{ fn from(map: &mut Map) -> Self { let variables = map.variables()?; let keys = variables.keys().cloned().collect(); - let values = variables.values().cloned().collect(); + let values = variables.values().map(|(value, _)| value.clone()).collect(); let mut table = Table::new(keys); table