Skip to content

Commit

Permalink
Merge pull request #805 from tidalcycles/pq-functions
Browse files Browse the repository at this point in the history
tidal style d1 ... d9 functions + more
  • Loading branch information
felixroos committed Nov 17, 2023
2 parents 49aa9cf + 265f01e commit 47a6af2
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 31 deletions.
5 changes: 0 additions & 5 deletions packages/core/evaluate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,5 @@ export const evaluate = async (code, transpiler) => {
// if no transpiler is given, we expect a single instruction (!wrapExpression)
const options = { wrapExpression: !!transpiler };
let evaluated = await safeEval(code, options);
if (!isPattern(evaluated)) {
console.log('evaluated', evaluated);
const message = `got "${typeof evaluated}" instead of pattern`;
throw new Error(message + (typeof evaluated === 'function' ? ', did you forget to call a function?' : '.'));
}
return { mode: 'javascript', pattern: evaluated, meta };
};
14 changes: 7 additions & 7 deletions packages/core/pattern.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1178,7 +1178,7 @@ export function reify(thing) {
* @return {Pattern}
* @synonyms polyrhythm, pr
* @example
* stack(g3, b3, [e4, d4]).note() // "g3,b3,[e4,d4]".note()
* stack("g3", "b3", ["e4", "d4"]).note() // "g3,b3,[e4,d4]".note()
*/
export function stack(...pats) {
// Array test here is to avoid infinite recursions..
Expand All @@ -1193,7 +1193,7 @@ export function stack(...pats) {
*
* @return {Pattern}
* @example
* slowcat(e5, b4, [d5, c5])
* slowcat("e5", "b4", ["d5", "c5"])
*
*/
export function slowcat(...pats) {
Expand Down Expand Up @@ -1237,7 +1237,7 @@ export function slowcatPrime(...pats) {
* @synonyms slowcat
* @return {Pattern}
* @example
* cat(e5, b4, [d5, c5]).note() // "<e5 b4 [d5 c5]>".note()
* cat("e5", "b4", ["d5", "c5"]).note() // "<e5 b4 [d5 c5]>".note()
*
*/
export function cat(...pats) {
Expand All @@ -1247,7 +1247,7 @@ export function cat(...pats) {
/** Like {@link Pattern.seq}, but each step has a length, relative to the whole.
* @return {Pattern}
* @example
* timeCat([3,e3],[1, g3]).note() // "e3@3 g3".note()
* timeCat([3,"e3"],[1, "g3"]).note() // "e3@3 g3".note()
*/
export function timeCat(...timepats) {
const total = timepats.map((a) => a[0]).reduce((a, b) => a.add(b), Fraction(0));
Expand Down Expand Up @@ -1287,7 +1287,7 @@ export function sequence(...pats) {
/** Like **cat**, but the items are crammed into one cycle.
* @synonyms fastcat, sequence
* @example
* seq(e5, b4, [d5, c5]).note() // "e5 b4 [d5 c5]".note()
* seq("e5", "b4", ["d5", "c5"]).note() // "e5 b4 [d5 c5]".note()
*
*/
export function seq(...pats) {
Expand Down Expand Up @@ -1975,9 +1975,9 @@ export const press = register('press', function (pat) {
* s("hh*3")
* )
*/
export const hush = register('hush', function (pat) {
Pattern.prototype.hush = function () {
return silence;
});
};

/**
* Applies `rev` to a pattern every other cycle, so that the pattern alternates between forwards and backwards.
Expand Down
60 changes: 49 additions & 11 deletions packages/core/repl.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { evaluate as _evaluate } from './evaluate.mjs';
import { logger } from './logger.mjs';
import { setTime } from './time.mjs';
import { evalScope } from './evaluate.mjs';
import { register } from './pattern.mjs';
import { register, Pattern, isPattern, silence, stack } from './pattern.mjs';

export function repl({
interval,
Expand All @@ -24,22 +24,37 @@ export function repl({
getTime,
onToggle,
});
let playPatterns = [];
let pPatterns = {};
let allTransform;

const hush = function () {
pPatterns = {};
allTransform = undefined;
return silence;
};

const setPattern = (pattern, autostart = true) => {
pattern = editPattern?.(pattern) || pattern;
scheduler.setPattern(pattern, autostart);
};
setTime(() => scheduler.now()); // TODO: refactor?
const evaluate = async (code, autostart = true) => {
const evaluate = async (code, autostart = true, shouldHush = true) => {
if (!code) {
throw new Error('no code to evaluate');
}
try {
await beforeEval?.({ code });
playPatterns = [];
shouldHush && hush();
let { pattern, meta } = await _evaluate(code, transpiler);
if (playPatterns.length) {
pattern = pattern.stack(...playPatterns);
if (Object.keys(pPatterns).length) {
pattern = stack(...Object.values(pPatterns));
}
if (allTransform) {
pattern = allTransform(pattern);
}
if (!isPattern(pattern)) {
const message = `got "${typeof evaluated}" instead of pattern`;
throw new Error(message + (typeof evaluated === 'function' ? ', did you forget to call a function?' : '.'));
}
logger(`[eval] code updated`);
setPattern(pattern, autostart);
Expand All @@ -62,10 +77,32 @@ export function repl({
return pat.loopAtCps(cycles, scheduler.cps);
});

const play = register('play', (pat) => {
playPatterns.push(pat);
return pat;
});
Pattern.prototype.p = function (id) {
pPatterns[id] = this;
return this;
};
Pattern.prototype.q = function (id) {
return silence;
};

const all = function (transform) {
allTransform = transform;
return silence;
};

for (let i = 1; i < 10; ++i) {
Object.defineProperty(Pattern.prototype, `d${i}`, {
get() {
return this.p(i);
},
});
Object.defineProperty(Pattern.prototype, `p${i}`, {
get() {
return this.p(i);
},
});
Pattern.prototype[`q${i}`] = silence;
}

const fit = register('fit', (pat) =>
pat.withHap((hap) =>
Expand All @@ -80,7 +117,8 @@ export function repl({
evalScope({
loopAt,
fit,
play,
all,
hush,
setCps,
setcps: setCps,
setCpm,
Expand Down
3 changes: 0 additions & 3 deletions packages/transpiler/test/transpiler.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ describe('transpiler', () => {
it('wraps backtick string with mini and adds location', () => {
expect(transpiler('`c3`', simple).output).toEqual("m('c3', 0);");
});
it('replaces note variables with note strings', () => {
expect(transpiler('seq(c3, d3)', simple).output).toEqual("seq('c3', 'd3');");
});
it('keeps tagged template literal as is', () => {
expect(transpiler('xxx`c3`', simple).output).toEqual('xxx`c3`;');
});
Expand Down
5 changes: 0 additions & 5 deletions packages/transpiler/transpiler.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ export function transpiler(input, options = {}) {
});
return this.replace(widgetWithLocation(node));
}
// TODO: remove pseudo note variables?
if (node.type === 'Identifier' && isNoteWithOctave(node.name)) {
this.skip();
return this.replace({ type: 'Literal', value: node.name });
}
},
leave(node, parent, prop, index) {},
});
Expand Down

0 comments on commit 47a6af2

Please sign in to comment.