remove bootstrap + Pattern.patternify
This commit is contained in:
parent
1890e65b75
commit
b9781915a4
7 changed files with 4 additions and 106 deletions
|
|
@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isPattern, Pattern } from './index.mjs';
|
import { isPattern } from './index.mjs';
|
||||||
|
|
||||||
let scoped = false;
|
let scoped = false;
|
||||||
export const evalScope = async (...args) => {
|
export const evalScope = async (...args) => {
|
||||||
|
|
@ -19,7 +19,7 @@ export const evalScope = async (...args) => {
|
||||||
console.warn(`evalScope: module with index ${i} could not be loaded:`, result.reason);
|
console.warn(`evalScope: module with index ${i} could not be loaded:`, result.reason);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Object.assign(globalThis, ...modules, Pattern.prototype.bootstrap());
|
Object.assign(globalThis, ...modules);
|
||||||
};
|
};
|
||||||
|
|
||||||
function safeEval(str, options = {}) {
|
function safeEval(str, options = {}) {
|
||||||
|
|
|
||||||
|
|
@ -581,21 +581,6 @@ export class Pattern {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
patternify(join, func) {
|
|
||||||
const pat = this;
|
|
||||||
return function (...args) {
|
|
||||||
// the problem here: args could be a pattern that has been
|
|
||||||
// turned into an object to add location to avoid object
|
|
||||||
// checking for every pattern method, we can remove it here...
|
|
||||||
// in the future, patternified args should be marked as well +
|
|
||||||
// some better object handling
|
|
||||||
args = args.map((arg) => (isPattern(arg) ? arg.fmap((value) => value.value || value) : arg));
|
|
||||||
const pat_arg = sequence(...args);
|
|
||||||
// arg.locations has to go somewhere..
|
|
||||||
return join(pat_arg.fmap((arg) => func.call(pat, arg)));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
asNumber() {
|
asNumber() {
|
||||||
return this.fmap(parseNumeral);
|
return this.fmap(parseNumeral);
|
||||||
}
|
}
|
||||||
|
|
@ -1921,83 +1906,3 @@ const { loopAt, loopat } = register(['loopAt', 'loopat'], function (factor, pat)
|
||||||
const { loopAtCps, loopatcps } = register(['loopAtCps', 'loopatcps'], function (factor, cps, pat) {
|
const { loopAtCps, loopatcps } = register(['loopAtCps', 'loopatcps'], function (factor, cps, pat) {
|
||||||
return _loopAt(factor, pat, cps);
|
return _loopAt(factor, pat, cps);
|
||||||
});
|
});
|
||||||
|
|
||||||
// problem: curried functions with spread arguments must have pat at the beginning
|
|
||||||
// with this, we cannot keep the pattern open at the end.. solution for now: use array to keep using pat as last arg
|
|
||||||
|
|
||||||
// these are the core composable functions. they are extended with Pattern.prototype.define below
|
|
||||||
Pattern.prototype.composable = { early, late, superimpose };
|
|
||||||
|
|
||||||
// adds Pattern.prototype.composable to given function as child functions
|
|
||||||
// then you can do transpose(2).late(0.2) instead of x => x.transpose(2).late(0.2)
|
|
||||||
export function makeComposable(func) {
|
|
||||||
Object.entries(Pattern.prototype.composable).forEach(([functionName, composable]) => {
|
|
||||||
// compose with dot
|
|
||||||
func[functionName] = (...args) => {
|
|
||||||
// console.log(`called ${functionName}(${args.join(',')})`);
|
|
||||||
const composition = compose(func, composable(...args));
|
|
||||||
// the composition itself must be composable too :)
|
|
||||||
// then you can do endless chaining transpose(2).late(0.2).fast(2) ...
|
|
||||||
return makeComposable(composition);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return func;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const patternify = (f) => (pata, pat) => pata.fmap((a) => f.call(pat, a)).innerJoin();
|
|
||||||
export const patternify2 = (f) =>
|
|
||||||
function (pata, patb, pat) {
|
|
||||||
return pata
|
|
||||||
.fmap((a) => (b) => f.call(pat, a, b))
|
|
||||||
.appLeft(patb)
|
|
||||||
.innerJoin();
|
|
||||||
};
|
|
||||||
export const patternify3 = (f) => (pata, patb, patc, pat) =>
|
|
||||||
pata
|
|
||||||
.fmap((a) => (b) => (c) => f.call(pat, a, b, c))
|
|
||||||
.appLeft(patb)
|
|
||||||
.appLeft(patc)
|
|
||||||
.innerJoin();
|
|
||||||
export const patternify4 = (f) => (pata, patb, patc, patd, pat) =>
|
|
||||||
pata
|
|
||||||
.fmap((a) => (b) => (c) => (d) => f.call(pat, a, b, c, d))
|
|
||||||
.appLeft(patb)
|
|
||||||
.appLeft(patc)
|
|
||||||
.appLeft(patd)
|
|
||||||
.innerJoin();
|
|
||||||
|
|
||||||
Pattern.prototype.patternified = [];
|
|
||||||
|
|
||||||
// call this after all Pattern.prototype.define calls have been executed! (right before evaluate)
|
|
||||||
Pattern.prototype.bootstrap = function () {
|
|
||||||
const bootstrapped = Object.fromEntries(
|
|
||||||
Object.entries(Pattern.prototype.composable).map(([functionName, composable]) => {
|
|
||||||
if (Pattern.prototype[functionName]) {
|
|
||||||
// without this, 'C^7'.m.chordBass.transpose(2) will throw "C^7".m.chordBass.transpose is not a function
|
|
||||||
// Pattern.prototype[functionName] = makeComposable(Pattern.prototype[functionName]); // is this needed?
|
|
||||||
}
|
|
||||||
return [functionName, curry(composable, makeComposable)];
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.patternified.forEach((prop) => {
|
|
||||||
// the following will patternify all functions in Pattern.prototype.patternified
|
|
||||||
Pattern.prototype[prop] = function (...args) {
|
|
||||||
return this.patternify((x) => x.innerJoin(), Pattern.prototype['_' + prop])(...args);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return bootstrapped;
|
|
||||||
};
|
|
||||||
|
|
||||||
// this will add func as name to list of composable / patternified functions.
|
|
||||||
// those lists will be used in bootstrap to curry and compose everything, to support various call patterns
|
|
||||||
Pattern.prototype.define = (name, func, options = {}) => {
|
|
||||||
if (options.composable) {
|
|
||||||
Pattern.prototype.composable[name] = func;
|
|
||||||
}
|
|
||||||
if (options.patternified) {
|
|
||||||
Pattern.prototype.patternified = Pattern.prototype.patternified.concat([name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Pattern.prototype.bootstrap(); // automatically bootstrap after new definition
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -225,9 +225,8 @@ function isPatternArg(parents) {
|
||||||
function hasModifierCall(parent) {
|
function hasModifierCall(parent) {
|
||||||
// TODO: modifiers are more than composables, for example every is not composable but should be seen as modifier..
|
// TODO: modifiers are more than composables, for example every is not composable but should be seen as modifier..
|
||||||
// need all prototypes of Pattern
|
// need all prototypes of Pattern
|
||||||
return (
|
return parent?.type === 'StaticMemberExpression';
|
||||||
parent?.type === 'StaticMemberExpression' && Object.keys(Pattern.prototype.composable).includes(parent.property)
|
// && Object.keys(Pattern.prototype.composable).includes(parent.property)
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const factories = Object.keys(Pattern.prototype.factories).concat(['mini']);
|
const factories = Object.keys(Pattern.prototype.factories).concat(['mini']);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,6 @@ export const transpose = register('transpose', function (intervalOrSemitones, pa
|
||||||
});
|
});
|
||||||
|
|
||||||
// example: transpose(3).late(0.2) will be equivalent to compose(transpose(3), late(0.2))
|
// example: transpose(3).late(0.2) will be equivalent to compose(transpose(3), late(0.2))
|
||||||
// TODO: add Pattern.define(name, function, options) that handles all the meta programming stuff
|
|
||||||
// TODO: find out how to patternify this function when it's standalone
|
|
||||||
// e.g. `stack(c3).superimpose(transpose(slowcat(7, 5)))` or
|
// e.g. `stack(c3).superimpose(transpose(slowcat(7, 5)))` or
|
||||||
// or even `stack(c3).superimpose(transpose.slowcat(7, 5))` or
|
// or even `stack(c3).superimpose(transpose.slowcat(7, 5))` or
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// import { Pattern, getFrequency, patternify2 } from '@strudel.cycles/core';
|
|
||||||
import * as strudel from '@strudel.cycles/core';
|
import * as strudel from '@strudel.cycles/core';
|
||||||
import { fromMidi, logger, toMidi } from '@strudel.cycles/core';
|
import { fromMidi, logger, toMidi } from '@strudel.cycles/core';
|
||||||
import './feedbackdelay.mjs';
|
import './feedbackdelay.mjs';
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,6 @@ const loadSoundfont = () => {};
|
||||||
evalScope(
|
evalScope(
|
||||||
// Tone,
|
// Tone,
|
||||||
strudel,
|
strudel,
|
||||||
strudel.Pattern.prototype.bootstrap(),
|
|
||||||
toneHelpersMocked,
|
toneHelpersMocked,
|
||||||
uiHelpersMocked,
|
uiHelpersMocked,
|
||||||
controls,
|
controls,
|
||||||
|
|
|
||||||
|
|
@ -757,8 +757,6 @@ Turns chord symbols into voicings, using the smoothest voice leading possible:
|
||||||
|
|
||||||
<MiniRepl tune={`stack("<C^7 A7 Dm7 G7>".voicings('lefthand'), "<C3 A2 D3 G2>").note()`} />
|
<MiniRepl tune={`stack("<C^7 A7 Dm7 G7>".voicings('lefthand'), "<C3 A2 D3 G2>").note()`} />
|
||||||
|
|
||||||
<!-- TODO: use voicing collection as first param + patternify. -->
|
|
||||||
|
|
||||||
### rootNotes(octave = 2)
|
### rootNotes(octave = 2)
|
||||||
|
|
||||||
Turns chord symbols into root notes of chords in given octave.
|
Turns chord symbols into root notes of chords in given octave.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue