1use core::ops::Range;
2
3use pretty::DocAllocator;
4
5use crate::ast::expressions::{
6 BinaryOperation, DatexExpression, DatexExpressionData, List, Map,
7 VariableAccess, VariableDeclaration,
8};
9use crate::fmt::Assoc;
10use crate::references::reference::ReferenceMutability;
11use crate::{
12 fmt::{
13 Format, Formatter, Operation, ParentContext,
14 options::{StatementFormatting, VariantFormatting},
15 },
16 values::core_values::{
17 decimal::typed_decimal::TypedDecimal,
18 integer::typed_integer::TypedInteger,
19 },
20};
21
22impl<'a> Formatter<'a> {
23 pub fn datex_expression_to_source_code(
24 &'a self,
25 expr: &'a DatexExpression,
26 ) -> Format<'a> {
27 let a = &self.alloc;
28 match &expr.data {
29 DatexExpressionData::Integer(i) => a.as_string(i),
30 DatexExpressionData::TypedInteger(ti) => {
31 self.typed_integer_to_source_code(ti, &expr.span)
32 }
33 DatexExpressionData::Decimal(d) => a.as_string(d),
34 DatexExpressionData::TypedDecimal(td) => {
35 self.typed_decimal_to_source_code(td, &expr.span)
36 }
37 DatexExpressionData::Boolean(b) => a.as_string(b),
38 DatexExpressionData::Text(t) => self.text_to_source_code(t),
39 DatexExpressionData::Endpoint(e) => a.text(e.to_string()),
40 DatexExpressionData::Null => a.text("null"),
41 DatexExpressionData::Identifier(l) => unreachable!(
42 "Identifiers should have been resolved before formatting"
43 ),
44 DatexExpressionData::Map(map) => self.map_to_source_code(map),
45 DatexExpressionData::List(list) => self.list_to_source_code(list),
46 DatexExpressionData::CreateRef(create_ref) => {
47 (match create_ref.mutability {
48 ReferenceMutability::Immutable => a.text("&"),
49 ReferenceMutability::Mutable => a.text("&mut "),
50 }) + self.format_datex_expression(&create_ref.expression)
51 }
52 DatexExpressionData::BinaryOperation(BinaryOperation {
53 operator,
54 left,
55 right,
56 ..
57 }) => {
58 let (precedence, associativity, _is_assoc) =
59 self.binary_operator_info(operator);
60
61 let left_doc = self.format_datex_expression_with_parent(
63 left,
64 Some(ParentContext {
65 precedence,
66 associativity,
67 operation: Operation::Binary(operator),
68 }),
69 true,
70 );
71 let right_doc = self.format_datex_expression_with_parent(
72 right,
73 Some(ParentContext {
74 precedence,
75 associativity,
76 operation: Operation::Binary(operator),
77 }),
78 false,
79 );
80
81 let a = &self.alloc;
82 (left_doc
83 + self.operator_with_spaces(a.text(operator.to_string()))
84 + right_doc)
85 .group()
86 }
87 DatexExpressionData::Statements(statements) => {
88 let is_terminated = statements.is_terminated;
89 let docs: Vec<_> = statements
90 .statements
91 .iter()
92 .enumerate()
93 .map(|(i, stmt)| {
94 self.format_datex_expression_with_parent(
95 stmt,
96 Some(ParentContext {
97 precedence: 0,
98 associativity: Assoc::None,
99 operation: Operation::Statements,
100 }),
101 false,
102 ) + (if is_terminated
103 || i < statements.statements.len() - 1
104 {
105 a.text(";")
106 } else {
107 self.alloc.nil()
108 })
109 })
110 .collect();
111
112 let joined = a.intersperse(
113 docs,
114 match self.options.statement_formatting {
115 StatementFormatting::NewlineBetween => a.hardline(),
116 StatementFormatting::SpaceBetween => a.space(),
117 StatementFormatting::Compact => a.nil(),
118 },
119 );
120 joined.group()
121 }
122 DatexExpressionData::VariableDeclaration(VariableDeclaration {
123 id: _,
124 init_expression,
125 kind,
126 name,
127 type_annotation,
128 }) => {
129 let type_annotation_doc =
130 if let Some(type_annotation) = type_annotation {
131 self.type_declaration_colon()
132 + self.format_type_expression(type_annotation)
133 } else {
134 a.nil()
135 };
136 a.text(kind.to_string())
137 + a.space()
138 + a.text(name)
139 + type_annotation_doc
140 + self.operator_with_spaces(a.text("="))
141 + self.format_datex_expression(init_expression)
142 }
143 DatexExpressionData::TypeExpression(type_expr) => {
144 let a = &self.alloc;
145 let inner = self.format_type_expression(type_expr);
146 (a.text("type<") + a.line_() + inner + a.line_() + a.text(">"))
147 .group()
148 }
149 DatexExpressionData::VariableAccess(VariableAccess {
150 name,
151 ..
152 }) => a.text(name),
153 e => core::panic!("Formatter not implemented for {:?}", e),
154 }
155 }
156
157 fn typed_integer_to_source_code(
159 &'a self,
160 ti: &'a TypedInteger,
161 span: &'a Range<usize>,
162 ) -> Format<'a> {
163 let a = &self.alloc;
164 match self.options.variant_formatting {
165 VariantFormatting::KeepAll => a.text(self.tokens_at(span)),
166 VariantFormatting::WithSuffix => a.text(ti.to_string_with_suffix()),
167 VariantFormatting::WithoutSuffix => a.text(ti.to_string()),
168 }
169 }
170
171 fn typed_decimal_to_source_code(
173 &'a self,
174 td: &'a TypedDecimal,
175 span: &'a Range<usize>,
176 ) -> Format<'a> {
177 let a = &self.alloc;
178 match self.options.variant_formatting {
179 VariantFormatting::KeepAll => a.text(self.tokens_at(span)),
180 VariantFormatting::WithSuffix => a.text(td.to_string_with_suffix()),
181 VariantFormatting::WithoutSuffix => a.text(td.to_string()),
182 }
183 }
184
185 fn list_to_source_code(&'a self, elements: &'a List) -> Format<'a> {
187 self.wrap_collection(
188 elements
189 .items
190 .iter()
191 .map(|e| self.format_datex_expression(e)),
192 ("[", "]"),
193 ",",
194 )
195 }
196
197 fn text_to_source_code(&'a self, s: &'a str) -> Format<'a> {
199 self.alloc.text(format!("{:?}", s)) }
201
202 fn map_to_source_code(&'a self, map: &'a Map) -> Format<'a> {
204 let a = &self.alloc;
205 let entries = map.entries.iter().map(|(key, value)| {
206 self.format_datex_expression(key)
207 + a.text(":")
208 + (self.options.space_in_collection.then(|| a.space()))
209 + self.format_datex_expression(value)
210 });
211 self.wrap_collection(entries, ("{", "}"), ",")
212 }
213}