From 8826d08392c805f707312b2d99f54b84162c454f Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 30 Nov 2023 00:57:15 -0500 Subject: [PATCH] Implement list type checks --- src/abstract_tree/assignment.rs | 25 +++--- src/abstract_tree/block.rs | 4 +- src/abstract_tree/expression.rs | 5 +- src/abstract_tree/for.rs | 8 +- src/abstract_tree/function_call.rs | 4 +- src/abstract_tree/identifier.rs | 8 +- src/abstract_tree/if_else.rs | 4 +- src/abstract_tree/index.rs | 4 +- src/abstract_tree/index_assignment.rs | 6 +- src/abstract_tree/logic.rs | 6 +- src/abstract_tree/match.rs | 4 +- src/abstract_tree/math.rs | 4 +- src/abstract_tree/mod.rs | 4 +- src/abstract_tree/statement.rs | 4 +- src/abstract_tree/type_defintion.rs | 109 +++++++++++++------------- src/abstract_tree/use.rs | 6 +- src/abstract_tree/value_node.rs | 48 +++++++----- src/abstract_tree/while.rs | 4 +- src/abstract_tree/yield.rs | 4 +- src/error.rs | 10 +-- src/value/function.rs | 4 +- src/value/mod.rs | 26 +++--- 22 files changed, 160 insertions(+), 141 deletions(-) diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index 038f6f0..c93542b 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -1,12 +1,12 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Identifier, Map, Result, Statement, Type, TypeDefintion, Value}; +use crate::{AbstractTree, Error, Identifier, Map, Result, Statement, Type, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Assignment { identifier: Identifier, - type_definition: Option, + type_definition: Option, operator: AssignmentOperator, statement: Statement, } @@ -27,7 +27,9 @@ impl AbstractTree for Assignment { let type_node = node.child_by_field_name("type"); let type_definition = if let Some(type_node) = type_node { - Some(TypeDefintion::from_syntax_node(source, type_node, context)?) + Some(TypeDefinition::from_syntax_node( + source, type_node, context, + )?) } else { None }; @@ -57,14 +59,7 @@ impl AbstractTree for Assignment { if let Some(type_defintion) = &type_definition { let statement_type = statement.expected_type(context)?; - if type_defintion.r#type() != &statement_type { - return Err(Error::TypeCheck { - expected: type_defintion.r#type().clone(), - actual: statement_type, - location: node.start_position(), - source: source[node.byte_range()].to_string(), - }); - } + type_defintion.check(&statement_type, context)?; } Ok(Assignment { @@ -100,7 +95,9 @@ impl AbstractTree for Assignment { }; if let Some(type_definition) = &self.type_definition { - type_definition.check(&new_value, context)?; + let new_value_type = new_value.r#type(context)?; + + type_definition.check(&new_value_type, context)?; } context.variables_mut()?.insert(key.clone(), new_value); @@ -108,7 +105,7 @@ impl AbstractTree for Assignment { Ok(Value::Empty) } - fn expected_type(&self, _context: &Map) -> Result { - Ok(Type::Empty) + fn expected_type(&self, _context: &Map) -> Result { + Ok(TypeDefinition::new(Type::Empty)) } } diff --git a/src/abstract_tree/block.rs b/src/abstract_tree/block.rs index 6b58d75..3ab01b9 100644 --- a/src/abstract_tree/block.rs +++ b/src/abstract_tree/block.rs @@ -4,7 +4,7 @@ use rayon::prelude::*; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Map, Result, Statement, Type, Value}; +use crate::{AbstractTree, Error, Map, Result, Statement, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Block { @@ -82,7 +82,7 @@ impl AbstractTree for Block { } } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.statements.last().unwrap().expected_type(context) } } diff --git a/src/abstract_tree/expression.rs b/src/abstract_tree/expression.rs index e10c671..2f9f189 100644 --- a/src/abstract_tree/expression.rs +++ b/src/abstract_tree/expression.rs @@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - value_node::ValueNode, AbstractTree, Error, Identifier, Index, Map, Result, Type, Value, Yield, + value_node::ValueNode, AbstractTree, Error, Identifier, Index, Map, Result, TypeDefinition, + Value, Yield, }; use super::{function_call::FunctionCall, logic::Logic, math::Math}; @@ -71,7 +72,7 @@ impl AbstractTree for Expression { } } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { match self { Expression::Value(value_node) => value_node.expected_type(context), Expression::Identifier(identifier) => identifier.expected_type(context), diff --git a/src/abstract_tree/for.rs b/src/abstract_tree/for.rs index 7271125..92c0935 100644 --- a/src/abstract_tree/for.rs +++ b/src/abstract_tree/for.rs @@ -2,7 +2,9 @@ use rayon::prelude::*; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, Value}; +use crate::{ + AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, TypeDefinition, Value, +}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct For { @@ -77,7 +79,7 @@ impl AbstractTree for For { Ok(Value::Empty) } - fn expected_type(&self, _context: &Map) -> Result { - Ok(Type::Empty) + fn expected_type(&self, _context: &Map) -> Result { + Ok(TypeDefinition::new(Type::Empty)) } } diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 8926108..e9246e7 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Map, Result, Type, Value, BUILT_IN_FUNCTIONS}; +use crate::{AbstractTree, Error, Map, Result, TypeDefinition, Value, BUILT_IN_FUNCTIONS}; use super::expression::Expression; @@ -87,7 +87,7 @@ impl AbstractTree for FunctionCall { function.run(source, &mut function_context) } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.function.expected_type(context) } } diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index 195cff9..7b23c77 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Map, Result, Type, Value}; +use crate::{AbstractTree, Error, Map, Result, Type, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Identifier(String); @@ -37,11 +37,11 @@ impl AbstractTree for Identifier { } } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { if let Some(value) = context.variables()?.get(&self.0) { - Ok(value.r#type(context)?) + value.r#type(context) } else { - Ok(Type::Empty) + Ok(TypeDefinition::new(Type::Empty)) } } } diff --git a/src/abstract_tree/if_else.rs b/src/abstract_tree/if_else.rs index b8f1e18..fd30ea1 100644 --- a/src/abstract_tree/if_else.rs +++ b/src/abstract_tree/if_else.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Block, Expression, Map, Result, Type, Value}; +use crate::{AbstractTree, Block, Expression, Map, Result, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct IfElse { @@ -81,7 +81,7 @@ impl AbstractTree for IfElse { } } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.if_block.expected_type(context) } } diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index 956e444..c737621 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Expression, List, Map, Result, Type, Value}; +use crate::{AbstractTree, Error, Expression, List, Map, Result, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Index { @@ -78,7 +78,7 @@ impl AbstractTree for Index { } } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.collection.expected_type(context) } } diff --git a/src/abstract_tree/index_assignment.rs b/src/abstract_tree/index_assignment.rs index a5588ff..d5500ee 100644 --- a/src/abstract_tree/index_assignment.rs +++ b/src/abstract_tree/index_assignment.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Index, Map, Result, Statement, Type, Value}; +use crate::{AbstractTree, Error, Index, Map, Result, Statement, Type, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct IndexAssignment { @@ -91,7 +91,7 @@ impl AbstractTree for IndexAssignment { Ok(Value::Empty) } - fn expected_type(&self, _context: &Map) -> Result { - Ok(Type::Empty) + fn expected_type(&self, _context: &Map) -> Result { + Ok(TypeDefinition::new(Type::Empty)) } } diff --git a/src/abstract_tree/logic.rs b/src/abstract_tree/logic.rs index 6deeb61..ab97319 100644 --- a/src/abstract_tree/logic.rs +++ b/src/abstract_tree/logic.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Expression, Map, Result, Type, Value}; +use crate::{AbstractTree, Error, Expression, Map, Result, Type, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Logic { @@ -74,8 +74,8 @@ impl AbstractTree for Logic { Ok(Value::Boolean(result)) } - fn expected_type(&self, _context: &Map) -> Result { - Ok(Type::Boolean) + fn expected_type(&self, _context: &Map) -> Result { + Ok(TypeDefinition::new(Type::Boolean)) } } diff --git a/src/abstract_tree/match.rs b/src/abstract_tree/match.rs index a361e14..71dd95f 100644 --- a/src/abstract_tree/match.rs +++ b/src/abstract_tree/match.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Map, Result, Type, Value}; +use crate::{AbstractTree, Map, Result, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Match {} @@ -20,7 +20,7 @@ impl AbstractTree for Match { todo!() } - fn expected_type(&self, _context: &Map) -> Result { + fn expected_type(&self, _context: &Map) -> Result { todo!() } } diff --git a/src/abstract_tree/math.rs b/src/abstract_tree/math.rs index 538441f..b25b043 100644 --- a/src/abstract_tree/math.rs +++ b/src/abstract_tree/math.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Expression, Map, Result, Type, Value}; +use crate::{AbstractTree, Error, Expression, Map, Result, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Math { @@ -56,7 +56,7 @@ impl AbstractTree for Math { Ok(value) } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.left.expected_type(context) } } diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index c2154f2..cf7439f 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -66,7 +66,7 @@ impl AbstractTree for Root { Ok(value) } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.statements.last().unwrap().expected_type(context) } } @@ -88,5 +88,5 @@ pub trait AbstractTree: Sized { /// Execute dust code by traversing the tree. fn run(&self, source: &str, context: &Map) -> Result; - fn expected_type(&self, context: &Map) -> Result; + fn expected_type(&self, context: &Map) -> Result; } diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index 4bf2197..d8607ef 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -3,7 +3,7 @@ use tree_sitter::Node; use crate::{ AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Map, Match, - Result, Type, Use, Value, While, + Result, TypeDefinition, Use, Value, While, }; /// Abstract representation of a statement. @@ -82,7 +82,7 @@ impl AbstractTree for Statement { } } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { match self { Statement::Assignment(assignment) => assignment.expected_type(context), Statement::Return(expression) => expression.expected_type(context), diff --git a/src/abstract_tree/type_defintion.rs b/src/abstract_tree/type_defintion.rs index 9bbf269..5b8619f 100644 --- a/src/abstract_tree/type_defintion.rs +++ b/src/abstract_tree/type_defintion.rs @@ -6,44 +6,83 @@ use tree_sitter::Node; use crate::{AbstractTree, Error, Map, Result, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] -pub struct TypeDefintion { +pub struct TypeDefinition { r#type: Type, } -impl TypeDefintion { +impl TypeDefinition { + pub fn new(r#type: Type) -> Self { + Self { r#type } + } + pub fn r#type(&self) -> &Type { &self.r#type } + + pub fn check(&self, other: &TypeDefinition, context: &Map) -> Result<()> { + match (&self.r#type, &other.r#type) { + (Type::Any, _) + | (_, Type::Any) + | (Type::Boolean, Type::Boolean) + | (Type::Empty, Type::Empty) + | (Type::Float, Type::Float) + | (Type::Integer, Type::Integer) + | (Type::Map, Type::Map) + | (Type::Number, Type::Number) + | (Type::Number, Type::Integer) + | (Type::Number, Type::Float) + | (Type::Integer, Type::Number) + | (Type::Float, Type::Number) + | (Type::String, Type::String) + | (Type::Table, Type::Table) => Ok(()), + (Type::List(self_item_type), Type::List(other_item_type)) => { + let self_defintion = TypeDefinition::new(self_item_type.as_ref().clone()); + let other_definition = &TypeDefinition::new(other_item_type.as_ref().clone()); + + self_defintion.check(other_definition, context) + } + _ => Err(Error::RuntimeTypeCheck { + expected: self.clone(), + actual: other.clone(), + }), + } + } } -impl AbstractTree for TypeDefintion { +impl AbstractTree for TypeDefinition { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "type_definition", node)?; let type_node = node.child(1).unwrap(); let r#type = Type::from_syntax_node(source, type_node, context)?; - Ok(TypeDefintion { r#type }) + Ok(TypeDefinition { r#type }) } fn run(&self, source: &str, context: &Map) -> Result { self.r#type.run(source, context) } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.r#type.expected_type(context) } } -#[derive(Debug, Clone, Serialize, Deserialize, PartialOrd, Ord)] +impl Display for TypeDefinition { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "<{}>", self.r#type) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub enum Type { Any, Boolean, Empty, Float, Function { - parameter_types: Vec, - return_type: Box, + parameter_types: Vec, + return_type: Box, }, Integer, List(Box), @@ -53,19 +92,6 @@ pub enum Type { Table, } -impl TypeDefintion { - pub fn check(&self, value: &Value, context: &Map) -> Result<()> { - if self.r#type == value.r#type(context)? { - Ok(()) - } else { - Err(Error::RuntimeTypeCheck { - expected: self.r#type.clone(), - actual: value.clone(), - }) - } - } -} - impl AbstractTree for Type { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "type", node)?; @@ -85,7 +111,7 @@ impl AbstractTree for Type { let parameter_type = Type::from_syntax_node(source, parameter_type_node, context)?; - parameter_types.push(parameter_type); + parameter_types.push(TypeDefinition::new(parameter_type)); } let return_type_node = node.child(child_count - 1).unwrap(); @@ -93,7 +119,7 @@ impl AbstractTree for Type { Type::Function { parameter_types, - return_type: Box::new(return_type), + return_type: Box::new(TypeDefinition::new(return_type)), } } "int" => Type::Integer, @@ -124,35 +150,8 @@ impl AbstractTree for Type { Ok(Value::Empty) } - fn expected_type(&self, _context: &Map) -> Result { - Ok(Type::Empty) - } -} - -impl Eq for Type {} - -impl PartialEq for Type { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Type::Any, _) - | (_, Type::Any) - | (Type::Boolean, Type::Boolean) - | (Type::Empty, Type::Empty) - | (Type::Float, Type::Float) - | (Type::Integer, Type::Integer) - | (Type::Map, Type::Map) - | (Type::Number, Type::Number) - | (Type::Number, Type::Integer) - | (Type::Number, Type::Float) - | (Type::Integer, Type::Number) - | (Type::Float, Type::Number) - | (Type::String, Type::String) - | (Type::Table, Type::Table) => true, - (Type::List(self_item_type), Type::List(other_item_type)) => { - self_item_type == other_item_type - } - _ => false, - } + fn expected_type(&self, _context: &Map) -> Result { + Ok(TypeDefinition::new(Type::Empty)) } } @@ -175,11 +174,11 @@ impl Display for Type { write!(f, "-> {return_type}") } - Type::Integer => write!(f, "integer"), + Type::Integer => write!(f, "int"), Type::List(item_type) => write!(f, "list {item_type}"), Type::Map => write!(f, "map"), - Type::Number => write!(f, "number"), - Type::String => write!(f, "string"), + Type::Number => write!(f, "num"), + Type::String => write!(f, "str"), Type::Table => write!(f, "table"), } } diff --git a/src/abstract_tree/use.rs b/src/abstract_tree/use.rs index 28adfd7..d5ef0a6 100644 --- a/src/abstract_tree/use.rs +++ b/src/abstract_tree/use.rs @@ -3,7 +3,7 @@ use std::fs::read_to_string; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{evaluate_with_context, AbstractTree, Error, Map, Result, Type, Value}; +use crate::{evaluate_with_context, AbstractTree, Error, Map, Result, Type, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Use { @@ -29,7 +29,7 @@ impl AbstractTree for Use { Ok(Value::Map(file_context)) } - fn expected_type(&self, _context: &Map) -> Result { - Ok(Type::Map) + fn expected_type(&self, _context: &Map) -> Result { + Ok(TypeDefinition::new(Type::Map)) } } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index c6dc7ce..25ab586 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -5,7 +5,7 @@ use tree_sitter::Node; use crate::{ AbstractTree, Error, Expression, Function, Identifier, List, Map, Result, Statement, Table, - Type, Value, + Type, TypeDefinition, Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -181,30 +181,42 @@ impl AbstractTree for ValueNode { Ok(value) } - fn expected_type(&self, context: &Map) -> Result { - let r#type = match self { - ValueNode::Boolean(_) => Type::Boolean, - ValueNode::Float(_) => Type::Float, - ValueNode::Integer(_) => Type::Integer, - ValueNode::String(_) => Type::String, + fn expected_type(&self, context: &Map) -> Result { + let type_definition = match self { + ValueNode::Boolean(_) => TypeDefinition::new(Type::Boolean), + ValueNode::Float(_) => TypeDefinition::new(Type::Float), + ValueNode::Integer(_) => TypeDefinition::new(Type::Integer), + ValueNode::String(_) => TypeDefinition::new(Type::String), ValueNode::List(expressions) => { - let first_expression_type = if let Some(first) = expressions.first() { - first.expected_type(context)? - } else { - Type::Any - }; + let mut previous_type = None; - Type::List(Box::new(first_expression_type)) + for expression in expressions { + let expression_type = expression.expected_type(context)?; + + if let Some(previous) = previous_type { + if expression_type != previous { + return Ok(TypeDefinition::new(Type::Any)); + } + } + + previous_type = Some(expression_type); + } + + if let Some(previous) = previous_type { + previous + } else { + TypeDefinition::new(Type::Any) + } } - ValueNode::Empty => Type::Any, - ValueNode::Map(_) => Type::Map, + ValueNode::Empty => TypeDefinition::new(Type::Any), + ValueNode::Map(_) => TypeDefinition::new(Type::Map), ValueNode::Table { column_names: _, rows: _, - } => Type::Table, - ValueNode::Function(function) => function.expected_type(context)?, + } => TypeDefinition::new(Type::Table), + ValueNode::Function(function) => return function.expected_type(context), }; - Ok(r#type) + Ok(type_definition) } } diff --git a/src/abstract_tree/while.rs b/src/abstract_tree/while.rs index d9cbf21..6ea74c5 100644 --- a/src/abstract_tree/while.rs +++ b/src/abstract_tree/while.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Block, Expression, Map, Result, Type, Value}; +use crate::{AbstractTree, Block, Expression, Map, Result, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct While { @@ -30,7 +30,7 @@ impl AbstractTree for While { Ok(Value::Empty) } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.block.expected_type(context) } } diff --git a/src/abstract_tree/yield.rs b/src/abstract_tree/yield.rs index b9f111c..d56786c 100644 --- a/src/abstract_tree/yield.rs +++ b/src/abstract_tree/yield.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Expression, FunctionCall, Map, Result, Type, Value}; +use crate::{AbstractTree, Expression, FunctionCall, Map, Result, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Yield { @@ -39,7 +39,7 @@ impl AbstractTree for Yield { self.call.run(source, context) } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.call.expected_type(context) } } diff --git a/src/error.rs b/src/error.rs index 8b9c1be..7e379f9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,7 +5,7 @@ use tree_sitter::{Node, Point}; -use crate::{value::Value, Identifier, Type}; +use crate::{value::Value, Identifier, TypeDefinition}; use std::{fmt, io, num::ParseFloatError, string::FromUtf8Error, sync::PoisonError, time}; @@ -21,15 +21,15 @@ pub enum Error { }, TypeCheck { - expected: Type, - actual: Type, + expected: TypeDefinition, + actual: TypeDefinition, location: Point, source: String, }, RuntimeTypeCheck { - expected: Type, - actual: Value, + expected: TypeDefinition, + actual: TypeDefinition, }, /// The 'assert' macro did not resolve successfully. diff --git a/src/value/function.rs b/src/value/function.rs index 1118fb2..b2af5f7 100644 --- a/src/value/function.rs +++ b/src/value/function.rs @@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter}; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Block, Error, Identifier, Map, Result, Type, Value}; +use crate::{AbstractTree, Block, Error, Identifier, Map, Result, TypeDefinition, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Function { @@ -49,7 +49,7 @@ impl AbstractTree for Function { Ok(return_value) } - fn expected_type(&self, context: &Map) -> Result { + fn expected_type(&self, context: &Map) -> Result { self.body.expected_type(context) } } diff --git a/src/value/mod.rs b/src/value/mod.rs index 4d74abd..99eba30 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -1,7 +1,7 @@ //! Types that represent runtime values. use crate::{ error::{Error, Result}, - AbstractTree, Function, List, Map, Table, Type, + AbstractTree, Function, List, Map, Table, Type, TypeDefinition, }; use serde::{ @@ -43,16 +43,24 @@ pub enum Value { } impl Value { - pub fn r#type(&self, context: &Map) -> Result { + pub fn r#type(&self, context: &Map) -> Result { let r#type = match self { Value::List(list) => { - let first_item_type = if let Some(first) = list.items().first() { - first.r#type(context)? - } else { - Type::Any - }; + let mut previous_type = None; - Type::List(Box::new(first_item_type)) + for value in list.items().iter() { + let value_type = value.r#type(context)?; + + if let Some(previous) = &previous_type { + if &value_type != previous { + break; + } + } + + previous_type = Some(value_type); + } + + Type::List(Box::new(Type::Any)) } Value::Map(_) => Type::Map, Value::Table(_) => Type::Table, @@ -77,7 +85,7 @@ impl Value { Value::Empty => Type::Empty, }; - Ok(r#type) + Ok(TypeDefinition::new(r#type)) } pub fn is_table(&self) -> bool {