flow-ir-core 0.2.0

flow.ir Pure Rust schema + sync interpreter — Node / Expr / Dispatcher / eval (no mlua, no async)
Documentation

flow-ir-core

flow.ir Pure Rust schema + sync interpreter. The core substrate (layer 2 of the 4-layer flow.ir stack).

No mlua, no async, no I/O — pure schema + eval + Dispatcher trait.

Stack position

  1. flow-ir-lua — Pure Lua DSL (separate repo, ecosystem-neutral)
  2. flow-ir-core — this crate: Pure Rust schema + sync interpreter
  3. mlua-flow-ir — async runtime + mlua binding (re-exports this crate)
  4. mlua-swarm-engine — host concerns (Spawner / Worker / Loop / AuthzPolicy / cp_state persist)

What's in

  • 7 Node kindsStep { ref, in, out }, Seq { children }, Branch { cond, then, else }, Fanout { items, bind, body, join, out }, Loop { counter, cond, body, max }, Try { body, catch, err_at }, Assign { at, value }
  • 20 Expr ops — read/literal (Path, Lit), comparison (Eq, Ne, Lt, Lte, Gt, Gte), boolean (Not, And, Or), existence (Exists), arithmetic (Add, Sub, Mul, Div, Mod), aggregate (Len, In), and the CallExtern hatch
  • Discriminated unions#[serde(tag = "kind")] / #[serde(tag = "op")] + deny_unknown_fields
  • Dispatcher trait — host provides concrete dispatch(&str, Value) -> Result<Value> implementations

Quick start

use flow_ir_core::{eval, Dispatcher, EvalError, Node};
use serde_json::{json, Value};

let node: Node = serde_json::from_value(json!({
    "kind": "step",
    "ref": "uppercase",
    "in": { "op": "path", "at": "$.input" },
    "out": { "op": "path", "at": "$.output" },
})).unwrap();

struct Fixture;
impl Dispatcher for Fixture {
    fn dispatch(&self, _r: &str, input: Value) -> Result<Value, EvalError> {
        if let Value::String(s) = input {
            Ok(Value::String(s.to_uppercase()))
        } else {
            Ok(input)
        }
    }
}

let result = eval(&node, json!({ "input": "hello" }), &Fixture).unwrap();
assert_eq!(result, json!({ "input": "hello", "output": "HELLO" }));

License

MIT OR Apache-2.0