lemma/evaluation/
operations.rs

1//! Operation types and result handling for evaluation
2
3use crate::{
4    ArithmeticComputation, ComparisonComputation, FactPath, LiteralValue, LogicalComputation,
5    MathematicalComputation, RulePath,
6};
7use serde::Serialize;
8
9/// Result of an operation (evaluating a rule or expression)
10#[derive(Debug, Clone, PartialEq, Serialize)]
11pub enum OperationResult {
12    /// Operation produced a value
13    Value(LiteralValue),
14    /// Operation was vetoed (valid result, no value)
15    Veto(Option<String>),
16}
17
18impl OperationResult {
19    pub fn is_veto(&self) -> bool {
20        matches!(self, OperationResult::Veto(_))
21    }
22
23    #[must_use]
24    pub fn value(&self) -> Option<&LiteralValue> {
25        match self {
26            OperationResult::Value(v) => Some(v),
27            OperationResult::Veto(_) => None,
28        }
29    }
30}
31
32/// The kind of computation performed
33#[derive(Debug, Clone, Serialize)]
34#[serde(tag = "type", rename_all = "snake_case")]
35pub enum ComputationKind {
36    Arithmetic(ArithmeticComputation),
37    Comparison(ComparisonComputation),
38    Logical(LogicalComputation),
39    Mathematical(MathematicalComputation),
40}
41
42/// A record of a single operation during evaluation
43#[derive(Debug, Clone, Serialize)]
44pub struct OperationRecord {
45    #[serde(flatten)]
46    pub kind: OperationKind,
47}
48
49/// The kind of operation performed
50#[derive(Debug, Clone, Serialize)]
51#[serde(tag = "type", rename_all = "snake_case")]
52pub enum OperationKind {
53    FactUsed {
54        fact_ref: FactPath,
55        value: LiteralValue,
56    },
57    RuleUsed {
58        rule_path: RulePath,
59        result: OperationResult,
60    },
61    Computation {
62        kind: ComputationKind,
63        inputs: Vec<LiteralValue>,
64        result: LiteralValue,
65        #[serde(skip_serializing_if = "Option::is_none", default)]
66        expr: Option<String>,
67    },
68    RuleBranchEvaluated {
69        #[serde(skip_serializing_if = "Option::is_none")]
70        index: Option<usize>,
71        matched: bool,
72        #[serde(skip_serializing_if = "Option::is_none", default)]
73        condition_expr: Option<String>,
74        #[serde(skip_serializing_if = "Option::is_none", default)]
75        result_expr: Option<String>,
76        #[serde(skip_serializing_if = "Option::is_none", default)]
77        result_value: Option<OperationResult>,
78    },
79}