Implement parsing and runtime checks
This commit is contained in:
parent
5f960021b1
commit
b6422a438b
@ -350,6 +350,7 @@ module.exports = grammar({
|
||||
choice(
|
||||
"any",
|
||||
"bool",
|
||||
"float",
|
||||
seq(
|
||||
"fn",
|
||||
repeat(
|
||||
|
@ -19,15 +19,15 @@ pub enum AssignmentOperator {
|
||||
}
|
||||
|
||||
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)?;
|
||||
|
||||
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,
|
||||
|
@ -13,7 +13,7 @@ pub struct 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)?;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ pub enum 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)?;
|
||||
|
||||
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",
|
||||
|
@ -13,7 +13,7 @@ pub struct 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)?;
|
||||
|
||||
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,
|
||||
|
@ -21,19 +21,19 @@ impl 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());
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -21,12 +21,12 @@ impl 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)?;
|
||||
|
||||
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> {
|
||||
|
@ -13,12 +13,12 @@ pub struct 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 = 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)?);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,16 +11,20 @@ pub struct 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 = 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
|
||||
};
|
||||
|
@ -18,11 +18,11 @@ pub enum AssignmentOperator {
|
||||
}
|
||||
|
||||
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)?;
|
||||
|
||||
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,
|
||||
|
@ -11,9 +11,9 @@ pub struct 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 = 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,
|
||||
|
@ -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<Self> {
|
||||
fn from_syntax_node(_source: &str, _node: Node, _context: &Map) -> Result<Self> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
@ -11,9 +11,9 @@ pub struct 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 = 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,
|
||||
|
@ -40,7 +40,7 @@ pub struct 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)?;
|
||||
|
||||
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<Self>;
|
||||
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self>;
|
||||
|
||||
/// Execute dust code by traversing the tree.
|
||||
fn run(&self, source: &str, context: &Map) -> Result<Value>;
|
||||
|
@ -22,41 +22,41 @@ pub enum 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)?;
|
||||
|
||||
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",
|
||||
|
@ -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<Self> {
|
||||
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
||||
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<Self> {
|
||||
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
||||
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"),
|
||||
|
@ -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<Self> {
|
||||
fn from_syntax_node(source: &str, node: Node, _context: &Map) -> Result<Self> {
|
||||
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 })
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ pub enum 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());
|
||||
|
||||
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))
|
||||
|
@ -10,14 +10,14 @@ pub struct 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());
|
||||
|
||||
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 })
|
||||
}
|
||||
|
@ -9,12 +9,12 @@ pub struct 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 = 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);
|
||||
}
|
||||
|
20
src/error.rs
20
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}."
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -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<Self> {
|
||||
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,
|
||||
|
@ -22,7 +22,7 @@ impl 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)?;
|
||||
|
||||
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 })
|
||||
}
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user