move evaluate/evaluateBlock to different functions
This commit is contained in:
parent
1a7f464998
commit
160ef84b47
4 changed files with 152 additions and 109 deletions
|
|
@ -44,7 +44,7 @@ export const evalBlock = (strudelMirror) => {
|
||||||
if (block) {
|
if (block) {
|
||||||
// Flash the block being evaluated
|
// Flash the block being evaluated
|
||||||
strudelMirror.flash(200, { from: a, to: b });
|
strudelMirror.flash(200, { from: a, to: b });
|
||||||
strudelMirror.repl.evaluate(block, true, true, { range });
|
strudelMirror.repl.evaluateBlock(block, true, { range });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,48 @@ export function repl({
|
||||||
};
|
};
|
||||||
setTime(() => scheduler.now()); // TODO: refactor?
|
setTime(() => scheduler.now()); // TODO: refactor?
|
||||||
|
|
||||||
|
// Helper function to apply pattern transformations (solo, each, all)
|
||||||
|
// this should be abstracted more
|
||||||
|
function applyPatternTransforms(pattern) {
|
||||||
|
const allPatterns = Object.values(pPatterns);
|
||||||
|
|
||||||
|
if (allPatterns.length) {
|
||||||
|
let patterns = [];
|
||||||
|
let soloActive = false;
|
||||||
|
for (const [key, value] of Object.entries(pPatterns)) {
|
||||||
|
// handle soloed patterns ex: S$: s("bd!4")
|
||||||
|
const isSolod = key.length > 1 && key.startsWith('S');
|
||||||
|
if (isSolod && soloActive === false) {
|
||||||
|
// first time we see a soloed pattern, clear existing patterns
|
||||||
|
patterns = [];
|
||||||
|
soloActive = true;
|
||||||
|
}
|
||||||
|
if (!soloActive || (soloActive && isSolod)) {
|
||||||
|
const valWithState = value.withState((state) => state.setControls({ id: key }));
|
||||||
|
patterns.push(valWithState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (eachTransform) {
|
||||||
|
// Explicit lambda so only element (not index and array) are passed
|
||||||
|
patterns = patterns.map((x) => eachTransform(x));
|
||||||
|
}
|
||||||
|
pattern = stack(...patterns);
|
||||||
|
} else if (eachTransform) {
|
||||||
|
pattern = eachTransform(pattern);
|
||||||
|
}
|
||||||
|
if (allTransforms.length) {
|
||||||
|
for (const transform of allTransforms) {
|
||||||
|
pattern = transform(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPattern(pattern)) {
|
||||||
|
pattern = silence;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
const stop = () => {
|
const stop = () => {
|
||||||
codeBlocks = {};
|
codeBlocks = {};
|
||||||
blockPatterns.clear();
|
blockPatterns.clear();
|
||||||
|
|
@ -306,7 +348,7 @@ export function repl({
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const evaluate = async (code, autostart = true, blockBased = false, options = {}) => {
|
const evaluate = async (code, autostart = true) => {
|
||||||
if (!code) {
|
if (!code) {
|
||||||
throw new Error('no code to evaluate');
|
throw new Error('no code to evaluate');
|
||||||
}
|
}
|
||||||
|
|
@ -314,20 +356,60 @@ export function repl({
|
||||||
updateState({ code, pending: true });
|
updateState({ code, pending: true });
|
||||||
await injectPatternMethods();
|
await injectPatternMethods();
|
||||||
setTime(() => scheduler.now()); // TODO: refactor?
|
setTime(() => scheduler.now()); // TODO: refactor?
|
||||||
await beforeEval?.({ code, blockBased });
|
await beforeEval?.({ code, blockBased: false });
|
||||||
|
allTransforms = []; // reset all transforms
|
||||||
|
|
||||||
|
codeBlocks = {};
|
||||||
|
hush();
|
||||||
|
|
||||||
|
if (mondo) {
|
||||||
|
code = `mondolang\`${code}\``;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { pattern, meta } = await _evaluate(code, transpiler, transpilerOptions);
|
||||||
|
|
||||||
|
pattern = applyPatternTransforms(pattern);
|
||||||
|
|
||||||
|
logger(`[eval] code updated`);
|
||||||
|
pattern = await setPattern(pattern, autostart);
|
||||||
|
updateState({
|
||||||
|
miniLocations: meta?.miniLocations || [],
|
||||||
|
widgets: meta?.widgets || [],
|
||||||
|
sliders: meta?.sliders || [],
|
||||||
|
activeCode: code,
|
||||||
|
pattern,
|
||||||
|
evalError: undefined,
|
||||||
|
schedulerError: undefined,
|
||||||
|
pending: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEval?.({ code, pattern, meta, range: undefined, widgetRemoved: false });
|
||||||
|
return pattern;
|
||||||
|
} catch (err) {
|
||||||
|
logger(`[eval] error: ${err.message}`, 'error');
|
||||||
|
console.error(err);
|
||||||
|
updateState({ evalError: err, pending: false });
|
||||||
|
onEvalError?.(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const evaluateBlock = async (code, autostart = true, options = {}) => {
|
||||||
|
if (!code) {
|
||||||
|
throw new Error('no code to evaluate');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
updateState({ code, pending: true });
|
||||||
|
await injectPatternMethods();
|
||||||
|
setTime(() => scheduler.now()); // TODO: refactor?
|
||||||
|
await beforeEval?.({ code, blockBased: true });
|
||||||
allTransforms = []; // reset all transforms
|
allTransforms = []; // reset all transforms
|
||||||
|
|
||||||
const transpilerOptionsWithBlock = {
|
const transpilerOptionsWithBlock = {
|
||||||
...transpilerOptions,
|
...transpilerOptions,
|
||||||
blockBased,
|
blockBased: true,
|
||||||
range: options.range || [],
|
range: options.range || [],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!blockBased) {
|
|
||||||
codeBlocks = {};
|
|
||||||
hush();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mondo) {
|
if (mondo) {
|
||||||
code = `mondolang\`${code}\``;
|
code = `mondolang\`${code}\``;
|
||||||
}
|
}
|
||||||
|
|
@ -337,13 +419,11 @@ export function repl({
|
||||||
// Track activeVisualizer cleanup: check if any block's visualizer was removed
|
// Track activeVisualizer cleanup: check if any block's visualizer was removed
|
||||||
let widgetRemoved = false;
|
let widgetRemoved = false;
|
||||||
|
|
||||||
if (blockBased) {
|
|
||||||
const labels = meta.labels || [];
|
const labels = meta.labels || [];
|
||||||
|
|
||||||
// Store code blocks in dictionary using labels as keys
|
// Store code blocks in dictionary using labels as keys
|
||||||
if (labels.length > 0) {
|
if (labels.length > 0) {
|
||||||
for (let i = 0; i < labels.length; i++) {
|
for (let i = 0; i < labels.length; i++) {
|
||||||
// processLabeledBlock(labels, i, code, options, meta);
|
|
||||||
// processing transpiler output instead of code is simply to avoid
|
// processing transpiler output instead of code is simply to avoid
|
||||||
// extra regex in detecting whether or not an inline widget has been commented out
|
// extra regex in detecting whether or not an inline widget has been commented out
|
||||||
processLabeledBlock(labels, i, meta.output, options, meta);
|
processLabeledBlock(labels, i, meta.output, options, meta);
|
||||||
|
|
@ -365,8 +445,6 @@ export function repl({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For block-based evaluation, collect from all blocks
|
|
||||||
// The highlight/widget/slider systems will handle selective updates based on the range
|
|
||||||
meta.miniLocations = collectFromBlocks('miniLocations');
|
meta.miniLocations = collectFromBlocks('miniLocations');
|
||||||
meta.widgets = collectFromBlocks('widgets');
|
meta.widgets = collectFromBlocks('widgets');
|
||||||
meta.sliders = collectFromBlocks('sliders');
|
meta.sliders = collectFromBlocks('sliders');
|
||||||
|
|
@ -374,6 +452,7 @@ export function repl({
|
||||||
// Track activeVisualizer cleanup: check if any block's visualizer was removed
|
// Track activeVisualizer cleanup: check if any block's visualizer was removed
|
||||||
const blocksToUpdate = labels.map((label) => label.name);
|
const blocksToUpdate = labels.map((label) => label.name);
|
||||||
|
|
||||||
|
// this is the hackiest bit
|
||||||
for (const [key, block] of Object.entries(codeBlocks)) {
|
for (const [key, block] of Object.entries(codeBlocks)) {
|
||||||
if (blocksToUpdate.includes(key)) {
|
if (blocksToUpdate.includes(key)) {
|
||||||
// This block was just updated
|
// This block was just updated
|
||||||
|
|
@ -387,51 +466,14 @@ export function repl({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const allPatterns = Object.values(pPatterns);
|
|
||||||
|
|
||||||
if (blockBased) {
|
|
||||||
pPatterns = Object.fromEntries(
|
pPatterns = Object.fromEntries(
|
||||||
Object.entries(pPatterns).filter(([key]) => {
|
Object.entries(pPatterns).filter(([key]) => {
|
||||||
return Object.keys(codeBlocks).includes(key);
|
return Object.keys(codeBlocks).includes(key);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
if (allPatterns.length) {
|
pattern = applyPatternTransforms(pattern);
|
||||||
let patterns = [];
|
|
||||||
let soloActive = false;
|
|
||||||
for (const [key, value] of Object.entries(pPatterns)) {
|
|
||||||
// handle soloed patterns ex: S$: s("bd!4")
|
|
||||||
const isSolod = key.length > 1 && key.startsWith('S');
|
|
||||||
if (isSolod && soloActive === false) {
|
|
||||||
// first time we see a soloed pattern, clear existing patterns
|
|
||||||
patterns = [];
|
|
||||||
soloActive = true;
|
|
||||||
}
|
|
||||||
if (!soloActive || (soloActive && isSolod)) {
|
|
||||||
const valWithState = value.withState((state) => state.setControls({ id: key }));
|
|
||||||
patterns.push(valWithState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (eachTransform) {
|
|
||||||
// Explicit lambda so only element (not index and array) are passed
|
|
||||||
patterns = patterns.map((x) => eachTransform(x));
|
|
||||||
}
|
|
||||||
pattern = stack(...patterns);
|
|
||||||
} else if (eachTransform) {
|
|
||||||
pattern = eachTransform(pattern);
|
|
||||||
}
|
|
||||||
if (allTransforms.length) {
|
|
||||||
for (const transform of allTransforms) {
|
|
||||||
pattern = transform(pattern);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isPattern(pattern)) {
|
|
||||||
pattern = silence;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger(`[eval] code updated`);
|
logger(`[eval] code updated`);
|
||||||
pattern = await setPattern(pattern, autostart);
|
pattern = await setPattern(pattern, autostart);
|
||||||
|
|
@ -455,8 +497,9 @@ export function repl({
|
||||||
onEvalError?.(err);
|
onEvalError?.(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setCode = (code) => updateState({ code });
|
const setCode = (code) => updateState({ code });
|
||||||
return { scheduler, evaluate, start, stop, pause, setCps, setPattern, setCode, toggle, state };
|
return { scheduler, evaluate, evaluateBlock, start, stop, pause, setCps, setPattern, setCode, toggle, state };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getTrigger =
|
export const getTrigger =
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const skippedExamples = [
|
||||||
'accelerationX',
|
'accelerationX',
|
||||||
'defaultmidimap',
|
'defaultmidimap',
|
||||||
'midimaps',
|
'midimaps',
|
||||||
'clearScope'
|
'clearScope',
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('runs examples', () => {
|
describe('runs examples', () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue