From 8737175df0fac1add1adbf9be5096ed0a0a1c43f Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 6 Jan 2024 08:11:09 -0500 Subject: [PATCH] Implement formatting --- src/abstract_tree/assignment.rs | 57 +---- src/abstract_tree/assignment_operator.rs | 55 +++++ src/abstract_tree/block.rs | 23 +- src/abstract_tree/built_in_value.rs | 31 ++- src/abstract_tree/expression.rs | 23 +- src/abstract_tree/for.rs | 27 +-- src/abstract_tree/function_call.rs | 24 +- src/abstract_tree/function_expression.rs | 22 +- src/abstract_tree/function_node.rs | 40 ++-- src/abstract_tree/identifier.rs | 12 +- src/abstract_tree/if_else.rs | 38 +-- src/abstract_tree/index.rs | 25 +- src/abstract_tree/index_assignment.rs | 38 +-- src/abstract_tree/index_expression.rs | 26 +- src/abstract_tree/logic.rs | 74 +----- src/abstract_tree/logic_operator.rs | 70 ++++++ src/abstract_tree/match.rs | 32 ++- src/abstract_tree/math.rs | 59 +---- src/abstract_tree/math_operator.rs | 57 +++++ src/abstract_tree/mod.rs | 29 ++- src/abstract_tree/statement.rs | 30 +-- src/abstract_tree/type.rs | 290 +++++++++++++++++++++++ src/abstract_tree/type_definition.rs | 247 +------------------ src/abstract_tree/value_node.rs | 71 ++++-- src/abstract_tree/while.rs | 15 +- src/abstract_tree/yield.rs | 12 +- src/built_in_functions/mod.rs | 19 +- src/interpret.rs | 8 +- src/value/function.rs | 50 ++-- src/value/mod.rs | 2 +- 30 files changed, 818 insertions(+), 688 deletions(-) create mode 100644 src/abstract_tree/assignment_operator.rs create mode 100644 src/abstract_tree/logic_operator.rs create mode 100644 src/abstract_tree/math_operator.rs create mode 100644 src/abstract_tree/type.rs diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index 07e9863..7864ee5 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -1,10 +1,8 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use crate::{ - AbstractTree, Error, Identifier, Map, Result, Statement, SyntaxNode, SyntaxPosition, Type, - TypeDefinition, Value, + AbstractTree, AssignmentOperator, Error, Format, Identifier, Map, Result, Statement, + SyntaxNode, SyntaxPosition, Type, TypeDefinition, Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -34,24 +32,8 @@ impl AbstractTree for Assignment { None }; - let operator_node = syntax_node - .child(child_count - 2) - .unwrap() - .child(0) - .unwrap(); - let operator = match operator_node.kind() { - "=" => AssignmentOperator::Equal, - "+=" => AssignmentOperator::PlusEqual, - "-=" => AssignmentOperator::MinusEqual, - _ => { - return Err(Error::UnexpectedSyntaxNode { - expected: "=, += or -=".to_string(), - actual: operator_node.kind().to_string(), - location: operator_node.start_position(), - relevant_source: source[operator_node.byte_range()].to_string(), - }) - } - }; + let operator_node = syntax_node.child(child_count - 2).unwrap(); + let operator = AssignmentOperator::from_syntax_node(source, operator_node, context)?; let statement_node = syntax_node.child(child_count - 1).unwrap(); let statement = Statement::from_syntax_node(source, statement_node, context)?; @@ -159,8 +141,8 @@ impl AbstractTree for Assignment { } } -impl Display for Assignment { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl Format for Assignment { + fn format(&self, output: &mut String, indent_level: u8) { let Assignment { identifier, type_definition, @@ -169,29 +151,16 @@ impl Display for Assignment { syntax_position: _, } = self; - write!(f, "{identifier}")?; + self.identifier.format(output, indent_level); if let Some(type_definition) = type_definition { - write!(f, " {type_definition}")?; + type_definition.format(output, indent_level); } - write!(f, " {operator} {statement}") - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] -pub enum AssignmentOperator { - Equal, - PlusEqual, - MinusEqual, -} - -impl Display for AssignmentOperator { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - AssignmentOperator::Equal => write!(f, "="), - AssignmentOperator::PlusEqual => write!(f, "-="), - AssignmentOperator::MinusEqual => write!(f, "+="), - } + output.push_str(" "); + self.operator.format(output, indent_level); + output.push_str(" "); + + self.statement.format(output, indent_level); } } diff --git a/src/abstract_tree/assignment_operator.rs b/src/abstract_tree/assignment_operator.rs new file mode 100644 index 0000000..05db814 --- /dev/null +++ b/src/abstract_tree/assignment_operator.rs @@ -0,0 +1,55 @@ +use serde::{Deserialize, Serialize}; + +use crate::{AbstractTree, Error, Format, Map, Result, Type, Value}; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub enum AssignmentOperator { + Equal, + PlusEqual, + MinusEqual, +} + +impl AbstractTree for AssignmentOperator { + fn from_syntax_node( + source: &str, + node: tree_sitter::Node, + context: &crate::Map, + ) -> Result { + Error::expect_syntax_node(source, "assignment_operator", node)?; + + let operator_node = node.child(0).unwrap(); + let operator = match operator_node.kind() { + "=" => AssignmentOperator::Equal, + "+=" => AssignmentOperator::PlusEqual, + "-=" => AssignmentOperator::MinusEqual, + _ => { + return Err(Error::UnexpectedSyntaxNode { + expected: "=, += or -=".to_string(), + actual: operator_node.kind().to_string(), + location: operator_node.start_position(), + relevant_source: source[operator_node.byte_range()].to_string(), + }) + } + }; + + Ok(operator) + } + + fn run(&self, source: &str, context: &Map) -> Result { + Ok(Value::none()) + } + + fn expected_type(&self, context: &Map) -> Result { + Ok(Type::None) + } +} + +impl Format for AssignmentOperator { + fn format(&self, output: &mut String, indent_level: u8) { + match self { + AssignmentOperator::Equal => output.push('='), + AssignmentOperator::PlusEqual => output.push_str("+="), + AssignmentOperator::MinusEqual => output.push_str("-="), + } + } +} diff --git a/src/abstract_tree/block.rs b/src/abstract_tree/block.rs index 3b080f0..ab35fed 100644 --- a/src/abstract_tree/block.rs +++ b/src/abstract_tree/block.rs @@ -1,13 +1,10 @@ -use std::{ - fmt::{self, Display, Formatter}, - sync::RwLock, -}; +use std::sync::RwLock; use rayon::prelude::*; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Map, Result, Statement, Type, Value}; +use crate::{AbstractTree, Error, Format, Map, Result, Statement, Type, Value}; /// Abstract representation of a block. /// @@ -131,18 +128,22 @@ impl AbstractTree for Block { } } -impl Display for Block { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl Format for Block { + fn format(&self, output: &mut String, indent_level: u8) { if self.is_async { - writeln!(f, "async {{")?; + output.push_str("async {"); } else { - writeln!(f, "{{")?; + output.push('{'); } for statement in &self.statements { - writeln!(f, " {statement}")?; + for _ in 0..=indent_level { + output.push_str(" "); + } + + statement.format(output, indent_level); } - writeln!(f, "}}") + output.push('}'); } } diff --git a/src/abstract_tree/built_in_value.rs b/src/abstract_tree/built_in_value.rs index 164c0a9..e93a7c8 100644 --- a/src/abstract_tree/built_in_value.rs +++ b/src/abstract_tree/built_in_value.rs @@ -1,15 +1,11 @@ -use std::{ - env::args, - fmt::{self, Display, Formatter}, - sync::OnceLock, -}; +use std::{env::args, sync::OnceLock}; use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - built_in_functions::string_functions, AbstractTree, BuiltInFunction, Function, List, Map, - Result, Type, Value, + built_in_functions::string_functions, AbstractTree, BuiltInFunction, Format, Function, List, + Map, Result, Type, Value, }; static ARGS: OnceLock = OnceLock::new(); @@ -31,6 +27,19 @@ pub enum BuiltInValue { } impl BuiltInValue { + pub fn name(&self) -> &'static str { + match self { + BuiltInValue::Args => "args", + BuiltInValue::AssertEqual => "assert_equal", + BuiltInValue::Fs => "fs", + BuiltInValue::Json => "json", + BuiltInValue::Length => "length", + BuiltInValue::Output => "output", + BuiltInValue::Random => "random", + BuiltInValue::String => "string", + } + } + fn r#type(&self) -> Type { match self { BuiltInValue::Args => Type::list(Type::String), @@ -72,7 +81,7 @@ impl BuiltInValue { json_context .set( - "parse".to_string(), + BuiltInFunction::JsonParse.name().to_string(), Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)), None, ) @@ -153,8 +162,8 @@ impl AbstractTree for BuiltInValue { } } -impl Display for BuiltInValue { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.get()) +impl Format for BuiltInValue { + fn format(&self, output: &mut String, indent_level: u8) { + output.push_str(&self.get().to_string()); } } diff --git a/src/abstract_tree/expression.rs b/src/abstract_tree/expression.rs index 8b4f11f..e28d366 100644 --- a/src/abstract_tree/expression.rs +++ b/src/abstract_tree/expression.rs @@ -1,10 +1,9 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - value_node::ValueNode, AbstractTree, Error, Identifier, Index, Map, Result, Type, Value, Yield, + value_node::ValueNode, AbstractTree, Error, Format, Identifier, Index, Map, Result, Type, + Value, Yield, }; use super::{function_call::FunctionCall, logic::Logic, math::Math}; @@ -104,16 +103,16 @@ impl AbstractTree for Expression { } } -impl Display for Expression { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl Format for Expression { + fn format(&self, output: &mut String, indent_level: u8) { match self { - Expression::Value(value_node) => write!(f, "{value_node}"), - Expression::Identifier(identifier) => write!(f, "{identifier}"), - Expression::Math(math) => write!(f, "{math}"), - Expression::Logic(logic) => write!(f, "{logic}"), - Expression::FunctionCall(function_call) => write!(f, "{function_call}"), - Expression::Index(index) => write!(f, "{index}"), - Expression::Yield(r#yield) => write!(f, "{}", r#yield), + Expression::Value(value_node) => value_node.format(output, indent_level), + Expression::Identifier(identifier) => identifier.format(output, indent_level), + Expression::Math(math) => math.format(output, indent_level), + Expression::Logic(logic) => logic.format(output, indent_level), + Expression::FunctionCall(function_call) => function_call.format(output, indent_level), + Expression::Index(index) => index.format(output, indent_level), + Expression::Yield(r#yield) => r#yield.format(output, indent_level), } } } diff --git a/src/abstract_tree/for.rs b/src/abstract_tree/for.rs index a183620..8270a2d 100644 --- a/src/abstract_tree/for.rs +++ b/src/abstract_tree/for.rs @@ -1,10 +1,10 @@ -use std::fmt::{self, Display, Formatter}; +use std::fmt::Write; use rayon::prelude::*; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, Value}; +use crate::{AbstractTree, Block, Error, Expression, Format, Identifier, Map, Result, Type, Value}; /// Abstract representation of a for loop statement. #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -81,21 +81,18 @@ impl AbstractTree for For { } } -impl Display for For { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let For { - is_async, - item_id, - collection, - block, - } = self; - - if *is_async { - write!(f, "async for ")?; +impl Format for For { + fn format(&self, output: &mut String, indent_level: u8) { + if self.is_async { + output.write_str("async for "); } else { - write!(f, "for ")?; + output.write_str("for "); } - write!(f, "{item_id} in {collection}, {{{block}}}") + self.item_id.format(output, indent_level); + output.push_str(" in "); + self.collection.format(output, indent_level); + output.push_str(" "); + self.block.format(output, indent_level); } } diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 8a36e09..202d816 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -1,10 +1,9 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - AbstractTree, Error, Expression, FunctionExpression, Map, Result, SyntaxPosition, Type, Value, + AbstractTree, Error, Expression, Format, FunctionExpression, Map, Result, SyntaxPosition, Type, + Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -162,20 +161,15 @@ impl AbstractTree for FunctionCall { } } -impl Display for FunctionCall { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let FunctionCall { - function_expression, - arguments, - .. - } = self; +impl Format for FunctionCall { + fn format(&self, output: &mut String, indent_level: u8) { + self.function_expression.format(output, indent_level); + output.push('('); - write!(f, "{function_expression}(")?; - - for expression in arguments { - write!(f, "{expression}")?; + for expression in &self.arguments { + expression.format(output, indent_level); } - write!(f, ")") + output.push(')'); } } diff --git a/src/abstract_tree/function_expression.rs b/src/abstract_tree/function_expression.rs index d4795ce..ccf6421 100644 --- a/src/abstract_tree/function_expression.rs +++ b/src/abstract_tree/function_expression.rs @@ -1,11 +1,9 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type, Value, ValueNode, - Yield, + AbstractTree, Error, Format, FunctionCall, Identifier, Index, Map, Result, Type, Value, + ValueNode, Yield, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -77,14 +75,16 @@ impl AbstractTree for FunctionExpression { } } -impl Display for FunctionExpression { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl Format for FunctionExpression { + fn format(&self, output: &mut String, indent_level: u8) { match self { - FunctionExpression::Value(value_node) => write!(f, "{value_node}"), - FunctionExpression::Identifier(identifier) => write!(f, "{identifier}"), - FunctionExpression::FunctionCall(function_call) => write!(f, "{function_call}"), - FunctionExpression::Index(index) => write!(f, "{index}"), - FunctionExpression::Yield(r#yield) => write!(f, "{}", r#yield), + FunctionExpression::Value(value_node) => value_node.format(output, indent_level), + FunctionExpression::Identifier(identifier) => identifier.format(output, indent_level), + FunctionExpression::FunctionCall(function_call) => { + function_call.format(output, indent_level) + } + FunctionExpression::Index(index) => index.format(output, indent_level), + FunctionExpression::Yield(r#yield) => r#yield.format(output, indent_level), } } } diff --git a/src/abstract_tree/function_node.rs b/src/abstract_tree/function_node.rs index c61d531..c97bcf5 100644 --- a/src/abstract_tree/function_node.rs +++ b/src/abstract_tree/function_node.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - AbstractTree, Block, Error, Function, Identifier, Map, Result, SyntaxPosition, Type, + AbstractTree, Block, Error, Format, Function, Identifier, Map, Result, SyntaxPosition, Type, TypeDefinition, Value, }; @@ -146,31 +146,39 @@ impl AbstractTree for FunctionNode { } } -impl Display for FunctionNode { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let FunctionNode { - parameters, - body, - r#type, - .. - } = self; - +impl Format for FunctionNode { + fn format(&self, output: &mut String, indent_level: u8) { let (parameter_types, return_type) = if let Type::Function { parameter_types, return_type, - } = r#type + } = &self.r#type { (parameter_types, return_type) } else { - return Ok(()); + return; }; - write!(f, "(")?; + output.push('('); - for (identifier, r#type) in parameters.iter().zip(parameter_types.iter()) { - write!(f, "{identifier} <{}>", r#type)?; + for (identifier, r#type) in self.parameters.iter().zip(parameter_types.iter()) { + identifier.format(output, indent_level); + output.push('<'); + r#type.format(output, indent_level); + output.push('>'); } - write!(f, ") <{return_type}> {body}") + output.push_str(") <"); + return_type.format(output, indent_level); + output.push_str("> "); + self.body.format(output, indent_level); + } +} + +impl Display for FunctionNode { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let mut string = String::new(); + + self.format(&mut string, 0); + f.write_str(&string) } } diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index 377c2e8..9a0d18d 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter}; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Map, Result, Type, Value}; +use crate::{AbstractTree, Error, Format, Map, Result, Type, Value}; /// A string by which a variable is known to a context. /// @@ -13,8 +13,8 @@ use crate::{AbstractTree, Error, Map, Result, Type, Value}; pub struct Identifier(String); impl Identifier { - pub fn new(inner: String) -> Self { - Identifier(inner) + pub fn new>(inner: T) -> Self { + Identifier(inner.into()) } pub fn take_inner(self) -> String { @@ -56,6 +56,12 @@ impl AbstractTree for Identifier { } } +impl Format for Identifier { + fn format(&self, output: &mut String, indent_level: u8) { + output.push_str(&self.0); + } +} + impl Display for Identifier { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{}", self.0) diff --git a/src/abstract_tree/if_else.rs b/src/abstract_tree/if_else.rs index e879b41..e53e580 100644 --- a/src/abstract_tree/if_else.rs +++ b/src/abstract_tree/if_else.rs @@ -1,9 +1,7 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Block, Expression, Map, Result, Type, Value}; +use crate::{AbstractTree, Block, Expression, Format, Map, Result, Type, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct IfElse { @@ -88,26 +86,28 @@ impl AbstractTree for IfElse { } } -impl Display for IfElse { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let IfElse { - if_expression, - if_block, - else_if_expressions, - else_if_blocks, - else_block, - } = self; +impl Format for IfElse { + fn format(&self, output: &mut String, indent_level: u8) { + output.push_str("if "); + self.if_expression.format(output, indent_level); + output.push(' '); + self.if_block.format(output, indent_level); - write!(f, "if {if_expression} {{{if_block}}}")?; + let else_ifs = self + .else_if_expressions + .iter() + .zip(self.else_if_blocks.iter()); - for (expression, block) in else_if_expressions.iter().zip(else_if_blocks.iter()) { - write!(f, "else if {expression} {{{block}}}")?; + for (expression, block) in else_ifs { + output.push_str("else if "); + expression.format(output, indent_level); + output.push(' '); + block.format(output, indent_level); } - if let Some(block) = else_block { - write!(f, "else {{{block}}}")?; + if let Some(block) = &self.else_block { + output.push_str("else "); + block.format(output, indent_level); } - - Ok(()) } } diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index 10fcb35..9bc64c1 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -1,9 +1,7 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, IndexExpression, List, Map, Result, Type, Value}; +use crate::{AbstractTree, Error, Format, IndexExpression, List, Map, Result, Type, Value}; /// Abstract representation of an index expression. /// @@ -101,20 +99,15 @@ impl AbstractTree for Index { } } -impl Display for Index { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let Index { - collection, - index, - index_end, - } = self; +impl Format for Index { + fn format(&self, output: &mut String, indent_level: u8) { + self.collection.format(output, indent_level); + output.push(':'); + self.index.format(output, indent_level); - write!(f, "{collection}:{index}")?; - - if let Some(expression) = index_end { - write!(f, "..{expression}")?; + if let Some(expression) = &self.index_end { + output.push_str(".."); + expression.format(output, indent_level); } - - Ok(()) } } diff --git a/src/abstract_tree/index_assignment.rs b/src/abstract_tree/index_assignment.rs index 30b0224..274e9ae 100644 --- a/src/abstract_tree/index_assignment.rs +++ b/src/abstract_tree/index_assignment.rs @@ -1,11 +1,9 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - AbstractTree, AssignmentOperator, Error, Index, IndexExpression, Map, Result, Statement, Type, - Value, + AbstractTree, AssignmentOperator, Error, Format, Index, IndexExpression, Map, Result, + Statement, Type, Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -22,20 +20,8 @@ impl AbstractTree for IndexAssignment { let index_node = node.child(0).unwrap(); 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() { - "=" => AssignmentOperator::Equal, - "+=" => AssignmentOperator::PlusEqual, - "-=" => AssignmentOperator::MinusEqual, - _ => { - return Err(Error::UnexpectedSyntaxNode { - expected: "=, += or -=".to_string(), - actual: operator_node.kind().to_string(), - location: operator_node.start_position(), - relevant_source: source[operator_node.byte_range()].to_string(), - }) - } - }; + let operator_node = node.child(1).unwrap(); + let operator = AssignmentOperator::from_syntax_node(source, operator_node, context)?; let statement_node = node.child(2).unwrap(); let statement = Statement::from_syntax_node(source, statement_node, context)?; @@ -94,14 +80,12 @@ impl AbstractTree for IndexAssignment { } } -impl Display for IndexAssignment { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let IndexAssignment { - index, - operator, - statement, - } = self; - - write!(f, "{index} {operator} {statement}") +impl Format for IndexAssignment { + fn format(&self, output: &mut String, indent_level: u8) { + self.index.format(output, indent_level); + output.push(' '); + self.operator.format(output, indent_level); + output.push(' '); + self.statement.format(output, indent_level); } } diff --git a/src/abstract_tree/index_expression.rs b/src/abstract_tree/index_expression.rs index c1aec2c..7e8d5ef 100644 --- a/src/abstract_tree/index_expression.rs +++ b/src/abstract_tree/index_expression.rs @@ -1,10 +1,8 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use crate::{ - value_node::ValueNode, AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type, - Value, + value_node::ValueNode, AbstractTree, Error, Format, FunctionCall, Identifier, Index, Map, + Result, Type, Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -69,13 +67,21 @@ impl AbstractTree for IndexExpression { } } -impl Display for IndexExpression { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl Format for IndexExpression { + fn format(&self, output: &mut String, indent_level: u8) { match self { - IndexExpression::Value(value_node) => write!(f, "{value_node}"), - IndexExpression::Identifier(identifier) => write!(f, "{identifier}"), - IndexExpression::FunctionCall(function_call) => write!(f, "{function_call}"), - IndexExpression::Index(index) => write!(f, "{index}"), + IndexExpression::Value(value_node) => { + if let ValueNode::BuiltInValue(built_in_value) = value_node { + output.push_str(built_in_value.name()); + } else { + value_node.format(output, indent_level); + } + } + IndexExpression::Identifier(identifier) => identifier.format(output, indent_level), + IndexExpression::FunctionCall(function_call) => { + function_call.format(output, indent_level) + } + IndexExpression::Index(index) => index.format(output, indent_level), } } } diff --git a/src/abstract_tree/logic.rs b/src/abstract_tree/logic.rs index fb301b8..6fab60c 100644 --- a/src/abstract_tree/logic.rs +++ b/src/abstract_tree/logic.rs @@ -1,9 +1,7 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Expression, Map, Result, Type, Value}; +use crate::{AbstractTree, Error, Expression, Format, LogicOperator, Map, Result, Type, Value}; /// Abstract representation of a logic expression. #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -20,38 +18,17 @@ impl AbstractTree for Logic { let first_node = node.child(0).unwrap(); let (left_node, operator_node, right_node) = { if first_node.is_named() { - ( - first_node, - node.child(1).unwrap().child(0).unwrap(), - node.child(2).unwrap(), - ) + (first_node, node.child(1).unwrap(), node.child(2).unwrap()) } else { ( node.child(1).unwrap(), - node.child(2).unwrap().child(0).unwrap(), + node.child(2).unwrap(), node.child(3).unwrap(), ) } }; let left = Expression::from_syntax_node(source, left_node, context)?; - let operator = match operator_node.kind() { - "==" => LogicOperator::Equal, - "!=" => LogicOperator::NotEqual, - "&&" => LogicOperator::And, - "||" => LogicOperator::Or, - ">" => LogicOperator::Greater, - "<" => LogicOperator::Less, - ">=" => LogicOperator::GreaterOrEqual, - "<=" => LogicOperator::LessOrEqual, - _ => { - return Err(Error::UnexpectedSyntaxNode { - expected: "==, !=, &&, ||, >, <, >= or <=".to_string(), - actual: operator_node.kind().to_string(), - location: operator_node.start_position(), - relevant_source: source[operator_node.byte_range()].to_string(), - }) - } - }; + let operator = LogicOperator::from_syntax_node(source, operator_node, context)?; let right = Expression::from_syntax_node(source, right_node, context)?; Ok(Logic { @@ -95,41 +72,12 @@ impl AbstractTree for Logic { } } -impl Display for Logic { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let Logic { - left, - operator, - right, - } = self; - - write!(f, "{left} {operator} {right}") - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] -pub enum LogicOperator { - Equal, - NotEqual, - And, - Or, - Greater, - Less, - GreaterOrEqual, - LessOrEqual, -} - -impl Display for LogicOperator { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - LogicOperator::Equal => write!(f, "="), - LogicOperator::NotEqual => write!(f, "!="), - LogicOperator::And => write!(f, "&&"), - LogicOperator::Or => write!(f, "||"), - LogicOperator::Greater => write!(f, ">"), - LogicOperator::Less => write!(f, "<"), - LogicOperator::GreaterOrEqual => write!(f, ">="), - LogicOperator::LessOrEqual => write!(f, "<="), - } +impl Format for Logic { + fn format(&self, output: &mut String, indent_level: u8) { + self.left.format(output, indent_level); + output.push(' '); + self.operator.format(output, indent_level); + output.push(' '); + self.right.format(output, indent_level); } } diff --git a/src/abstract_tree/logic_operator.rs b/src/abstract_tree/logic_operator.rs new file mode 100644 index 0000000..19ed7f9 --- /dev/null +++ b/src/abstract_tree/logic_operator.rs @@ -0,0 +1,70 @@ +use serde::{Deserialize, Serialize}; + +use crate::{AbstractTree, Error, Format, Map, Result, Type, Value}; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub enum LogicOperator { + Equal, + NotEqual, + And, + Or, + Greater, + Less, + GreaterOrEqual, + LessOrEqual, +} + +impl AbstractTree for LogicOperator { + fn from_syntax_node( + source: &str, + node: tree_sitter::Node, + _context: &crate::Map, + ) -> crate::Result { + Error::expect_syntax_node(source, "logic_operator", node)?; + + let operator_node = node.child(0).unwrap(); + let operator = match operator_node.kind() { + "==" => LogicOperator::Equal, + "!=" => LogicOperator::NotEqual, + "&&" => LogicOperator::And, + "||" => LogicOperator::Or, + ">" => LogicOperator::Greater, + "<" => LogicOperator::Less, + ">=" => LogicOperator::GreaterOrEqual, + "<=" => LogicOperator::LessOrEqual, + _ => { + return Err(Error::UnexpectedSyntaxNode { + expected: "==, !=, &&, ||, >, <, >= or <=".to_string(), + actual: operator_node.kind().to_string(), + location: operator_node.start_position(), + relevant_source: source[operator_node.byte_range()].to_string(), + }) + } + }; + + Ok(operator) + } + + fn run(&self, _source: &str, _context: &Map) -> Result { + Ok(Value::none()) + } + + fn expected_type(&self, _context: &Map) -> Result { + Ok(Type::None) + } +} + +impl Format for LogicOperator { + fn format(&self, output: &mut String, _indent_level: u8) { + match self { + LogicOperator::Equal => output.push('='), + LogicOperator::NotEqual => output.push_str("!="), + LogicOperator::And => output.push_str("&&"), + LogicOperator::Or => output.push_str("||"), + LogicOperator::Greater => output.push('>'), + LogicOperator::Less => output.push('<'), + LogicOperator::GreaterOrEqual => output.push_str(">="), + LogicOperator::LessOrEqual => output.push_str("<="), + } + } +} diff --git a/src/abstract_tree/match.rs b/src/abstract_tree/match.rs index 34cf543..279ee78 100644 --- a/src/abstract_tree/match.rs +++ b/src/abstract_tree/match.rs @@ -2,13 +2,10 @@ //! //! Note that this module is called "match" but is escaped as "r#match" because //! "match" is a keyword in Rust. - -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Expression, Map, Result, Statement, Type, Value}; +use crate::{AbstractTree, Error, Expression, Format, Map, Result, Statement, Type, Value}; /// Abstract representation of a match statement. #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -85,24 +82,23 @@ impl AbstractTree for Match { } } -impl Display for Match { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let Match { - matcher, - options, - fallback, - } = self; +impl Format for Match { + fn format(&self, output: &mut String, indent_level: u8) { + output.push_str("match "); + self.matcher.format(output, indent_level); + output.push_str(" {"); - write!(f, "match {matcher} {{")?; - - for (expression, statement) in options { - write!(f, "{expression} => {statement}")?; + for (expression, statement) in &self.options { + expression.format(output, indent_level); + output.push_str(" => "); + statement.format(output, indent_level); } - if let Some(statement) = fallback { - write!(f, "* => {statement}")?; + if let Some(statement) = &self.fallback { + output.push_str("* => "); + statement.format(output, indent_level); } - write!(f, "}}") + output.push('}'); } } diff --git a/src/abstract_tree/math.rs b/src/abstract_tree/math.rs index 81ef5d5..63ad7ab 100644 --- a/src/abstract_tree/math.rs +++ b/src/abstract_tree/math.rs @@ -1,9 +1,7 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Expression, Map, Result, Type, Value}; +use crate::{AbstractTree, Error, Expression, Format, Map, MathOperator, Result, Type, Value}; /// Abstract representation of a math operation. /// @@ -23,22 +21,8 @@ impl AbstractTree for Math { let left_node = node.child(0).unwrap(); 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() { - "+" => MathOperator::Add, - "-" => MathOperator::Subtract, - "*" => MathOperator::Multiply, - "/" => MathOperator::Divide, - "%" => MathOperator::Modulo, - _ => { - return Err(Error::UnexpectedSyntaxNode { - expected: "+, -, *, / or %".to_string(), - actual: operator_node.kind().to_string(), - location: operator_node.start_position(), - relevant_source: source[operator_node.byte_range()].to_string(), - }) - } - }; + let operator_node = node.child(1).unwrap(); + let operator = MathOperator::from_syntax_node(source, operator_node, context)?; let right_node = node.child(2).unwrap(); let right = Expression::from_syntax_node(source, right_node, context)?; @@ -69,35 +53,12 @@ impl AbstractTree for Math { } } -impl Display for Math { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let Math { - left, - operator, - right, - } = self; - - write!(f, "{left} {operator} {right}") - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] -pub enum MathOperator { - Add, - Subtract, - Multiply, - Divide, - Modulo, -} - -impl Display for MathOperator { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - MathOperator::Add => write!(f, "+"), - MathOperator::Subtract => write!(f, "-"), - MathOperator::Multiply => write!(f, "*"), - MathOperator::Divide => write!(f, "/"), - MathOperator::Modulo => write!(f, "%"), - } +impl Format for Math { + fn format(&self, output: &mut String, indent_level: u8) { + self.left.format(output, indent_level); + output.push(' '); + self.operator.format(output, indent_level); + output.push(' '); + self.right.format(output, indent_level); } } diff --git a/src/abstract_tree/math_operator.rs b/src/abstract_tree/math_operator.rs new file mode 100644 index 0000000..0fe9291 --- /dev/null +++ b/src/abstract_tree/math_operator.rs @@ -0,0 +1,57 @@ +use serde::{Deserialize, Serialize}; + +use crate::{AbstractTree, Error, Format, Map, Result, Type, Value}; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub enum MathOperator { + Add, + Subtract, + Multiply, + Divide, + Modulo, +} + +impl AbstractTree for MathOperator { + fn from_syntax_node(source: &str, node: tree_sitter::Node, context: &Map) -> Result { + let operator_node = node.child(0).unwrap(); + let operator = match operator_node.kind() { + "+" => MathOperator::Add, + "-" => MathOperator::Subtract, + "*" => MathOperator::Multiply, + "/" => MathOperator::Divide, + "%" => MathOperator::Modulo, + _ => { + return Err(Error::UnexpectedSyntaxNode { + expected: "+, -, *, / or %".to_string(), + actual: operator_node.kind().to_string(), + location: operator_node.start_position(), + relevant_source: source[operator_node.byte_range()].to_string(), + }) + } + }; + + Ok(operator) + } + + fn run(&self, _source: &str, _context: &Map) -> Result { + Ok(Value::none()) + } + + fn expected_type(&self, _context: &Map) -> Result { + Ok(Type::None) + } +} + +impl Format for MathOperator { + fn format(&self, output: &mut String, indent_level: u8) { + let char = match self { + MathOperator::Add => '+', + MathOperator::Subtract => '-', + MathOperator::Multiply => '*', + MathOperator::Divide => '/', + MathOperator::Modulo => '%', + }; + + output.push(char); + } +} diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index 79427ca..9cce2c0 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -7,6 +7,7 @@ //! examples. pub mod assignment; +pub mod assignment_operator; pub mod block; pub mod built_in_value; pub mod expression; @@ -20,23 +21,25 @@ pub mod index; pub mod index_assignment; pub mod index_expression; pub mod logic; +pub mod logic_operator; pub mod r#match; pub mod math; +pub mod math_operator; pub mod statement; +pub mod r#type; pub mod type_definition; pub mod value_node; pub mod r#while; pub mod r#yield; pub use { - assignment::*, block::*, built_in_value::*, expression::*, function_call::*, - function_expression::*, function_node::*, identifier::*, if_else::*, index::*, - index_assignment::IndexAssignment, index_expression::*, logic::*, math::*, r#for::*, - r#match::*, r#while::*, r#yield::*, statement::*, type_definition::*, value_node::*, + assignment::*, assignment_operator::*, block::*, built_in_value::*, expression::*, + function_call::*, function_expression::*, function_node::*, identifier::*, if_else::*, + index::*, index_assignment::IndexAssignment, index_expression::*, logic::*, logic_operator::*, + math::*, math_operator::*, r#for::*, r#match::*, r#type::*, r#while::*, r#yield::*, + statement::*, type_definition::*, value_node::*, }; -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; @@ -118,19 +121,17 @@ impl AbstractTree for Root { } } -impl Display for Root { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { +impl Format for Root { + fn format(&self, output: &mut String, indent_level: u8) { for statement in &self.statements { - write!(f, "{statement}")?; + statement.format(output, indent_level); } - - Ok(()) } } /// This trait is implemented by the Evaluator's internal types to form an /// executable tree that resolves to a single value. -pub trait AbstractTree: Sized { +pub trait AbstractTree: Sized + Format { /// Interpret the syntax tree at the given node and return the abstraction. /// /// This function is used to convert nodes in the Tree Sitter concrete @@ -152,3 +153,7 @@ pub trait AbstractTree: Sized { fn expected_type(&self, context: &Map) -> Result; } + +pub trait Format { + fn format(&self, output: &mut String, indent_level: u8); +} diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index 1c3fc4d..f4ae71c 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -1,11 +1,9 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Map, Match, - Result, Type, Value, While, + AbstractTree, Assignment, Block, Error, Expression, For, Format, IfElse, IndexAssignment, Map, + Match, Result, Type, Value, While, }; /// Abstract representation of a statement. @@ -113,18 +111,20 @@ impl AbstractTree for Statement { } } -impl Display for Statement { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl Format for Statement { + fn format(&self, output: &mut String, indent_level: u8) { match self { - Statement::Assignment(assignment) => write!(f, "{assignment}"), - Statement::Expression(expression) => write!(f, "{expression}"), - Statement::IfElse(if_else) => write!(f, "{if_else}"), - Statement::Match(r#match) => write!(f, "{}", r#match), - Statement::While(r#while) => write!(f, "{}", r#while), - Statement::Block(block) => write!(f, "{block}"), - Statement::For(r#for) => write!(f, "{}", r#for), - Statement::IndexAssignment(index_assignment) => write!(f, "{index_assignment}"), - Statement::Return(statement) => write!(f, "{statement}"), + Statement::Assignment(assignment) => assignment.format(output, indent_level), + Statement::Expression(expression) => expression.format(output, indent_level), + Statement::IfElse(if_else) => if_else.format(output, indent_level), + Statement::Match(r#match) => r#match.format(output, indent_level), + Statement::While(r#while) => r#while.format(output, indent_level), + Statement::Block(block) => block.format(output, indent_level), + Statement::For(r#for) => r#for.format(output, indent_level), + Statement::IndexAssignment(index_assignment) => { + index_assignment.format(output, indent_level) + } + Statement::Return(statement) => statement.format(output, indent_level), } } } diff --git a/src/abstract_tree/type.rs b/src/abstract_tree/type.rs new file mode 100644 index 0000000..078b529 --- /dev/null +++ b/src/abstract_tree/type.rs @@ -0,0 +1,290 @@ +use std::fmt::{self, Display, Formatter}; + +use serde::{Deserialize, Serialize}; +use tree_sitter::Node; + +use crate::{AbstractTree, Error, Format, Map, Result, Structure, Value}; + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub enum Type { + Any, + Boolean, + Collection, + Float, + Function { + parameter_types: Vec, + return_type: Box, + }, + Integer, + List(Box), + Map(Option), + None, + Number, + String, + Option(Box), +} + +impl Type { + pub fn list(item_type: Type) -> Self { + Type::List(Box::new(item_type)) + } + + pub fn function(parameter_types: Vec, return_type: Type) -> Self { + Type::Function { + parameter_types, + return_type: Box::new(return_type), + } + } + + pub fn option(optional_type: Type) -> Self { + Type::Option(Box::new(optional_type)) + } + + pub fn check(&self, other: &Type) -> Result<()> { + match (self, other) { + (Type::Any, _) + | (_, Type::Any) + | (Type::Boolean, Type::Boolean) + | (Type::Collection, Type::Collection) + | (Type::Collection, Type::List(_)) + | (Type::List(_), Type::Collection) + | (Type::Collection, Type::Map(_)) + | (Type::Map(_), Type::Collection) + | (Type::Collection, Type::String) + | (Type::String, Type::Collection) + | (Type::Float, Type::Float) + | (Type::Integer, Type::Integer) + | (Type::Map(_), Type::Map(_)) + | (Type::Number, Type::Number) + | (Type::Number, Type::Integer) + | (Type::Number, Type::Float) + | (Type::Integer, Type::Number) + | (Type::Float, Type::Number) + | (Type::None, Type::None) + | (Type::String, Type::String) => Ok(()), + (Type::Option(left), Type::Option(right)) => { + if left == right { + Ok(()) + } else if let Type::Any = left.as_ref() { + Ok(()) + } else if let Type::Any = right.as_ref() { + Ok(()) + } else { + Err(Error::TypeCheck { + expected: self.clone(), + actual: other.clone(), + }) + } + } + (Type::Option(_), Type::None) | (Type::None, Type::Option(_)) => Ok(()), + (Type::List(self_item_type), Type::List(other_item_type)) => { + if self_item_type.check(other_item_type).is_err() { + Err(Error::TypeCheck { + expected: self.clone(), + actual: other.clone(), + }) + } else { + Ok(()) + } + } + ( + Type::Function { + parameter_types: self_parameter_types, + return_type: self_return_type, + }, + Type::Function { + parameter_types: other_parameter_types, + return_type: other_return_type, + }, + ) => { + let parameter_type_pairs = self_parameter_types + .iter() + .zip(other_parameter_types.iter()); + + for (self_parameter_type, other_parameter_type) in parameter_type_pairs { + if self_parameter_type.check(other_parameter_type).is_err() { + return Err(Error::TypeCheck { + expected: self.clone(), + actual: other.clone(), + }); + } + } + + if self_return_type.check(other_return_type).is_err() { + Err(Error::TypeCheck { + expected: self.clone(), + actual: other.clone(), + }) + } else { + Ok(()) + } + } + _ => Err(Error::TypeCheck { + expected: self.clone(), + actual: other.clone(), + }), + } + } +} + +impl AbstractTree for Type { + fn from_syntax_node(_source: &str, node: Node, _context: &Map) -> Result { + Error::expect_syntax_node(_source, "type", node)?; + + let type_node = node.child(0).unwrap(); + + let r#type = match type_node.kind() { + "[" => { + let item_type_node = node.child(1).unwrap(); + let item_type = Type::from_syntax_node(_source, item_type_node, _context)?; + + Type::List(Box::new(item_type)) + } + "any" => Type::Any, + "bool" => Type::Boolean, + "collection" => Type::Collection, + "float" => Type::Float, + "(" => { + let child_count = node.child_count(); + let mut parameter_types = Vec::new(); + + for index in 1..child_count - 2 { + let child = node.child(index).unwrap(); + + if child.is_named() { + let parameter_type = Type::from_syntax_node(_source, child, _context)?; + + parameter_types.push(parameter_type); + } + } + + let final_node = node.child(child_count - 1).unwrap(); + let return_type = if final_node.is_named() { + Type::from_syntax_node(_source, final_node, _context)? + } else { + Type::None + }; + + Type::Function { + parameter_types, + return_type: Box::new(return_type), + } + } + "int" => Type::Integer, + "map" => Type::Map(None), + "num" => Type::Number, + "none" => Type::None, + "str" => Type::String, + "option" => { + let inner_type_node = node.child(2).unwrap(); + let inner_type = Type::from_syntax_node(_source, inner_type_node, _context)?; + + Type::Option(Box::new(inner_type)) + } + _ => { + return Err(Error::UnexpectedSyntaxNode { + expected: "any, bool, float, int, num, str, option, (, [ or {".to_string(), + actual: type_node.kind().to_string(), + location: type_node.start_position(), + relevant_source: _source[type_node.byte_range()].to_string(), + }) + } + }; + + Ok(r#type) + } + + fn run(&self, _source: &str, _context: &Map) -> Result { + Ok(Value::none()) + } + + fn expected_type(&self, _context: &Map) -> Result { + Ok(Type::None) + } +} + +impl Format for Type { + fn format(&self, output: &mut String, indent_level: u8) { + match self { + Type::Any => output.push_str("any"), + Type::Boolean => output.push_str("bool"), + Type::Collection => output.push_str("collection"), + Type::Float => output.push_str("float"), + Type::Function { + parameter_types, + return_type, + } => { + output.push('('); + + for (index, parameter_type) in parameter_types.iter().enumerate() { + parameter_type.format(output, indent_level); + + if index != parameter_types.len() - 1 { + output.push(' '); + } + } + + output.push_str(") -> "); + return_type.format(output, indent_level); + } + Type::Integer => output.push_str("int"), + Type::List(item_type) => { + output.push('['); + item_type.format(output, indent_level); + output.push(']'); + } + Type::Map(structure_option) => { + if let Some(structure) = structure_option { + output.push_str(&structure.to_string()); + } else { + output.push_str("map"); + } + } + Type::None => output.push_str("none"), + Type::Number => output.push_str("number"), + Type::String => output.push_str("str"), + Type::Option(optional_type) => { + output.push_str("option("); + optional_type.format(output, indent_level); + output.push(')'); + } + } + } +} + +impl Display for Type { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Type::Any => write!(f, "any"), + Type::Boolean => write!(f, "bool"), + Type::Collection => write!(f, "collection"), + Type::Float => write!(f, "float"), + Type::Function { + parameter_types, + return_type, + } => { + write!(f, "(")?; + + for (index, parameter_type) in parameter_types.iter().enumerate() { + write!(f, "{parameter_type}")?; + + if index != parameter_types.len() - 1 { + write!(f, " ")?; + } + } + + write!(f, ")")?; + write!(f, " -> {return_type}") + } + Type::Integer => write!(f, "int"), + Type::List(item_type) => write!(f, "[{item_type}]"), + Type::Map(_) => write!(f, "map"), + Type::Number => write!(f, "num"), + Type::None => write!(f, "none"), + Type::String => write!(f, "str"), + Type::Option(inner_type) => { + write!(f, "option({})", inner_type) + } + } + } +} diff --git a/src/abstract_tree/type_definition.rs b/src/abstract_tree/type_definition.rs index 511ed32..78f3dbd 100644 --- a/src/abstract_tree/type_definition.rs +++ b/src/abstract_tree/type_definition.rs @@ -1,9 +1,7 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Map, Result, Structure, Value}; +use crate::{AbstractTree, Error, Format, Map, Result, Type, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct TypeDefinition { @@ -43,243 +41,10 @@ impl AbstractTree for TypeDefinition { } } -impl Display for TypeDefinition { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "<{}>", self.r#type) - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] -pub enum Type { - Any, - Boolean, - Collection, - Float, - Function { - parameter_types: Vec, - return_type: Box, - }, - Integer, - List(Box), - Map(Option), - None, - Number, - String, - Option(Box), -} - -impl Type { - pub fn list(item_type: Type) -> Self { - Type::List(Box::new(item_type)) - } - - pub fn function(parameter_types: Vec, return_type: Type) -> Self { - Type::Function { - parameter_types, - return_type: Box::new(return_type), - } - } - - pub fn option(optional_type: Type) -> Self { - Type::Option(Box::new(optional_type)) - } - - pub fn check(&self, other: &Type) -> Result<()> { - match (self, other) { - (Type::Any, _) - | (_, Type::Any) - | (Type::Boolean, Type::Boolean) - | (Type::Collection, Type::Collection) - | (Type::Collection, Type::List(_)) - | (Type::List(_), Type::Collection) - | (Type::Collection, Type::Map(_)) - | (Type::Map(_), Type::Collection) - | (Type::Collection, Type::String) - | (Type::String, Type::Collection) - | (Type::Float, Type::Float) - | (Type::Integer, Type::Integer) - | (Type::Map(_), Type::Map(_)) - | (Type::Number, Type::Number) - | (Type::Number, Type::Integer) - | (Type::Number, Type::Float) - | (Type::Integer, Type::Number) - | (Type::Float, Type::Number) - | (Type::None, Type::None) - | (Type::String, Type::String) => Ok(()), - (Type::Option(left), Type::Option(right)) => { - if left == right { - Ok(()) - } else if let Type::Any = left.as_ref() { - Ok(()) - } else if let Type::Any = right.as_ref() { - Ok(()) - } else { - Err(Error::TypeCheck { - expected: self.clone(), - actual: other.clone(), - }) - } - } - (Type::Option(_), Type::None) | (Type::None, Type::Option(_)) => Ok(()), - (Type::List(self_item_type), Type::List(other_item_type)) => { - if self_item_type.check(other_item_type).is_err() { - Err(Error::TypeCheck { - expected: self.clone(), - actual: other.clone(), - }) - } else { - Ok(()) - } - } - ( - Type::Function { - parameter_types: self_parameter_types, - return_type: self_return_type, - }, - Type::Function { - parameter_types: other_parameter_types, - return_type: other_return_type, - }, - ) => { - let parameter_type_pairs = self_parameter_types - .iter() - .zip(other_parameter_types.iter()); - - for (self_parameter_type, other_parameter_type) in parameter_type_pairs { - if self_parameter_type.check(other_parameter_type).is_err() { - return Err(Error::TypeCheck { - expected: self.clone(), - actual: other.clone(), - }); - } - } - - if self_return_type.check(other_return_type).is_err() { - Err(Error::TypeCheck { - expected: self.clone(), - actual: other.clone(), - }) - } else { - Ok(()) - } - } - _ => Err(Error::TypeCheck { - expected: self.clone(), - actual: other.clone(), - }), - } - } -} - -impl AbstractTree for Type { - fn from_syntax_node(_source: &str, node: Node, _context: &Map) -> Result { - Error::expect_syntax_node(_source, "type", node)?; - - let type_node = node.child(0).unwrap(); - - let r#type = match type_node.kind() { - "[" => { - let item_type_node = node.child(1).unwrap(); - let item_type = Type::from_syntax_node(_source, item_type_node, _context)?; - - Type::List(Box::new(item_type)) - } - "any" => Type::Any, - "bool" => Type::Boolean, - "collection" => Type::Collection, - "float" => Type::Float, - "(" => { - let child_count = node.child_count(); - let mut parameter_types = Vec::new(); - - for index in 1..child_count - 2 { - let child = node.child(index).unwrap(); - - if child.is_named() { - let parameter_type = Type::from_syntax_node(_source, child, _context)?; - - parameter_types.push(parameter_type); - } - } - - let final_node = node.child(child_count - 1).unwrap(); - let return_type = if final_node.is_named() { - Type::from_syntax_node(_source, final_node, _context)? - } else { - Type::None - }; - - Type::Function { - parameter_types, - return_type: Box::new(return_type), - } - } - "int" => Type::Integer, - "map" => Type::Map(None), - "num" => Type::Number, - "none" => Type::None, - "str" => Type::String, - "option" => { - let inner_type_node = node.child(2).unwrap(); - let inner_type = Type::from_syntax_node(_source, inner_type_node, _context)?; - - Type::Option(Box::new(inner_type)) - } - _ => { - return Err(Error::UnexpectedSyntaxNode { - expected: "any, bool, float, int, num, str, option, (, [ or {".to_string(), - actual: type_node.kind().to_string(), - location: type_node.start_position(), - relevant_source: _source[type_node.byte_range()].to_string(), - }) - } - }; - - Ok(r#type) - } - - fn run(&self, _source: &str, _context: &Map) -> Result { - Ok(Value::none()) - } - - fn expected_type(&self, _context: &Map) -> Result { - Ok(Type::None) - } -} - -impl Display for Type { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - Type::Any => write!(f, "any"), - Type::Boolean => write!(f, "bool"), - Type::Collection => write!(f, "collection"), - Type::Float => write!(f, "float"), - Type::Function { - parameter_types, - return_type, - } => { - write!(f, "(")?; - - for (index, parameter_type) in parameter_types.iter().enumerate() { - write!(f, "{parameter_type}")?; - - if index != parameter_types.len() - 1 { - write!(f, " ")?; - } - } - - write!(f, ")")?; - write!(f, " -> {return_type}") - } - Type::Integer => write!(f, "int"), - Type::List(item_type) => write!(f, "[{item_type}]"), - Type::Map(_) => write!(f, "map"), - Type::Number => write!(f, "num"), - Type::None => write!(f, "none"), - Type::String => write!(f, "str"), - Type::Option(inner_type) => { - write!(f, "option({})", inner_type) - } - } +impl Format for TypeDefinition { + fn format(&self, output: &mut String, indent_level: u8) { + output.push('<'); + self.r#type.format(output, indent_level); + output.push('>'); } } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index a00109f..6207083 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -1,14 +1,11 @@ -use std::{ - collections::BTreeMap, - fmt::{self, Display, Formatter}, -}; +use std::{collections::BTreeMap, fmt::Write}; use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - AbstractTree, BuiltInValue, Error, Expression, Function, Identifier, List, Map, Result, - Statement, Structure, Type, TypeDefinition, Value, + AbstractTree, BuiltInValue, Error, Expression, Format, Function, FunctionNode, Identifier, + List, Map, Result, Statement, Structure, Type, TypeDefinition, Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -33,7 +30,11 @@ impl AbstractTree for ValueNode { let value_node = match child.kind() { "boolean" => ValueNode::Boolean(source[child.byte_range()].to_string()), "float" => ValueNode::Float(source[child.byte_range()].to_string()), - "function" => ValueNode::Function(Function::from_syntax_node(source, child, context)?), + "function" => { + let function_node = FunctionNode::from_syntax_node(source, child, context)?; + + ValueNode::Function(Function::ContextDefined(function_node)) + } "integer" => ValueNode::Integer(source[child.byte_range()].to_string()), "string" => { let without_quotes = child.start_byte() + 1..child.end_byte() - 1; @@ -300,53 +301,75 @@ impl AbstractTree for ValueNode { } } -impl Display for ValueNode { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl Format for ValueNode { + fn format(&self, output: &mut String, indent_level: u8) { match self { ValueNode::Boolean(source) | ValueNode::Float(source) | ValueNode::Integer(source) - | ValueNode::String(source) => write!(f, "{source}"), - ValueNode::Function(function) => write!(f, "{function}"), + | ValueNode::String(source) => output.push_str(source), + ValueNode::Function(function) => function.format(output, indent_level), ValueNode::List(expressions) => { + output.push('['); + for expression in expressions { - write!(f, "{expression}")?; + expression.format(output, indent_level); } - Ok(()) + output.push(']'); } ValueNode::Option(option) => { if let Some(expression) = option { - write!(f, "some({})", expression) + output.push_str("some("); + expression.format(output, indent_level); + output.push(')'); } else { - write!(f, "none") + output.push_str("none"); } } ValueNode::Map(nodes) => { - writeln!(f, "{{")?; + output.push('{'); for (key, (statement, type_option)) in nodes { if let Some(r#type) = type_option { - writeln!(f, " {key} <{}> = {statement}", r#type)?; + output.push_str(" "); + output.push_str(key); + output.push_str(" <"); + r#type.format(output, indent_level); + output.push_str("> = "); + statement.format(output, indent_level); } else { - writeln!(f, " {key} = {statement}")?; + output.push_str(" "); + output.push_str(key); + output.push_str(" = "); + statement.format(output, indent_level); } } - write!(f, "}}") + + output.push('}'); } - ValueNode::BuiltInValue(built_in_value) => write!(f, "{built_in_value}"), + ValueNode::BuiltInValue(built_in_value) => built_in_value.format(output, indent_level), ValueNode::Structure(nodes) => { - writeln!(f, "{{")?; + output.push('{'); for (key, (value_option, r#type)) in nodes { if let Some(value) = value_option { - writeln!(f, " {key} <{}> = {value}", r#type)?; + output.push_str(" "); + output.push_str(key); + output.push_str(" <"); + r#type.format(output, indent_level); + output.push_str("> = "); + value.format(output, indent_level); } else { - writeln!(f, " {key} <{}>", r#type)?; + output.push_str(" "); + output.push_str(key); + output.push_str(" <"); + r#type.format(output, indent_level); + output.push('>'); } } - write!(f, "}}") + output.push('}'); } } } diff --git a/src/abstract_tree/while.rs b/src/abstract_tree/while.rs index 2051177..480a6d1 100644 --- a/src/abstract_tree/while.rs +++ b/src/abstract_tree/while.rs @@ -1,9 +1,7 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Block, Error, Expression, Map, Result, Type, Value}; +use crate::{AbstractTree, Block, Error, Expression, Format, Map, Result, Type, Value}; /// Abstract representation of a while loop. /// @@ -40,10 +38,11 @@ impl AbstractTree for While { } } -impl Display for While { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let While { expression, block } = self; - - write!(f, "while {expression} {{{block}}}") +impl Format for While { + fn format(&self, output: &mut String, indent_level: u8) { + output.push_str("while "); + self.expression.format(output, indent_level); + output.push(' '); + self.expression.format(output, indent_level); } } diff --git a/src/abstract_tree/yield.rs b/src/abstract_tree/yield.rs index f2606c6..ba8b85b 100644 --- a/src/abstract_tree/yield.rs +++ b/src/abstract_tree/yield.rs @@ -1,11 +1,9 @@ -use std::fmt::{self, Display, Formatter}; - use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - function_expression::FunctionExpression, AbstractTree, Error, Expression, FunctionCall, Map, - Result, Type, Value, + function_expression::FunctionExpression, AbstractTree, Error, Expression, Format, FunctionCall, + Map, Result, Type, Value, }; /// Abstract representation of a yield expression. @@ -55,8 +53,8 @@ impl AbstractTree for Yield { } } -impl Display for Yield { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.call) +impl Format for Yield { + fn format(&self, output: &mut String, indent_level: u8) { + self.call.format(output, indent_level); } } diff --git a/src/built_in_functions/mod.rs b/src/built_in_functions/mod.rs index a12cdef..d1fab6e 100644 --- a/src/built_in_functions/mod.rs +++ b/src/built_in_functions/mod.rs @@ -1,11 +1,14 @@ mod string; -use std::fs::read_to_string; +use std::{ + fmt::{self, Display, Formatter}, + fs::read_to_string, +}; use rand::{random, thread_rng, Rng}; use serde::{Deserialize, Serialize}; -use crate::{Error, Map, Result, Type, Value}; +use crate::{Error, Format, Map, Result, Type, Value}; pub use string::{string_functions, StringFunction}; @@ -148,3 +151,15 @@ impl BuiltInFunction { } } } + +impl Format for BuiltInFunction { + fn format(&self, output: &mut String, indent_level: u8) { + output.push_str(self.name()); + } +} + +impl Display for BuiltInFunction { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.name()) + } +} diff --git a/src/interpret.rs b/src/interpret.rs index daa802b..c3795e2 100644 --- a/src/interpret.rs +++ b/src/interpret.rs @@ -4,7 +4,7 @@ //! functions or by constructing your own Evaluator. use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor}; -use crate::{language, AbstractTree, Error, Map, Result, Root, Value}; +use crate::{language, AbstractTree, Error, Format, Map, Result, Root, Value}; /// Interpret the given source code. /// @@ -132,7 +132,11 @@ impl Interpreter { pub fn format(&self) -> String { if let Some(root_node) = &self.abstract_tree { - root_node.to_string() + let mut formatted_source = String::new(); + + root_node.format(&mut formatted_source, 0); + + formatted_source } else { "".to_string() } diff --git a/src/value/function.rs b/src/value/function.rs index d1154da..b1ae934 100644 --- a/src/value/function.rs +++ b/src/value/function.rs @@ -1,9 +1,8 @@ use std::fmt::{self, Display, Formatter}; use serde::{Deserialize, Serialize}; -use tree_sitter::Node; -use crate::{AbstractTree, BuiltInFunction, FunctionNode, Map, Result, Type, Value}; +use crate::{BuiltInFunction, Format, FunctionNode, Map, Result, Type, Value}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub enum Function { @@ -11,17 +10,6 @@ pub enum Function { ContextDefined(FunctionNode), } -impl Display for Function { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - Function::BuiltIn(built_in_function) => write!(f, "{}", built_in_function.r#type()), - Function::ContextDefined(function_node) => { - write!(f, "{}", function_node) - } - } - } -} - impl Function { pub fn call( &self, @@ -50,30 +38,20 @@ impl Function { } } -impl AbstractTree for Function { - fn from_syntax_node(_source: &str, _node: Node, _context: &Map) -> Result { - let inner_function = FunctionNode::from_syntax_node(_source, _node, _context)?; - - Ok(Function::ContextDefined(inner_function)) - } - - fn check_type(&self, _source: &str, _context: &Map) -> Result<()> { +impl Format for Function { + fn format(&self, output: &mut String, indent_level: u8) { match self { - Function::BuiltIn(_) => Ok(()), - Function::ContextDefined(defined_function) => { - defined_function.check_type(_source, _context) - } - } - } - - fn run(&self, _source: &str, _context: &Map) -> Result { - Ok(Value::Function(self.clone())) - } - - fn expected_type(&self, _context: &Map) -> Result { - match self { - Function::BuiltIn(built_in) => Ok(built_in.r#type()), - Function::ContextDefined(context_defined) => Ok(context_defined.r#type().clone()), + Function::BuiltIn(built_in_function) => built_in_function.format(output, indent_level), + Function::ContextDefined(function_node) => function_node.format(output, indent_level), + } + } +} + +impl Display for Function { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Function::BuiltIn(built_in_function) => write!(f, "{built_in_function}"), + Function::ContextDefined(function_node) => write!(f, "{function_node}"), } } } diff --git a/src/value/mod.rs b/src/value/mod.rs index 5db9c85..d77936f 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -527,7 +527,7 @@ impl Serialize for Value { impl Display for Value { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Value::String(string) => write!(f, "{}", string.read().unwrap()), + Value::String(string) => write!(f, "'{}'", string.read().unwrap()), Value::Float(float) => write!(f, "{float}"), Value::Integer(int) => write!(f, "{int}"), Value::Boolean(boolean) => write!(f, "{boolean}"),