use crate::parser::ast::*; use crate::runtime::executor::Visitor; pub struct TreePrinter { indent: usize, buffer: String, } impl TreePrinter { pub fn new() -> Self { Self { indent: 0, buffer: String::new(), } } pub fn increment(&mut self) { self.indent = self.indent.saturating_add(1); } pub fn decrement(&mut self) { self.indent = self.indent.saturating_sub(1); } pub fn get_indent(&self) -> String { vec!["\t"; self.indent].join("") } fn write(&mut self, value: impl ToString) { self.buffer.push_str(value.to_string().as_str()); } fn writeln(&mut self, value: impl ToString) { self.buffer.push_str(value.to_string().as_str()); self.buffer.push('\n'); } fn write_indent(&mut self) { self.write(self.get_indent()); } fn new_line(&mut self) { self.buffer.push('\n'); } fn format_expression_list(&self, list: &ExpressionList) -> String { let mut inner_printer = TreePrinter::new(); inner_printer.indent = self.indent; let len = list.len(); let mut iter = list.expressions.iter(); let mut counter = 1; while let Some(value) = iter.next() { inner_printer.evaluate_expression(value); if counter < len { inner_printer.writeln(";"); } counter += 1; } if list.is_void { inner_printer.writeln(";"); } inner_printer.buffer } pub fn value(&self) -> &str { self.buffer.as_str() } pub fn take_value(&mut self) -> String { std::mem::take(&mut self.buffer) } } impl Visitor for TreePrinter { fn evaluate_value_expression(&mut self, expression: &ValueExpression) { match expression { ValueExpression::Unary { operand, operator } => { self.write(operator); self.evaluate_value_expression(operand.as_ref()); } ValueExpression::Binary { operator, rhs, lhs } => { self.evaluate_value_expression(lhs.as_ref()); self.write(operator); self.evaluate_value_expression(rhs.as_ref()); } ValueExpression::Block(list) => { self.writeln("{"); self.increment(); self.write(self.format_expression_list(list)); self.decrement(); self.writeln("}"); } ValueExpression::Literal(value) => self.write(value), ValueExpression::DeclareIdentifier(dec_ident) => match dec_ident { DeclareIdent::WithoutValue(ident) => { self.write("let "); self.write(ident); } DeclareIdent::WithValue(assign) => { self.write("let "); self.write(&assign.ident); self.write(" = "); self.evaluate_value_expression(assign.value.as_ref()); } }, ValueExpression::Assignment(assign) => { self.write(&assign.ident); self.write(" = "); self.evaluate_value_expression(assign.value.as_ref()); } ValueExpression::ConditionalBlock(condition) => { let mut iter = condition.blocks.iter(); let mut curr = 1; let count = iter.len(); while let Some(item) = iter.next() { self.write("if "); self.evaluate_value_expression(item.guard.as_ref()); self.writeln(" {"); self.increment(); self.write(self.format_expression_list(&item.block)); self.decrement(); if curr < count { self.write("} else "); } else { self.write("}"); } } if let Some(fall) = &condition.fallback { self.writeln(" else {"); self.increment(); self.write(self.format_expression_list(fall)); self.decrement(); self.writeln("}"); } } ValueExpression::Grouped(GroupedExpression { inner }) => { self.write("("); self.evaluate_value_expression(inner.as_ref()); self.write(")"); } ValueExpression::Identifier(ident) => { self.write(ident); } ValueExpression::FunctionCall(call) => { self.write(&call.name); self.write("("); let list = call .params .iter() .map(|param| { let mut inner = TreePrinter { indent: self.indent, buffer: String::new(), }; inner.evaluate_value_expression(param); inner.take_value() }) .collect::<Vec<String>>(); self.write(list.as_slice().join(", ")); self.write(")"); } ValueExpression::DeclareFunction(declare) => { self.write("fn "); self.write(&declare.ident); self.write("("); let list = declare .params .iter() .map(|param| { let mut inner = TreePrinter { indent: self.indent, buffer: String::new(), }; match param { DeclareIdent::WithValue(assign) => { inner.write(&assign.ident); inner.write(" = "); inner.evaluate_value_expression(assign.value.as_ref()); } DeclareIdent::WithoutValue(identifier) => inner.write(identifier), } inner.take_value() }) .collect::<Vec<String>>(); self.write(list.as_slice().join(", ")); self.writeln(") {"); self.increment(); self.writeln(self.format_expression_list(&declare.body)); self.decrement(); self.writeln("}"); } } } fn evaluate_void_expression(&mut self, expression: &VoidExpression) { match expression { VoidExpression::ConditionLoop(cond) => { self.write("while "); self.evaluate_value_expression(cond.block.guard.as_ref()); self.writeln(" {"); self.increment(); self.writeln(self.format_expression_list(&cond.block.block)); self.decrement(); self.writeln(" {"); } VoidExpression::Import(import) => { self.write("import { "); let ident_list = import .items .iter() .map(|idn| format!("{}", idn)) .collect::<Vec<String>>(); self.write(ident_list.as_slice().join(", ")); self.write(" } from \""); self.write(&import.source); self.write("\""); } VoidExpression::Export(export) => { self.write("export {"); let ident_list = export .items .iter() .map(|idn| format!("{}", idn)) .collect::<Vec<String>>(); self.write(ident_list.as_slice().join(", ")); self.write("}"); } VoidExpression::Print(print) => { self.write("print "); self.evaluate_value_expression(print.expr.as_ref()); } } } fn evaluate_program(&mut self, program: &Program) { self.writeln(self.format_expression_list(&program.0)); } }