Implement parsing and runtime checks

This commit is contained in:
Jeff 2023-11-29 22:54:46 -05:00
parent 5f960021b1
commit b6422a438b
24 changed files with 149 additions and 94 deletions

View File

@ -350,6 +350,7 @@ module.exports = grammar({
choice( choice(
"any", "any",
"bool", "bool",
"float",
seq( seq(
"fn", "fn",
repeat( repeat(

View File

@ -19,15 +19,15 @@ pub enum AssignmentOperator {
} }
impl AbstractTree for Assignment { impl AbstractTree for Assignment {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
Error::expect_syntax_node(source, "assignment", node)?; Error::expect_syntax_node(source, "assignment", node)?;
let identifier_node = node.child_by_field_name("identifier").unwrap(); 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_node = node.child_by_field_name("type");
let type_definition = if let Some(type_node) = type_node { 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 { } else {
None None
}; };
@ -52,7 +52,20 @@ impl AbstractTree for Assignment {
}; };
let statement_node = node.child_by_field_name("statement").unwrap(); 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 { Ok(Assignment {
identifier, identifier,

View File

@ -13,7 +13,7 @@ pub struct Block {
} }
impl AbstractTree for Block { impl AbstractTree for Block {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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();
@ -30,7 +30,7 @@ impl AbstractTree for Block {
let child_node = node.child(index).unwrap(); let child_node = node.child(index).unwrap();
if child_node.is_named() { 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); statements.push(statement);
} }
} }

View File

@ -19,7 +19,7 @@ pub enum Expression {
} }
impl AbstractTree for Expression { impl AbstractTree for Expression {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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() {
@ -29,15 +29,23 @@ impl AbstractTree for Expression {
}; };
let expression = match child.kind() { let expression = match child.kind() {
"value" => Expression::Value(ValueNode::from_syntax_node(source, child)?), "value" => Expression::Value(ValueNode::from_syntax_node(source, child, context)?),
"identifier" => Expression::Identifier(Identifier::from_syntax_node(source, child)?), "identifier" => {
"index" => Expression::Index(Box::new(Index::from_syntax_node(source, child)?)), Expression::Identifier(Identifier::from_syntax_node(source, child, context)?)
"math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)), }
"logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)), "index" => {
"function_call" => { Expression::Index(Box::new(Index::from_syntax_node(source, child, context)?))
Expression::FunctionCall(Box::new(FunctionCall::from_syntax_node(source, child)?)) }
"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 { return Err(Error::UnexpectedSyntaxNode {
expected: "value, identifier, index, math, logic, function_call or yield", expected: "value, identifier, index, math, logic, function_call or yield",

View File

@ -13,7 +13,7 @@ pub struct For {
} }
impl AbstractTree for For { impl AbstractTree for For {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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();
@ -31,13 +31,13 @@ impl AbstractTree for For {
}; };
let identifier_node = node.child(1).unwrap(); 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_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_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 { Ok(For {
is_async, is_async,

View File

@ -21,19 +21,19 @@ impl FunctionCall {
} }
impl AbstractTree for FunctionCall { impl AbstractTree for FunctionCall {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
debug_assert_eq!("function_call", node.kind()); debug_assert_eq!("function_call", node.kind());
let expression_node = node.child(1).unwrap(); 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(); let mut arguments = Vec::new();
for index in 2..node.child_count() - 1 { for index in 2..node.child_count() - 1 {
let node = node.child(index).unwrap(); let child = node.child(index).unwrap();
if node.is_named() { if child.is_named() {
let expression = Expression::from_syntax_node(source, node)?; let expression = Expression::from_syntax_node(source, child, context)?;
arguments.push(expression); arguments.push(expression);
} }

View File

@ -21,12 +21,12 @@ impl Identifier {
} }
impl AbstractTree for Identifier { impl AbstractTree for Identifier {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, _context: &Map) -> Result<Self> {
Error::expect_syntax_node(source, "identifier", node)?; 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<Value> { fn run(&self, _source: &str, context: &Map) -> Result<Value> {

View File

@ -13,12 +13,12 @@ pub struct IfElse {
} }
impl AbstractTree for IfElse { impl AbstractTree for IfElse {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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)?; 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_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 child_count = node.child_count();
let mut else_if_expressions = Vec::new(); let mut else_if_expressions = Vec::new();
@ -30,19 +30,19 @@ impl AbstractTree for IfElse {
if child.kind() == "else_if" { if child.kind() == "else_if" {
let expression_node = child.child(1).unwrap(); 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); else_if_expressions.push(expression);
let block_node = child.child(2).unwrap(); 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); else_if_blocks.push(block);
} }
if child.kind() == "else" { if child.kind() == "else" {
let else_node = child.child(1).unwrap(); 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)?);
} }
} }

View File

@ -11,16 +11,20 @@ pub struct Index {
} }
impl AbstractTree for Index { impl AbstractTree for Index {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
let collection_node = node.child(0).unwrap(); 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_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_node = node.child(4);
let index_end = if let Some(index_end_node) = index_end_node { 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 { } else {
None None
}; };

View File

@ -18,11 +18,11 @@ pub enum AssignmentOperator {
} }
impl AbstractTree for IndexAssignment { impl AbstractTree for IndexAssignment {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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();
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_node = node.child(1).unwrap().child(0).unwrap();
let operator = match operator_node.kind() { let operator = match operator_node.kind() {
@ -40,7 +40,7 @@ impl AbstractTree for IndexAssignment {
}; };
let statement_node = node.child(2).unwrap(); 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 { Ok(IndexAssignment {
index, index,

View File

@ -11,9 +11,9 @@ pub struct Logic {
} }
impl AbstractTree for Logic { impl AbstractTree for Logic {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
let left_node = node.child(0).unwrap(); 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_node = node.child(1).unwrap().child(0).unwrap();
let operator = match operator_node.kind() { let operator = match operator_node.kind() {
@ -36,7 +36,7 @@ impl AbstractTree for Logic {
}; };
let right_node = node.child(2).unwrap(); 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 { Ok(Logic {
left, left,

View File

@ -12,7 +12,7 @@ use crate::{AbstractTree, Map, Result, Type, Value};
pub struct Match {} pub struct Match {}
impl AbstractTree for Match { impl AbstractTree for Match {
fn from_syntax_node(_source: &str, _node: Node) -> Result<Self> { fn from_syntax_node(_source: &str, _node: Node, _context: &Map) -> Result<Self> {
todo!() todo!()
} }

View File

@ -11,9 +11,9 @@ pub struct Math {
} }
impl AbstractTree for Math { impl AbstractTree for Math {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
let left_node = node.child(0).unwrap(); 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_node = node.child(1).unwrap().child(0).unwrap();
let operator = match operator_node.kind() { let operator = match operator_node.kind() {
@ -33,7 +33,7 @@ impl AbstractTree for Math {
}; };
let right_node = node.child(2).unwrap(); 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 { Ok(Math {
left, left,

View File

@ -40,7 +40,7 @@ pub struct Root {
} }
impl AbstractTree for Root { impl AbstractTree for Root {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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();
@ -48,7 +48,7 @@ impl AbstractTree for Root {
for index in 0..statement_count { for index in 0..statement_count {
let statement_node = node.child(index).unwrap(); 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); statements.push(statement);
} }
@ -83,7 +83,7 @@ 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) -> Result<Self>; fn from_syntax_node(source: &str, node: Node, context: &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: &Map) -> Result<Value>;

View File

@ -22,41 +22,41 @@ pub enum Statement {
} }
impl AbstractTree for Statement { impl AbstractTree for Statement {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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();
match child.kind() { match child.kind() {
"assignment" => Ok(Statement::Assignment(Box::new( "assignment" => Ok(Statement::Assignment(Box::new(
Assignment::from_syntax_node(source, child)?, Assignment::from_syntax_node(source, child, context)?,
))), ))),
"return" => { "return" => {
let expression_node = child.child(1).unwrap(); 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( "expression" => Ok(Self::Expression(Expression::from_syntax_node(
source, child, source, child, context
)?)), )?)),
"if_else" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node( "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( "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( "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( "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( "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( "index_assignment" => Ok(Statement::IndexAssignment(Box::new(IndexAssignment::from_syntax_node(
source, child, source, child, context
)?))), )?))),
_ => Err(Error::UnexpectedSyntaxNode { _ => Err(Error::UnexpectedSyntaxNode {
expected: "assignment, expression, if...else, while, for, transform, filter, tool, async, find, remove, select, insert, index_assignment or yield", expected: "assignment, expression, if...else, while, for, transform, filter, tool, async, find, remove, select, insert, index_assignment or yield",

View File

@ -10,12 +10,18 @@ pub struct TypeDefintion {
r#type: Type, r#type: Type,
} }
impl TypeDefintion {
pub fn r#type(&self) -> &Type {
&self.r#type
}
}
impl AbstractTree for TypeDefintion { impl AbstractTree for TypeDefintion {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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();
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 }) Ok(TypeDefintion { r#type })
} }
@ -52,7 +58,7 @@ impl TypeDefintion {
if self.r#type == value.r#type(context)? { if self.r#type == value.r#type(context)? {
Ok(()) Ok(())
} else { } else {
Err(Error::TypeCheck { Err(Error::RuntimeTypeCheck {
expected: self.r#type.clone(), expected: self.r#type.clone(),
actual: value.clone(), actual: value.clone(),
}) })
@ -61,7 +67,7 @@ impl TypeDefintion {
} }
impl AbstractTree for Type { impl AbstractTree for Type {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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();
@ -76,13 +82,14 @@ impl AbstractTree for Type {
for index in 1..child_count - 2 { for index in 1..child_count - 2 {
let parameter_type_node = node.child(index).unwrap(); 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); parameter_types.push(parameter_type);
} }
let return_type_node = node.child(child_count - 1).unwrap(); 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 { Type::Function {
parameter_types, parameter_types,
@ -92,7 +99,7 @@ impl AbstractTree for Type {
"int" => Type::Integer, "int" => Type::Integer,
"list" => { "list" => {
let item_type_node = node.child(1).unwrap(); 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)) Type::List(Box::new(item_type))
} }
@ -141,6 +148,9 @@ impl PartialEq for Type {
| (Type::Float, Type::Number) | (Type::Float, Type::Number)
| (Type::String, Type::String) | (Type::String, Type::String)
| (Type::Table, Type::Table) => true, | (Type::Table, Type::Table) => true,
(Type::List(self_item_type), Type::List(other_item_type)) => {
self_item_type == other_item_type
}
_ => false, _ => false,
} }
} }
@ -166,7 +176,7 @@ impl Display for Type {
write!(f, "-> {return_type}") write!(f, "-> {return_type}")
} }
Type::Integer => write!(f, "integer"), 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::Map => write!(f, "map"),
Type::Number => write!(f, "number"), Type::Number => write!(f, "number"),
Type::String => write!(f, "string"), Type::String => write!(f, "string"),

View File

@ -1,6 +1,7 @@
use std::fs::read_to_string; use std::fs::read_to_string;
use serde::{Deserialize, Serialize}; 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, Value};
@ -10,14 +11,12 @@ pub struct Use {
} }
impl AbstractTree for Use { impl AbstractTree for Use {
fn from_syntax_node(source: &str, node: tree_sitter::Node) -> crate::Result<Self> { fn from_syntax_node(source: &str, node: Node, _context: &Map) -> Result<Self> {
Error::expect_syntax_node(source, "use", node)?; Error::expect_syntax_node(source, "use", node)?;
let string_node = node.child(1).unwrap(); let string_node = node.child(1).unwrap();
let path = source[string_node.start_byte() + 1..string_node.end_byte() - 1].to_string(); let path = source[string_node.start_byte() + 1..string_node.end_byte() - 1].to_string();
println!("{path}");
Ok(Use { path }) Ok(Use { path })
} }

View File

@ -25,7 +25,7 @@ pub enum ValueNode {
} }
impl AbstractTree for ValueNode { impl AbstractTree for ValueNode {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
debug_assert_eq!("value", node.kind()); debug_assert_eq!("value", node.kind());
let child = node.child(0).unwrap(); let child = node.child(0).unwrap();
@ -45,7 +45,8 @@ impl AbstractTree for ValueNode {
let current_node = child.child(index).unwrap(); let current_node = child.child(index).unwrap();
if current_node.is_named() { 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); expressions.push(expression);
} }
} }
@ -61,14 +62,15 @@ impl AbstractTree for ValueNode {
let identifier_node = identifier_list_node.child(index).unwrap(); let identifier_node = identifier_list_node.child(index).unwrap();
if identifier_node.is_named() { 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) column_names.push(identifier)
} }
} }
let expression_node = child.child(2).unwrap(); 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 { ValueNode::Table {
column_names, column_names,
@ -84,12 +86,14 @@ impl AbstractTree for ValueNode {
if child_syntax_node.kind() == "identifier" { if child_syntax_node.kind() == "identifier" {
current_key = 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" { if child_syntax_node.kind() == "statement" {
let key = current_key.clone(); 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); child_nodes.insert(key, statement);
} }
@ -97,7 +101,7 @@ impl AbstractTree for ValueNode {
ValueNode::Map(child_nodes) 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 { return Err(Error::UnexpectedSyntaxNode {
expected: expected:
@ -187,7 +191,7 @@ impl AbstractTree for ValueNode {
let first_expression_type = if let Some(first) = expressions.first() { let first_expression_type = if let Some(first) = expressions.first() {
first.expected_type(context)? first.expected_type(context)?
} else { } else {
Type::Empty Type::Any
}; };
Type::List(Box::new(first_expression_type)) Type::List(Box::new(first_expression_type))

View File

@ -10,14 +10,14 @@ pub struct While {
} }
impl AbstractTree for While { impl AbstractTree for While {
fn from_syntax_node(source: &str, node: Node) -> crate::Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> crate::Result<Self> {
debug_assert_eq!("while", node.kind()); debug_assert_eq!("while", node.kind());
let expression_node = node.child(1).unwrap(); 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_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 }) Ok(While { expression, block })
} }

View File

@ -9,12 +9,12 @@ pub struct Yield {
} }
impl AbstractTree for Yield { impl AbstractTree for Yield {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
let input_node = node.child(0).unwrap(); 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_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(); let mut arguments = Vec::new();
@ -24,7 +24,7 @@ impl AbstractTree for Yield {
let node = node.child(index).unwrap(); let node = node.child(index).unwrap();
if node.is_named() { if node.is_named() {
let expression = Expression::from_syntax_node(source, node)?; let expression = Expression::from_syntax_node(source, node, context)?;
arguments.push(expression); arguments.push(expression);
} }

View File

@ -21,6 +21,13 @@ pub enum Error {
}, },
TypeCheck { TypeCheck {
expected: Type,
actual: Type,
location: Point,
source: String,
},
RuntimeTypeCheck {
expected: Type, expected: Type,
actual: Value, actual: Value,
}, },
@ -356,9 +363,18 @@ impl fmt::Display for Error {
Syntax { source, location } => { Syntax { source, location } => {
write!(f, "Syntax error at {location}, this is not valid: {source}") write!(f, "Syntax error at {location}, this is not valid: {source}")
} }
TypeCheck { expected, actual } => write!( TypeCheck {
expected,
actual,
location,
source,
} => write!(
f, 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}."
), ),
} }
} }

View File

@ -65,7 +65,7 @@ pub struct Interpreter<'c, 's> {
impl<'c, 's> Interpreter<'c, 's> { impl<'c, 's> Interpreter<'c, 's> {
pub fn parse(mut parser: Parser, context: &'c mut Map, source: &'s str) -> Result<Self> { pub fn parse(mut parser: Parser, context: &'c mut Map, source: &'s str) -> Result<Self> {
let syntax_tree = parser.parse(source, None).unwrap(); 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 { Ok(Interpreter {
_parser: parser, _parser: parser,

View File

@ -22,7 +22,7 @@ impl Function {
} }
impl AbstractTree for Function { impl AbstractTree for Function {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node, context: &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();
@ -32,13 +32,13 @@ impl AbstractTree for Function {
let child = node.child(index).unwrap(); let child = node.child(index).unwrap();
if child.is_named() { if child.is_named() {
let identifier = Identifier::from_syntax_node(source, child)?; let identifier = Identifier::from_syntax_node(source, child, context)?;
parameters.push(identifier); parameters.push(identifier);
} }
} }
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)?; let body = Block::from_syntax_node(source, body_node, context)?;
Ok(Function { parameters, body }) Ok(Function { parameters, body })
} }

View File

@ -49,7 +49,7 @@ impl Value {
let first_item_type = if let Some(first) = list.items().first() { let first_item_type = if let Some(first) = list.items().first() {
first.r#type(context)? first.r#type(context)?
} else { } else {
Type::Empty Type::Any
}; };
Type::List(Box::new(first_item_type)) Type::List(Box::new(first_item_type))