package dsp import "fmt" // Op type categories for static (compile-time / editor) type propagation. // These mirror the runtime dispatch in the synthetic graph evaluator and the // frontend's inferNodeTypes (web/src/lib/synthTypes.ts) — keep the three in // sync; a parity test guards the Go/TS pair. var ( // reductionOps collapse an array (or scalar) to a single scalar. reductionOps = map[string]bool{ "index": true, "length": true, "sum": true, "mean": true, "min": true, "max": true, } // arrayProducerOps require an array input and yield an array. arrayProducerOps = map[string]bool{ "fft": true, "slice": true, } // scalarOnlyOps reject array inputs and yield a scalar. Stateful filters // plus lua (whose state/closure cannot be broadcast per array lane). scalarOnlyOps = map[string]bool{ "moving_average": true, "rms": true, "lowpass": true, "derivative": true, "integrate": true, "lua": true, } ) // OpOutputType reports the output ValType of an op given its input types, and // an error if the inputs are definitely incompatible with the op. Inputs may be // ValUnknown (a source whose real type is not yet known at compile time); such // inputs never trigger an error — runtime Sample typing is authoritative. func OpOutputType(op string, in []ValType) (ValType, error) { switch { case reductionOps[op]: return ValScalar, nil case arrayProducerOps[op]: for _, t := range in { if t == ValScalar { return ValUnknown, fmt.Errorf("%s requires an array input", op) } } return ValArray, nil case scalarOnlyOps[op]: for _, t := range in { if t == ValArray { return ValUnknown, fmt.Errorf("%s does not accept an array input", op) } } return ValScalar, nil default: // Elementwise stateless ops (gain, offset, add, subtract, multiply, // divide, clamp, threshold, expr): array if any input is an array, // scalar if all inputs are definitely scalar, otherwise unknown. anyArray, anyUnknown := false, false for _, t := range in { switch t { case ValArray: anyArray = true case ValUnknown: anyUnknown = true } } switch { case anyArray: return ValArray, nil case anyUnknown: return ValUnknown, nil default: return ValScalar, nil } } }