diff --git a/iclc2023/slides/src/EventEditor.jsx b/iclc2023/slides/src/EventEditor.jsx
index 45ad97114..bbb31cbec 100644
--- a/iclc2023/slides/src/EventEditor.jsx
+++ b/iclc2023/slides/src/EventEditor.jsx
@@ -28,7 +28,7 @@ function EventEditor({ code: initialCode }) {
await initAudio;
json.forEach((value) => {
const hap = new Hap(new TimeSpan(0, 1), new TimeSpan(0, 1), value);
- webaudioOutput(hap, 0.1, 1, 1);
+ webaudioOutput(hap, 0.01, 1, 1);
});
} else if (e.key === '.') {
stop();
diff --git a/iclc2023/slides/src/EventsDemo.jsx b/iclc2023/slides/src/EventsDemo.jsx
index 1bdb4e322..50aa72ccd 100644
--- a/iclc2023/slides/src/EventsDemo.jsx
+++ b/iclc2023/slides/src/EventsDemo.jsx
@@ -1,8 +1,8 @@
import EventEditor from './EventEditor.jsx';
-import { useState } from 'react';
+import Stepper from './Stepper.jsx';
const snippets = [
- [`{ "s": "cp" }`, 'Samples'],
+ [`{ "s": "cp", "crush": 4 }`, 'Samples'],
[`{ "s": "sawtooth", "note": "e3" }`, 'Oscillators'],
[
`[
@@ -24,21 +24,15 @@ const snippets = [
];
function EventsDemo() {
- const [step, setStep] = useState(1);
-
return (
-
- {snippets.slice(0, step).map(([code, label], i) => {
- const isActive = i === step - 1;
- return (
-
-
{label}
-
-
- );
- })}
- {step < snippets.length &&
}
-
+ (
+ <>
+ {label}
+
+ >
+ ))}
+ />
);
}
diff --git a/iclc2023/slides/src/Highlight.jsx b/iclc2023/slides/src/Highlight.jsx
index 0e9ac75ec..51415bd31 100644
--- a/iclc2023/slides/src/Highlight.jsx
+++ b/iclc2023/slides/src/Highlight.jsx
@@ -1,12 +1,17 @@
-import SyntaxHighlighter from 'react-syntax-highlighter';
+//import {Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
+//import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
+//import SyntaxHighlighter from 'react-syntax-highlighter';
import { atomOneDark } from 'react-syntax-highlighter/dist/esm/styles/hljs';
-
-Object.assign(atomOneDark.hljs, { padding: '10px' });
+import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
+import js from 'react-syntax-highlighter/dist/esm/languages/hljs/javascript';
+import hs from 'react-syntax-highlighter/dist/esm/languages/hljs/haskell';
+SyntaxHighlighter.registerLanguage('javascript', js);
+SyntaxHighlighter.registerLanguage('haskell', hs);
function Highlight({ code, language }) {
return (
-
+
{code}
diff --git a/iclc2023/slides/src/MiniComparison.jsx b/iclc2023/slides/src/MiniComparison.jsx
index 1196681d3..a9d2e5dcb 100644
--- a/iclc2023/slides/src/MiniComparison.jsx
+++ b/iclc2023/slides/src/MiniComparison.jsx
@@ -1,5 +1,5 @@
-import { useState } from 'react';
import { SlideRepl } from './SlideRepl.jsx';
+import Stepper from './Stepper.jsx';
const snippets = [
[`sound("bd [hh sd]")`, `sound(seq("bd", ["hh", "sd"]))`, 'Nested Sequences'], //
@@ -11,7 +11,6 @@ const snippets = [
];
function MiniComparison() {
- const [step, setStep] = useState(1);
return (
<>
@@ -19,25 +18,21 @@ function MiniComparison() {
External DSL
-
- {snippets.slice(0, step).map(([a, b, label], i) => {
- const isActive = i === step - 1;
- return (
-
-
{label}
-
-

-
-
-
-

-
-
+
(
+ <>
+ {label}
+
+

+
- );
- })}
-
- {step < snippets.length &&
}
+
+

+
+
+ >
+ ))}
+ />
>
);
}
diff --git a/iclc2023/slides/src/QueryDemo.jsx b/iclc2023/slides/src/QueryDemo.jsx
index 9a55fe0b1..d71178e41 100644
--- a/iclc2023/slides/src/QueryDemo.jsx
+++ b/iclc2023/slides/src/QueryDemo.jsx
@@ -1,22 +1,23 @@
import { SlideRepl } from './SlideRepl.jsx';
import Highlight from './Highlight.jsx';
-import { useState } from 'react';
+import Stepper from './Stepper.jsx';
const snippets = [
- [
, 'Logging Events'],
+ [
, 'Logging Events'],
[
<>
e.show()))`}
language="javascript"
/>
1/2 | sound:bd",
- "1/2 -> 3/4 | sound:hh",
- "3/4 -> 1/1 | sound:sd"
+ "0/1 -> 1/2 | s:bd crush:4",
+ "1/2 -> 3/4 | s:hh crush:4",
+ "3/4 -> 1/1 | s:sd crush:4"
]`}
/>
>,
@@ -25,20 +26,15 @@ const snippets = [
];
function QueryDemo() {
- const [step, setStep] = useState(1);
return (
-
- {snippets.slice(0, step).map(([snippet, label], i) => {
- const isActive = i === step - 1;
- return (
-
-
{label}
- {snippet}
-
- );
- })}
- {step < snippets.length &&
}
-
+ (
+ <>
+ {label}
+ {snippet}
+ >
+ ))}
+ />
);
}
diff --git a/iclc2023/slides/src/Slides.jsx b/iclc2023/slides/src/Slides.jsx
index e6794eb96..73d41bd9f 100644
--- a/iclc2023/slides/src/Slides.jsx
+++ b/iclc2023/slides/src/Slides.jsx
@@ -16,7 +16,18 @@ const loadedMDXFiles = await Promise.all(
}),
);
-const order = ['01', '02-0', '02-1', '02-2', 'mini-comparison', 'patterns-events', 'events-audio', '04'];
+const order = [
+ 'cover',
+ 'whatIsStrudel',
+ 'history',
+ 'hs2js',
+ 'mini-comparison',
+ 'patterns-events',
+ 'events-audio',
+ 'transpilation',
+ 'replflow',
+ 'systems',
+];
const slideEntries = order.map((name) => loadedMDXFiles.find(([file]) => file === name));
diff --git a/iclc2023/slides/src/Stepper.jsx b/iclc2023/slides/src/Stepper.jsx
new file mode 100644
index 000000000..f3427d602
--- /dev/null
+++ b/iclc2023/slides/src/Stepper.jsx
@@ -0,0 +1,20 @@
+import { useState } from 'react';
+
+function Stepper({ steps }) {
+ const [step, setStep] = useState(1);
+ return (
+
+ {steps.slice(0, step).map((snippet, i) => {
+ const isActive = i === step - 1;
+ return (
+
+ {snippet}
+
+ );
+ })}
+ {step < steps.length &&
}
+
+ );
+}
+
+export default Stepper;
diff --git a/iclc2023/slides/src/SyntaxComparison.jsx b/iclc2023/slides/src/SyntaxComparison.jsx
index 623323d9b..93d7bca59 100644
--- a/iclc2023/slides/src/SyntaxComparison.jsx
+++ b/iclc2023/slides/src/SyntaxComparison.jsx
@@ -1,6 +1,6 @@
-import { useState } from 'react';
import { SlideRepl } from './SlideRepl.jsx';
import Highlight from './Highlight.jsx';
+import Stepper from './Stepper.jsx';
const snippets = [
[`sound "bd ~ [sd cp]"`, [`sound("bd ~ [sd cp]")`], 'Mini Notation'], //
@@ -40,7 +40,6 @@ const snippets = [
];
function SyntaxComparison() {
- const [step, setStep] = useState(1);
return (
<>
@@ -48,35 +47,27 @@ function SyntaxComparison() {
Internal DSL / Fluent Interface
-
- {/*
*/}
- {snippets.slice(0, step).map(([hs, js, label], i) => {
- const isActive = i === step - 1;
- return (
-
-
{label}
+
(
+ <>
+ {label}
+
+
+

+
+
-
-

-
-
-
- {js.map((c, j) => (
-
-

-
-
- ))}
-
+ {js.map((c, j) => (
+
+

+
+
+ ))}
- );
- })}
-
- {step < snippets.length &&
}
+ >
+ ))}
+ />
>
);
}
diff --git a/iclc2023/slides/src/TranspilationDemo.jsx b/iclc2023/slides/src/TranspilationDemo.jsx
new file mode 100644
index 000000000..36ce41c28
--- /dev/null
+++ b/iclc2023/slides/src/TranspilationDemo.jsx
@@ -0,0 +1,91 @@
+import { useState, useCallback } from 'react';
+import { atomone } from '@uiw/codemirror-themes-all';
+import { CodeMirror, flash, useKeydown } from '@strudel.cycles/react';
+import { transpiler } from '@strudel.cycles/transpiler';
+import Highlight from './Highlight';
+import Stepper from './Stepper';
+import escodegen from 'escodegen';
+
+function getTranspiled(code) {
+ return transpiler(code, {
+ addReturn: false,
+ codegenOptions: {
+ format: escodegen.FORMAT_MINIFY,
+ },
+ });
+}
+
+function TranspilationEditor({ code: initialCode }) {
+ const [code, setCode] = useState(initialCode);
+ const [transpiled, setTranspiled] = useState(getTranspiled(initialCode));
+ const [view, setView] = useState();
+ useKeydown(
+ useCallback(
+ async (e) => {
+ if (view?.hasFocus) {
+ if (e.ctrlKey || e.altKey) {
+ if (e.code === 'Enter') {
+ /* if (getAudioContext().state !== 'running') {
+ alert('please click play to initialize the audio. you can use shortcuts after that!');
+ return;
+ } */
+ e.preventDefault();
+ flash(view);
+ const t = getTranspiled(code);
+ setTranspiled(t);
+ console.log('transpiled', t);
+ } else if (e.key === '.') {
+ stop();
+ e.preventDefault();
+ }
+ }
+ }
+ },
+ [code, view],
+ ),
+ );
+ return (
+ <>
+
{
+ setCode(v);
+ }}
+ theme={atomone}
+ onViewChanged={(v) => setView(v)}
+ fontSize={32}
+ />
+
+ ⬇️ transpiles to ⬇️ via acorn / estree-walker / escodegen
+
+
+ >
+ );
+}
+
+function TranspilationDemo() {
+ return (
+
+ ,
+ <>
+ ⬇️ calls ⬇️ via peggy
+
+ ➡️ location can be used for highlighting
+ >,
+ ]}
+ />
+
+ );
+}
+
+export default TranspilationDemo;
diff --git a/iclc2023/slides/src/slides/01.mdx b/iclc2023/slides/src/slides/cover.mdx
similarity index 100%
rename from iclc2023/slides/src/slides/01.mdx
rename to iclc2023/slides/src/slides/cover.mdx
diff --git a/iclc2023/slides/src/slides/02-1.mdx b/iclc2023/slides/src/slides/history.mdx
similarity index 100%
rename from iclc2023/slides/src/slides/02-1.mdx
rename to iclc2023/slides/src/slides/history.mdx
diff --git a/iclc2023/slides/src/slides/02-2.mdx b/iclc2023/slides/src/slides/hs2js.mdx
similarity index 100%
rename from iclc2023/slides/src/slides/02-2.mdx
rename to iclc2023/slides/src/slides/hs2js.mdx
diff --git a/iclc2023/slides/src/slides/04.mdx b/iclc2023/slides/src/slides/replflow.mdx
similarity index 100%
rename from iclc2023/slides/src/slides/04.mdx
rename to iclc2023/slides/src/slides/replflow.mdx
diff --git a/iclc2023/slides/src/slides/02-3.mdx b/iclc2023/slides/src/slides/systems.mdx
similarity index 100%
rename from iclc2023/slides/src/slides/02-3.mdx
rename to iclc2023/slides/src/slides/systems.mdx
diff --git a/iclc2023/slides/src/slides/transpilation.mdx b/iclc2023/slides/src/slides/transpilation.mdx
new file mode 100644
index 000000000..3e101aefa
--- /dev/null
+++ b/iclc2023/slides/src/slides/transpilation.mdx
@@ -0,0 +1,5 @@
+import TranspilationDemo from '../TranspilationDemo';
+
+# Transpilation
+
+
diff --git a/iclc2023/slides/src/slides/02-0.mdx b/iclc2023/slides/src/slides/whatIsStrudel.mdx
similarity index 100%
rename from iclc2023/slides/src/slides/02-0.mdx
rename to iclc2023/slides/src/slides/whatIsStrudel.mdx
diff --git a/packages/transpiler/transpiler.mjs b/packages/transpiler/transpiler.mjs
index fee9d542e..18f87bd3d 100644
--- a/packages/transpiler/transpiler.mjs
+++ b/packages/transpiler/transpiler.mjs
@@ -4,7 +4,7 @@ import { walk } from 'estree-walker';
import { isNoteWithOctave } from '@strudel.cycles/core';
export function transpiler(input, options = {}) {
- const { wrapAsync = false, addReturn = true, simpleLocs = false } = options;
+ const { wrapAsync = false, addReturn = true, simpleLocs = false, codegenOptions = {} } = options;
let ast = parse(input, {
ecmaVersion: 2022,
@@ -47,7 +47,7 @@ export function transpiler(input, options = {}) {
argument: expression,
};
}
- const output = escodegen.generate(ast);
+ const output = escodegen.generate(ast, codegenOptions);
if (wrapAsync) {
return `(async ()=>{${output}})()`;
}