Implement formatting

This commit is contained in:
Jeff 2024-01-06 08:11:09 -05:00
parent 731bf1cb98
commit 8737175df0
30 changed files with 818 additions and 688 deletions

View File

@ -1,10 +1,8 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
AbstractTree, Error, Identifier, Map, Result, Statement, SyntaxNode, SyntaxPosition, Type, AbstractTree, AssignmentOperator, Error, Format, Identifier, Map, Result, Statement,
TypeDefinition, Value, SyntaxNode, SyntaxPosition, Type, TypeDefinition, Value,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -34,24 +32,8 @@ impl AbstractTree for Assignment {
None None
}; };
let operator_node = syntax_node let operator_node = syntax_node.child(child_count - 2).unwrap();
.child(child_count - 2) let operator = AssignmentOperator::from_syntax_node(source, operator_node, context)?;
.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 statement_node = syntax_node.child(child_count - 1).unwrap(); let statement_node = syntax_node.child(child_count - 1).unwrap();
let statement = Statement::from_syntax_node(source, statement_node, context)?; let statement = Statement::from_syntax_node(source, statement_node, context)?;
@ -159,8 +141,8 @@ impl AbstractTree for Assignment {
} }
} }
impl Display for Assignment { impl Format for Assignment {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let Assignment { let Assignment {
identifier, identifier,
type_definition, type_definition,
@ -169,29 +151,16 @@ impl Display for Assignment {
syntax_position: _, syntax_position: _,
} = self; } = self;
write!(f, "{identifier}")?; self.identifier.format(output, indent_level);
if let Some(type_definition) = type_definition { if let Some(type_definition) = type_definition {
write!(f, " {type_definition}")?; type_definition.format(output, indent_level);
} }
write!(f, " {operator} {statement}") output.push_str(" ");
} self.operator.format(output, indent_level);
} output.push_str(" ");
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] self.statement.format(output, indent_level);
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, "+="),
}
} }
} }

View File

@ -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<Self> {
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<Value> {
Ok(Value::none())
}
fn expected_type(&self, context: &Map) -> Result<Type> {
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("-="),
}
}
}

View File

@ -1,13 +1,10 @@
use std::{ use std::sync::RwLock;
fmt::{self, Display, Formatter},
sync::RwLock,
};
use rayon::prelude::*; use rayon::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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. /// Abstract representation of a block.
/// ///
@ -131,18 +128,22 @@ impl AbstractTree for Block {
} }
} }
impl Display for Block { impl Format for Block {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
if self.is_async { if self.is_async {
writeln!(f, "async {{")?; output.push_str("async {");
} else { } else {
writeln!(f, "{{")?; output.push('{');
} }
for statement in &self.statements { 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('}');
} }
} }

View File

@ -1,15 +1,11 @@
use std::{ use std::{env::args, sync::OnceLock};
env::args,
fmt::{self, Display, Formatter},
sync::OnceLock,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
built_in_functions::string_functions, AbstractTree, BuiltInFunction, Function, List, Map, built_in_functions::string_functions, AbstractTree, BuiltInFunction, Format, Function, List,
Result, Type, Value, Map, Result, Type, Value,
}; };
static ARGS: OnceLock<Value> = OnceLock::new(); static ARGS: OnceLock<Value> = OnceLock::new();
@ -31,6 +27,19 @@ pub enum BuiltInValue {
} }
impl 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 { fn r#type(&self) -> Type {
match self { match self {
BuiltInValue::Args => Type::list(Type::String), BuiltInValue::Args => Type::list(Type::String),
@ -72,7 +81,7 @@ impl BuiltInValue {
json_context json_context
.set( .set(
"parse".to_string(), BuiltInFunction::JsonParse.name().to_string(),
Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)), Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)),
None, None,
) )
@ -153,8 +162,8 @@ impl AbstractTree for BuiltInValue {
} }
} }
impl Display for BuiltInValue { impl Format for BuiltInValue {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
write!(f, "{}", self.get()) output.push_str(&self.get().to_string());
} }
} }

