1use std::{
2 fmt,
3 sync::Arc,
4};
5use anyhow::Result;
6use crate::{
7 Cell, aim::{ContextLike, Rule, Typedef, Writer, WriterLike}, expressions::{Branch, Expression, ExpressionLike, Retry, parse_coalesce}, values::{Errata, Format, Value}
8};
9
10#[derive(Debug, Clone, PartialEq)]
11pub enum Row {
12 Empty,
13 Comment(Arc<str>),
14 Rule(Arc<Rule>),
15 Touched(Arc<Rule>),
16}
17
18impl Row {
19 pub fn convert(cell: Cell) -> Self {
20 match cell {
21 Cell::Empty => Row::Empty,
23 Cell::Comment{comment} => Row::Comment(comment),
24 Cell::Errata{identifier, typedef, reason, formula, location} => {
25 let errata = if location.len() > 0 {
26 Errata::new_reason_formula_location(reason, formula, location)
27 } else if formula.len() > 0 {
28 Errata::new_reason_formula(reason, formula)
29 } else {
30 Errata::new_reason(reason)
31 };
32 let rule = Rule::new(
33 identifier,
34 Typedef::convert(&typedef),
35 Expression::Empty,
36 Arc::new(errata)
37 );
38 Row::Touched(Arc::new(rule))
39 }
40
41 Cell::Node{identifier, value} => {
43 let rule = Rule::new(
44 identifier,
45 Typedef::Node,
46 Expression::Empty,
47 Value::convert(value),
48 );
49 Row::Touched(Arc::new(rule))
50 }
51 Cell::Format{identifier, instruction, template, examples} => {
52 let format = Format::as_value(instruction, template, examples);
53 let rule = Rule::new(
54 identifier,
55 Typedef::Format,
56 Expression::Empty,
57 Arc::new(format)
58 );
59 Row::Touched(Arc::new(rule))
60 }
61 Cell::Branch{identifier, condition, target} => {
62 let expression = match parse_coalesce(&condition) {
63 Ok((_, coalesce)) => Expression::Branch(Branch::new(coalesce, target)),
64 Err(nom::Err::Incomplete(_)) => {
65 Errata::new_expression(
66 Arc::from("Incomplete Expression"),
67 condition.clone(),
68 )
69 }
70 Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => {
71 Errata::new_expression_location(
72 Arc::from(format!("Syntax Error ({})", e)),
73 condition.clone(),
74 Arc::from(e.input),
75 )
76 }
77 };
78 let rule = Rule::new(
79 identifier,
80 Typedef::Branch,
81 expression,
82 Value::empty()
83 );
84 Row::Touched(Arc::new(rule))
85 }
86 Cell::Retry{identifier, count, condition, target} => {
87 let expression = match parse_coalesce(&condition) {
88 Ok((_, coalesce)) => Expression::Retry(Retry::new(count,coalesce, target)),
89 Err(nom::Err::Incomplete(_)) => {
90 Errata::new_expression(
91 Arc::from("Incomplete Expression"),
92 condition.clone(),
93 )
94 }
95 Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => {
96 Errata::new_expression_location(
97 Arc::from(format!("Syntax Error ({})", e)),
98 condition.clone(),
99 Arc::from(e.input),
100 )
101 }
102 };
103 let rule = Rule::new(
104 identifier,
105 Typedef::Branch,
106 expression,
107 Value::empty()
108 );
109 Row::Touched(Arc::new(rule))
110 }
111 Cell::Formula{identifier, typedef, formula, value} => {
112 let rule = Rule::convert(identifier, typedef, formula, value);
113 Row::Touched(Arc::new(rule))
114 }
115
116 Cell::Result{identifier, typedef, value} => {
118 let rule = Rule::new(
119 identifier,
120 Typedef::convert(&typedef),
121 Expression::Empty,
122 Value::convert(value),
123 );
124 Row::Touched(Arc::new(rule))
125 }
126 }
127 }
128
129 pub fn is_empty(&self) -> bool {
130 match self {
131 Row::Empty => true,
132 _ => false,
133 }
134 }
135 pub fn is_comment(&self) -> bool {
136 match self {
137 Row::Comment(_) => true,
138 _ => false,
139 }
140 }
141 pub fn is_rule(&self) -> bool {
142 match self {
143 Row::Rule(_) | Row::Touched(_) => true,
144 _ => false,
145 }
146 }
147 pub fn is_touched(&self) -> bool {
148 match self {
149 Row::Touched(_) => true,
150 _ => false,
151 }
152 }
153
154 pub fn rule(&self) -> Option<Arc<Rule>> {
155 if let Row::Rule(rule) | Row::Touched(rule) = self {
156 Some(rule.clone())
157 } else {
158 None
159 }
160 }
161
162 pub fn comment(&self) -> Arc<str> {
163 match self {
164 Row::Comment(comment) => comment.clone(),
165 _ => Value::empty_str(),
166 }
167 }
168
169 pub fn identifier(&self) -> Arc<str> {
170 match self {
171 Row::Rule(rule)
172 | Row::Touched(rule) => rule.identifier(),
173 _ => Value::empty_str(),
174 }
175 }
176
177 pub fn typedef(&self) -> Option<&Typedef> {
178 match self {
179 Row::Rule(rule)
180 | Row::Touched(rule) => Some(rule.typedef()),
181 _ => None,
182 }
183 }
184
185 pub fn formula(&self) -> Option<&Expression> {
186 match self {
187 Row::Rule(rule)
188 | Row::Touched(rule) => Some(rule.expression()),
189 _ => None,
190 }
191 }
192
193 pub fn value(&self) -> Arc<Value> {
194 match self {
195 Row::Rule(rule)
196 | Row::Touched(rule) => rule.value().clone(),
197 _ => Value::empty(),
198 }
199 }
200
201 pub fn save(&self, writer: &mut Writer) -> Option<Self> {
206 match self {
207 Row::Empty => {}
208 Row::Comment(comment) => writer.write_str(comment),
209 Row::Rule(rule) => rule.print(writer),
210 Row::Touched(rule) => {
211 rule.print(writer);
212 writer.write_eol();
213 return Some(Row::Rule(rule.clone()));
214 }
215 }
216 writer.write_eol();
217 None
218 }
219
220 pub fn partial_save(&self, index: usize, writer: &mut Writer) -> Option<Self> {
231 if let Row::Touched(rule) = self {
232 writer.write_unsigned(index as u32);
234 writer.write_char(' ');
235 rule.print(writer);
236 writer.write_eol();
237 Some(Row::Rule(rule.clone()))
238 } else {
239 None
240 }
241 }
242
243 pub fn print(&self, writer: &mut Writer) {
244 match self {
245 Row::Rule(rule) | Row::Touched(rule) => rule.print(writer),
246 Row::Comment(comment) => {
247 if writer.is_formulizer() {
248 writer.write_str(comment);
249 }
250 }
251 _ => {}
252 }
253 if writer.is_formulizer() {
254 writer.write_eol();
255 }
256 }
257
258}
259
260impl ExpressionLike for Row {
261 fn evaluate(&self, context: &mut dyn ContextLike) -> Result<Arc<Value>> {
262 match self {
263 Row::Rule(rule) | Row::Touched(rule) => rule.evaluate(context),
264 _ => Ok(Value::empty()),
265 }
266 }
267
268 fn to_formula(&self) -> String {
270 let mut writer = Writer::formulizer();
271 self.print(&mut writer);
272 writer.finish()
273 }
274}
275
276impl WriterLike for Row {
277 fn write(&self, writer: &mut Writer) {
278 self.print(writer);
279 }
280}
281
282impl fmt::Display for Row {
283 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
284 write!(f, "{}", self.to_stringized())
285 }
286}