From 822f12b44dde488ea06d179c2fc3ed1c035d6a96 Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 26 Jun 2024 12:50:46 -0400 Subject: [PATCH] Add Display implementations for abstract tree --- dust-lang/src/abstract_tree/as.rs | 11 ++- dust-lang/src/abstract_tree/assignment.rs | 26 +++++ dust-lang/src/abstract_tree/async_block.rs | 17 +++- dust-lang/src/abstract_tree/block.rs | 14 +++ .../src/abstract_tree/enum_declaration.rs | 38 ++++++++ dust-lang/src/abstract_tree/expression.rs | 17 ++++ dust-lang/src/abstract_tree/function_call.rs | 40 +++++++- dust-lang/src/abstract_tree/if_else.rs | 27 ++++++ dust-lang/src/abstract_tree/list_index.rs | 10 ++ dust-lang/src/abstract_tree/logic.rs | 18 ++++ dust-lang/src/abstract_tree/loop.rs | 15 +++ dust-lang/src/abstract_tree/map_index.rs | 10 ++ dust-lang/src/abstract_tree/math.rs | 14 +++ dust-lang/src/abstract_tree/statement.rs | 20 ++++ .../src/abstract_tree/structure_definition.rs | 16 +++ dust-lang/src/abstract_tree/type_alias.rs | 13 +++ dust-lang/src/abstract_tree/value_node.rs | 97 ++++++++++++++++++- dust-lang/src/abstract_tree/while.rs | 14 +++ 18 files changed, 413 insertions(+), 4 deletions(-) diff --git a/dust-lang/src/abstract_tree/as.rs b/dust-lang/src/abstract_tree/as.rs index 0d499da..0664b50 100644 --- a/dust-lang/src/abstract_tree/as.rs +++ b/dust-lang/src/abstract_tree/as.rs @@ -1,4 +1,7 @@ -use std::borrow::Borrow; +use std::{ + borrow::Borrow, + fmt::{self, Display, Formatter}, +}; use serde::{Deserialize, Serialize}; @@ -77,3 +80,9 @@ impl AbstractNode for As { .map(|r#type| Some(r#type)) } } + +impl Display for As { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{} as {}", self.expression, self.constructor) + } +} diff --git a/dust-lang/src/abstract_tree/assignment.rs b/dust-lang/src/abstract_tree/assignment.rs index b047cc7..fbc4eec 100644 --- a/dust-lang/src/abstract_tree/assignment.rs +++ b/dust-lang/src/abstract_tree/assignment.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -237,3 +239,27 @@ impl AbstractNode for Assignment { Ok(None) } } + +impl Display for Assignment { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let Assignment { + identifier, + constructor, + operator, + statement, + } = self; + write!(f, "{} ", identifier.node)?; + + if let Some(constructor) = constructor { + write!(f, ": {constructor} ")?; + } + + match operator { + AssignmentOperator::Assign => write!(f, "="), + AssignmentOperator::AddAssign => write!(f, "+="), + AssignmentOperator::SubAssign => write!(f, "-="), + }?; + + write!(f, " {statement}") + } +} diff --git a/dust-lang/src/abstract_tree/async_block.rs b/dust-lang/src/abstract_tree/async_block.rs index 61d46e2..9d219cb 100644 --- a/dust-lang/src/abstract_tree/async_block.rs +++ b/dust-lang/src/abstract_tree/async_block.rs @@ -1,4 +1,7 @@ -use std::sync::Mutex; +use std::{ + fmt::{self, Display, Formatter}, + sync::Mutex, +}; use rayon::prelude::*; use serde::{Deserialize, Serialize}; @@ -69,3 +72,15 @@ impl AbstractNode for AsyncBlock { self.statements.last().unwrap().expected_type(_context) } } + +impl Display for AsyncBlock { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "async {{")?; + + for statement in &self.statements { + write!(f, "{statement}")?; + } + + write!(f, "}}") + } +} diff --git a/dust-lang/src/abstract_tree/block.rs b/dust-lang/src/abstract_tree/block.rs index 25e2fc4..11dffd0 100644 --- a/dust-lang/src/abstract_tree/block.rs +++ b/dust-lang/src/abstract_tree/block.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -62,6 +64,18 @@ impl AbstractNode for Block { } } +impl Display for Block { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{{")?; + + for statement in &self.statements { + write!(f, "{statement}")?; + } + + write!(f, "}}") + } +} + #[cfg(test)] mod tests { use crate::{ diff --git a/dust-lang/src/abstract_tree/enum_declaration.rs b/dust-lang/src/abstract_tree/enum_declaration.rs index 116f60f..460f8ae 100644 --- a/dust-lang/src/abstract_tree/enum_declaration.rs +++ b/dust-lang/src/abstract_tree/enum_declaration.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -90,6 +92,42 @@ impl AbstractNode for EnumDeclaration { } } +impl Display for EnumDeclaration { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let EnumDeclaration { + name, + type_parameters, + variants, + } = self; + + write!(f, "enum {}", name.node)?; + + if let Some(parameters) = type_parameters { + write!(f, "<")?; + for WithPosition { node, .. } in parameters { + write!(f, "{node}, ")?; + } + write!(f, ">")?; + } + + for EnumVariant { name, content } in variants { + write!(f, "{}", name.node)?; + + if let Some(content) = content { + write!(f, "(")?; + + for constructor in content { + write!(f, "{constructor}, ")?; + } + + write!(f, ")")?; + } + } + + Ok(()) + } +} + #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct EnumVariant { pub name: WithPosition, diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index 66dc594..d0ea068 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -138,3 +140,18 @@ impl AbstractNode for Expression { } } } + +impl Display for Expression { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Expression::As(inner) => write!(f, "{}", inner.node), + Expression::FunctionCall(inner) => write!(f, "{}", inner.node), + Expression::Identifier(inner) => write!(f, "{}", inner.node), + Expression::MapIndex(inner) => write!(f, "{}", inner.node), + Expression::ListIndex(inner) => write!(f, "{}", inner.node), + Expression::Logic(inner) => write!(f, "{}", inner.node), + Expression::Math(inner) => write!(f, "{}", inner.node), + Expression::Value(inner) => write!(f, "{}", inner.node), + } + } +} diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index 4c1da92..6033d16 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -1,4 +1,7 @@ -use std::cmp::Ordering; +use std::{ + cmp::Ordering, + fmt::{self, Display, Formatter}, +}; use serde::{Deserialize, Serialize}; @@ -291,6 +294,41 @@ impl AbstractNode for FunctionCall { } } +impl Display for FunctionCall { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let FunctionCall { + function_expression, + type_arguments, + value_arguments, + context, + } = self; + + write!(f, "{function_expression}")?; + + if let Some(type_arguments) = type_arguments { + write!(f, "::<")?; + + for constructor in type_arguments { + write!(f, "{constructor}, ")?; + } + + write!(f, ">")?; + } + + write!(f, "(")?; + + if let Some(value_arguments) = value_arguments { + for expression in value_arguments { + write!(f, "{expression}, ")?; + } + } + + write!(f, ")")?; + + Ok(()) + } +} + impl Eq for FunctionCall {} impl PartialEq for FunctionCall { diff --git a/dust-lang/src/abstract_tree/if_else.rs b/dust-lang/src/abstract_tree/if_else.rs index acd8db5..fecf5b7 100644 --- a/dust-lang/src/abstract_tree/if_else.rs +++ b/dust-lang/src/abstract_tree/if_else.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -177,6 +179,31 @@ impl AbstractNode for IfElse { } } +impl Display for IfElse { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let IfElse { + if_expression, + if_block, + else_ifs, + else_block, + } = self; + + write!(f, "if {if_expression} {}", if_block.node)?; + + if let Some(else_ifs) = else_ifs { + for (expression, block) in else_ifs { + write!(f, "else if {expression} {}", block.node)?; + } + } + + if let Some(else_block) = else_block { + write!(f, "{}", else_block.node)?; + } + + Ok(()) + } +} + #[cfg(test)] mod tests { use crate::{ diff --git a/dust-lang/src/abstract_tree/list_index.rs b/dust-lang/src/abstract_tree/list_index.rs index 464d5ab..1c41f6b 100644 --- a/dust-lang/src/abstract_tree/list_index.rs +++ b/dust-lang/src/abstract_tree/list_index.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -148,3 +150,11 @@ impl AbstractNode for ListIndex { } } } + +impl Display for ListIndex { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let ListIndex { collection, index } = self; + + write!(f, "{collection}[{index}]") + } +} diff --git a/dust-lang/src/abstract_tree/logic.rs b/dust-lang/src/abstract_tree/logic.rs index 325484d..81827b2 100644 --- a/dust-lang/src/abstract_tree/logic.rs +++ b/dust-lang/src/abstract_tree/logic.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -257,6 +259,22 @@ impl AbstractNode for Logic { } } +impl Display for Logic { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Logic::Equal(left, right) => write!(f, "{left} == {right}"), + Logic::NotEqual(left, right) => write!(f, "{left} != {right}"), + Logic::Greater(left, right) => write!(f, "{left} > {right}"), + Logic::Less(left, right) => write!(f, "{left} < {right}"), + Logic::GreaterOrEqual(left, right) => write!(f, "{left} >= {right}"), + Logic::LessOrEqual(left, right) => write!(f, "{left} <= {right}"), + Logic::And(left, right) => write!(f, "{left} && {right}"), + Logic::Or(left, right) => write!(f, "{left} || {right}"), + Logic::Not(expression) => write!(f, "!{expression}"), + } + } +} + #[cfg(test)] mod tests { use crate::abstract_tree::{ValueNode, WithPos}; diff --git a/dust-lang/src/abstract_tree/loop.rs b/dust-lang/src/abstract_tree/loop.rs index fc00b5d..e05b3ea 100644 --- a/dust-lang/src/abstract_tree/loop.rs +++ b/dust-lang/src/abstract_tree/loop.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -21,6 +23,7 @@ impl Loop { self.statements.last().unwrap() } } + impl AbstractNode for Loop { fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { for statement in &self.statements { @@ -58,3 +61,15 @@ impl AbstractNode for Loop { self.last_statement().expected_type(_context) } } + +impl Display for Loop { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "loop {{ ")?; + + for statement in &self.statements { + write!(f, "{statement}")?; + } + + write!(f, " }}") + } +} diff --git a/dust-lang/src/abstract_tree/map_index.rs b/dust-lang/src/abstract_tree/map_index.rs index 9dfee7a..b8c38c1 100644 --- a/dust-lang/src/abstract_tree/map_index.rs +++ b/dust-lang/src/abstract_tree/map_index.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -175,3 +177,11 @@ impl AbstractNode for MapIndex { }) } } + +impl Display for MapIndex { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let MapIndex { collection, index } = self; + + write!(f, "{collection}.{index}") + } +} diff --git a/dust-lang/src/abstract_tree/math.rs b/dust-lang/src/abstract_tree/math.rs index 8e6baeb..30785bd 100644 --- a/dust-lang/src/abstract_tree/math.rs +++ b/dust-lang/src/abstract_tree/math.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -360,3 +362,15 @@ impl AbstractNode for Math { } } } + +impl Display for Math { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Math::Add(left, right) => write!(f, "{left} + {right}"), + Math::Subtract(left, right) => write!(f, "{left} - {right}"), + Math::Multiply(left, right) => write!(f, "{left} * {right}"), + Math::Divide(left, right) => write!(f, "{left} / {right}"), + Math::Modulo(left, right) => write!(f, "{left} % {right}"), + } + } +} diff --git a/dust-lang/src/abstract_tree/statement.rs b/dust-lang/src/abstract_tree/statement.rs index eb9f295..a731298 100644 --- a/dust-lang/src/abstract_tree/statement.rs +++ b/dust-lang/src/abstract_tree/statement.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -144,3 +146,21 @@ impl AbstractNode for Statement { } } } + +impl Display for Statement { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Statement::Assignment(inner) => write!(f, "{}", inner.node), + Statement::AsyncBlock(inner) => write!(f, "{}", inner.node), + Statement::Block(inner) => write!(f, "{}", inner.node), + Statement::Break(_) => write!(f, "break"), + Statement::IfElse(inner) => write!(f, "{}", inner.node), + Statement::Loop(inner) => write!(f, "{}", inner.node), + Statement::StructureDefinition(inner) => write!(f, "{}", inner.node), + Statement::TypeAlias(inner) => write!(f, "{}", inner.node), + Statement::EnumDeclaration(inner) => write!(f, "{}", inner.node), + Statement::Expression(expression) => write!(f, "{expression}"), + Statement::While(inner) => write!(f, "{}", inner.node), + } + } +} diff --git a/dust-lang/src/abstract_tree/structure_definition.rs b/dust-lang/src/abstract_tree/structure_definition.rs index 809fa8e..0b04f87 100644 --- a/dust-lang/src/abstract_tree/structure_definition.rs +++ b/dust-lang/src/abstract_tree/structure_definition.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -71,3 +73,17 @@ impl AbstractNode for StructureDefinition { Ok(None) } } + +impl Display for StructureDefinition { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let StructureDefinition { name, fields } = self; + + write!(f, "struct {name} {{ ")?; + + for (identifer, constructor) in fields { + write!(f, "{identifer}: {constructor}, ")?; + } + + write!(f, " }}") + } +} diff --git a/dust-lang/src/abstract_tree/type_alias.rs b/dust-lang/src/abstract_tree/type_alias.rs index 5823442..73555d1 100644 --- a/dust-lang/src/abstract_tree/type_alias.rs +++ b/dust-lang/src/abstract_tree/type_alias.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -44,3 +46,14 @@ impl AbstractNode for TypeAlias { Ok(None) } } + +impl Display for TypeAlias { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let TypeAlias { + identifier, + constructor, + } = self; + + write!(f, "type {} = {constructor}", identifier.node) + } +} diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index 50591bd..0d00591 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -1,4 +1,9 @@ -use std::{cmp::Ordering, collections::BTreeMap, ops::Range}; +use std::{ + cmp::Ordering, + collections::BTreeMap, + fmt::{self, Display, Formatter}, + ops::Range, +}; use serde::{Deserialize, Serialize}; @@ -622,6 +627,96 @@ impl Ord for ValueNode { } } +impl Display for ValueNode { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + ValueNode::Boolean(boolean) => write!(f, "{boolean}"), + ValueNode::BuiltInFunction(built_in_function) => write!(f, "{built_in_function}"), + ValueNode::EnumInstance { + type_name, + variant, + content, + } => { + write!(f, "{}::{}", type_name.node, variant.node)?; + + if let Some(content) = content { + for expression in content { + write!(f, "{expression}")?; + } + } + + Ok(()) + } + ValueNode::Float(float) => write!(f, "{float}"), + ValueNode::Integer(integer) => write!(f, "{integer}"), + ValueNode::List(expressions) => { + for expression in expressions { + write!(f, "{expression}")?; + } + + Ok(()) + } + ValueNode::Map(fields) => { + write!(f, "{{ ")?; + + for (identifier, type_option, expression) in fields { + write!(f, "{identifier}")?; + + if let Some(r#type) = type_option { + write!(f, ": {type}")?; + } + + write!(f, " = {expression}")?; + } + + write!(f, " }}") + } + ValueNode::Range(range) => write!(f, "{}..{}", range.start, range.end), + ValueNode::String(string) => write!(f, "{string}"), + ValueNode::Structure { name, fields } => { + write!(f, "{}", name.node)?; + + for (identifier, expression) in fields { + write!(f, "{} = {expression},", identifier.node)?; + } + + Ok(()) + } + ValueNode::Function(FunctionNode { + type_parameters, + value_parameters, + return_type, + body, + context_template, + }) => { + write!(f, "fn ")?; + + if let Some(type_parameters) = type_parameters { + write!(f, "(")?; + + for identifier in type_parameters { + write!(f, "{identifier}")?; + } + + write!(f, ")")?; + } + + if let Some(value_parameters) = value_parameters { + write!(f, "(")?; + + for (identifier, constructor) in value_parameters { + write!(f, "{identifier}: {constructor}")?; + } + + write!(f, ")")?; + } + + write!(f, "{}", body.node) + } + } + } +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct FunctionNode { type_parameters: Option>, diff --git a/dust-lang/src/abstract_tree/while.rs b/dust-lang/src/abstract_tree/while.rs index 6867f61..d14dfdb 100644 --- a/dust-lang/src/abstract_tree/while.rs +++ b/dust-lang/src/abstract_tree/while.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display, Formatter}; + use serde::{Deserialize, Serialize}; use crate::{ @@ -83,3 +85,15 @@ impl AbstractNode for While { self.statements.last().unwrap().expected_type(_context) } } + +impl Display for While { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "while {} {{", self.expression)?; + + for statement in &self.statements { + write!(f, "{statement}")?; + } + + write!(f, "}}") + } +}