View File

@ -1,10 +1,9 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ 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}; use super::{function_call::FunctionCall, logic::Logic, math::Math};
@ -104,16 +103,16 @@ impl AbstractTree for Expression {
} }
} }
impl Display for Expression { impl Format for Expression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
match self { match self {
Expression::Value(value_node) => write!(f, "{value_node}"), Expression::Value(value_node) => value_node.format(output, indent_level),
Expression::Identifier(identifier) => write!(f, "{identifier}"), Expression::Identifier(identifier) => identifier.format(output, indent_level),
Expression::Math(math) => write!(f, "{math}"), Expression::Math(math) => math.format(output, indent_level),
Expression::Logic(logic) => write!(f, "{logic}"), Expression::Logic(logic) => logic.format(output, indent_level),
Expression::FunctionCall(function_call) => write!(f, "{function_call}"), Expression::FunctionCall(function_call) => function_call.format(output, indent_level),
Expression::Index(index) => write!(f, "{index}"), Expression::Index(index) => index.format(output, indent_level),
Expression::Yield(r#yield) => write!(f, "{}", r#yield), Expression::Yield(r#yield) => r#yield.format(output, indent_level),
} }
} }
} }

View File

@ -1,10 +1,10 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::Write;
use rayon::prelude::*; use rayon::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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. /// Abstract representation of a for loop statement.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -81,21 +81,18 @@ impl AbstractTree for For {
} }
} }
impl Display for For { impl Format for For {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let For { if self.is_async {
is_async, output.write_str("async for ");
item_id,
collection,
block,
} = self;
if *is_async {
write!(f, "async for ")?;
} else { } 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);
} }
} }

View File

@ -1,10 +1,9 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ 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)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -162,20 +161,15 @@ impl AbstractTree for FunctionCall {
} }
} }
impl Display for FunctionCall { impl Format for FunctionCall {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let FunctionCall { self.function_expression.format(output, indent_level);
function_expression, output.push('(');
arguments,
..
} = self;
write!(f, "{function_expression}(")?; for expression in &self.arguments {
expression.format(output, indent_level);
for expression in arguments {
write!(f, "{expression}")?;
} }
write!(f, ")") output.push(')');
} }
} }

View File

