diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 23f3890..99b1fe5 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::{ error::{RuntimeError, SyntaxError, ValidationError}, AbstractTree, BuiltInValue, Expression, Format, Function, FunctionNode, Identifier, List, Map, - Statement, Structure, SyntaxNode, Type, TypeSpecification, Value, + SourcePosition, Statement, Structure, SyntaxNode, Type, TypeSpecification, Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] @@ -17,7 +17,7 @@ pub enum ValueNode { String(String), List(Vec), Option(Option>), - Map(BTreeMap)>), + Map(BTreeMap)>, SourcePosition), BuiltInValue(BuiltInValue), Structure(BTreeMap, Type)>), Range(RangeInclusive), @@ -83,7 +83,7 @@ impl AbstractTree for ValueNode { } } - ValueNode::Map(child_nodes) + ValueNode::Map(child_nodes, SourcePosition::from(child.range())) } "option" => { let first_grandchild = child.child(0).unwrap(); @@ -217,7 +217,7 @@ impl AbstractTree for ValueNode { Type::None } } - ValueNode::Map(_) => Type::Map(None), + ValueNode::Map(_, _) => Type::Map(None), ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?, ValueNode::Structure(node_map) => { let mut value_map = BTreeMap::new(); @@ -234,11 +234,26 @@ impl AbstractTree for ValueNode { Ok(r#type) } - fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> { + fn validate(&self, _source: &str, context: &Map) -> Result<(), ValidationError> { match self { ValueNode::Function(function) => { if let Function::ContextDefined(function_node) = function { - function_node.validate(_source, _context)?; + function_node.validate(_source, context)?; + } + } + ValueNode::Map(statements, source_position) => { + for (key, (statement, r#type)) in statements { + if let Some(expected) = r#type { + let actual = statement.expected_type(context)?; + + if !expected.accepts(&actual) { + return Err(ValidationError::TypeCheck { + expected: expected.clone(), + actual, + position: source_position.clone(), + }); + } + } } } _ => {} @@ -278,7 +293,7 @@ impl AbstractTree for ValueNode { Value::Option(option_value) } - ValueNode::Map(key_statement_pairs) => { + ValueNode::Map(key_statement_pairs, _) => { let map = Map::new(); { @@ -344,7 +359,7 @@ impl Format for ValueNode { output.push_str("none"); } } - ValueNode::Map(nodes) => { + ValueNode::Map(nodes, _) => { output.push_str("{\n"); for (key, (statement, type_option)) in nodes { @@ -413,8 +428,8 @@ impl Ord for ValueNode { (ValueNode::List(_), _) => Ordering::Greater, (ValueNode::Option(left), ValueNode::Option(right)) => left.cmp(right), (ValueNode::Option(_), _) => Ordering::Greater, - (ValueNode::Map(left), ValueNode::Map(right)) => left.cmp(right), - (ValueNode::Map(_), _) => Ordering::Greater, + (ValueNode::Map(left, _), ValueNode::Map(right, _)) => left.cmp(right), + (ValueNode::Map(_, _), _) => Ordering::Greater, (ValueNode::BuiltInValue(left), ValueNode::BuiltInValue(right)) => left.cmp(right), (ValueNode::BuiltInValue(_), _) => Ordering::Greater, (ValueNode::Structure(left), ValueNode::Structure(right)) => left.cmp(right), diff --git a/tests/assignment.rs b/tests/assignment.rs index 6df7f82..6691b40 100644 --- a/tests/assignment.rs +++ b/tests/assignment.rs @@ -44,12 +44,12 @@ fn list_add_wrong_type() { expected: Type::String, actual: Type::Integer, position: SourcePosition { - start_byte: 0, - end_byte: 0, - start_row: 0, - start_column: 0, - end_row: 0, - end_column: 0 + start_byte: 40, + end_byte: 46, + start_row: 3, + start_column: 12, + end_row: 3, + end_column: 18 } })), result diff --git a/tests/types.rs b/tests/types.rs index 3caed77..5076b2a 100644 --- a/tests/types.rs +++ b/tests/types.rs @@ -10,11 +10,11 @@ fn simple_type_check() { actual: Type::Integer, position: SourcePosition { start_byte: 0, - end_byte: 0, - start_row: 0, + end_byte: 12, + start_row: 1, start_column: 0, - end_row: 0, - end_column: 0, + end_row: 1, + end_column: 12, } })), result @@ -59,12 +59,12 @@ fn callback_type_check() { return_type: Box::new(Type::Integer), }, position: SourcePosition { - start_byte: 0, - end_byte: 0, - start_row: 0, - start_column: 0, - end_row: 0, - end_column: 0 + start_byte: 91, + end_byte: 108, + start_row: 5, + start_column: 12, + end_row: 5, + end_column: 29, } })), result diff --git a/tests/value.rs b/tests/value.rs index f1bc814..e9bcb4c 100644 --- a/tests/value.rs +++ b/tests/value.rs @@ -106,11 +106,11 @@ fn map_type_errors() { actual: Type::String, position: SourcePosition { start_byte: 0, - end_byte: 0, - start_row: 0, + end_byte: 22, + start_row: 1, start_column: 0, - end_row: 0, - end_column: 0 + end_row: 1, + end_column: 22 } })) );