Skip to main content

Crate polydat_derive

Crate polydat_derive 

Source
Expand description

polydat-derive — proc-macro implementation of #[polydat_node].

See docs/SRD/80_node_function_macro_collapse.md for the design, the 8 open design questions this proc-macro is closing one-at-a-time, and the migration plan against existing polydat library nodes.

§Current scope (PR B.1)

This is the SCAFFOLDING pass. The macro recognizes the simplest case only:

  • A standalone fn (no impl block, no struct).
  • All wire input arguments are PRIMITIVES with implementations of polydat’s FromValue trait — concretely: u64, f64, bool, &str (or owned String).
  • Return type is a PRIMITIVE with a IntoValue implementation — same set.
  • No state, no const args, no JIT hooks, no variadic shapes, no polymorphism.

Out of scope (deferred to later PR B.* batches):

  • State-bearing nodes (probability PRNG, vectors readers).
  • JIT-eligible nodes (the compiled_u64 hooks).
  • Const-arg parameters with ConstConstraint.
  • Variadic shapes (Variadic<T>, &[T]).
  • Polymorphic outputs (SameAsInput).
  • Ext-typed args / returns (adapter-contributed types).

§Generated output (for the simple case)

Input:

#[polydat_node]
fn str_eq(a: &str, b: &str) -> u64 {
    if a == b { 1 } else { 0 }
}

Generated:

pub struct StrEq { meta: polydat::ast::NodeMeta }
impl Default for StrEq { fn default() -> Self { Self::new() } }
impl StrEq {
    pub fn new() -> Self {
        Self {
            meta: polydat::ast::NodeMeta {
                name: "str_eq".into(),
                ins: vec![
                    polydat::ast::Slot::Wire(polydat::ast::Port::new(
                        "a", polydat::ast::PortType::Str)),
                    polydat::ast::Slot::Wire(polydat::ast::Port::new(
                        "b", polydat::ast::PortType::Str)),
                ],
                outs: vec![polydat::ast::Port::new(
                    "output", polydat::ast::PortType::U64)],
            },
        }
    }
}
impl polydat::ast::PolydatNode for StrEq {
    fn meta(&self) -> &polydat::ast::NodeMeta { &self.meta }
    fn eval(
        &self,
        inputs: &[polydat::ast::Value],
        outputs: &mut [polydat::ast::Value],
    ) {
        let a = <&str as polydat::derive_support::FromValue>::from_value(&inputs[0]);
        let b = <&str as polydat::derive_support::FromValue>::from_value(&inputs[1]);
        let result: u64 = if a == b { 1 } else { 0 };
        outputs[0] = <u64 as polydat::derive_support::IntoValue>::into_value(result);
    }
}

The original fn str_eq is consumed by the macro — only the struct + impl is emitted. The body of str_eq becomes the body of the eval method (with parameter rebinding via FromValue::from_value).

FuncSig registration via inventory or similar is deferred to PR B.2 — for now the macro just generates the struct + impl so we can validate the boxing/unboxing path with a pilot node.

Attribute Macros§

polydat_node
#[polydat_node] — derive a polydat node from a typed Rust function signature.