@ -1,11 +1,9 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type, Value, ValueNode, AbstractTree, Error, Format, FunctionCall, Identifier, Index, Map, Result, Type, Value,
Yield, ValueNode, Yield,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -77,14 +75,16 @@ impl AbstractTree for FunctionExpression {
} }
} }
impl Display for FunctionExpression { impl Format for FunctionExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
match self { match self {
FunctionExpression::Value(value_node) => write!(f, "{value_node}"), FunctionExpression::Value(value_node) => value_node.format(output, indent_level),
FunctionExpression::Identifier(identifier) => write!(f, "{identifier}"), FunctionExpression::Identifier(identifier) => identifier.format(output, indent_level),
FunctionExpression::FunctionCall(function_call) => write!(f, "{function_call}"), FunctionExpression::FunctionCall(function_call) => {
FunctionExpression::Index(index) => write!(f, "{index}"), function_call.format(output, indent_level)
FunctionExpression::Yield(r#yield) => write!(f, "{}", r#yield), }
FunctionExpression::Index(index) => index.format(output, indent_level),
FunctionExpression::Yield(r#yield) => r#yield.format(output, indent_level),
} }
} }
} }

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Block, Error, Function, Identifier, Map, Result, SyntaxPosition, Type, AbstractTree, Block, Error, Format, Function, Identifier, Map, Result, SyntaxPosition, Type,
TypeDefinition, Value, TypeDefinition, Value,
}; };
@ -146,31 +146,39 @@ impl AbstractTree for FunctionNode {
} }
} }
impl Display for FunctionNode { impl Format for FunctionNode {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let FunctionNode {
parameters,
body,
r#type,
..
} = self;
let (parameter_types, return_type) = if let Type::Function { let (parameter_types, return_type) = if let Type::Function {
parameter_types, parameter_types,
return_type, return_type,
} = r#type } = &self.r#type
{ {
(parameter_types, return_type) (parameter_types, return_type)
} else { } else {
return Ok(()); return;
}; };
write!(f, "(")?; output.push('(');
for (identifier, r#type) in parameters.iter().zip(parameter_types.iter()) { for (identifier, r#type) in self.parameters.iter().zip(parameter_types.iter()) {
write!(f, "{identifier} <{}>", r#type)?; 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)
} }
} }

View File

@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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. /// 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); pub struct Identifier(String);
impl Identifier { impl Identifier {
pub fn new(inner: String) -> Self { pub fn new<T: Into<String>>(inner: T) -> Self {
Identifier(inner) Identifier(inner.into())
} }
pub fn take_inner(self) -> String { 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 { impl Display for Identifier {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.0) write!(f, "{}", self.0)

View File

@ -1,9 +1,7 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct IfElse { pub struct IfElse {
@ -88,26 +86,28 @@ impl AbstractTree for IfElse {
} }
} }
impl Display for IfElse { impl Format for IfElse {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let IfElse { output.push_str("if ");
if_expression, self.if_expression.format(output, indent_level);
if_block, output.push(' ');
else_if_expressions, self.if_block.format(output, indent_level);
else_if_blocks,
else_block,
} = self;
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()) { for (expression, block) in else_ifs {
write!(f, "else if {expression} {{{block}}}")?; output.push_str("else if ");
expression.format(output, indent_level);
output.push(' ');
block.format(output, indent_level);
} }
if let Some(block) = else_block { if let Some(block) = &self.else_block {
write!(f, "else {{{block}}}")?; output.push_str("else ");
block.format(output, indent_level);
} }
Ok(())
} }
} }

View File

@ -1,9 +1,7 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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. /// Abstract representation of an index expression.
/// ///
@ -101,20 +99,15 @@ impl AbstractTree for Index {
} }
} }
impl Display for Index { impl Format for Index {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let Index { self.collection.format(output, indent_level);
collection, output.push(':');
index, self.index.format(output, indent_level);
index_end,
} = self;
write!(f, "{collection}:{index}")?; if let Some(expression) = &self.index_end {
output.push_str("..");
if let Some(expression) = index_end { expression.format(output, indent_level);
write!(f, "..{expression}")?;
} }
Ok(())
} }
} }

View File

@ -1,11 +1,9 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, AssignmentOperator, Error, Index, IndexExpression, Map, Result, Statement, Type, AbstractTree, AssignmentOperator, Error, Format, Index, IndexExpression, Map, Result,
Value, Statement, Type, Value,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[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_node = node.child(0).unwrap();
let index = Index::from_syntax_node(source, index_node, context)?; 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();
let operator = match operator_node.kind() { let operator = AssignmentOperator::from_syntax_node(source, operator_node, context)?;
"=" => 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 statement_node = node.child(2).unwrap(); let statement_node = node.child(2).unwrap();
let statement = Statement::from_syntax_node(source, statement_node, context)?; let statement = Statement::from_syntax_node(source, statement_node, context)?;
@ -94,14 +80,12 @@ impl AbstractTree for IndexAssignment {
} }
} }
impl Display for IndexAssignment { impl Format for IndexAssignment {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let IndexAssignment { self.index.format(output, indent_level);
index, output.push(' ');
operator, self.operator.format(output, indent_level);
statement, output.push(' ');
} = self; self.statement.format(output, indent_level);
write!(f, "{index} {operator} {statement}")
} }
} }

View File

