Last active
January 27, 2026 17:19
-
-
Save dfl/45e894d28e8df238adc6b6109a92d827 to your computer and use it in GitHub Desktop.
Revisions
-
dfl revised this gist
Jan 24, 2026 . 1 changed file with 5 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -91,3 +91,8 @@ process = filter(1000, 1.5); process = filter(1000, gain: 2.0); // skip q, override gain process = filter(freq: 1000, gain: 2.0); // named + default ``` ### Branch - **Branch**: [`feature/default-parameters`](https://github.com/dfl/faust/tree/feature/default-parameters) - **Base**: `master-dev` -
dfl revised this gist
Jan 24, 2026 . 1 changed file with 9 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -75,3 +75,12 @@ The large diff in `faustlexer.cpp`, `faustparser.cpp`, and `faustparser.hpp` is | `global.cpp` | +1 | | `global.hh` | +1 | | `sourcereader.cpp` | +40 | ### Backward Compatibility Fully backward compatible - existing import syntax continues to work unchanged. ### Branch - **Branch**: [`feature/python-style-imports`](https://github.com/dfl/faust/tree/feature/python-style-imports) - **Base**: `master-dev` -
dfl revised this gist
Jan 24, 2026 . 1 changed file with 5 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -121,3 +121,8 @@ After integration: filter(freq, q=0.707) = ...; process = filter(freq: 1000); // q defaults to 0.707 ``` ### Branch - **Branch**: [`feature/keyword-arguments`](https://github.com/dfl/faust/tree/feature/keyword-arguments) - **Base**: `master-dev` -
dfl revised this gist
Jan 24, 2026 . 1 changed file with 1 addition and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -129,6 +129,5 @@ Fully backward compatible - new option, no changes to existing behavior. ### Branch - **Branch**: [`feature/inline-libraries`](https://github.com/dfl/faust/tree/feature/inline-libraries) - **Base**: `master-dev` -
dfl revised this gist
Jan 24, 2026 . 1 changed file with 9 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -107,7 +107,15 @@ Fully backward compatible - existing positional syntax continues to work unchang ### Future Work #### Integration with default parameters This feature is designed to integrate with default parameters (separate PR). When rebasing onto default-params: 1. Extend `DefParamMap` to store parameter names (currently stores only default values by position) 2. Update `buildBoxApplWithDefaults()` to handle mixed positional + kwargs 3. Resolve kwargs to positions using stored parameter names After integration: ```faust filter(freq, q=0.707) = ...; -
dfl revised this gist
Jan 24, 2026 . 1 changed file with 3 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -54,7 +54,7 @@ scale(x, factor, offset=factor*0.1) = x * factor + offset; ### Implementation - **Parser**: Extended function parameter syntax to accept `= expression` - **Boxes**: Default values stored by position (nil for required params) - **Eval**: Modified function application to fill missing arguments from defaults ### Testing @@ -71,7 +71,8 @@ The large diff in generated files (`faustparser.cpp`, etc.) is from flex/bison r | File | Lines changed | |------|---------------| | `faustparser.y` | +97 | | `global.hh` | +6 | | `sourcereader.cpp` | +16/-9 | ### Backward Compatibility -
dfl revised this gist
Jan 24, 2026 . 1 changed file with 28 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,7 +10,7 @@ This PR adds a new `-il` (`--inline-libraries`) option that produces a self-cont faust -il myfile.dsp -o myfile_standalone.dsp ``` The output preserves readable Faust source code, unlike `-e` which exports an unreadable expanded box tree. **Tree-shaking** automatically removes unused definitions to keep output minimal. ### Motivation @@ -25,27 +25,30 @@ fx = library("myeffects.lib"); process = _ : half : fx.gain; ``` **mymath.lib:** ```faust half(x) = x * 0.5; double(x) = x * 2; // unused by this program ``` **Output with `-il`:** (note: `double` is removed by tree-shaking) ```faust // Self-contained DSP file generated with -il option // Inlined libraries: 2 // Tree-shaking: enabled (5 definitions used) // ===== Imported: mymath.lib ===== half(x) = x * 0.5; // ===== End of: mymath.lib ===== // Library: mymath.lib __lib_mymath = environment { half(x) = x * 0.5; }; // Library: myeffects.lib __lib_myeffects = environment { gain = *(0.8); }; // ===== Main DSP ===== @@ -55,14 +58,25 @@ process = _ : half : fx.gain; ### How It Works 1. **Evaluation phase**: Runs normal Faust evaluation, tracking which definitions are used 2. **Collection phase**: Recursively discovers all `import()` and `library()` dependencies 3. **Output phase**: - `import()` content inlined directly at top level (into global scope) - `library()` content wrapped in `environment { }` as top-level definitions - **Tree-shaking**: Only used definitions are included in output - Files used as both `import()` and `library()` are handled correctly - Circular dependencies detected and reported - Duplicate variable definitions skipped ### Tree-Shaking The `-il` option automatically removes unused definitions by: 1. Evaluating the program first to determine which symbols are actually used 2. Tracking all symbol lookups during evaluation in `gUsedDefinitions` 3. Filtering the output to only include definitions whose names appear in the tracked set This significantly reduces output size when importing large libraries but only using a few functions. ### Implementation As suggested in the original discussion, this reuses infrastructure from the `-i` option: @@ -81,14 +95,16 @@ The `-i` option handles C++ `#include` in architecture files with simple text su | | `library()` → wrap in `environment { }` | | Single use pattern | Files can be used as both import AND library | | | Must track variable definitions to avoid duplicates | | | Tree-shaking removes unused definitions | | File | Changes | |------|---------| | `global.hh` | +2 lines (flags) | | `global.cpp` | +8 lines (option parsing, init, help) | | `libcode.cpp` | +15 lines (integration) | | `sourcereader.hh` | +3 lines (declaration) | | `sourcereader.cpp` | +280 lines (inlining + tree-shaking logic) | | `eval.cpp` | +8 lines (symbol tracking) | ### Testing @@ -97,8 +113,8 @@ The `-i` option handles C++ `#include` in architecture files with simple text su faust -il test.dsp -o test_inlined.dsp faust -e test_inlined.dsp # Verify it compiles # Tree-shaking in action faust -il uses_one_function.dsp -o small_output.dsp ``` ### Option Naming -
dfl created this gist
Jan 24, 2026 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,92 @@ ## Add default parameter values for function definitions ### Summary This PR adds support for default parameter values in function definitions, reducing boilerplate and improving API ergonomics: ```faust // Define with defaults lowpass(freq, q=0.707) = fi.resonlp(freq, q, 1); // Call - omit defaulted parameters process = lowpass(1000); // q = 0.707 process = lowpass(1000, 1.5); // q = 1.5 ``` ### Motivation Currently, Faust functions require all parameters at every call site, even when sensible defaults exist: ```faust // Without defaults - must specify q every time lowpass(freq, q) = fi.resonlp(freq, q, 1); process = lowpass(1000, 0.707), lowpass(2000, 0.707), lowpass(500, 0.707); // With defaults - cleaner code lowpass(freq, q=0.707) = fi.resonlp(freq, q, 1); process = lowpass(1000), lowpass(2000), lowpass(500); ``` This could be especially valuable for library functions where most users want standard values but experts need tunability. ### Syntax ```faust // Single default gain(x, amount=1.0) = x * amount; // Multiple defaults (must be rightmost parameters) mix(a, b, ratio=0.5) = a * (1-ratio) + b * ratio; env(attack=0.01, decay=0.1, sustain=0.7, release=0.3) = ...; // Defaults can be expressions SR = 48000; nyquist(sr=SR/2) = sr; // Defaults can reference earlier parameters scale(x, factor, offset=factor*0.1) = x * factor + offset; ``` **Constraints:** - Parameters with defaults must come after parameters without defaults - Default expressions are evaluated at definition time ### Implementation - **Parser**: Extended function parameter syntax to accept `= expression` - **Boxes**: Parameters stored with optional default values - **Eval**: Modified function application to fill missing arguments from defaults ### Testing Pass tests: - `default-params-basic.dsp` - single default parameter - `default-params-multiple.dsp` - multiple defaults in one function - `default-params-expression.dsp` - defaults using expressions/constants ### Note on diff size The large diff in generated files (`faustparser.cpp`, etc.) is from flex/bison regeneration. Actual source changes: | File | Lines changed | |------|---------------| | `faustparser.y` | +97 | | `global.hh` | +5 | ### Backward Compatibility Fully backward compatible - existing function definitions without defaults work unchanged. ### Future Work Combines naturally with keyword arguments (separate PR): ```faust filter(freq, q=0.707, gain=1.0) = ...; // All these work: process = filter(1000); process = filter(1000, 1.5); process = filter(1000, gain: 2.0); // skip q, override gain process = filter(freq: 1000, gain: 2.0); // named + default ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,118 @@ ## Add -il option to inline all libraries **Discussion**: https://github.com/grame-cncm/faust/discussions/832 ### Summary This PR adds a new `-il` (`--inline-libraries`) option that produces a self-contained DSP file with all library code inlined: ```bash faust -il myfile.dsp -o myfile_standalone.dsp ``` The output preserves readable Faust source code, unlike `-e` which exports an unreadable expanded box tree. ### Motivation From issue #832: Users need self-contained DSP files for sharing, archiving, or using in environments without library access. The existing `-e` option exports expanded DSP but produces unreadable output. ### Example **Input (`mytest.dsp`):** ```faust import("mymath.lib"); fx = library("myeffects.lib"); process = _ : half : fx.gain; ``` **Output with `-il`:** ```faust // Self-contained DSP file generated with -il option // Inlined libraries: 2 // ===== Imported: mymath.lib ===== half(x) = x * 0.5; double(x) = x * 2; // ===== End of: mymath.lib ===== // Library: mymath.lib __lib_mymath = environment { half(x) = x * 0.5; double(x) = x * 2; }; // Library: myeffects.lib __lib_myeffects = environment { mm = __lib_mymath; gain = *(0.8); attenuate = mm.half; }; // ===== Main DSP ===== fx = __lib_myeffects; process = _ : half : fx.gain; ``` ### How It Works 1. **Collection phase**: Recursively discovers all `import()` and `library()` dependencies 2. **Output phase**: - `import()` content inlined directly at top level (into global scope) - `library()` content wrapped in `environment { }` as top-level definitions - Files used as both `import()` and `library()` are handled correctly - Circular dependencies detected and reported - Duplicate variable definitions skipped ### Implementation As suggested in the original discussion, this reuses infrastructure from the `-i` option: - Uses `gGlobal->gAlreadyIncluded` set for tracking visited files - Uses `fopenSearch()` for resolving library paths - Similar recursive inject pattern **Why new code was needed on top of `-i`:** The `-i` option handles C++ `#include` in architecture files with simple text substitution. The `-il` option needs Faust-specific semantics: | `-i` (architecture) | `-il` (libraries) | |---------------------|-------------------| | Detects `#include <faust/...>` | Must parse `import("...")` and `library("...")` | | Just copies file content | `import()` → inline directly | | | `library()` → wrap in `environment { }` | | Single use pattern | Files can be used as both import AND library | | | Must track variable definitions to avoid duplicates | | File | Changes | |------|---------| | `global.hh` | +1 line (flag) | | `global.cpp` | +8 lines (option parsing, init, help) | | `libcode.cpp` | +15 lines (integration) | | `sourcereader.hh` | +3 lines (declaration) | | `sourcereader.cpp` | +233 lines (inlining logic) | ### Testing ```bash # Simple test faust -il test.dsp -o test_inlined.dsp faust -e test_inlined.dsp # Verify it compiles # With standard libraries faust -il complex.dsp -o complex_inlined.dsp # ~43K lines for stdfaust.lib ``` ### Option Naming Follows the pattern of `-it` (`--inline-table`): - `-il` = inline libraries - `-it` = inline table ### Backward Compatibility Fully backward compatible - new option, no changes to existing behavior. ### Branch - **Worktree**: `../faust-inline-libs` - **Branch**: `feature/inline-libraries` - **Base**: `master-dev` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,115 @@ ## 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 ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,77 @@ ## Add Python-style selective imports ### Summary This PR adds a new import syntax that allows importing specific definitions from a library file, optionally with aliasing: ```faust from "maths.lib" import PI, SR; from "filters.lib" import lowpass, highpass as hp; ``` ### Motivation Currently, importing a library dumps all its definitions into the namespace, requiring the use of short prefixes like `ma.`, `fi.`, etc: ```faust import("stdfaust.lib"); process = fi.lowpass(2, ma.PI * 100); ``` This has two drawbacks: 1. **Cryptic prefixes** - `ma`, `fi`, `os` etc. are not self-documenting 2. **Namespace pollution** - entire libraries are imported even when only one or two definitions are needed The new syntax allows explicit, selective imports: ```faust from "maths.lib" import PI; from "filters.lib" import lowpass; process = lowpass(2, PI * 100); ``` ### Syntax ```faust // Import specific names from "library.lib" import name1, name2, name3; // Import with aliasing from "library.lib" import originalName as aliasName; // Mixed from "maths.lib" import PI, SR as sampleRate; ``` The syntax mirrors Python's `from X import Y` and uses the existing `,` (PAR) separator that Faust already uses for argument lists. ### Implementation - **Lexer**: Added `FROM` and `AS` keywords - **Parser**: Added grammar rules for `from uqstring import importnames` - **AST**: New `selectiveImportFile(filename, names)` tree type - **Source reader**: Modified `expandRec()` to filter definitions when expanding selective imports, with optional renaming for aliases The implementation reuses existing infrastructure - selective imports are expanded during the same phase as regular imports, just with filtering applied. ### Testing Tested with: - Basic selective import from a simple library - Multiple imports in one statement - Aliasing (`import X as Y`) - Importing from standard libraries (`maths.lib`) ### Note on diff size The large diff in `faustlexer.cpp`, `faustparser.cpp`, and `faustparser.hpp` is due to these being **generated files** that are regenerated by flex/bison. The actual source changes are minimal: | File | Lines changed | |------|---------------| | `faustlexer.l` | +2 | | `faustparser.y` | +14 | | `boxes.cpp` | +9 | | `boxes.hh` | +3 | | `global.cpp` | +1 | | `global.hh` | +1 | | `sourcereader.cpp` | +40 |