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, RangeBound,
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 RangeBound {
166 bound: RangeBound,
167 operand: Box<ShowExpression>,
168 },
169 IsVeto {
170 operand: Box<ShowExpression>,
171 },
172 SpecMember {
173 base: String,
174 member: String,
175 },
176}
177
178impl From<&DomainShowExpression> for ShowExpression {
179 fn from(expression: &DomainShowExpression) -> Self {
180 match expression {
181 DomainShowExpression::Literal(typed) => {
182 let domain_value = type_scoped_result_value_from_literal(
183 &typed.to_literal(),
184 typed.lemma_type.as_ref(),
185 )
186 .unwrap_or_else(|failure| {
187 panic!(
188 "BUG: show branch literal failed type_scoped_result_value_from_literal: {}",
189 crate::result_value::rule_result_value_failure_message(failure)
190 )
191 });
192 Self::Literal {
193 value: Box::new(RuleResultValue::from(&domain_value)),
194 }
195 }
196 DomainShowExpression::Data { name } => Self::Data { name: name.clone() },
197 DomainShowExpression::Rule { name } => Self::Rule { name: name.clone() },
198 DomainShowExpression::And { left, right } => Self::And {
199 left: Box::new(ShowExpression::from(left.as_ref())),
200 right: Box::new(ShowExpression::from(right.as_ref())),
201 },
202 DomainShowExpression::Not { operand } => Self::Not {
203 operand: Box::new(ShowExpression::from(operand.as_ref())),
204 },
205 DomainShowExpression::Arithmetic { op, left, right } => Self::Arithmetic {
206 op: op.clone(),
207 left: Box::new(ShowExpression::from(left.as_ref())),
208 right: Box::new(ShowExpression::from(right.as_ref())),
209 },
210 DomainShowExpression::Comparison { op, left, right } => Self::Comparison {
211 op: op.clone(),
212 left: Box::new(ShowExpression::from(left.as_ref())),
213 right: Box::new(ShowExpression::from(right.as_ref())),
214 },
215 DomainShowExpression::UnitConversion { operand, target } => Self::UnitConversion {
216 operand: Box::new(ShowExpression::from(operand.as_ref())),
217 target: ShowConversionTarget::from(target),
218 },
219 DomainShowExpression::Math { op, operand } => Self::Math {
220 op: op.clone(),
221 operand: Box::new(ShowExpression::from(operand.as_ref())),
222 },
223 DomainShowExpression::Veto { message } => Self::Veto {
224 message: message.clone(),
225 },
226 DomainShowExpression::Now => Self::Now,
227 DomainShowExpression::DateRelative { kind, operand } => Self::DateRelative {
228 kind: *kind,
229 operand: Box::new(ShowExpression::from(operand.as_ref())),
230 },
231 DomainShowExpression::DateCalendar {
232 kind,
233 unit,
234 operand,
235 } => Self::DateCalendar {
236 kind: *kind,
237 unit: *unit,
238 operand: Box::new(ShowExpression::from(operand.as_ref())),
239 },
240 DomainShowExpression::RangeLiteral { from, to } => Self::RangeLiteral {
241 from: Box::new(ShowExpression::from(from.as_ref())),
242 to: Box::new(ShowExpression::from(to.as_ref())),
243 },
244 DomainShowExpression::PastFutureRange { kind, operand } => Self::PastFutureRange {
245 kind: *kind,
246 operand: Box::new(ShowExpression::from(operand.as_ref())),
247 },
248 DomainShowExpression::RangeContainment { value, range } => Self::RangeContainment {
249 value: Box::new(ShowExpression::from(value.as_ref())),
250 range: Box::new(ShowExpression::from(range.as_ref())),
251 },
252 DomainShowExpression::RangeBound { bound, operand } => Self::RangeBound {
253 bound: *bound,
254 operand: Box::new(ShowExpression::from(operand.as_ref())),
255 },
256 DomainShowExpression::IsVeto { operand } => Self::IsVeto {
257 operand: Box::new(ShowExpression::from(operand.as_ref())),
258 },
259 DomainShowExpression::SpecMember { base, member } => Self::SpecMember {
260 base: base.clone(),
261 member: member.clone(),
262 },
263 }
264 }
265}
266
267#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
268pub struct ShowBranch {
269 #[serde(skip_serializing_if = "Option::is_none", default)]
270 pub condition: Option<ShowExpression>,
271 pub result: ShowExpression,
272}
273
274impl From<&DomainShowBranch> for ShowBranch {
275 fn from(branch: &DomainShowBranch) -> Self {
276 Self {
277 condition: branch.condition.as_ref().map(ShowExpression::from),
278 result: ShowExpression::from(&branch.result),
279 }
280 }
281}
282
283#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
284pub struct ShowRule {
285 #[serde(rename = "type")]
286 pub lemma_type: LemmaType,
287 pub path: Vec<PathSegment>,
288 pub branches: Vec<ShowBranch>,
289 pub depends_on_rules: Vec<String>,
290}
291
292impl From<&DomainShowRule> for ShowRule {
293 fn from(rule: &DomainShowRule) -> Self {
294 Self {
295 lemma_type: LemmaType::from(&rule.lemma_type),
296 path: rule.path.iter().map(PathSegment::from).collect(),
297 branches: rule.branches.iter().map(ShowBranch::from).collect(),
298 depends_on_rules: rule.depends_on_rules.clone(),
299 }
300 }
301}
302
303#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
304pub struct Show {
305 #[serde(skip_serializing_if = "Option::is_none", default)]
306 pub repository: Option<String>,
307 pub spec: String,
308 #[serde(skip_serializing_if = "Option::is_none", default)]
309 pub commentary: Option<String>,
310 #[serde(skip_serializing_if = "Option::is_none", default)]
311 pub effective_from: Option<DateTimeValue>,
312 #[serde(skip_serializing_if = "Option::is_none", default)]
313 pub effective_to: Option<DateTimeValue>,
314 #[serde(skip_serializing_if = "Vec::is_empty", default)]
315 pub versions: Vec<ShowVersion>,
316 pub start_line: usize,
317 #[serde(skip_serializing_if = "Option::is_none", default)]
318 pub source_type: Option<SourceType>,
319 pub data: IndexMap<String, ShowData>,
320 pub rules: IndexMap<String, ShowRule>,
321 pub meta: IndexMap<String, Value>,
322}
323
324impl From<&DomainShow> for Show {
325 fn from(show: &DomainShow) -> Self {
326 Self {
327 repository: show.repository.clone(),
328 spec: show.spec.clone(),
329 commentary: show.commentary.clone(),
330 effective_from: show.effective_from.clone(),
331 effective_to: show.effective_to.clone(),
332 versions: show.versions.iter().map(ShowVersion::from).collect(),
333 start_line: show.start_line,
334 source_type: show.source_type.clone(),
335 data: show
336 .data
337 .iter()
338 .map(|(name, data)| (name.clone(), ShowData::from(data)))
339 .collect(),
340 rules: show
341 .rules
342 .iter()
343 .map(|(name, rule)| (name.clone(), ShowRule::from(rule)))
344 .collect(),
345 meta: show.meta.clone(),
346 }
347 }
348}