@ -1,10 +1,8 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
value_node::ValueNode, AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type, value_node::ValueNode, AbstractTree, Error, Format, FunctionCall, Identifier, Index, Map,
Value, Result, Type, Value,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -69,13 +67,21 @@ impl AbstractTree for IndexExpression {
} }
} }
impl Display for IndexExpression { impl Format for IndexExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
match self { match self {
IndexExpression::Value(value_node) => write!(f, "{value_node}"), IndexExpression::Value(value_node) => {
IndexExpression::Identifier(identifier) => write!(f, "{identifier}"), if let ValueNode::BuiltInValue(built_in_value) = value_node {
IndexExpression::FunctionCall(function_call) => write!(f, "{function_call}"), output.push_str(built_in_value.name());
IndexExpression::Index(index) => write!(f, "{index}"), } 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),
} }
} }
} }

View File

@ -1,9 +1,7 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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. /// Abstract representation of a logic expression.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[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 first_node = node.child(0).unwrap();
let (left_node, operator_node, right_node) = { let (left_node, operator_node, right_node) = {
if first_node.is_named() { if first_node.is_named() {
( (first_node, node.child(1).unwrap(), node.child(2).unwrap())
first_node,
node.child(1).unwrap().child(0).unwrap(),
node.child(2).unwrap(),
)
} else { } else {
( (
node.child(1).unwrap(), node.child(1).unwrap(),
node.child(2).unwrap().child(0).unwrap(), node.child(2).unwrap(),
node.child(3).unwrap(), node.child(3).unwrap(),
) )
} }
}; };
let left = Expression::from_syntax_node(source, left_node, context)?; let left = Expression::from_syntax_node(source, left_node, context)?;
let operator = match operator_node.kind() { let operator = LogicOperator::from_syntax_node(source, operator_node, context)?;
"==" => 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 right = Expression::from_syntax_node(source, right_node, context)?; let right = Expression::from_syntax_node(source, right_node, context)?;
Ok(Logic { Ok(Logic {
@ -95,41 +72,12 @@ impl AbstractTree for Logic {
} }
} }
impl Display for Logic { impl Format for Logic {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let Logic { self.left.format(output, indent_level);
left, output.push(' ');
operator, self.operator.format(output, indent_level);
right, output.push(' ');
} = self; self.right.format(output, indent_level);
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, "<="),
}
} }
} }

View File

@ -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<Self> {
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<Value> {
Ok(Value::none())
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
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("<="),
}
}
}

View File

@ -2,13 +2,10 @@
//! //!
//! Note that this module is called "match" but is escaped as "r#match" because //! Note that this module is called "match" but is escaped as "r#match" because
//! "match" is a keyword in Rust. //! "match" is a keyword in Rust.
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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. /// Abstract representation of a match statement.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -85,24 +82,23 @@ impl AbstractTree for Match {
} }
} }
impl Display for Match { impl Format for Match {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let Match { output.push_str("match ");
matcher, self.matcher.format(output, indent_level);
options, output.push_str(" {");
fallback,
} = self;
write!(f, "match {matcher} {{")?; for (expression, statement) in &self.options {
expression.format(output, indent_level);
for (expression, statement) in options { output.push_str(" => ");
write!(f, "{expression} => {statement}")?; statement.format(output, indent_level);
} }
if let Some(statement) = fallback { if let Some(statement) = &self.fallback {
write!(f, "* => {statement}")?; output.push_str("* => ");
statement.format(output, indent_level);
} }
write!(f, "}}") output.push('}');
} }
} }

View File

@ -1,9 +1,7 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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. /// Abstract representation of a math operation.
/// ///
@ -23,22 +21,8 @@ impl AbstractTree for Math {
let left_node = node.child(0).unwrap(); let left_node = node.child(0).unwrap();
let left = Expression::from_syntax_node(source, left_node, context)?; 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();
let operator = match operator_node.kind() { let operator = MathOperator::from_syntax_node(source, operator_node, context)?;
"+" => 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 right_node = node.child(2).unwrap(); let right_node = node.child(2).unwrap();
let right = Expression::from_syntax_node(source, right_node, context)?; let right = Expression::from_syntax_node(source, right_node, context)?;
@ -69,35 +53,12 @@ impl AbstractTree for Math {
} }
} }
impl Display for Math { impl Format for Math {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let Math { self.left.format(output, indent_level);
left, output.push(' ');
operator, self.operator.format(output, indent_level);
right, output.push(' ');
} = self; self.right.format(output, indent_level);
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, "%"),
}
} }
} }

