1use std::{
2 fmt,
3 sync::Arc,
4};
5
6use crate::{
8 aim::{Row, Rule, Writer, WriterLike}, expressions::{Expression, ExpressionLike}, values::Value
9};
10
11
12#[derive(Debug, Clone, PartialEq)]
13pub enum Cell {
14 Empty,
16 Comment{comment: Arc<str>},
17 Errata{identifier: Arc<str>, typedef: Arc<str>, reason: Arc<str>, formula: Arc<str>, location: Arc<str>},
18
19 Node{identifier: Arc<str>, value: Arc<str>},
21 Format{identifier: Arc<str>, instruction: Arc<str>, template: Arc<str>, examples: Arc<Vec<Arc<str>>>},
22 Branch{identifier: Arc<str>, condition: Arc<str>, target: Arc<str>},
23 Retry{identifier: Arc<str>, count: u32, condition: Arc<str>, target: Arc<str>},
24 Formula{identifier: Arc<str>, typedef: Arc<str>, formula: Arc<str>, value: Arc<str>},
25
26 Result{identifier: Arc<str>, typedef: Arc<str>, value: Arc<str>},
28
29 }
32
33impl Cell {
34
35 #[doc = include_str!("../docs/cell/new.md")]
37 pub fn new(identifier: &str, typedef: &str, formula: &str, value: &str) -> Self {
38 Cell::Formula {
39 identifier: Arc::from(identifier),
40 typedef: Arc::from(typedef),
41 formula: Arc::from(formula),
42 value: Arc::from(value)
43 }
44 }
45
46 #[doc = include_str!("../docs/cell/convert_row.md")]
48 pub fn convert_row(row: &Row) -> Self {
49 match row {
50 Row::Empty => Cell::Empty,
51 Row::Comment(comment) => Cell::Comment { comment: comment.clone() },
52 Row::Rule(rule) | Row::Touched(rule) => Self::convert_rule(rule),
53 }
54 }
55
56 #[doc = include_str!("../docs/cell/convert_result.md")]
58 pub fn convert_result(row: &Row) -> Self {
59 match row {
60 Row::Empty => Cell::Empty,
61 Row::Comment(comment) => Cell::Comment { comment: comment.clone() },
62 Row::Rule(rule) | Row::Touched(rule) => {
63 if rule.is_error() {
65 let value = rule.value();
66 if value.is_error() && let Value::Errata(errata) = &*value {
67 return Cell::Errata {
68 identifier: rule.identifier(),
69 typedef: Arc::from(rule.typedef().as_str()),
70 reason: errata.reason(),
71 formula: errata.formula(),
72 location: errata.location(),
73 };
74 }
75 }
76 Cell::Result {
78 identifier: rule.identifier(),
79 typedef: Arc::from(rule.typedef().as_str()),
80 value: rule.value().to_arc_str(),
81 }
82 }
83 }
84 }
85
86 #[doc = include_str!("../docs/cell/convert_rule.md")]
88 pub fn convert_rule(rule: &Rule) -> Self {
89 if rule.is_error() {
91 let value = rule.value();
92 if value.is_error() && let Value::Errata(errata) = &*value {
93 return Cell::Errata {
94 identifier: rule.identifier(),
95 typedef: Arc::from(rule.typedef().as_str()),
96 reason: errata.reason(),
97 formula: errata.formula(),
98 location: errata.location(),
99 };
100 }
101 let expression = rule.expression();
102 if expression.is_error() && let Expression::Errata(errata) = expression {
103 return Cell::Errata {
104 identifier: rule.identifier(),
105 typedef: Arc::from(rule.typedef().as_str()),
106 reason: errata.reason(),
107 formula: errata.formula(),
108 location: errata.location(),
109 };
110 }
111 }
112 if rule.is_node() {
114 return Cell::Node {
115 identifier: rule.identifier(),
116 value: rule.value().to_arc_str(),
117 };
118 }
119
120 let typedef = rule.typedef();
121
122 if typedef.is_format() {
124 let value = rule.value();
125 if let Value::Format(format) = &*value {
126 return Cell::Format {
127 identifier: rule.identifier(),
128 instruction: format.instruction(),
129 template: format.template(),
130 examples: format.examples(),
131 };
132 }
133 }
134
135 if typedef.is_branch() {
149 let expression = rule.expression();
150 if let Expression::Branch(branch) = expression {
151 return Cell::Branch {
152 identifier: rule.identifier(),
153 condition: Arc::from(branch.condition().to_formula()),
154 target: branch.target(),
155 };
156 }
157 }
158 if typedef.is_retry() {
160 let expression = rule.expression();
161 if let Expression::Retry(retry) = expression {
162 return Cell::Retry {
163 identifier: rule.identifier(),
164 count: retry.count(),
165 condition: Arc::from(retry.condition().to_formula()),
166 target: retry.target(),
167 };
168 }
169 }
170
171 Cell::Formula {
172 identifier: rule.identifier(),
173 typedef: Arc::from(typedef.as_str()),
174 formula: Arc::from(rule.expression().to_formula()),
175 value: rule.value().to_arc_str(),
176 }
177 }
178
179 #[doc = include_str!("../docs/cell/is_empty.md")]
181 pub fn is_empty(&self) -> bool {
182 matches!(self, Cell::Empty)
183 }
184
185 #[doc = include_str!("../docs/cell/is_comment.md")]
187 pub fn is_comment(&self) -> bool {
188 matches!(self, Cell::Comment{..})
189 }
190
191 #[doc = include_str!("../docs/cell/is_error.md")]
193 pub fn is_error(&self) -> bool {
194 matches!(self, Cell::Errata{..})
195 }
196
197 #[doc = include_str!("../docs/cell/is_node.md")]
199 pub fn is_node(&self) -> bool {
200 matches!(self, Cell::Node{..})
201 }
202
203 #[doc = include_str!("../docs/cell/is_format.md")]
205 pub fn is_format(&self) -> bool {
206 matches!(self, Cell::Format{..})
207 }
208
209 #[doc = include_str!("../docs/cell/is_branch.md")]
211 pub fn is_branch(&self) -> bool {
212 matches!(self, Cell::Branch{..})
213 }
214
215 #[doc = include_str!("../docs/cell/is_retry.md")]
217 pub fn is_retry(&self) -> bool {
218 matches!(self, Cell::Retry{..})
219 }
220
221 #[doc = include_str!("../docs/cell/is_formula.md")]
223 pub fn is_formula(&self) -> bool {
224 matches!(self, Cell::Formula{..})
225 }
226
227 #[doc = include_str!("../docs/cell/is_result.md")]
229 pub fn is_result(&self) -> bool {
230 matches!(self, Cell::Result{..})
231 }
232
233 #[doc = include_str!("../docs/cell/comment.md")]
235 pub fn comment(&self) -> Option<Arc<str>> {
236 match self {
237 Cell::Comment { comment } => Some(comment.clone()),
238 _ => None,
239 }
240 }
241
242 #[doc = include_str!("../docs/cell/identifier.md")]
244 pub fn identifier(&self) -> Option<Arc<str>> {
245 match self {
246 Cell::Errata { identifier, typedef: _, reason: _, formula: _, location: _ }
247 | Cell::Node { identifier, value: _ }
248 | Cell::Format { identifier, instruction: _, template: _, examples: _ }
249 | Cell::Branch { identifier, condition: _, target: _ }
250 | Cell::Retry { identifier, count: _, condition: _, target: _ }
251 | Cell::Formula { identifier, typedef: _, formula: _, value: _ }
252 | Cell::Result { identifier, typedef: _, value: _ } => Some(identifier.clone()),
253 _ => None,
254 }
255 }
256
257 #[doc = include_str!("../docs/cell/typedef.md")]
259 pub fn typedef(&self) -> Option<Arc<str>> {
260 match self {
261 Cell::Errata { identifier: _, typedef, reason: _, formula: _, location: _ }
262 | Cell::Formula { identifier: _, typedef, formula: _, value: _ }
263 | Cell::Result { identifier: _, typedef, value: _ } => Some(typedef.clone()),
264 Cell::Node { .. } => Some(Arc::from("Node")),
265 Cell::Format { .. } => Some(Arc::from("Format")),
266 Cell::Branch { .. } => Some(Arc::from("Branch")),
267 Cell::Retry { .. } => Some(Arc::from("Retry")),
268 _ => None,
269 }
270
271 }
272
273 #[doc = include_str!("../docs/cell/reason.md")]
275 pub fn reason(&self) -> Option<Arc<str>> {
276 match self {
277 Cell::Errata { identifier: _, typedef: _, reason, formula: _, location: _ } => Some(reason.clone()),
278 _ => None,
279 }
280 }
281
282 #[doc = include_str!("../docs/cell/formula.md")]
284 pub fn formula(&self) -> Option<Arc<str>> {
285 match self {
286 Cell::Errata { identifier: _, typedef: _, reason: _, formula, location: _ }
287 | Cell::Formula { identifier: _, typedef: _, formula, value: _ } => Some(formula.clone()),
288 _ => None,
289 }
290 }
291
292 #[doc = include_str!("../docs/cell/location.md")]
294 pub fn location(&self) -> Option<Arc<str>> {
295 match self {
296 Cell::Errata { identifier: _, typedef: _, reason: _, formula: _, location } => {
297 if location.is_empty() {
298 None
299 } else {
300 Some(location.clone())
301 }
302 }
303 _ => None,
304 }
305 }
306
307 #[doc = include_str!("../docs/cell/value.md")]
309 pub fn value(&self) -> Option<Arc<str>> {
310 match self {
311 Cell::Node { identifier: _, value }
312 | Cell::Formula { identifier: _, typedef: _, formula: _, value }
313 | Cell::Result { identifier: _, typedef: _, value } => Some(value.clone()),
314 _ => None,
315 }
316 }
317
318 #[doc = include_str!("../docs/cell/instruction.md")]
320 pub fn instruction(&self) -> Option<Arc<str>> {
321 match self {
322 Cell::Format { identifier: _, instruction, template: _, examples: _ } => Some(instruction.clone()),
323 _ => None,
324 }
325 }
326
327 #[doc = include_str!("../docs/cell/template.md")]
329 pub fn template(&self) -> Option<Arc<str>> {
330 match self {
331 Cell::Format { identifier: _, instruction: _, template, examples: _ } => Some(template.clone()),
332 _ => None,
333 }
334 }
335
336 #[doc = include_str!("../docs/cell/examples.md")]
338 pub fn examples(&self) -> Option<Arc<Vec<Arc<str>>>> {
339 match self {
340 Cell::Format { identifier: _, instruction: _, template: _, examples } => Some(examples.clone()),
341 _ => None,
342 }
343 }
344
345 #[doc = include_str!("../docs/cell/condition.md")]
347 pub fn condition(&self) -> Option<Arc<str>> {
348 match self {
349 Cell::Branch { identifier: _, condition, target: _ }
350 | Cell::Retry { identifier: _, count: _, condition, target: _ } => Some(condition.clone()),
351 _ => None,
352 }
353 }
354
355 #[doc = include_str!("../docs/cell/target.md")]
357 pub fn target(&self) -> Option<Arc<str>> {
358 match self {
359 Cell::Branch { identifier: _, condition: _, target }
360 | Cell::Retry { identifier: _, count: _, condition: _, target } => Some(target.clone()),
361 _ => None,
362 }
363 }
364
365 #[doc = include_str!("../docs/cell/count.md")]
367 pub fn count(&self) -> Option<u32> {
368 match self {
369 Cell::Retry { identifier: _, count, condition: _, target: _ } => Some(*count),
370 _ => None,
371 }
372 }
373
374
375 #[doc = include_str!("../docs/cell/print.md")]
377 pub fn print(&self, writer: &mut Writer) {
378 match self {
379 Cell::Empty => {}
380 Cell::Comment{comment} => {
381 if writer.is_formulizer() {
382 writer.write_str(comment);
383 }
384 }
385 Cell::Errata { identifier, typedef, reason, formula, location } => {
386 writer.write_str(identifier);
387 writer.write_str(": ");
388 writer.write_str(typedef);
389 writer.write_str(" =");
390 if !formula.is_empty() {
391 writer.write_char(' ');
392 writer.write_str(formula);
393 }
394 writer.write_str(" # ");
395 writer.write_str(reason);
396 let _ = location;
397 }
398 Cell::Result { identifier, typedef, value } => {
399 writer.write_str(identifier);
400 writer.write_str(": ");
401 writer.write_str(typedef);
402 writer.write_str(" =");
403 if !value.is_empty() {
404 writer.write_str(" $");
405 writer.print(value);
406 }
407 }
408 Cell::Node { identifier, value} => {
409 writer.write_str(identifier);
410 writer.write_str(": Node =");
411 if !value.is_empty() {
412 writer.write_str(" $");
413 writer.print(value);
414 }
415 }
416 Cell::Format { identifier, instruction, template, examples } => {
417 writer.write_str(identifier);
418 writer.write_str(": Format = ");
419 writer.print(instruction);
420 writer.write_str(" <");
421 writer.print(template);
422 writer.write_str("> ");
423 for (index, example) in examples.iter().enumerate() {
424 if index > 0 {
425 writer.write_str(", ");
426 }
427 writer.print(example);
428 }
429 }
430 Cell::Branch { identifier, condition, target } => {
431 writer.write_str(identifier);
432 writer.write_str(": Branch = ");
433 writer.print(condition);
434 writer.write_str(" -> ");
435 writer.print(target);
436 }
437 Cell::Retry { identifier, count, condition, target } => {
438 writer.write_str(identifier);
439 writer.write_str(": Retry = ");
440 writer.write_unsigned(*count);
441 writer.write_str(", ");
442 writer.print(condition);
443 writer.write_str(" -> ");
444 writer.print(target);
445
446 }
447 Cell::Formula { identifier, typedef, formula, value} => {
448 writer.write_str(identifier);
449 writer.write_str(": ");
450 writer.write_str(typedef);
451 writer.write_str(" =");
452 if !formula.is_empty() {
453 writer.write_char(' ');
454 writer.write_str(formula);
455 }
456 if !value.is_empty() {
457 writer.write_str(" $");
458 writer.print(value);
459 }
460 }
461 }
462 if writer.is_formulizer() {
463 writer.write_eol();
464 }
465 }
466
467 #[doc = include_str!("../docs/cell/to_formula.md")]
469 pub fn to_formula(&self) -> String {
470 let mut writer = Writer::formulizer();
471 self.print(&mut writer);
472 writer.finish()
473 }
474}
475
476impl WriterLike for Cell {
477 fn write(&self, writer: &mut Writer) {
478 self.print(writer);
479 }
480}
481
482impl fmt::Display for Cell {
483 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484 write!(f, "{}", self.to_stringized())
485 }
486}