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 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}")
}
}
output.push_str(" ");
self.operator.format(output, indent_level);
output.push_str(" ");
#[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, "+="),
}
self.statement.format(output, indent_level);
}
}

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::{
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(" ");
}
writeln!(f, "}}")
statement.format(output, indent_level);
}
output.push('}');
}
}

View File

@ -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<Value> = 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());
}
}

View File

@ -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),
}
}
}

View File

@ -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);
}
}

View File

@ -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(')');
}
}

View File

@ -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),
}
}
}

View File

@ -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)
}
}

View File

@ -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<T: Into<String>>(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)

View File

@ -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}}}")?;
}
Ok(())
if let Some(block) = &self.else_block {
output.push_str("else ");
block.format(output, indent_level);
}
}
}

View File

@ -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}")?;
}
Ok(())
if let Some(expression) = &self.index_end {
output.push_str("..");
expression.format(output, indent_level);
}
}
}

View File

@ -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);
}
}

View File

@ -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),
}
}
}

View File

@ -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);
}
}

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
//! "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('}');
}
}

View File

@ -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);
}
}

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.
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<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 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),
}
}
}

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 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<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)
}
}
impl Format for TypeDefinition {
fn format(&self, output: &mut String, indent_level: u8) {
output.push('<');
self.r#type.format(output, indent_level);
output.push('>');
}
}

View File

@ -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('}');
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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())
}
}

View File

@ -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()
}

View File

@ -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<Self> {
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)
Function::BuiltIn(built_in_function) => built_in_function.format(output, indent_level),
Function::ContextDefined(function_node) => function_node.format(output, indent_level),
}
}
}
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
Ok(Value::Function(self.clone()))
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
impl Display for Function {
fn fmt(&self, f: &mut Formatter) -> fmt::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) => write!(f, "{built_in_function}"),
Function::ContextDefined(function_node) => write!(f, "{function_node}"),
}
}
}

View File

@ -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}"),