View File

@ -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<Self> {
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<Value> {
Ok(Value::none())
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
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);
}
}

View File

@ -7,6 +7,7 @@
//! examples. //! examples.
pub mod assignment; pub mod assignment;
pub mod assignment_operator;
pub mod block; pub mod block;
pub mod built_in_value; pub mod built_in_value;
pub mod expression; pub mod expression;
@ -20,23 +21,25 @@ pub mod index;
pub mod index_assignment; pub mod index_assignment;
pub mod index_expression; pub mod index_expression;
pub mod logic; pub mod logic;
pub mod logic_operator;
pub mod r#match; pub mod r#match;
pub mod math; pub mod math;
pub mod math_operator;
pub mod statement; pub mod statement;
pub mod r#type;
pub mod type_definition; pub mod type_definition;
pub mod value_node; pub mod value_node;
pub mod r#while; pub mod r#while;
pub mod r#yield; pub mod r#yield;
pub use { pub use {
assignment::*, block::*, built_in_value::*, expression::*, function_call::*, assignment::*, assignment_operator::*, block::*, built_in_value::*, expression::*,
function_expression::*, function_node::*, identifier::*, if_else::*, index::*, function_call::*, function_expression::*, function_node::*, identifier::*, if_else::*,
index_assignment::IndexAssignment, index_expression::*, logic::*, math::*, r#for::*, index::*, index_assignment::IndexAssignment, index_expression::*, logic::*, logic_operator::*,
r#match::*, r#while::*, r#yield::*, statement::*, type_definition::*, value_node::*, 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 serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
@ -118,19 +121,17 @@ impl AbstractTree for Root {
} }
} }
impl Display for Root { impl Format for Root {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
for statement in &self.statements { 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 /// This trait is implemented by the Evaluator's internal types to form an
/// executable tree that resolves to a single value. /// 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. /// Interpret the syntax tree at the given node and return the abstraction.
/// ///
/// This function is used to convert nodes in the Tree Sitter concrete /// 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<Type>; fn expected_type(&self, context: &Map) -> Result<Type>;
} }
pub trait Format {
fn format(&self, output: &mut String, indent_level: u8);
}

View File

@ -1,11 +1,9 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Map, Match, AbstractTree, Assignment, Block, Error, Expression, For, Format, IfElse, IndexAssignment, Map,
Result, Type, Value, While, Match, Result, Type, Value, While,
}; };
/// Abstract representation of a statement. /// Abstract representation of a statement.
@ -113,18 +111,20 @@ impl AbstractTree for Statement {
} }
} }
impl Display for Statement { impl Format for Statement {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
match self { match self {
Statement::Assignment(assignment) => write!(f, "{assignment}"), Statement::Assignment(assignment) => assignment.format(output, indent_level),
Statement::Expression(expression) => write!(f, "{expression}"), Statement::Expression(expression) => expression.format(output, indent_level),
Statement::IfElse(if_else) => write!(f, "{if_else}"), Statement::IfElse(if_else) => if_else.format(output, indent_level),
Statement::Match(r#match) => write!(f, "{}", r#match), Statement::Match(r#match) => r#match.format(output, indent_level),
Statement::While(r#while) => write!(f, "{}", r#while), Statement::While(r#while) => r#while.format(output, indent_level),
Statement::Block(block) => write!(f, "{block}"), Statement::Block(block) => block.format(output, indent_level),
Statement::For(r#for) => write!(f, "{}", r#for), Statement::For(r#for) => r#for.format(output, indent_level),
Statement::IndexAssignment(index_assignment) => write!(f, "{index_assignment}"), Statement::IndexAssignment(index_assignment) => {
Statement::Return(statement) => write!(f, "{statement}"), index_assignment.format(output, indent_level)
}
Statement::Return(statement) => statement.format(output, indent_level),
} }
} }
} }

290
src/abstract_tree/type.rs Normal file
View File

@ -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<Type>,
return_type: Box<Type>,
},
Integer,
List(Box<Type>),
Map(Option<Structure>),
None,
Number,
String,
Option(Box<Type>),
}
impl Type {
pub fn list(item_type: Type) -> Self {
Type::List(Box::new(item_type))
}
pub fn function(parameter_types: Vec<Type>, 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<Self> {
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<Value> {
Ok(Value::none())
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
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)
}
}
}
}

