1use crate::api::types::LemmaType;
4use crate::api::value::RuleResultValue;
5use crate::literals::Value;
6use crate::parsing::ast::{
7 ArithmeticComputation, CalendarPeriodUnit, ComparisonComputation, DateCalendarKind,
8 DateRelativeKind, DateTimeValue, MathematicalComputation, PrimitiveKind,
9};
10use crate::parsing::source::SourceType;
11use crate::planning::execution_plan::{
12 Show as DomainShow, ShowBranch as DomainShowBranch,
13 ShowConversionTarget as DomainConversionTarget, ShowData as DomainShowData,
14 ShowExpression as DomainShowExpression, ShowRule as DomainShowRule,
15 ShowVersion as DomainShowVersion,
16};
17use crate::planning::semantics::PathSegment as DomainPathSegment;
18use crate::result_value::type_scoped_result_value_from_literal;
19use indexmap::IndexMap;
20use serde::{Deserialize, Serialize};
21
22#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
24pub struct PathSegment {
25 pub uses: String,
26 #[serde(skip_serializing_if = "Option::is_none", default)]
27 pub repository: Option<String>,
28 pub spec: String,
29}
30
31impl From<&DomainPathSegment> for PathSegment {
32 fn from(segment: &DomainPathSegment) -> Self {
33 Self {
34 uses: segment.uses.clone(),
35 repository: segment.repository.clone(),
36 spec: segment.spec.clone(),
37 }
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
42pub struct ShowData {
43 #[serde(rename = "type")]
44 pub lemma_type: LemmaType,
45 pub path: Vec<PathSegment>,
46 #[serde(skip_serializing_if = "Option::is_none", default)]
47 pub fill: Option<RuleResultValue>,
48 #[serde(skip_serializing_if = "Option::is_none", default)]
49 pub suggestion: Option<RuleResultValue>,
50 pub needed_by_rules: Vec<String>,
51}
52
53impl From<&DomainShowData> for ShowData {
54 fn from(data: &DomainShowData) -> Self {
55 Self {
56 lemma_type: LemmaType::from(&data.lemma_type),
57 path: data.path.iter().map(PathSegment::from).collect(),
58 fill: data.fill.as_ref().map(RuleResultValue::from),
59 suggestion: data.suggestion.as_ref().map(RuleResultValue::from),
60 needed_by_rules: data.needed_by_rules.clone(),
61 }
62 }
63}
64
65#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
66pub struct ShowVersion {
67 #[serde(skip_serializing_if = "Option::is_none", default)]
68 pub effective_from: Option<DateTimeValue>,
69 #[serde(skip_serializing_if = "Option::is_none", default)]
70 pub effective_to: Option<DateTimeValue>,
71}
72
73impl From<&DomainShowVersion> for ShowVersion {
74 fn from(version: &DomainShowVersion) -> Self {
75 Self {
76 effective_from: version.effective_from.clone(),
77 effective_to: version.effective_to.clone(),
78 }
79 }
80}
81
82#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
83#[serde(rename_all = "snake_case")]
84pub enum ShowConversionTarget {
85 Type(PrimitiveKind),
86 Unit { unit_name: String },
87}
88
89impl From<&DomainConversionTarget> for ShowConversionTarget {
90 fn from(target: &DomainConversionTarget) -> Self {
91 match target {
92 DomainConversionTarget::Type(kind) => Self::Type(*kind),
93 DomainConversionTarget::Unit { unit_name } => Self::Unit {
94 unit_name: unit_name.clone(),
95 },
96 }
97 }
98}
99
100#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
102#[serde(tag = "type", rename_all = "snake_case")]
103pub enum ShowExpression {
104 Literal {
105 #[serde(flatten)]
106 value: Box<RuleResultValue>,
107 },
108 Data {
109 name: String,
110 },
111 Rule {
112 name: String,
113 },
114 And {
115 left: Box<ShowExpression>,
116 right: Box<ShowExpression>,
117 },
118 Not {
119 operand: Box<ShowExpression>,
120 },
121 Arithmetic {
122 op: ArithmeticComputation,
123 left: Box<ShowExpression>,
124 right: Box<ShowExpression>,
125 },
126 Comparison {
127 op: ComparisonComputation,
128 left: Box<ShowExpression>,
129 right: Box<ShowExpression>,
130 },
131 UnitConversion {
132 operand: Box<ShowExpression>,
133 target: ShowConversionTarget,
134 },
135 Math {
136 op: MathematicalComputation,
137 operand: Box<ShowExpression>,
138 },
139 Veto {
140 #[serde(skip_serializing_if = "Option::is_none", default)]
141 message: Option<String>,
142 },
143 Now,
144 DateRelative {
145 kind: DateRelativeKind,
146 operand: Box<ShowExpression>,
147 },
148 DateCalendar {
149 kind: DateCalendarKind,
150 unit: CalendarPeriodUnit,
151 operand: Box<ShowExpression>,
152 },
153 RangeLiteral {
154 from: Box<ShowExpression>,
155 to: Box<ShowExpression>,
156 },
157 PastFutureRange {
158 kind: DateRelativeKind,
159 operand: Box<ShowExpression>,
160 },
161 RangeContainment {
162 value: Box<ShowExpression>,
163 range: Box<ShowExpression>,
164 },
165 IsVeto {
166 operand: Box<ShowExpression>,
167 },
168}
169
170impl From<&DomainShowExpression> for ShowExpression {
171 fn from(expression: &DomainShowExpression) -> Self {
172 match expression {
173 DomainShowExpression::Literal(typed) => {
174 let domain_value = type_scoped_result_value_from_literal(
175 &typed.to_literal(),
176 typed.lemma_type.as_ref(),
177 )
178 .unwrap_or_else(|failure| {
179 panic!(
180 "BUG: show branch literal failed type_scoped_result_value_from_literal: {}",
181 crate::result_value::rule_result_value_failure_message(failure)
182 )
183 });
184 Self::Literal {
185 value: Box::new(RuleResultValue::from(&domain_value)),
186 }
187 }
188 DomainShowExpression::Data { name } => Self::Data { name: name.clone() },
189 DomainShowExpression::Rule { name } => Self::Rule { name: name.clone() },
190 DomainShowExpression::And { left, right } => Self::And {
191 left: Box::new(ShowExpression::from(left.as_ref())),
192 right: Box::new(ShowExpression::from(right.as_ref())),
193 },
194 DomainShowExpression::Not { operand } => Self::Not {
195 operand: Box::new(ShowExpression::from(operand.as_ref())),
196 },
197 DomainShowExpression::Arithmetic { op, left, right } => Self::Arithmetic {
198 op: op.clone(),
199 left: Box::new(ShowExpression::from(left.as_ref())),
200 right: Box::new(ShowExpression::from(right.as_ref())),
201 },
202 DomainShowExpression::Comparison { op, left, right } => Self::Comparison {
203 op: op.clone(),
204 left: Box::new(ShowExpression::from(left.as_ref())),
205 right: Box::new(ShowExpression::from(right.as_ref())),
206 },
207 DomainShowExpression::UnitConversion { operand, target } => Self::UnitConversion {
208 operand: Box::new(ShowExpression::from(operand.as_ref())),
209 target: ShowConversionTarget::from(target),
210 },
211 DomainShowExpression::Math { op, operand } => Self::Math {
212 op: op.clone(),
213 operand: Box::new(ShowExpression::from(operand.as_ref())),
214 },
215 DomainShowExpression::Veto { message } => Self::Veto {
216 message: message.clone(),
217 },
218 DomainShowExpression::Now => Self::Now,
219 DomainShowExpression::DateRelative { kind, operand } => Self::DateRelative {
220 kind: *kind,
221 operand: Box::new(ShowExpression::from(operand.as_ref())),
222 },
223 DomainShowExpression::DateCalendar {
224 kind,
225 unit,
226 operand,
227 } => Self::DateCalendar {
228 kind: *kind,
229 unit: *unit,
230 operand: Box::new(ShowExpression::from(operand.as_ref())),
231 },
232 DomainShowExpression::RangeLiteral { from, to } => Self::RangeLiteral {
233 from: Box::new(ShowExpression::from(from.as_ref())),
234 to: Box::new(ShowExpression::from(to.as_ref())),
235 },
236 DomainShowExpression::PastFutureRange { kind, operand } => Self::PastFutureRange {
237 kind: *kind,
238 operand: Box::new(ShowExpression::from(operand.as_ref())),
239 },
240 DomainShowExpression::RangeContainment { value, range } => Self::RangeContainment {
241 value: Box::new(ShowExpression::from(value.as_ref())),
242 range: Box::new(ShowExpression::from(range.as_ref())),
243 },
244 DomainShowExpression::IsVeto { operand } => Self::IsVeto {
245 operand: Box::new(ShowExpression::from(operand.as_ref())),
246 },
247 }
248 }
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
252pub struct ShowBranch {
253 #[serde(skip_serializing_if = "Option::is_none", default)]
254 pub condition: Option<ShowExpression>,
255 pub result: ShowExpression,
256}
257
258impl From<&DomainShowBranch> for ShowBranch {
259 fn from(branch: &DomainShowBranch) -> Self {
260 Self {
261 condition: branch.condition.as_ref().map(ShowExpression::from),
262 result: ShowExpression::from(&branch.result),
263 }
264 }
265}
266
267#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
268pub struct ShowRule {
269 #[serde(rename = "type")]
270 pub lemma_type: LemmaType,
271 pub path: Vec<PathSegment>,
272 pub branches: Vec<ShowBranch>,
273 pub depends_on_rules: Vec<String>,
274}
275
276impl From<&DomainShowRule> for ShowRule {
277 fn from(rule: &DomainShowRule) -> Self {
278 Self {
279 lemma_type: LemmaType::from(&rule.lemma_type),
280 path: rule.path.iter().map(PathSegment::from).collect(),
281 branches: rule.branches.iter().map(ShowBranch::from).collect(),
282 depends_on_rules: rule.depends_on_rules.clone(),
283 }
284 }
285}
286
287#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
288pub struct Show {
289 #[serde(skip_serializing_if = "Option::is_none", default)]
290 pub repository: Option<String>,
291 pub spec: String,
292 #[serde(skip_serializing_if = "Option::is_none", default)]
293 pub commentary: Option<String>,
294 #[serde(skip_serializing_if = "Option::is_none", default)]
295 pub effective_from: Option<DateTimeValue>,
296 #[serde(skip_serializing_if = "Option::is_none", default)]
297 pub effective_to: Option<DateTimeValue>,
298 #[serde(skip_serializing_if = "Vec::is_empty", default)]
299 pub versions: Vec<ShowVersion>,
300 pub start_line: usize,
301 #[serde(skip_serializing_if = "Option::is_none", default)]
302 pub source_type: Option<SourceType>,
303 pub data: IndexMap<String, ShowData>,
304 pub rules: IndexMap<String, ShowRule>,
305 pub meta: IndexMap<String, Value>,
306}
307
308impl From<&DomainShow> for Show {
309 fn from(show: &DomainShow) -> Self {
310 Self {
311 repository: show.repository.clone(),
312 spec: show.spec.clone(),
313 commentary: show.commentary.clone(),
314 effective_from: show.effective_from.clone(),
315 effective_to: show.effective_to.clone(),
316 versions: show.versions.iter().map(ShowVersion::from).collect(),
317 start_line: show.start_line,
318 source_type: show.source_type.clone(),
319 data: show
320 .data
321 .iter()
322 .map(|(name, data)| (name.clone(), ShowData::from(data)))
323 .collect(),
324 rules: show
325 .rules
326 .iter()
327 .map(|(name, rule)| (name.clone(), ShowRule::from(rule)))
328 .collect(),
329 meta: show.meta.clone(),
330 }
331 }
332}