From b6422a438beda0e9602deec0364c213c9c39e826 Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 29 Nov 2023 22:54:46 -0500 Subject: [PATCH] Implement parsing and runtime checks --- grammar.js | 1 + src/abstract_tree/assignment.rs | 21 +++++++++++++++++---- src/abstract_tree/block.rs | 4 ++-- src/abstract_tree/expression.rs | 26 +++++++++++++++++--------- src/abstract_tree/for.rs | 8 ++++---- src/abstract_tree/function_call.rs | 10 +++++----- src/abstract_tree/identifier.rs | 6 +++--- src/abstract_tree/if_else.rs | 12 ++++++------ src/abstract_tree/index.rs | 12 ++++++++---- src/abstract_tree/index_assignment.rs | 6 +++--- src/abstract_tree/logic.rs | 6 +++--- src/abstract_tree/match.rs | 2 +- src/abstract_tree/math.rs | 6 +++--- src/abstract_tree/mod.rs | 6 +++--- src/abstract_tree/statement.rs | 22 +++++++++++----------- src/abstract_tree/type_defintion.rs | 26 ++++++++++++++++++-------- src/abstract_tree/use.rs | 5 ++--- src/abstract_tree/value_node.rs | 20 ++++++++++++-------- src/abstract_tree/while.rs | 6 +++--- src/abstract_tree/yield.rs | 8 ++++---- src/error.rs | 20 ++++++++++++++++++-- src/evaluate.rs | 2 +- src/value/function.rs | 6 +++--- src/value/mod.rs | 2 +- 24 files changed, 149 insertions(+), 94 deletions(-) diff --git a/grammar.js b/grammar.js index 3858355..56a68b2 100644 --- a/grammar.js +++ b/grammar.js @@ -350,6 +350,7 @@ module.exports = grammar({ choice( "any", "bool", + "float", seq( "fn", repeat( diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index 29b040a..038f6f0 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -19,15 +19,15 @@ pub enum AssignmentOperator { } impl AbstractTree for Assignment { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "assignment", node)?; let identifier_node = node.child_by_field_name("identifier").unwrap(); - let identifier = Identifier::from_syntax_node(source, identifier_node)?; + let identifier = Identifier::from_syntax_node(source, identifier_node, context)?; 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)?) + Some(TypeDefintion::from_syntax_node(source, type_node, context)?) } else { None }; @@ -52,7 +52,20 @@ impl AbstractTree for Assignment { }; let statement_node = node.child_by_field_name("statement").unwrap(); - let statement = Statement::from_syntax_node(source, statement_node)?; + let statement = Statement::from_syntax_node(source, statement_node, context)?; + + 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(), + }); + } + } Ok(Assignment { identifier, diff --git a/src/abstract_tree/block.rs b/src/abstract_tree/block.rs index 782e686..6b58d75 100644 --- a/src/abstract_tree/block.rs +++ b/src/abstract_tree/block.rs @@ -13,7 +13,7 @@ pub struct Block { } impl AbstractTree for Block { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "block", node)?; let first_child = node.child(0).unwrap(); @@ -30,7 +30,7 @@ impl AbstractTree for Block { let child_node = node.child(index).unwrap(); if child_node.is_named() { - let statement = Statement::from_syntax_node(source, child_node)?; + let statement = Statement::from_syntax_node(source, child_node, context)?; statements.push(statement); } } diff --git a/src/abstract_tree/expression.rs b/src/abstract_tree/expression.rs index 0a71239..e10c671 100644 --- a/src/abstract_tree/expression.rs +++ b/src/abstract_tree/expression.rs @@ -19,7 +19,7 @@ pub enum Expression { } impl AbstractTree for Expression { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "expression", node)?; let child = if node.child(0).unwrap().is_named() { @@ -29,15 +29,23 @@ impl AbstractTree for Expression { }; let expression = match child.kind() { - "value" => Expression::Value(ValueNode::from_syntax_node(source, child)?), - "identifier" => Expression::Identifier(Identifier::from_syntax_node(source, child)?), - "index" => Expression::Index(Box::new(Index::from_syntax_node(source, child)?)), - "math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)), - "logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)), - "function_call" => { - Expression::FunctionCall(Box::new(FunctionCall::from_syntax_node(source, child)?)) + "value" => Expression::Value(ValueNode::from_syntax_node(source, child, context)?), + "identifier" => { + Expression::Identifier(Identifier::from_syntax_node(source, child, context)?) + } + "index" => { + Expression::Index(Box::new(Index::from_syntax_node(source, child, context)?)) + } + "math" => Expression::Math(Box::new(Math::from_syntax_node(source, child, context)?)), + "logic" => { + Expression::Logic(Box::new(Logic::from_syntax_node(source, child, context)?)) + } + "function_call" => Expression::FunctionCall(Box::new(FunctionCall::from_syntax_node( + source, child, context, + )?)), + "yield" => { + Expression::Yield(Box::new(Yield::from_syntax_node(source, child, context)?)) } - "yield" => Expression::Yield(Box::new(Yield::from_syntax_node(source, child)?)), _ => { return Err(Error::UnexpectedSyntaxNode { expected: "value, identifier, index, math, logic, function_call or yield", diff --git a/src/abstract_tree/for.rs b/src/abstract_tree/for.rs index 5ea21d3..7271125 100644 --- a/src/abstract_tree/for.rs +++ b/src/abstract_tree/for.rs @@ -13,7 +13,7 @@ pub struct For { } impl AbstractTree for For { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "for", node)?; let for_node = node.child(0).unwrap(); @@ -31,13 +31,13 @@ impl AbstractTree for For { }; let identifier_node = node.child(1).unwrap(); - let identifier = Identifier::from_syntax_node(source, identifier_node)?; + let identifier = Identifier::from_syntax_node(source, identifier_node, context)?; let expression_node = node.child(3).unwrap(); - let expression = Expression::from_syntax_node(source, expression_node)?; + let expression = Expression::from_syntax_node(source, expression_node, context)?; let item_node = node.child(4).unwrap(); - let item = Block::from_syntax_node(source, item_node)?; + let item = Block::from_syntax_node(source, item_node, context)?; Ok(For { is_async, diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 766a830..8926108 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -21,19 +21,19 @@ impl FunctionCall { } impl AbstractTree for FunctionCall { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { debug_assert_eq!("function_call", node.kind()); let expression_node = node.child(1).unwrap(); - let function = Expression::from_syntax_node(source, expression_node)?; + let function = Expression::from_syntax_node(source, expression_node, context)?; let mut arguments = Vec::new(); for index in 2..node.child_count() - 1 { - let node = node.child(index).unwrap(); + let child = node.child(index).unwrap(); - if node.is_named() { - let expression = Expression::from_syntax_node(source, node)?; + if child.is_named() { + let expression = Expression::from_syntax_node(source, child, context)?; arguments.push(expression); } diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index ab9784a..195cff9 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -21,12 +21,12 @@ impl Identifier { } impl AbstractTree for Identifier { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, _context: &Map) -> Result { Error::expect_syntax_node(source, "identifier", node)?; - let identifier = &source[node.byte_range()]; + let text = &source[node.byte_range()]; - Ok(Identifier(identifier.to_string())) + Ok(Identifier(text.to_string())) } fn run(&self, _source: &str, context: &Map) -> Result { diff --git a/src/abstract_tree/if_else.rs b/src/abstract_tree/if_else.rs index fe01548..b8f1e18 100644 --- a/src/abstract_tree/if_else.rs +++ b/src/abstract_tree/if_else.rs @@ -13,12 +13,12 @@ pub struct IfElse { } impl AbstractTree for IfElse { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { let if_expression_node = node.child(0).unwrap().child(1).unwrap(); - let if_expression = Expression::from_syntax_node(source, if_expression_node)?; + let if_expression = Expression::from_syntax_node(source, if_expression_node, context)?; let if_block_node = node.child(0).unwrap().child(2).unwrap(); - let if_block = Block::from_syntax_node(source, if_block_node)?; + let if_block = Block::from_syntax_node(source, if_block_node, context)?; let child_count = node.child_count(); let mut else_if_expressions = Vec::new(); @@ -30,19 +30,19 @@ impl AbstractTree for IfElse { if child.kind() == "else_if" { let expression_node = child.child(1).unwrap(); - let expression = Expression::from_syntax_node(source, expression_node)?; + let expression = Expression::from_syntax_node(source, expression_node, context)?; else_if_expressions.push(expression); let block_node = child.child(2).unwrap(); - let block = Block::from_syntax_node(source, block_node)?; + let block = Block::from_syntax_node(source, block_node, context)?; else_if_blocks.push(block); } if child.kind() == "else" { let else_node = child.child(1).unwrap(); - else_block = Some(Block::from_syntax_node(source, else_node)?); + else_block = Some(Block::from_syntax_node(source, else_node, context)?); } } diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index 8e68c60..956e444 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -11,16 +11,20 @@ pub struct Index { } impl AbstractTree for Index { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { let collection_node = node.child(0).unwrap(); - let collection = Expression::from_syntax_node(source, collection_node)?; + let collection = Expression::from_syntax_node(source, collection_node, context)?; let index_node = node.child(2).unwrap(); - let index = Expression::from_syntax_node(source, index_node)?; + let index = Expression::from_syntax_node(source, index_node, context)?; let index_end_node = node.child(4); let index_end = if let Some(index_end_node) = index_end_node { - Some(Expression::from_syntax_node(source, index_end_node)?) + Some(Expression::from_syntax_node( + source, + index_end_node, + context, + )?) } else { None }; diff --git a/src/abstract_tree/index_assignment.rs b/src/abstract_tree/index_assignment.rs index b887432..a5588ff 100644 --- a/src/abstract_tree/index_assignment.rs +++ b/src/abstract_tree/index_assignment.rs @@ -18,11 +18,11 @@ pub enum AssignmentOperator { } impl AbstractTree for IndexAssignment { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "index_assignment", node)?; let index_node = node.child(0).unwrap(); - let index = Index::from_syntax_node(source, index_node)?; + let index = Index::from_syntax_node(source, index_node, context)?; let operator_node = node.child(1).unwrap().child(0).unwrap(); let operator = match operator_node.kind() { @@ -40,7 +40,7 @@ impl AbstractTree for IndexAssignment { }; let statement_node = node.child(2).unwrap(); - let statement = Statement::from_syntax_node(source, statement_node)?; + let statement = Statement::from_syntax_node(source, statement_node, context)?; Ok(IndexAssignment { index, diff --git a/src/abstract_tree/logic.rs b/src/abstract_tree/logic.rs index 1699f48..6deeb61 100644 --- a/src/abstract_tree/logic.rs +++ b/src/abstract_tree/logic.rs @@ -11,9 +11,9 @@ pub struct Logic { } impl AbstractTree for Logic { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { let left_node = node.child(0).unwrap(); - let left = Expression::from_syntax_node(source, left_node)?; + let left = Expression::from_syntax_node(source, left_node, context)?; let operator_node = node.child(1).unwrap().child(0).unwrap(); let operator = match operator_node.kind() { @@ -36,7 +36,7 @@ impl AbstractTree for Logic { }; let right_node = node.child(2).unwrap(); - let right = Expression::from_syntax_node(source, right_node)?; + let right = Expression::from_syntax_node(source, right_node, context)?; Ok(Logic { left, diff --git a/src/abstract_tree/match.rs b/src/abstract_tree/match.rs index 16b4133..a361e14 100644 --- a/src/abstract_tree/match.rs +++ b/src/abstract_tree/match.rs @@ -12,7 +12,7 @@ use crate::{AbstractTree, Map, Result, Type, Value}; pub struct Match {} impl AbstractTree for Match { - fn from_syntax_node(_source: &str, _node: Node) -> Result { + fn from_syntax_node(_source: &str, _node: Node, _context: &Map) -> Result { todo!() } diff --git a/src/abstract_tree/math.rs b/src/abstract_tree/math.rs index 4a413f3..538441f 100644 --- a/src/abstract_tree/math.rs +++ b/src/abstract_tree/math.rs @@ -11,9 +11,9 @@ pub struct Math { } impl AbstractTree for Math { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { let left_node = node.child(0).unwrap(); - let left = Expression::from_syntax_node(source, left_node)?; + let left = Expression::from_syntax_node(source, left_node, context)?; let operator_node = node.child(1).unwrap().child(0).unwrap(); let operator = match operator_node.kind() { @@ -33,7 +33,7 @@ impl AbstractTree for Math { }; let right_node = node.child(2).unwrap(); - let right = Expression::from_syntax_node(source, right_node)?; + let right = Expression::from_syntax_node(source, right_node, context)?; Ok(Math { left, diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index eb299e5..c2154f2 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -40,7 +40,7 @@ pub struct Root { } impl AbstractTree for Root { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "root", node)?; let statement_count = node.child_count(); @@ -48,7 +48,7 @@ impl AbstractTree for Root { for index in 0..statement_count { let statement_node = node.child(index).unwrap(); - let statement = Statement::from_syntax_node(source, statement_node)?; + let statement = Statement::from_syntax_node(source, statement_node, context)?; statements.push(statement); } @@ -83,7 +83,7 @@ pub trait AbstractTree: Sized { /// /// If necessary, the source code can be accessed directly by getting the /// node's byte range. - fn from_syntax_node(source: &str, node: Node) -> Result; + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result; /// Execute dust code by traversing the tree. fn run(&self, source: &str, context: &Map) -> Result; diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index d1b2c69..4bf2197 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -22,41 +22,41 @@ pub enum Statement { } impl AbstractTree for Statement { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "statement", node)?; let child = node.child(0).unwrap(); match child.kind() { "assignment" => Ok(Statement::Assignment(Box::new( - Assignment::from_syntax_node(source, child)?, + Assignment::from_syntax_node(source, child, context)?, ))), "return" => { let expression_node = child.child(1).unwrap(); - Ok(Statement::Return(Expression::from_syntax_node(source, expression_node)?)) + Ok(Statement::Return(Expression::from_syntax_node(source, expression_node, context)?)) }, "expression" => Ok(Self::Expression(Expression::from_syntax_node( - source, child, + source, child, context )?)), "if_else" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node( - source, child, + source, child, context )?))), "tool" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node( - source, child, + source, child, context )?))), "while" => Ok(Statement::While(Box::new(While::from_syntax_node( - source, child, + source, child, context )?))), "block" => Ok(Statement::Block(Box::new(Block::from_syntax_node( - source, child, + source, child, context )?))), "for" => Ok(Statement::For(Box::new(For::from_syntax_node( - source, child, + source, child, context )?))), - "use" => Ok(Statement::Use(Use::from_syntax_node(source, child)?)), + "use" => Ok(Statement::Use(Use::from_syntax_node(source, child, context)?)), "index_assignment" => Ok(Statement::IndexAssignment(Box::new(IndexAssignment::from_syntax_node( - source, child, + source, child, context )?))), _ => Err(Error::UnexpectedSyntaxNode { expected: "assignment, expression, if...else, while, for, transform, filter, tool, async, find, remove, select, insert, index_assignment or yield", diff --git a/src/abstract_tree/type_defintion.rs b/src/abstract_tree/type_defintion.rs index df867ce..9bbf269 100644 --- a/src/abstract_tree/type_defintion.rs +++ b/src/abstract_tree/type_defintion.rs @@ -10,12 +10,18 @@ pub struct TypeDefintion { r#type: Type, } +impl TypeDefintion { + pub fn r#type(&self) -> &Type { + &self.r#type + } +} + impl AbstractTree for TypeDefintion { - fn from_syntax_node(source: &str, node: Node) -> Result { + 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)?; + let r#type = Type::from_syntax_node(source, type_node, context)?; Ok(TypeDefintion { r#type }) } @@ -52,7 +58,7 @@ impl TypeDefintion { if self.r#type == value.r#type(context)? { Ok(()) } else { - Err(Error::TypeCheck { + Err(Error::RuntimeTypeCheck { expected: self.r#type.clone(), actual: value.clone(), }) @@ -61,7 +67,7 @@ impl TypeDefintion { } impl AbstractTree for Type { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "type", node)?; let type_node = node.child(0).unwrap(); @@ -76,13 +82,14 @@ impl AbstractTree for Type { for index in 1..child_count - 2 { let parameter_type_node = node.child(index).unwrap(); - let parameter_type = Type::from_syntax_node(source, parameter_type_node)?; + let parameter_type = + Type::from_syntax_node(source, parameter_type_node, context)?; parameter_types.push(parameter_type); } let return_type_node = node.child(child_count - 1).unwrap(); - let return_type = Type::from_syntax_node(source, return_type_node)?; + let return_type = Type::from_syntax_node(source, return_type_node, context)?; Type::Function { parameter_types, @@ -92,7 +99,7 @@ impl AbstractTree for Type { "int" => Type::Integer, "list" => { let item_type_node = node.child(1).unwrap(); - let item_type = Type::from_syntax_node(source, item_type_node)?; + let item_type = Type::from_syntax_node(source, item_type_node, context)?; Type::List(Box::new(item_type)) } @@ -141,6 +148,9 @@ impl PartialEq for Type { | (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, } } @@ -166,7 +176,7 @@ impl Display for Type { write!(f, "-> {return_type}") } Type::Integer => write!(f, "integer"), - Type::List(_) => write!(f, "list"), + Type::List(item_type) => write!(f, "list {item_type}"), Type::Map => write!(f, "map"), Type::Number => write!(f, "number"), Type::String => write!(f, "string"), diff --git a/src/abstract_tree/use.rs b/src/abstract_tree/use.rs index dd114e3..28adfd7 100644 --- a/src/abstract_tree/use.rs +++ b/src/abstract_tree/use.rs @@ -1,6 +1,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}; @@ -10,14 +11,12 @@ pub struct Use { } impl AbstractTree for Use { - fn from_syntax_node(source: &str, node: tree_sitter::Node) -> crate::Result { + fn from_syntax_node(source: &str, node: Node, _context: &Map) -> Result { Error::expect_syntax_node(source, "use", node)?; let string_node = node.child(1).unwrap(); let path = source[string_node.start_byte() + 1..string_node.end_byte() - 1].to_string(); - println!("{path}"); - Ok(Use { path }) } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 5dbce5b..c6dc7ce 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -25,7 +25,7 @@ pub enum ValueNode { } impl AbstractTree for ValueNode { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { debug_assert_eq!("value", node.kind()); let child = node.child(0).unwrap(); @@ -45,7 +45,8 @@ impl AbstractTree for ValueNode { let current_node = child.child(index).unwrap(); if current_node.is_named() { - let expression = Expression::from_syntax_node(source, current_node)?; + let expression = + Expression::from_syntax_node(source, current_node, context)?; expressions.push(expression); } } @@ -61,14 +62,15 @@ impl AbstractTree for ValueNode { let identifier_node = identifier_list_node.child(index).unwrap(); if identifier_node.is_named() { - let identifier = Identifier::from_syntax_node(source, identifier_node)?; + let identifier = + Identifier::from_syntax_node(source, identifier_node, context)?; column_names.push(identifier) } } let expression_node = child.child(2).unwrap(); - let expression = Expression::from_syntax_node(source, expression_node)?; + let expression = Expression::from_syntax_node(source, expression_node, context)?; ValueNode::Table { column_names, @@ -84,12 +86,14 @@ impl AbstractTree for ValueNode { if child_syntax_node.kind() == "identifier" { current_key = - Identifier::from_syntax_node(source, child_syntax_node)?.take_inner(); + Identifier::from_syntax_node(source, child_syntax_node, context)? + .take_inner(); } if child_syntax_node.kind() == "statement" { let key = current_key.clone(); - let statement = Statement::from_syntax_node(source, child_syntax_node)?; + let statement = + Statement::from_syntax_node(source, child_syntax_node, context)?; child_nodes.insert(key, statement); } @@ -97,7 +101,7 @@ impl AbstractTree for ValueNode { ValueNode::Map(child_nodes) } - "function" => ValueNode::Function(Function::from_syntax_node(source, child)?), + "function" => ValueNode::Function(Function::from_syntax_node(source, child, context)?), _ => { return Err(Error::UnexpectedSyntaxNode { expected: @@ -187,7 +191,7 @@ impl AbstractTree for ValueNode { let first_expression_type = if let Some(first) = expressions.first() { first.expected_type(context)? } else { - Type::Empty + Type::Any }; Type::List(Box::new(first_expression_type)) diff --git a/src/abstract_tree/while.rs b/src/abstract_tree/while.rs index 85d6a68..d9cbf21 100644 --- a/src/abstract_tree/while.rs +++ b/src/abstract_tree/while.rs @@ -10,14 +10,14 @@ pub struct While { } impl AbstractTree for While { - fn from_syntax_node(source: &str, node: Node) -> crate::Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> crate::Result { debug_assert_eq!("while", node.kind()); let expression_node = node.child(1).unwrap(); - let expression = Expression::from_syntax_node(source, expression_node)?; + let expression = Expression::from_syntax_node(source, expression_node, context)?; let block_node = node.child(2).unwrap(); - let block = Block::from_syntax_node(source, block_node)?; + let block = Block::from_syntax_node(source, block_node, context)?; Ok(While { expression, block }) } diff --git a/src/abstract_tree/yield.rs b/src/abstract_tree/yield.rs index 9a41c13..b9f111c 100644 --- a/src/abstract_tree/yield.rs +++ b/src/abstract_tree/yield.rs @@ -9,12 +9,12 @@ pub struct Yield { } impl AbstractTree for Yield { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { let input_node = node.child(0).unwrap(); - let input = Expression::from_syntax_node(source, input_node)?; + let input = Expression::from_syntax_node(source, input_node, context)?; let function_node = node.child(3).unwrap(); - let function = Expression::from_syntax_node(source, function_node)?; + let function = Expression::from_syntax_node(source, function_node, context)?; let mut arguments = Vec::new(); @@ -24,7 +24,7 @@ impl AbstractTree for Yield { let node = node.child(index).unwrap(); if node.is_named() { - let expression = Expression::from_syntax_node(source, node)?; + let expression = Expression::from_syntax_node(source, node, context)?; arguments.push(expression); } diff --git a/src/error.rs b/src/error.rs index a18fe85..8b9c1be 100644 --- a/src/error.rs +++ b/src/error.rs @@ -21,6 +21,13 @@ pub enum Error { }, TypeCheck { + expected: Type, + actual: Type, + location: Point, + source: String, + }, + + RuntimeTypeCheck { expected: Type, actual: Value, }, @@ -356,9 +363,18 @@ impl fmt::Display for Error { Syntax { source, location } => { write!(f, "Syntax error at {location}, this is not valid: {source}") } - TypeCheck { expected, actual } => write!( + TypeCheck { + expected, + actual, + location, + source, + } => write!( f, - "Type check error. Expected a {expected} but got {actual}." + "Type check error at {location}. Expected type {expected} but got type {actual}: {source}." + ), + RuntimeTypeCheck { expected, actual } => write!( + f, + "Type check error. Expected type {expected} but got value {actual}." ), } } diff --git a/src/evaluate.rs b/src/evaluate.rs index 7b04c9a..d1157b0 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -65,7 +65,7 @@ pub struct Interpreter<'c, 's> { impl<'c, 's> Interpreter<'c, 's> { pub fn parse(mut parser: Parser, context: &'c mut Map, source: &'s str) -> Result { let syntax_tree = parser.parse(source, None).unwrap(); - let abstract_tree = Root::from_syntax_node(source, syntax_tree.root_node())?; + let abstract_tree = Root::from_syntax_node(source, syntax_tree.root_node(), context)?; Ok(Interpreter { _parser: parser, diff --git a/src/value/function.rs b/src/value/function.rs index deb1b06..1118fb2 100644 --- a/src/value/function.rs +++ b/src/value/function.rs @@ -22,7 +22,7 @@ impl Function { } impl AbstractTree for Function { - fn from_syntax_node(source: &str, node: Node) -> Result { + fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result { Error::expect_syntax_node(source, "function", node)?; let child_count = node.child_count(); @@ -32,13 +32,13 @@ impl AbstractTree for Function { let child = node.child(index).unwrap(); if child.is_named() { - let identifier = Identifier::from_syntax_node(source, child)?; + let identifier = Identifier::from_syntax_node(source, child, context)?; parameters.push(identifier); } } let body_node = node.child(child_count - 1).unwrap(); - let body = Block::from_syntax_node(source, body_node)?; + let body = Block::from_syntax_node(source, body_node, context)?; Ok(Function { parameters, body }) } diff --git a/src/value/mod.rs b/src/value/mod.rs index 5753a51..4d74abd 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -49,7 +49,7 @@ impl Value { let first_item_type = if let Some(first) = list.items().first() { first.r#type(context)? } else { - Type::Empty + Type::Any }; Type::List(Box::new(first_item_type))