diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 9c77018..c1accf7 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1,8 +1,8 @@ use pest::Parser; pub mod build; +mod pretty_print; pub mod unparse; - // Operators #[derive(Debug)] diff --git a/src/ast/pretty_print.rs b/src/ast/pretty_print.rs new file mode 100644 index 0000000..cdfb5b8 --- /dev/null +++ b/src/ast/pretty_print.rs @@ -0,0 +1,231 @@ +use crate::ast::*; +use crate::util::indent_writer::IndentWriter; +use std::fmt::Debug; + +trait PrettyPrint { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result; +} + +impl PrettyPrint for Identifier { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented(&format!("Identifier({})", self.name)) + } +} + +impl PrettyPrint for FullyQualifiedName { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("FullyQualifiedName")?; + writer.increase_indent(); + for identifier in &self.0 { + identifier.pretty_print(writer)?; + } + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for TypeUse { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + use TypeUse::*; + match self { + Void => { + writer.writeln_indented("TypeUse(Void)")?; + } + InterfaceOrClass(t) => { + writer.increase_indent(); + t.pretty_print(writer)?; + writer.decrease_indent(); + } + Tuple(t) => { + writer.increase_indent(); + t.pretty_print(writer)?; + writer.decrease_indent(); + } + Function(t) => { + writer.increase_indent(); + t.pretty_print(writer)?; + writer.decrease_indent(); + } + } + Ok(()) + } +} + +impl PrettyPrint for InterfaceOrClassTypeUse { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented(&format!( + "InterfaceOrClassTypeUse(borrow_count = {}, is_mutable = {})", + self.borrow_count, self.is_mutable + ))?; + writer.increase_indent(); + self.fqn.pretty_print(writer)?; + self.generics.pretty_print(writer)?; + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for TupleTypeUse { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented(&format!( + "TupleTypeUse(borrow_count = {}, is_mutable = {})", + self.borrow_count, + self.is_mutable + ))?; + writer.increase_indent(); + self.arguments.pretty_print(writer)?; + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for FunctionTypeUse { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented(&format!( + "FunctionTypeUse(borrow_count = {})", + self.borrow_count + ))?; + writer.increase_indent(); + if let Some(function_type_modifier) = &self.function_modifier { + function_type_modifier.pretty_print(writer)?; + } + self.generics.pretty_print(writer)?; + self.parameters.pretty_print(writer)?; + self.return_type.pretty_print(writer)?; + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for GenericArguments { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("GenericArguments")?; + writer.increase_indent(); + for type_use in &self.0 { + type_use.pretty_print(writer)?; + } + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for GenericParameters { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("GenericParameters")?; + writer.increase_indent(); + for identifier in &self.0 { + identifier.pretty_print(writer)?; + } + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for TupleArguments { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("TupleArguments")?; + writer.increase_indent(); + for type_use in &self.0 { + type_use.pretty_print(writer)?; + } + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for ImplementsList { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("ImplementsList")?; + writer.increase_indent(); + for type_use in &self.0 { + type_use.pretty_print(writer)?; + } + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for FunctionTypeModifier { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + use FunctionTypeModifier::*; + writer.writeln_indented(&format!( + "FunctionTypeModifier({})", + match self { + Cons => "cons", + MutRef => "mut ref", + Mut => "mut", + Ref => "ref" + } + )) + } +} + +impl PrettyPrint for Parameters { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("Parameters")?; + writer.increase_indent(); + for parameter in &self.0 { + parameter.pretty_print(writer)?; + } + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for Parameter { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("Parameter")?; + writer.increase_indent(); + self.identifier.pretty_print(writer)?; + self.type_use.pretty_print(writer)?; + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for ReturnType { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("ReturnType")?; + writer.increase_indent(); + self.declared_type.pretty_print(writer)?; + self.references.pretty_print(writer)?; + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for References { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("References")?; + writer.increase_indent(); + for identifier in &self.0 { + identifier.pretty_print(writer)?; + } + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for CompilationUnit { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.writeln_indented("CompilationUnit")?; + writer.increase_indent(); + if let Some(namespace) = &self.namespace { + writer.writeln_indented("Namespace")?; + writer.increase_indent(); + namespace.pretty_print(writer)?; + writer.decrease_indent(); + } + for declaration in &self.declarations { + declaration.pretty_print(writer)?; + } + writer.decrease_indent(); + Ok(()) + } +} + +impl PrettyPrint for ModuleLevelDeclaration { + fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + todo!() + } +} diff --git a/src/util/indent_writer.rs b/src/util/indent_writer.rs new file mode 100644 index 0000000..4b62a98 --- /dev/null +++ b/src/util/indent_writer.rs @@ -0,0 +1,44 @@ +use std::fmt::Write; + +pub struct IndentWriter { + indent_level: usize, + indent_string: String, + out: Box, +} + +impl IndentWriter { + pub fn new(start_level: usize, indent_string: String, out: Box) -> IndentWriter { + IndentWriter { + indent_level: start_level, + indent_string, + out, + } + } + + pub fn increase_indent(&mut self) { + self.indent_level += 1; + } + + pub fn decrease_indent(&mut self) { + self.indent_level -= 1; + } + + pub fn write(&mut self, s: &str) -> std::fmt::Result { + write!(self.out, "{}", s) + } + + pub fn writeln(&mut self, s: &str) -> std::fmt::Result { + self.write(&format!("{}\n", s)) + } + + pub fn write_indented(&mut self, s: &str) -> std::fmt::Result { + for _ in 0..self.indent_level { + write!(self.out, "{}", self.indent_string)?; + } + write!(self.out, "{}", s) + } + + pub fn writeln_indented(&mut self, s: &str) -> std::fmt::Result { + self.write_indented(&format!("{}\n", s)) + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 225296c..5198298 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1 +1 @@ -pub mod trie; +pub mod indent_writer;