View File

@ -1,9 +1,7 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct TypeDefinition { pub struct TypeDefinition {
@ -43,243 +41,10 @@ impl AbstractTree for TypeDefinition {
} }
} }
impl Display for TypeDefinition { impl Format for TypeDefinition {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
write!(f, "<{}>", self.r#type) output.push('<');
} self.r#type.format(output, indent_level);
} output.push('>');
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum Type {
Any,
Boolean,
Collection,
Float,
Function {
parameter_types: Vec<Type>,
return_type: Box<Type>,
},
Integer,
List(Box<Type>),
Map(Option<Structure>),
None,
Number,
String,
Option(Box<Type>),
}
impl Type {
pub fn list(item_type: Type) -> Self {
Type::List(Box::new(item_type))
}
pub fn function(parameter_types: Vec<Type>, 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<Self> {
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<Value> {
Ok(Value::none())
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
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)
}
}
} }
} }

View File

@ -1,14 +1,11 @@
use std::{ use std::{collections::BTreeMap, fmt::Write};
collections::BTreeMap,
fmt::{self, Display, Formatter},
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, BuiltInValue, Error, Expression, Function, Identifier, List, Map, Result, AbstractTree, BuiltInValue, Error, Expression, Format, Function, FunctionNode, Identifier,
Statement, Structure, Type, TypeDefinition, Value, List, Map, Result, Statement, Structure, Type, TypeDefinition, Value,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -33,7 +30,11 @@ impl AbstractTree for ValueNode {
let value_node = match child.kind() { let value_node = match child.kind() {
"boolean" => ValueNode::Boolean(source[child.byte_range()].to_string()), "boolean" => ValueNode::Boolean(source[child.byte_range()].to_string()),
"float" => ValueNode::Float(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()), "integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
"string" => { "string" => {
let without_quotes = child.start_byte() + 1..child.end_byte() - 1; let without_quotes = child.start_byte() + 1..child.end_byte() - 1;
@ -300,53 +301,75 @@ impl AbstractTree for ValueNode {
} }
} }
impl Display for ValueNode { impl Format for ValueNode {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
match self { match self {
ValueNode::Boolean(source) ValueNode::Boolean(source)
| ValueNode::Float(source) | ValueNode::Float(source)
| ValueNode::Integer(source) | ValueNode::Integer(source)
| ValueNode::String(source) => write!(f, "{source}"), | ValueNode::String(source) => output.push_str(source),
ValueNode::Function(function) => write!(f, "{function}"), ValueNode::Function(function) => function.format(output, indent_level),
ValueNode::List(expressions) => { ValueNode::List(expressions) => {
output.push('[');
for expression in expressions { for expression in expressions {
write!(f, "{expression}")?; expression.format(output, indent_level);
} }
Ok(()) output.push(']');
} }
ValueNode::Option(option) => { ValueNode::Option(option) => {
if let Some(expression) = option { if let Some(expression) = option {
write!(f, "some({})", expression) output.push_str("some(");
expression.format(output, indent_level);
output.push(')');
} else { } else {
write!(f, "none") output.push_str("none");
} }
} }
ValueNode::Map(nodes) => { ValueNode::Map(nodes) => {
writeln!(f, "{{")?; output.push('{');
for (key, (statement, type_option)) in nodes { for (key, (statement, type_option)) in nodes {
if let Some(r#type) = type_option { 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 { } 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) => { ValueNode::Structure(nodes) => {
writeln!(f, "{{")?; output.push('{');
for (key, (value_option, r#type)) in nodes { for (key, (value_option, r#type)) in nodes {
if let Some(value) = value_option { 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 { } 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('}');
} }
} }
} }

View File

@ -1,9 +1,7 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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. /// Abstract representation of a while loop.
/// ///
@ -40,10 +38,11 @@ impl AbstractTree for While {
} }
} }
impl Display for While { impl Format for While {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
let While { expression, block } = self; output.push_str("while ");
self.expression.format(output, indent_level);
write!(f, "while {expression} {{{block}}}") output.push(' ');
self.expression.format(output, indent_level);
} }
} }

View File

@ -1,11 +1,9 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
function_expression::FunctionExpression, AbstractTree, Error, Expression, FunctionCall, Map, function_expression::FunctionExpression, AbstractTree, Error, Expression, Format, FunctionCall,
Result, Type, Value, Map, Result, Type, Value,
}; };
/// Abstract representation of a yield expression. /// Abstract representation of a yield expression.
@ -55,8 +53,8 @@ impl AbstractTree for Yield {
} }
} }
impl Display for Yield { impl Format for Yield {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn format(&self, output: &mut String, indent_level: u8) {
write!(f, "{}", self.call) self.call.format(output, indent_level);
} }
} }

