diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index fec6c39ae..0edc4dfcf 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -400,7 +400,7 @@ const generic_params = [ * @example * freq("220 110 440 110").s("superzow").osc() * @example - * freq("110".mulOut(".5 1.5 .6 [2 3]")).s("superzow").osc() + * freq("110".mul.out(".5 1.5 .6 [2 3]")).s("superzow").osc() * */ ['f', 'freq', ''], diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 6c831ffe3..fd56c4085 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -1463,53 +1463,43 @@ function _composeOp(a, b, func) { // generate methods to do what and how for (const [what, [op, preprocess]] of Object.entries(composers)) { - for (const how of hows) { - Pattern.prototype[what + how] = function (...other) { - var pat = this; - other = sequence(other); - if (preprocess) { - pat = preprocess(pat); - other = preprocess(other); - } - var result; - // hack to remove undefs when doing 'keepif' - if (what === 'keepif') { - // avoid union, as we want to throw away the value of 'b' completely - result = pat['_op' + how](other, (a) => (b) => op(a, b)); - result = result.removeUndefineds(); - } else { - result = pat['_op' + how](other, (a) => (b) => _composeOp(a, b, op)); - } - return result; - }; - if (how === 'Squeeze') { - // support 'squeezeIn' longhand - Pattern.prototype[what + 'SqueezeIn'] = Pattern.prototype[what + how]; + + Object.defineProperty(Pattern.prototype, what, { + // a getter that returns a function, so 'pat' can be + // accessed by closures that are methods of that function.. + get: function() { + const pat = this; + + // wrap the 'in' function as default behaviour + const wrapper = (...other) => pat[what]['in'](...other); + + // add methods to that function for each behaviour + for (const how of hows) { + wrapper[how.toLowerCase()] = function (...other) { + var howpat = pat; + other = sequence(other); + if (preprocess) { + howpat = preprocess(howpat); + other = preprocess(other); + } + var result; + // hack to remove undefs when doing 'keepif' + if (what === 'keepif') { + // avoid union, as we want to throw away the value of 'b' completely + result = howpat['_op' + how](other, (a) => (b) => op(a, b)); + result = result.removeUndefineds(); + } else { + result = howpat['_op' + how](other, (a) => (b) => _composeOp(a, b, op)); + } + return result; + } + } + wrapper.squeezeIn = wrapper.squeeze + + return wrapper; } - if (how === 'In') { - // set 'in' to default, but with magic properties to pick a different 'how' - Object.defineProperty(Pattern.prototype, what, { - // a getter that returns a function, so 'pat' can be - // accessed by closures that are methods of that function.. - get: function() { - const pat = this; - // wrap the 'in' function as default behaviour - const wrapper = (...other) => pat[what + "In"](...other); - // add methods to that function to pick alternative behaviours - for (const wraphow of hows) { - wrapper[wraphow.toLowerCase()] = (...other) => pat[what + wraphow](...other); - } - - return wrapper; - } - }); - } else { - // default what to 'set', e.g. squeeze = setSqueeze - if (what === 'set') { - Pattern.prototype[how.toLowerCase()] = Pattern.prototype[what + how]; - } - } - } + }); + } // binary composers @@ -1524,14 +1514,14 @@ function _composeOp(a, b, func) { * .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~") * .slow(4) */ - Pattern.prototype.struct = Pattern.prototype.keepifOut; - Pattern.prototype.structAll = Pattern.prototype.keepOut; - Pattern.prototype.mask = Pattern.prototype.keepifIn; - Pattern.prototype.maskAll = Pattern.prototype.keepIn; - Pattern.prototype.reset = Pattern.prototype.keepifTrig; - Pattern.prototype.resetAll = Pattern.prototype.keepTrig; - Pattern.prototype.restart = Pattern.prototype.keepifTrigzero; - Pattern.prototype.restartAll = Pattern.prototype.keepTrigzero; + Pattern.prototype.struct = function(...args) { return this.keepif.out(...args) } + Pattern.prototype.structAll = function(...args) { return this.keep.out(...args) } + Pattern.prototype.mask = function(...args) { return this.keepif.in(...args) } + Pattern.prototype.maskAll = function(...args) { return this.keep.in(...args) } + Pattern.prototype.reset = function(...args) { return this.keepif.trig(...args) } + Pattern.prototype.resetAll = function(...args) { return this.keep.trig(...args) } + Pattern.prototype.restart = function(...args) { return this.keepif.trigzero(...args) } + Pattern.prototype.restartAll = function(...args) { return this.keep.trigzero(...args) } })(); // methods of Pattern that get callable factories @@ -1901,6 +1891,7 @@ Pattern.prototype.range2 = function (...args) { }; // call this after all Pattern.prototype.define calls have been executed! (right before evaluate) +// (but isn't this called for every define call anyway?) Pattern.prototype.bootstrap = function () { // makeComposable(Pattern.prototype); const bootstrapped = Object.fromEntries( diff --git a/packages/core/test/pattern.test.mjs b/packages/core/test/pattern.test.mjs index 6571080e9..72365d131 100644 --- a/packages/core/test/pattern.test.mjs +++ b/packages/core/test/pattern.test.mjs @@ -156,32 +156,32 @@ describe('Pattern', () => { describe('add()', () => { it('can structure In()', () => { expect(pure(3).add(pure(4)).query(st(0, 1))[0].value).toBe(7); - expect(pure(3).addIn(pure(4)).query(st(0, 1))[0].value).toBe(7); + expect(pure(3).add.in(pure(4)).query(st(0, 1))[0].value).toBe(7); }); it('can structure Out()', () => { - sameFirst(sequence(1, 2).addOut(4), sequence(5, 6).struct(true)); + sameFirst(sequence(1, 2).add.out(4), sequence(5, 6).struct(true)); }); it('can Mix() structure', () => { - expect(sequence(1, 2).addMix(silence, 5, silence).firstCycle()).toStrictEqual([ + expect(sequence(1, 2).add.mix(silence, 5, silence).firstCycle()).toStrictEqual([ new Hap(ts(1 / 3, 1 / 2), ts(1 / 3, 1 / 2), 6), new Hap(ts(1 / 2, 2 / 3), ts(1 / 2, 2 / 3), 7), ]); }); it('can Trig() structure', () => { sameFirst( - slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).addTrig(20, 30).early(2), + slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).add.trig(20, 30).early(2), sequence(26, 27, 36, 37), ); }); it('can Trigzero() structure', () => { sameFirst( - slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).addTrigzero(20, 30).early(2), + slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).add.trigzero(20, 30).early(2), sequence(21, 22, 31, 32), ); }); it('can Squeeze() structure', () => { sameFirst( - sequence(1, [2, 3]).addSqueeze(sequence(10, 20, 30)), + sequence(1, [2, 3]).add.squeeze(sequence(10, 20, 30)), sequence( [11, 21, 31], [ @@ -193,7 +193,7 @@ describe('Pattern', () => { }); it('can SqueezeOut() structure', () => { sameFirst( - sequence(1, [2, 3]).addSqueezeOut(10, 20, 30), + sequence(1, [2, 3]).add.squeezeout(10, 20, 30), sequence([11, [12, 13]], [21, [22, 23]], [31, [32, 33]]), ); }); @@ -204,32 +204,32 @@ describe('Pattern', () => { describe('keep()', () => { it('can structure In()', () => { expect(pure(3).keep(pure(4)).query(st(0, 1))[0].value).toBe(3); - expect(pure(3).keepIn(pure(4)).query(st(0, 1))[0].value).toBe(3); + expect(pure(3).keep.in(pure(4)).query(st(0, 1))[0].value).toBe(3); }); it('can structure Out()', () => { - sameFirst(sequence(1, 2).keepOut(4), sequence(1, 2).struct(true)); + sameFirst(sequence(1, 2).keep.out(4), sequence(1, 2).struct(true)); }); it('can Mix() structure', () => { - expect(sequence(1, 2).keepMix(silence, 5, silence).firstCycle()).toStrictEqual([ + expect(sequence(1, 2).keep.mix(silence, 5, silence).firstCycle()).toStrictEqual([ new Hap(ts(1 / 3, 1 / 2), ts(1 / 3, 1 / 2), 1), new Hap(ts(1 / 2, 2 / 3), ts(1 / 2, 2 / 3), 2), ]); }); it('can Trig() structure', () => { sameFirst( - slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepTrig(20, 30).early(2), + slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keep.trig(20, 30).early(2), sequence(6, 7, 6, 7), ); }); it('can Trigzero() structure', () => { sameFirst( - slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepTrigzero(20, 30).early(2), + slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keep.trigzero(20, 30).early(2), sequence(1, 2, 1, 2), ); }); it('can Squeeze() structure', () => { sameFirst( - sequence(1, [2, 3]).keepSqueeze(sequence(10, 20, 30)), + sequence(1, [2, 3]).keep.squeeze(sequence(10, 20, 30)), sequence( [1, 1, 1], [ @@ -239,39 +239,39 @@ describe('Pattern', () => { ), ); }); - it('can SqueezeOut() structure', () => { - sameFirst(sequence(1, [2, 3]).keepSqueezeOut(10, 20, 30), sequence([1, [2, 3]], [1, [2, 3]], [1, [2, 3]])); + it('can squeezeOut() structure', () => { + sameFirst(sequence(1, [2, 3]).keep.squeezeout(10, 20, 30), sequence([1, [2, 3]], [1, [2, 3]], [1, [2, 3]])); }); }); describe('keepif()', () => { it('can structure In()', () => { sameFirst(sequence(3, 4).keepif(true, false), sequence(3, silence)); - sameFirst(sequence(3, 4).keepifIn(true, false), sequence(3, silence)); + sameFirst(sequence(3, 4).keepif.in(true, false), sequence(3, silence)); }); it('can structure Out()', () => { - sameFirst(pure(1).keepifOut(true, false), sequence(1, silence)); + sameFirst(pure(1).keepif.out(true, false), sequence(1, silence)); }); it('can Mix() structure', () => { - expect(sequence(1, 2).keepifMix(false, true, false).firstCycle()).toStrictEqual([ + expect(sequence(1, 2).keepif.mix(false, true, false).firstCycle()).toStrictEqual([ new Hap(ts(1 / 3, 1 / 2), ts(1 / 3, 1 / 2), 1), new Hap(ts(1 / 2, 2 / 3), ts(1 / 2, 2 / 3), 2), ]); }); it('can Trig() structure', () => { sameFirst( - slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepifTrig(false, true).early(2), + slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepif.trig(false, true).early(2), sequence(silence, silence, 6, 7), ); }); it('can Trigzero() structure', () => { sameFirst( - slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepifTrigzero(false, true).early(2), + slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepif.trigzero(false, true).early(2), sequence(silence, silence, 1, 2), ); }); it('can Squeeze() structure', () => { sameFirst( - sequence(1, [2, 3]).keepifSqueeze(sequence(true, true, false)), + sequence(1, [2, 3]).keepif.squeeze(sequence(true, true, false)), sequence( [1, 1, silence], [ @@ -282,7 +282,7 @@ describe('Pattern', () => { ); }); it('can SqueezeOut() structure', () => { - sameFirst(sequence(1, [2, 3]).keepifSqueezeOut(true, true, false), sequence([1, [2, 3]], [1, [2, 3]], silence)); + sameFirst(sequence(1, [2, 3]).keepif.squeezeout(true, true, false), sequence([1, [2, 3]], [1, [2, 3]], silence)); }); }); describe('sub()', () => { @@ -320,15 +320,15 @@ describe('Pattern', () => { it('Can set things with plain values', () => { sameFirst(sequence(1, 2, 3).set(4), sequence(4).fast(3)); }); - describe('setOut()', () => { + describe('set.out()', () => { it('Can set things with structure from second pattern', () => { - sameFirst(sequence(1, 2).setOut(4), pure(4).mask(true, true)); + sameFirst(sequence(1, 2).set.out(4), pure(4).mask(true, true)); }); }); - describe('setSqueeze()', () => { + describe('set.squeeze()', () => { it('Can squeeze one pattern inside the haps of another', () => { sameFirst( - sequence(1, [2, 3]).setSqueeze(sequence('a', 'b', 'c')), + sequence(1, [2, 3]).set.squeeze(sequence('a', 'b', 'c')), sequence( ['a', 'b', 'c'], [ @@ -338,7 +338,7 @@ describe('Pattern', () => { ), ); sameFirst( - sequence(1, [2, 3]).setSqueeze('a', 'b', 'c'), + sequence(1, [2, 3]).set.squeeze('a', 'b', 'c'), sequence( ['a', 'b', 'c'], [