## Add keyword arguments for UI primitives and user-defined functions ### Summary This PR introduces Ruby/Python-style keyword arguments to Faust, enabling more readable and self-documenting code for both UI primitives and user-defined functions: ```faust // UI primitives hslider("volume", init: 0.5, min: 0.0, max: 1.0, step: 0.01) // User-defined functions mix(a, b, ratio) = a * (1-ratio) + b * ratio; process = mix(dry, wet, ratio: 0.7); ``` ### Motivation Faust's UI primitives require multiple positional arguments that are easy to confuse: ```faust // Which is init? min? max? step? hslider("volume", 0.5, 0.0, 1.0, 0.01) ``` Similarly, user-defined functions with multiple parameters benefit from named arguments for clarity at call sites. ### Syntax #### UI Primitives ```faust // Before: positional only hslider("volume", 0.5, 0.0, 1.0, 0.01) // After: keyword arguments (any order) hslider("volume", init: 0.5, min: 0.0, max: 1.0, step: 0.01) hslider("volume", min: 0.0, max: 1.0, init: 0.5, step: 0.01) ``` Supported: `hslider`, `vslider`, `nentry`, `hbargraph`, `vbargraph` #### User-Defined Functions ```faust filter(freq, q, gain) = ...; // Mixed positional + kwargs process = filter(1000, q: 0.7, gain: 1.0); // All kwargs (any order) process = filter(gain: 1.0, freq: 1000, q: 0.7); ``` **Constraints (Ruby-style):** - Keyword arguments must come after positional arguments - All required parameters must be provided - Unknown keywords produce clear error messages ### Error Messages ``` error: hslider: unknown keyword 'foo' Valid keywords are: init, min, max, step error: hslider: missing required keyword 'step' Required keywords are: init, min, max, step error: unknown keyword argument 'c' ``` ### Implementation - **Lexer**: Added `KWARG` token (pattern: `{ID}":"`) - **Parser**: Added `kwarg`, `kwarglist` grammar rules - **Boxes**: Added `BOXKWARG` box type for keyword argument representation - **Eval**: Modified `applyList()` to resolve kwargs to parameter positions ### Testing Pass tests: - `kwargs-ui-primitives.dsp` - all UI primitive variants - `kwargs-functions.dsp` - user-defined function calls - `kwargs-mixed.dsp` - combining both in one program Error tests: - `kwargs-unknown-ui.dsp` - unknown keyword for UI primitive - `kwargs-missing-ui.dsp` - missing required keyword - `kwargs-unknown-func.dsp` - unknown keyword for function ### Note on diff size The large diff in `faustlexer.cpp`, `faustparser.cpp`, and `faustparser.hpp` is due to these being **generated files**. The actual source changes are: | File | Lines changed | |------|---------------| | `faustlexer.l` | +1 | | `faustparser.y` | +130 | | `boxes.cpp` | +14 | | `boxes.hh` | +7 | | `eval.cpp` | +114 | | `global.cpp` | +1 | | `global.hh` | +1 | ### Backward Compatibility Fully backward compatible - existing positional syntax continues to work unchanged. ### Future Work This feature is designed to integrate with default parameters (separate PR): ```faust filter(freq, q=0.707) = ...; process = filter(freq: 1000); // q defaults to 0.707 ```