View File

@ -1,11 +1,14 @@
mod string; 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 rand::{random, thread_rng, Rng};
use serde::{Deserialize, Serialize}; 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}; 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())
}
}

View File

@ -4,7 +4,7 @@
//! functions or by constructing your own Evaluator. //! functions or by constructing your own Evaluator.
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor}; 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. /// Interpret the given source code.
/// ///
@ -132,7 +132,11 @@ impl Interpreter {
pub fn format(&self) -> String { pub fn format(&self) -> String {
if let Some(root_node) = &self.abstract_tree { 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 { } else {
"".to_string() "".to_string()
} }

View File

@ -1,9 +1,8 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; 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)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub enum Function { pub enum Function {
@ -11,17 +10,6 @@ pub enum Function {
ContextDefined(FunctionNode), 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 { impl Function {
pub fn call( pub fn call(
&self, &self,
@ -50,30 +38,20 @@ impl Function {
} }
} }
impl AbstractTree for Function { impl Format for Function {
fn from_syntax_node(_source: &str, _node: Node, _context: &Map) -> Result<Self> { fn format(&self, output: &mut String, indent_level: u8) {
let inner_function = FunctionNode::from_syntax_node(_source, _node, _context)?;
Ok(Function::ContextDefined(inner_function))
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<()> {
match self { match self {
Function::BuiltIn(_) => Ok(()), Function::BuiltIn(built_in_function) => built_in_function.format(output, indent_level),
Function::ContextDefined(defined_function) => { Function::ContextDefined(function_node) => function_node.format(output, indent_level),
defined_function.check_type(_source, _context) }
} }
} }
}
impl Display for Function {
fn run(&self, _source: &str, _context: &Map) -> Result<Value> { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Ok(Value::Function(self.clone())) match self {
} Function::BuiltIn(built_in_function) => write!(f, "{built_in_function}"),
Function::ContextDefined(function_node) => write!(f, "{function_node}"),
fn expected_type(&self, _context: &Map) -> Result<Type> {
match self {
Function::BuiltIn(built_in) => Ok(built_in.r#type()),
Function::ContextDefined(context_defined) => Ok(context_defined.r#type().clone()),
} }
} }
} }

View File

@ -527,7 +527,7 @@ impl Serialize for Value {
impl Display for Value { impl Display for Value {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { 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::Float(float) => write!(f, "{float}"),
Value::Integer(int) => write!(f, "{int}"), Value::Integer(int) => write!(f, "{int}"),
Value::Boolean(boolean) => write!(f, "{boolean}"), Value::Boolean(boolean) => write!(f, "{boolean}"),