1use std::fmt::{Display, Formatter, Result};
6
7use lexer::token::TokenKind;
8
9use crate::expression::*;
10use crate::literal::Literal;
11use crate::statement::{
12 FunctionDeclaration, RepeatForever, RepeatNTimes, RepeatUntil, Return, Set, Statement,
13};
14use crate::{Program, StatementList};
15
16impl Display for Program {
17 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
18 write!(f, "{}", format_semi_seperated(&self.statements))
19 }
20}
21
22impl Display for StatementList {
23 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
24 write!(f, "{}", format_semi_seperated(&self.statements))
25 }
26}
27
28impl Display for Statement {
29 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
30 match self {
31 Statement::Set(Set { ident, expr, .. }) => {
32 write!(f, "{} {} = {}", TokenKind::Set, ident.name, expr)
33 }
34 Statement::Return(Return { value, .. }) => {
35 write!(f, "{} {}", TokenKind::Return, value)
36 }
37 Statement::Expression(expr) => write!(f, "{}", expr),
38 Statement::FunctionDeclaration(FunctionDeclaration {
39 name,
40 parameters,
41 body,
42 ..
43 }) => {
44 write!(
45 f,
46 "{} {name}({}){}{}",
47 TokenKind::DefineFunction,
48 format_comma_seperated(¶meters),
49 format_stmt_list(body),
50 TokenKind::End
51 )
52 }
53 Statement::RepeatNTimes(RepeatNTimes { n, body, .. }) => {
54 write!(
55 f,
56 "{} {n} {}{}{}",
57 TokenKind::Repeat,
58 TokenKind::Times,
59 format_stmt_list(body),
60 TokenKind::End
61 )
62 }
63 Statement::RepeatUntil(RepeatUntil {
64 condition, body, ..
65 }) => {
66 write!(
67 f,
68 "{} {} {condition}{}{}",
69 TokenKind::Repeat,
70 TokenKind::Until,
71 format_stmt_list(body),
72 TokenKind::End
73 )
74 }
75 Statement::RepeatForever(RepeatForever { body, .. }) => {
76 write!(
77 f,
78 "{} {}{}{}",
79 TokenKind::Repeat,
80 TokenKind::Forever,
81 format_stmt_list(body),
82 TokenKind::End
83 )
84 }
85 Statement::Display(display) => {
86 write!(
87 f,
88 "{} {}",
89 TokenKind::Display,
90 format_comma_seperated(&display.expressions)
91 )
92 }
93 }
94 }
95}
96
97impl Display for Expression {
98 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
99 match self {
100 Expression::Identifier(ident) => write!(f, "{}", ident),
101 Expression::Literal(l) => write!(f, "{}", l),
102 Expression::Unary(Unary {
103 operator, operand, ..
104 }) => match operator {
105 TokenKind::Not => write!(f, "({} {})", operator, operand),
106 _ => write!(f, "({}{})", operator, operand),
107 },
108 Expression::Binary(Binary {
109 operator,
110 left,
111 right,
112 ..
113 }) => write!(f, "({} {} {})", left, operator, right),
114 Expression::FunctionCall(FunctionCall {
115 callee, arguments, ..
116 }) => write!(f, "{}({})", callee, format_comma_seperated(arguments)),
117 Expression::Index(Index { object, index, .. }) => write!(f, "{}[{}]", object, index),
118 Expression::Selection(Selection {
119 condition,
120 conditional,
121 else_conditional,
122 ..
123 }) => {
124 let formatted_conditional = match conditional.statements.is_empty() {
125 true => "".to_string(),
126 false => format!(" {}", conditional),
127 };
128
129 let formatted_else_conditional = match else_conditional {
130 Some(else_conditional) => match else_conditional.statements.is_empty() {
131 true => format!(" {}", TokenKind::Otherwise),
132 false => format!(" {} {else_conditional}", TokenKind::Otherwise),
133 },
134 None => "".to_string(),
135 };
136
137 write!(
138 f,
139 "{} {condition} {}{formatted_conditional}{formatted_else_conditional} {}",
140 TokenKind::If,
141 TokenKind::Then,
142 TokenKind::End,
143 )
144 }
145 Expression::Array(Array { elements, .. }) => {
146 write!(f, "[{}]", format_comma_seperated(&elements))
147 }
148 }
149 }
150}
151
152impl Display for Identifier {
153 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
154 write!(f, "{}", self.name)
155 }
156}
157
158impl Display for Literal {
159 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
160 match self {
161 Literal::Integer { value, .. } => write!(f, "{}", value),
162 Literal::Boolean { value, .. } => write!(f, "{}", value),
163 Literal::Float { value, .. } => write!(f, "{}", value),
164 Literal::String { value, .. } => write!(f, "\"{}\"", value),
165 }
166 }
167}
168
169fn format_stmt_list(list: &StatementList) -> String {
171 match list.statements.is_empty() {
175 true => " ".to_string(),
176 false => format!(" {} ", list),
177 }
178}
179
180fn format_semi_seperated<T: ToString>(items: &Vec<T>) -> String {
182 return items
183 .iter()
184 .map(|item| item.to_string())
185 .collect::<Vec<String>>()
186 .join("; ");
187}
188
189fn format_comma_seperated<T: ToString>(items: &Vec<T>) -> String {
191 return items
192 .iter()
193 .map(|item| item.to_string())
194 .collect::<Vec<String>>()
195 .join(", ");
196}