1use crate::ast::{ExpressionId, Span};
2use rust_decimal::Decimal;
3use serde::Serialize;
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq)]
8pub struct LemmaDoc {
9 pub name: String,
10 pub source: Option<String>,
11 pub start_line: usize,
12 pub commentary: Option<String>,
13 pub facts: Vec<LemmaFact>,
14 pub rules: Vec<LemmaRule>,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub struct LemmaFact {
19 pub fact_type: FactType,
20 pub value: FactValue,
21 pub span: Option<Span>,
22}
23
24#[derive(Debug, Clone, PartialEq)]
25pub enum FactType {
26 Local(String),
27 Foreign(ForeignFact),
28}
29
30#[derive(Debug, Clone, PartialEq)]
32pub struct ForeignFact {
33 pub reference: Vec<String>,
34}
35
36#[derive(Debug, Clone, PartialEq)]
42pub struct UnlessClause {
43 pub condition: Expression,
44 pub result: Expression,
45 pub span: Option<Span>,
46}
47
48#[derive(Debug, Clone, PartialEq)]
50pub struct LemmaRule {
51 pub name: String,
52 pub expression: Expression,
53 pub unless_clauses: Vec<UnlessClause>,
54 pub span: Option<Span>,
55}
56
57#[derive(Debug, Clone, PartialEq)]
59pub struct Expression {
60 pub kind: ExpressionKind,
61 pub span: Option<Span>,
62 pub id: ExpressionId,
63}
64
65impl Expression {
66 pub fn new(kind: ExpressionKind, span: Option<Span>, id: ExpressionId) -> Self {
68 Self { kind, span, id }
69 }
70}
71
72#[derive(Debug, Clone, PartialEq)]
74pub enum ExpressionKind {
75 Literal(LiteralValue),
76 FactReference(FactReference),
77 RuleReference(RuleReference),
78 LogicalAnd(Box<Expression>, Box<Expression>),
79 LogicalOr(Box<Expression>, Box<Expression>),
80 Arithmetic(Box<Expression>, ArithmeticOperation, Box<Expression>),
81 Comparison(Box<Expression>, ComparisonOperator, Box<Expression>),
82 FactHasAnyValue(FactReference),
83 UnitConversion(Box<Expression>, ConversionTarget),
84 LogicalNegation(Box<Expression>, NegationType),
85 MathematicalOperator(MathematicalOperator, Box<Expression>),
86 Veto(VetoExpression),
87}
88
89#[derive(Debug, Clone, PartialEq, Eq, Hash)]
91pub struct FactReference {
92 pub reference: Vec<String>, }
94
95#[derive(Debug, Clone, PartialEq, Eq, Hash)]
101pub struct RuleReference {
102 pub reference: Vec<String>, }
104
105#[derive(Debug, Clone, PartialEq, Eq, Hash)]
107pub enum ArithmeticOperation {
108 Add,
109 Subtract,
110 Multiply,
111 Divide,
112 Modulo,
113 Power,
114}
115
116impl ArithmeticOperation {
117 pub fn name(&self) -> &'static str {
119 match self {
120 ArithmeticOperation::Add => "addition",
121 ArithmeticOperation::Subtract => "subtraction",
122 ArithmeticOperation::Multiply => "multiplication",
123 ArithmeticOperation::Divide => "division",
124 ArithmeticOperation::Modulo => "modulo",
125 ArithmeticOperation::Power => "exponentiation",
126 }
127 }
128}
129
130#[derive(Debug, Clone, PartialEq, Eq, Hash)]
132pub enum ComparisonOperator {
133 GreaterThan,
134 LessThan,
135 GreaterThanOrEqual,
136 LessThanOrEqual,
137 Equal,
138 NotEqual,
139 Is,
140 IsNot,
141}
142
143impl ComparisonOperator {
144 pub fn name(&self) -> &'static str {
146 match self {
147 ComparisonOperator::GreaterThan => "greater than",
148 ComparisonOperator::LessThan => "less than",
149 ComparisonOperator::GreaterThanOrEqual => "greater than or equal",
150 ComparisonOperator::LessThanOrEqual => "less than or equal",
151 ComparisonOperator::Equal => "equal",
152 ComparisonOperator::NotEqual => "not equal",
153 ComparisonOperator::Is => "is",
154 ComparisonOperator::IsNot => "is not",
155 }
156 }
157}
158
159#[derive(Debug, Clone, PartialEq, Eq, Hash)]
161pub enum ConversionTarget {
162 Mass(MassUnit),
163 Length(LengthUnit),
164 Volume(VolumeUnit),
165 Duration(DurationUnit),
166 Temperature(TemperatureUnit),
167 Power(PowerUnit),
168 Force(ForceUnit),
169 Pressure(PressureUnit),
170 Energy(EnergyUnit),
171 Frequency(FrequencyUnit),
172 Data(DataUnit),
173 Money(MoneyUnit),
174 Percentage,
175}
176
177#[derive(Debug, Clone, PartialEq, Eq, Hash)]
179pub enum NegationType {
180 Not, HaveNot, NotHave, }
184
185#[derive(Debug, Clone, PartialEq)]
193pub struct VetoExpression {
194 pub message: Option<String>,
195}
196
197#[derive(Debug, Clone, PartialEq, Eq, Hash)]
199pub enum MathematicalOperator {
200 Sqrt, Sin, Cos, Tan, Asin, Acos, Atan, Log, Exp, }
210
211#[derive(Debug, Clone, PartialEq)]
212pub enum FactValue {
213 Literal(LiteralValue),
214 DocumentReference(String),
215 TypeAnnotation(TypeAnnotation),
216}
217
218#[derive(Debug, Clone, PartialEq)]
219pub enum TypeAnnotation {
220 LemmaType(LemmaType),
221}
222
223#[derive(Debug, Clone, PartialEq, Eq, Hash)]
225pub enum LemmaType {
226 Text,
227 Number,
228 Date,
229 Boolean,
230 Regex,
231 Percentage,
232 Mass,
233 Length,
234 Volume,
235 Duration,
236 Temperature,
237 Power,
238 Energy,
239 Force,
240 Pressure,
241 Frequency,
242 Data,
243 Money,
244}
245
246#[derive(Debug, Clone, PartialEq, Serialize)]
248pub enum LiteralValue {
249 Number(Decimal),
250 Text(String),
251 Date(DateTimeValue), Time(TimeValue), Boolean(bool),
254 Percentage(Decimal),
255 Unit(NumericUnit), Regex(String), }
258
259impl LiteralValue {
260 pub fn display_value(&self) -> String {
262 self.to_string()
263 }
264
265 pub fn to_type(&self) -> LemmaType {
267 match self {
268 LiteralValue::Text(_) => LemmaType::Text,
269 LiteralValue::Number(_) => LemmaType::Number,
270 LiteralValue::Date(_) => LemmaType::Date,
271 LiteralValue::Time(_) => LemmaType::Date,
272 LiteralValue::Boolean(_) => LemmaType::Boolean,
273 LiteralValue::Percentage(_) => LemmaType::Percentage,
274 LiteralValue::Regex(_) => LemmaType::Regex,
275 LiteralValue::Unit(unit) => match unit {
276 NumericUnit::Mass(_, _) => LemmaType::Mass,
277 NumericUnit::Length(_, _) => LemmaType::Length,
278 NumericUnit::Volume(_, _) => LemmaType::Volume,
279 NumericUnit::Duration(_, _) => LemmaType::Duration,
280 NumericUnit::Temperature(_, _) => LemmaType::Temperature,
281 NumericUnit::Power(_, _) => LemmaType::Power,
282 NumericUnit::Force(_, _) => LemmaType::Force,
283 NumericUnit::Pressure(_, _) => LemmaType::Pressure,
284 NumericUnit::Energy(_, _) => LemmaType::Energy,
285 NumericUnit::Frequency(_, _) => LemmaType::Frequency,
286 NumericUnit::Data(_, _) => LemmaType::Data,
287 NumericUnit::Money(_, _) => LemmaType::Money,
288 },
289 }
290 }
291}
292
293#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
295pub struct TimeValue {
296 pub hour: u8,
297 pub minute: u8,
298 pub second: u8,
299 pub timezone: Option<TimezoneValue>,
300}
301
302#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
304pub struct TimezoneValue {
305 pub offset_hours: i8,
306 pub offset_minutes: u8,
307}
308
309#[derive(Debug, Clone, PartialEq, Serialize)]
311pub struct DateTimeValue {
312 pub year: i32,
313 pub month: u32,
314 pub day: u32,
315 pub hour: u32,
316 pub minute: u32,
317 pub second: u32,
318 pub timezone: Option<TimezoneValue>,
319}
320
321macro_rules! impl_unit_serialize {
323 ($($unit_type:ty),+) => {
324 $(
325 impl Serialize for $unit_type {
326 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
327 where
328 S: serde::Serializer,
329 {
330 serializer.serialize_str(&self.to_string())
331 }
332 }
333 )+
334 };
335}
336
337impl_unit_serialize!(
338 MassUnit,
339 LengthUnit,
340 VolumeUnit,
341 DurationUnit,
342 TemperatureUnit,
343 PowerUnit,
344 ForceUnit,
345 PressureUnit,
346 EnergyUnit,
347 FrequencyUnit,
348 DataUnit,
349 MoneyUnit
350);
351
352#[derive(Debug, Clone, PartialEq, Eq, Hash)]
353pub enum MassUnit {
354 Kilogram,
355 Gram,
356 Milligram,
357 Ton,
358 Pound,
359 Ounce,
360}
361
362#[derive(Debug, Clone, PartialEq, Eq, Hash)]
363pub enum LengthUnit {
364 Kilometer,
365 Mile,
366 NauticalMile,
367 Meter,
368 Decimeter,
369 Centimeter,
370 Millimeter,
371 Yard,
372 Foot,
373 Inch,
374}
375
376#[derive(Debug, Clone, PartialEq, Eq, Hash)]
377pub enum VolumeUnit {
378 CubicMeter,
379 CubicCentimeter,
380 Liter,
381 Deciliter,
382 Centiliter,
383 Milliliter,
384 Gallon,
385 Quart,
386 Pint,
387 FluidOunce,
388}
389
390#[derive(Debug, Clone, PartialEq, Eq, Hash)]
391pub enum DurationUnit {
392 Year,
393 Month,
394 Week,
395 Day,
396 Hour,
397 Minute,
398 Second,
399 Millisecond,
400 Microsecond,
401}
402
403#[derive(Debug, Clone, PartialEq, Eq, Hash)]
404pub enum TemperatureUnit {
405 Celsius,
406 Fahrenheit,
407 Kelvin,
408}
409
410#[derive(Debug, Clone, PartialEq, Eq, Hash)]
411pub enum PowerUnit {
412 Megawatt,
413 Kilowatt,
414 Watt,
415 Milliwatt,
416 Horsepower,
417}
418
419#[derive(Debug, Clone, PartialEq, Eq, Hash)]
420pub enum ForceUnit {
421 Newton,
422 Kilonewton,
423 Lbf,
424}
425
426#[derive(Debug, Clone, PartialEq, Eq, Hash)]
427pub enum PressureUnit {
428 Megapascal,
429 Kilopascal,
430 Pascal,
431 Atmosphere,
432 Bar,
433 Psi,
434 Torr,
435 Mmhg,
436}
437
438#[derive(Debug, Clone, PartialEq, Eq, Hash)]
439pub enum EnergyUnit {
440 Megajoule,
441 Kilojoule,
442 Joule,
443 Kilowatthour,
444 Watthour,
445 Kilocalorie,
446 Calorie,
447 Btu,
448}
449
450#[derive(Debug, Clone, PartialEq, Eq, Hash)]
451pub enum FrequencyUnit {
452 Hertz,
453 Kilohertz,
454 Megahertz,
455 Gigahertz,
456}
457
458#[derive(Debug, Clone, PartialEq, Eq, Hash)]
459pub enum DataUnit {
460 Petabyte,
461 Terabyte,
462 Gigabyte,
463 Megabyte,
464 Kilobyte,
465 Byte,
466 Tebibyte,
467 Gibibyte,
468 Mebibyte,
469 Kibibyte,
470}
471
472#[derive(Debug, Clone, PartialEq, Eq, Hash)]
473pub enum MoneyUnit {
474 Eur,
475 Usd,
476 Gbp,
477 Jpy,
478 Cny,
479 Chf,
480 Cad,
481 Aud,
482 Inr,
483}
484
485#[derive(Debug, Clone, PartialEq, Serialize)]
492pub enum NumericUnit {
493 Mass(Decimal, MassUnit),
494 Length(Decimal, LengthUnit),
495 Volume(Decimal, VolumeUnit),
496 Duration(Decimal, DurationUnit),
497 Temperature(Decimal, TemperatureUnit),
498 Power(Decimal, PowerUnit),
499 Force(Decimal, ForceUnit),
500 Pressure(Decimal, PressureUnit),
501 Energy(Decimal, EnergyUnit),
502 Frequency(Decimal, FrequencyUnit),
503 Data(Decimal, DataUnit),
504 Money(Decimal, MoneyUnit),
505}
506
507impl NumericUnit {
508 pub fn value(&self) -> Decimal {
510 match self {
511 NumericUnit::Mass(v, _)
512 | NumericUnit::Length(v, _)
513 | NumericUnit::Volume(v, _)
514 | NumericUnit::Duration(v, _)
515 | NumericUnit::Temperature(v, _)
516 | NumericUnit::Power(v, _)
517 | NumericUnit::Force(v, _)
518 | NumericUnit::Pressure(v, _)
519 | NumericUnit::Energy(v, _)
520 | NumericUnit::Frequency(v, _)
521 | NumericUnit::Data(v, _)
522 | NumericUnit::Money(v, _) => *v,
523 }
524 }
525
526 pub fn same_category(&self, other: &NumericUnit) -> bool {
528 std::mem::discriminant(self) == std::mem::discriminant(other)
529 }
530
531 pub fn with_value(&self, new_value: Decimal) -> NumericUnit {
534 match self {
535 NumericUnit::Mass(_, u) => NumericUnit::Mass(new_value, u.clone()),
536 NumericUnit::Length(_, u) => NumericUnit::Length(new_value, u.clone()),
537 NumericUnit::Volume(_, u) => NumericUnit::Volume(new_value, u.clone()),
538 NumericUnit::Duration(_, u) => NumericUnit::Duration(new_value, u.clone()),
539 NumericUnit::Temperature(_, u) => NumericUnit::Temperature(new_value, u.clone()),
540 NumericUnit::Power(_, u) => NumericUnit::Power(new_value, u.clone()),
541 NumericUnit::Force(_, u) => NumericUnit::Force(new_value, u.clone()),
542 NumericUnit::Pressure(_, u) => NumericUnit::Pressure(new_value, u.clone()),
543 NumericUnit::Energy(_, u) => NumericUnit::Energy(new_value, u.clone()),
544 NumericUnit::Frequency(_, u) => NumericUnit::Frequency(new_value, u.clone()),
545 NumericUnit::Data(_, u) => NumericUnit::Data(new_value, u.clone()),
546 NumericUnit::Money(_, u) => NumericUnit::Money(new_value, u.clone()),
547 }
548 }
549
550 pub fn validate_same_currency(&self, other: &NumericUnit) -> Result<(), crate::LemmaError> {
553 if let (NumericUnit::Money(_, l_curr), NumericUnit::Money(_, r_curr)) = (self, other) {
554 if l_curr != r_curr {
555 return Err(crate::LemmaError::Engine(format!(
556 "Cannot operate on different currencies: {:?} and {:?}",
557 l_curr, r_curr
558 )));
559 }
560 }
561 Ok(())
562 }
563}
564
565impl fmt::Display for NumericUnit {
566 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
567 match self {
568 NumericUnit::Mass(v, u) => write!(f, "{} {}", v, u),
569 NumericUnit::Length(v, u) => write!(f, "{} {}", v, u),
570 NumericUnit::Volume(v, u) => write!(f, "{} {}", v, u),
571 NumericUnit::Duration(v, u) => write!(f, "{} {}", v, u),
572 NumericUnit::Temperature(v, u) => write!(f, "{} {}", v, u),
573 NumericUnit::Power(v, u) => write!(f, "{} {}", v, u),
574 NumericUnit::Force(v, u) => write!(f, "{} {}", v, u),
575 NumericUnit::Pressure(v, u) => write!(f, "{} {}", v, u),
576 NumericUnit::Energy(v, u) => write!(f, "{} {}", v, u),
577 NumericUnit::Frequency(v, u) => write!(f, "{} {}", v, u),
578 NumericUnit::Data(v, u) => write!(f, "{} {}", v, u),
579 NumericUnit::Money(v, u) => write!(f, "{} {}", v, u),
580 }
581 }
582}
583
584impl LemmaRule {
585 pub fn new(name: String, expression: Expression) -> Self {
586 Self {
587 name,
588 expression,
589 unless_clauses: Vec::new(),
590 span: None,
591 }
592 }
593
594 pub fn add_unless_clause(mut self, unless_clause: UnlessClause) -> Self {
595 self.unless_clauses.push(unless_clause);
596 self
597 }
598}
599
600impl LemmaFact {
601 pub fn new(fact_type: FactType, value: FactValue) -> Self {
602 Self {
603 fact_type,
604 value,
605 span: None,
606 }
607 }
608
609 pub fn with_span(mut self, span: Span) -> Self {
610 self.span = Some(span);
611 self
612 }
613}
614
615impl LemmaDoc {
616 pub fn new(name: String) -> Self {
617 Self {
618 name,
619 source: None,
620 start_line: 1,
621 commentary: None,
622 facts: Vec::new(),
623 rules: Vec::new(),
624 }
625 }
626
627 pub fn with_source(mut self, source: String) -> Self {
628 self.source = Some(source);
629 self
630 }
631
632 pub fn with_start_line(mut self, start_line: usize) -> Self {
633 self.start_line = start_line;
634 self
635 }
636
637 pub fn set_commentary(mut self, commentary: String) -> Self {
638 self.commentary = Some(commentary);
639 self
640 }
641
642 pub fn add_fact(mut self, fact: LemmaFact) -> Self {
643 self.facts.push(fact);
644 self
645 }
646
647 pub fn add_rule(mut self, rule: LemmaRule) -> Self {
648 self.rules.push(rule);
649 self
650 }
651}
652
653impl fmt::Display for LemmaDoc {
654 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
655 write!(f, "doc {}", self.name)?;
656 writeln!(f)?;
657
658 if let Some(ref commentary) = self.commentary {
659 writeln!(f, "\"\"\"{}", commentary)?;
660 writeln!(f, "\"\"\"")?;
661 }
662
663 for fact in &self.facts {
664 write!(f, "{}", fact)?;
665 }
666
667 for rule in &self.rules {
668 write!(f, "{}", rule)?;
669 }
670
671 Ok(())
672 }
673}
674
675impl fmt::Display for LemmaFact {
676 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
677 writeln!(f, "fact {} = {}", self.fact_type, self.value)
678 }
679}
680
681impl fmt::Display for LemmaRule {
682 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
683 write!(f, "rule {} = {}", self.name, self.expression)?;
684
685 for unless_clause in &self.unless_clauses {
686 write!(
687 f,
688 " unless {} then {}",
689 unless_clause.condition, unless_clause.result
690 )?;
691 }
692
693 writeln!(f)?;
694 Ok(())
695 }
696}
697
698impl fmt::Display for Expression {
699 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
700 match &self.kind {
701 ExpressionKind::Literal(lit) => write!(f, "{}", lit),
702 ExpressionKind::FactReference(fact_ref) => write!(f, "{}", fact_ref),
703 ExpressionKind::RuleReference(rule_ref) => write!(f, "{}", rule_ref),
704 ExpressionKind::Arithmetic(left, op, right) => {
705 write!(f, "{} {} {}", left, op, right)
706 }
707 ExpressionKind::Comparison(left, op, right) => {
708 write!(f, "{} {} {}", left, op, right)
709 }
710 ExpressionKind::FactHasAnyValue(fact_ref) => {
711 write!(f, "have {}", fact_ref)
712 }
713 ExpressionKind::UnitConversion(value, target) => {
714 write!(f, "{} in {}", value, target)
715 }
716 ExpressionKind::LogicalNegation(expr, negation_type) => {
717 let prefix = match negation_type {
718 NegationType::Not => "not",
719 NegationType::HaveNot => "have not",
720 NegationType::NotHave => "not have",
721 };
722 write!(f, "{} {}", prefix, expr)
723 }
724 ExpressionKind::LogicalAnd(left, right) => {
725 write!(f, "{} and {}", left, right)
726 }
727 ExpressionKind::LogicalOr(left, right) => {
728 write!(f, "{} or {}", left, right)
729 }
730 ExpressionKind::MathematicalOperator(op, operand) => {
731 let op_name = match op {
732 MathematicalOperator::Sqrt => "sqrt",
733 MathematicalOperator::Sin => "sin",
734 MathematicalOperator::Cos => "cos",
735 MathematicalOperator::Tan => "tan",
736 MathematicalOperator::Asin => "asin",
737 MathematicalOperator::Acos => "acos",
738 MathematicalOperator::Atan => "atan",
739 MathematicalOperator::Log => "log",
740 MathematicalOperator::Exp => "exp",
741 };
742 write!(f, "{} {}", op_name, operand)
743 }
744 ExpressionKind::Veto(veto) => match &veto.message {
745 Some(msg) => write!(f, "veto \"{}\"", msg),
746 None => write!(f, "veto"),
747 },
748 }
749 }
750}
751
752impl fmt::Display for LiteralValue {
753 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
754 match self {
755 LiteralValue::Number(n) => write!(f, "{}", n),
756 LiteralValue::Text(s) => write!(f, "\"{}\"", s),
757 LiteralValue::Date(dt) => write!(f, "{}", dt),
758 LiteralValue::Boolean(b) => write!(f, "{}", b),
759 LiteralValue::Percentage(p) => write!(f, "{}%", p),
760 LiteralValue::Unit(unit) => write!(f, "{}", unit),
761 LiteralValue::Regex(s) => write!(f, "{}", s),
762 LiteralValue::Time(time) => {
763 write!(f, "time({}, {}, {})", time.hour, time.minute, time.second)
764 }
765 }
766 }
767}
768
769impl LiteralValue {
770 pub fn describe(&self) -> String {
772 match self {
773 LiteralValue::Text(s) => format!("text value \"{}\"", s),
774 LiteralValue::Number(n) => format!("number {}", n),
775 LiteralValue::Boolean(b) => format!("boolean {}", b),
776 LiteralValue::Percentage(p) => format!("percentage {}%", p),
777 LiteralValue::Date(_) => "date value".to_string(),
778 LiteralValue::Unit(unit) => {
779 format!(
780 "{} value {}",
781 LiteralValue::Unit(unit.clone()).to_type(),
782 unit
783 )
784 }
785 LiteralValue::Regex(s) => format!("regex value {}", s),
786 LiteralValue::Time(time) => {
787 format!("time value {}:{}:{}", time.hour, time.minute, time.second)
788 }
789 }
790 }
791}
792
793impl fmt::Display for MassUnit {
794 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
795 match self {
796 MassUnit::Kilogram => write!(f, "kilogram"),
797 MassUnit::Gram => write!(f, "gram"),
798 MassUnit::Milligram => write!(f, "milligram"),
799 MassUnit::Ton => write!(f, "ton"),
800 MassUnit::Pound => write!(f, "pound"),
801 MassUnit::Ounce => write!(f, "ounce"),
802 }
803 }
804}
805
806impl fmt::Display for LengthUnit {
807 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
808 match self {
809 LengthUnit::Kilometer => write!(f, "kilometer"),
810 LengthUnit::Mile => write!(f, "mile"),
811 LengthUnit::NauticalMile => write!(f, "nautical_mile"),
812 LengthUnit::Meter => write!(f, "meter"),
813 LengthUnit::Decimeter => write!(f, "decimeter"),
814 LengthUnit::Centimeter => write!(f, "centimeter"),
815 LengthUnit::Millimeter => write!(f, "millimeter"),
816 LengthUnit::Yard => write!(f, "yard"),
817 LengthUnit::Foot => write!(f, "foot"),
818 LengthUnit::Inch => write!(f, "inch"),
819 }
820 }
821}
822
823impl fmt::Display for VolumeUnit {
824 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
825 match self {
826 VolumeUnit::CubicMeter => write!(f, "cubic_meter"),
827 VolumeUnit::CubicCentimeter => write!(f, "cubic_centimeter"),
828 VolumeUnit::Liter => write!(f, "liter"),
829 VolumeUnit::Deciliter => write!(f, "deciliter"),
830 VolumeUnit::Centiliter => write!(f, "centiliter"),
831 VolumeUnit::Milliliter => write!(f, "milliliter"),
832 VolumeUnit::Gallon => write!(f, "gallon"),
833 VolumeUnit::Quart => write!(f, "quart"),
834 VolumeUnit::Pint => write!(f, "pint"),
835 VolumeUnit::FluidOunce => write!(f, "fluid_ounce"),
836 }
837 }
838}
839
840impl fmt::Display for DurationUnit {
841 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
842 match self {
843 DurationUnit::Year => write!(f, "year"),
844 DurationUnit::Month => write!(f, "month"),
845 DurationUnit::Week => write!(f, "week"),
846 DurationUnit::Day => write!(f, "day"),
847 DurationUnit::Hour => write!(f, "hour"),
848 DurationUnit::Minute => write!(f, "minute"),
849 DurationUnit::Second => write!(f, "second"),
850 DurationUnit::Millisecond => write!(f, "millisecond"),
851 DurationUnit::Microsecond => write!(f, "microsecond"),
852 }
853 }
854}
855
856impl fmt::Display for TemperatureUnit {
857 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
858 match self {
859 TemperatureUnit::Celsius => write!(f, "celsius"),
860 TemperatureUnit::Fahrenheit => write!(f, "fahrenheit"),
861 TemperatureUnit::Kelvin => write!(f, "kelvin"),
862 }
863 }
864}
865
866impl fmt::Display for PowerUnit {
867 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
868 match self {
869 PowerUnit::Megawatt => write!(f, "megawatt"),
870 PowerUnit::Kilowatt => write!(f, "kilowatt"),
871 PowerUnit::Watt => write!(f, "watt"),
872 PowerUnit::Milliwatt => write!(f, "milliwatt"),
873 PowerUnit::Horsepower => write!(f, "horsepower"),
874 }
875 }
876}
877
878impl fmt::Display for ForceUnit {
879 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
880 match self {
881 ForceUnit::Newton => write!(f, "newton"),
882 ForceUnit::Kilonewton => write!(f, "kilonewton"),
883 ForceUnit::Lbf => write!(f, "lbf"),
884 }
885 }
886}
887
888impl fmt::Display for PressureUnit {
889 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
890 match self {
891 PressureUnit::Megapascal => write!(f, "megapascal"),
892 PressureUnit::Kilopascal => write!(f, "kilopascal"),
893 PressureUnit::Pascal => write!(f, "pascal"),
894 PressureUnit::Atmosphere => write!(f, "atmosphere"),
895 PressureUnit::Bar => write!(f, "bar"),
896 PressureUnit::Psi => write!(f, "psi"),
897 PressureUnit::Torr => write!(f, "torr"),
898 PressureUnit::Mmhg => write!(f, "mmhg"),
899 }
900 }
901}
902
903impl fmt::Display for EnergyUnit {
904 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
905 match self {
906 EnergyUnit::Megajoule => write!(f, "megajoule"),
907 EnergyUnit::Kilojoule => write!(f, "kilojoule"),
908 EnergyUnit::Joule => write!(f, "joule"),
909 EnergyUnit::Kilowatthour => write!(f, "kilowatthour"),
910 EnergyUnit::Watthour => write!(f, "watthour"),
911 EnergyUnit::Kilocalorie => write!(f, "kilocalorie"),
912 EnergyUnit::Calorie => write!(f, "calorie"),
913 EnergyUnit::Btu => write!(f, "btu"),
914 }
915 }
916}
917
918impl fmt::Display for FrequencyUnit {
919 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
920 match self {
921 FrequencyUnit::Hertz => write!(f, "hertz"),
922 FrequencyUnit::Kilohertz => write!(f, "kilohertz"),
923 FrequencyUnit::Megahertz => write!(f, "megahertz"),
924 FrequencyUnit::Gigahertz => write!(f, "gigahertz"),
925 }
926 }
927}
928
929impl fmt::Display for DataUnit {
930 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
931 match self {
932 DataUnit::Petabyte => write!(f, "petabyte"),
933 DataUnit::Terabyte => write!(f, "terabyte"),
934 DataUnit::Gigabyte => write!(f, "gigabyte"),
935 DataUnit::Megabyte => write!(f, "megabyte"),
936 DataUnit::Kilobyte => write!(f, "kilobyte"),
937 DataUnit::Byte => write!(f, "byte"),
938 DataUnit::Tebibyte => write!(f, "tebibyte"),
939 DataUnit::Gibibyte => write!(f, "gibibyte"),
940 DataUnit::Mebibyte => write!(f, "mebibyte"),
941 DataUnit::Kibibyte => write!(f, "kibibyte"),
942 }
943 }
944}
945
946impl fmt::Display for MoneyUnit {
947 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
948 match self {
949 MoneyUnit::Eur => write!(f, "EUR"),
950 MoneyUnit::Usd => write!(f, "USD"),
951 MoneyUnit::Gbp => write!(f, "GBP"),
952 MoneyUnit::Jpy => write!(f, "JPY"),
953 MoneyUnit::Cny => write!(f, "CNY"),
954 MoneyUnit::Chf => write!(f, "CHF"),
955 MoneyUnit::Cad => write!(f, "CAD"),
956 MoneyUnit::Aud => write!(f, "AUD"),
957 MoneyUnit::Inr => write!(f, "INR"),
958 }
959 }
960}
961
962impl fmt::Display for ConversionTarget {
963 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
964 match self {
965 ConversionTarget::Mass(unit) => write!(f, "{}", unit),
966 ConversionTarget::Length(unit) => write!(f, "{}", unit),
967 ConversionTarget::Volume(unit) => write!(f, "{}", unit),
968 ConversionTarget::Duration(unit) => write!(f, "{}", unit),
969 ConversionTarget::Temperature(unit) => write!(f, "{}", unit),
970 ConversionTarget::Power(unit) => write!(f, "{}", unit),
971 ConversionTarget::Force(unit) => write!(f, "{}", unit),
972 ConversionTarget::Pressure(unit) => write!(f, "{}", unit),
973 ConversionTarget::Energy(unit) => write!(f, "{}", unit),
974 ConversionTarget::Frequency(unit) => write!(f, "{}", unit),
975 ConversionTarget::Data(unit) => write!(f, "{}", unit),
976 ConversionTarget::Money(unit) => write!(f, "{}", unit),
977 ConversionTarget::Percentage => write!(f, "percentage"),
978 }
979 }
980}
981
982impl fmt::Display for LemmaType {
983 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
984 match self {
985 LemmaType::Text => write!(f, "text"),
986 LemmaType::Number => write!(f, "number"),
987 LemmaType::Date => write!(f, "date"),
988 LemmaType::Boolean => write!(f, "boolean"),
989 LemmaType::Regex => write!(f, "regex"),
990 LemmaType::Percentage => write!(f, "percentage"),
991 LemmaType::Mass => write!(f, "mass"),
992 LemmaType::Length => write!(f, "length"),
993 LemmaType::Volume => write!(f, "volume"),
994 LemmaType::Duration => write!(f, "duration"),
995 LemmaType::Temperature => write!(f, "temperature"),
996 LemmaType::Power => write!(f, "power"),
997 LemmaType::Force => write!(f, "force"),
998 LemmaType::Pressure => write!(f, "pressure"),
999 LemmaType::Energy => write!(f, "energy"),
1000 LemmaType::Frequency => write!(f, "frequency"),
1001 LemmaType::Data => write!(f, "data"),
1002 LemmaType::Money => write!(f, "money"),
1003 }
1004 }
1005}
1006
1007impl fmt::Display for TypeAnnotation {
1008 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1009 match self {
1010 TypeAnnotation::LemmaType(lemma_type) => write!(f, "{}", lemma_type),
1011 }
1012 }
1013}
1014
1015impl fmt::Display for FactValue {
1016 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1017 match self {
1018 FactValue::Literal(lit) => write!(f, "{}", lit),
1019 FactValue::TypeAnnotation(type_ann) => write!(f, "[{}]", type_ann),
1020 FactValue::DocumentReference(doc_name) => write!(f, "doc {}", doc_name),
1021 }
1022 }
1023}
1024
1025impl fmt::Display for FactReference {
1026 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1027 write!(f, "{}", self.reference.join("."))
1028 }
1029}
1030
1031impl fmt::Display for ForeignFact {
1032 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1033 write!(f, "{}", self.reference.join("."))
1034 }
1035}
1036
1037impl fmt::Display for FactType {
1038 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1039 match self {
1040 FactType::Local(name) => write!(f, "{}", name),
1041 FactType::Foreign(foreign_ref) => write!(f, "{}", foreign_ref),
1042 }
1043 }
1044}
1045
1046impl fmt::Display for RuleReference {
1047 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1048 write!(f, "{}?", self.reference.join("."))
1049 }
1050}
1051
1052impl fmt::Display for ArithmeticOperation {
1053 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1054 match self {
1055 ArithmeticOperation::Add => write!(f, "+"),
1056 ArithmeticOperation::Subtract => write!(f, "-"),
1057 ArithmeticOperation::Multiply => write!(f, "*"),
1058 ArithmeticOperation::Divide => write!(f, "/"),
1059 ArithmeticOperation::Modulo => write!(f, "%"),
1060 ArithmeticOperation::Power => write!(f, "^"),
1061 }
1062 }
1063}
1064
1065impl fmt::Display for ComparisonOperator {
1066 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1067 match self {
1068 ComparisonOperator::GreaterThan => write!(f, ">"),
1069 ComparisonOperator::LessThan => write!(f, "<"),
1070 ComparisonOperator::GreaterThanOrEqual => write!(f, ">="),
1071 ComparisonOperator::LessThanOrEqual => write!(f, "<="),
1072 ComparisonOperator::Equal => write!(f, "=="),
1073 ComparisonOperator::NotEqual => write!(f, "!="),
1074 ComparisonOperator::Is => write!(f, "is"),
1075 ComparisonOperator::IsNot => write!(f, "is not"),
1076 }
1077 }
1078}
1079
1080impl fmt::Display for TimeValue {
1081 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1082 write!(f, "{:02}:{:02}:{:02}", self.hour, self.minute, self.second)
1083 }
1084}
1085
1086impl fmt::Display for TimezoneValue {
1087 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1088 if self.offset_hours == 0 && self.offset_minutes == 0 {
1089 write!(f, "Z")
1090 } else {
1091 let sign = if self.offset_hours >= 0 { "+" } else { "-" };
1092 let hours = self.offset_hours.abs();
1093 write!(f, "{}{:02}:{:02}", sign, hours, self.offset_minutes)
1094 }
1095 }
1096}
1097
1098impl fmt::Display for DateTimeValue {
1099 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1100 write!(
1101 f,
1102 "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}",
1103 self.year, self.month, self.day, self.hour, self.minute, self.second
1104 )?;
1105 if let Some(tz) = &self.timezone {
1106 write!(f, "{}", tz)?;
1107 }
1108 Ok(())
1109 }
1110}