Implement parsing and runtime checks
This commit is contained in:
parent
5f960021b1
commit
b6422a438b
@ -350,6 +350,7 @@ module.exports = grammar({
|
|||||||
choice(
|
choice(
|
||||||
"any",
|
"any",
|
||||||
"bool",
|
"bool",
|
||||||
|
"float",
|
||||||
seq(
|
seq(
|
||||||
"fn",
|
"fn",
|
||||||
repeat(
|
repeat(
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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",
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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> {
|
||||||
|
@ -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)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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>;
|
||||||
|
@ -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",
|
||||||
|
@ -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"),
|
||||||
|
@ -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 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
@ -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 })
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
20
src/error.rs
20
src/error.rs
@ -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}."
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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 })
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
|
Loading…
Reference in New Issue
Block a user