rulemorph 0.3.3

YAML-based declarative data transformation engine for CSV/JSON to JSON
Documentation
//! v2 Expression Types for rulemorph v2.0
//!
//! This module defines the data structures for the v2 expression syntax,
//! which uses `@input.*`, `@context.*`, `@out.*` references and pipe-based
//! transformations.

use crate::model::Expr;
use serde_json::Value as JsonValue;

// =============================================================================
// v2 Expression Types
// =============================================================================

/// v2 expression - either a Pipe (new v2 syntax) or V1Fallback (legacy syntax)
#[derive(Debug, Clone, PartialEq)]
pub enum V2Expr {
    Pipe(V2Pipe),
    V1Fallback(Expr),
}

/// v2 Pipe - a start value followed by transformation steps
#[derive(Debug, Clone, PartialEq)]
pub struct V2Pipe {
    pub start: V2Start,
    pub steps: Vec<V2Step>,
}

/// v2 Start - the starting value of a pipe
#[derive(Debug, Clone, PartialEq)]
pub enum V2Start {
    Ref(V2Ref),
    PipeValue,
    ImplicitPipeValue,
    Literal(JsonValue),
    V1Expr(Box<Expr>),
}

/// v2 Reference - namespace-qualified references with @ prefix
/// Examples: @input.name, @context.users[0].id, @out.user_id, @item.value, @acc.total, @myVar
#[derive(Debug, Clone, PartialEq)]
pub enum V2Ref {
    Input(String),   // @input.path
    Context(String), // @context.path
    Out(String),     // @out.path
    Pipe(String),    // $.path
    Item(String),    // @item.path (in map)
    Acc(String),     // @acc.path (in reduce)
    Local(String),   // @varName (let-bound)
}

/// v2 Step - a transformation step in a pipe
#[derive(Debug, Clone, PartialEq)]
pub enum V2Step {
    Op(V2OpStep),
    CustomCall(V2CustomCallStep),
    Let(V2LetStep),
    If(V2IfStep),
    Map(V2MapStep),
    /// Reference step - returns a reference value (e.g., "@doubled" to return a let-bound variable)
    Ref(V2Ref),
}

/// v2 Op Step - a named operation with arguments
#[derive(Debug, Clone, PartialEq)]
pub struct V2OpStep {
    pub op: String,
    pub args: Vec<V2Expr>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct V2CustomCallStep {
    pub op: String,
    pub with: Option<Vec<(String, V2CallArg)>>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum V2CallArg {
    Expr(V2Expr),
    Value(JsonValue),
}

/// v2 Let Step - variable bindings
#[derive(Debug, Clone, PartialEq)]
pub struct V2LetStep {
    pub bindings: Vec<(String, V2Expr)>,
}

/// v2 If Step - conditional branching
#[derive(Debug, Clone, PartialEq)]
pub struct V2IfStep {
    pub cond: V2Condition,
    pub then_branch: V2Pipe,
    pub else_branch: Option<V2Pipe>,
}

/// v2 Map Step - array iteration
#[derive(Debug, Clone, PartialEq)]
pub struct V2MapStep {
    pub steps: Vec<V2Step>,
}

/// v2 Condition - logical conditions for if/when
#[derive(Debug, Clone, PartialEq)]
pub enum V2Condition {
    All(Vec<V2Condition>),
    Any(Vec<V2Condition>),
    Comparison(V2Comparison),
    Expr(V2Expr),
}

/// v2 Comparison - comparison operations
#[derive(Debug, Clone, PartialEq)]
pub struct V2Comparison {
    pub op: V2ComparisonOp,
    pub args: Vec<V2Expr>,
}

/// v2 Comparison Operator
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum V2ComparisonOp {
    Eq,
    Ne,
    Gt,
    Gte,
    Lt,
    Lte,
    Match,
}

// =============================================================================
// v2 Model Tests
// =============================================================================

#[cfg(test)]
#[path = "v2_model/tests.rs"]
mod v2_model_tests;