1<!doctype html> 2<html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 <title>tidal.html</title> 7 </head> 8 <body style="margin: 0; padding: 0"> 9 <textarea id="code" style="width: 100%; height: 200px"></textarea> 10 <pre id="result"></pre> 11 <script src="https://unpkg.com/hs2js@0.0.8"></script> 12 <script src="https://unpkg.com/@strudel/web@1.0.3"></script> 13 <script> 14 const { initStrudel } = strudel; 15 const { run, parse, setBase, loadParser } = hs2js; 16 setBase('https://unpkg.com/hs2js@0.0.4/dist/'); 17 const ready = loadParser(); 18 initStrudel({ 19 prebake: () => samples('github:tidalcycles/dirt-samples'), 20 }); 21 22 const textarea = document.getElementById('code'); 23 if (window.location.hash) { 24 textarea.value = atob(window.location.hash.slice(1)); 25 } else { 26 textarea.value = 'd1 $ s "jvbass(3,8)"'; 27 } 28 textarea.addEventListener('input', (e) => { 29 window.location.hash = btoa(e.target.value); 30 update(); 31 }); 32 update(); 33 34 function getInfixOperators() { 35 let operators = { 36 '>': 'set', 37 '#': 'set', 38 '+': 'add', 39 '-': 'sub', 40 '*': 'mul', 41 '/': 'div', 42 }; 43 let alignments = { 44 in: (s) => '|' + s, 45 out: (s) => s + '|', 46 mix: (s) => '|' + s + '|', 47 }; 48 let ops = {}; 49 Object.entries(operators).forEach(([o, name]) => { 50 // operator without alignment 51 ops[o] = (l, r) => reify(l)[name](reify(r)); 52 Object.entries(alignments).forEach(([a, getSymbol]) => { 53 // get symbol with alignment 54 let symbol = getSymbol(o); 55 ops[symbol] = (l, r) => reify(l)[name][a](reify(r)); 56 }); 57 }); 58 ops['~>'] = (l, r) => reify(l).late(reify(r)); 59 ops['<~'] = (l, r) => reify(l).early(reify(r)); 60 ops['<$>'] = (l, r) => reify(r).fmap(l).outerJoin(); // is this right? 61 return ops; 62 } 63 const ops = getInfixOperators(); 64 65 async function update() { 66 let result, tree; 67 await ready; 68 try { 69 tree = parse(textarea.value); 70 } catch (err) { 71 console.warn('parse error'); 72 console.error(err); 73 } 74 console.log('parsed tree'); 75 console.log(tree.rootNode.toString()); 76 try { 77 let patterns = {}; 78 window.p = (name, pattern) => { 79 patterns[name] = pattern; 80 }; 81 window.d1 = (pat) => window.p(1, pat); 82 window.d2 = (pat) => window.p(2, pat); 83 window.d3 = (pat) => window.p(3, pat); 84 window.rot = late; 85 result = run(tree.rootNode, window, ops); 86 if (Object.values(patterns).length) { 87 stack(...Object.values(patterns)).play(); 88 } 89 } catch (err) { 90 console.warn('eval error'); 91 console.error(err); 92 result = 'ERROR: ' + err.message; 93 } 94 document.getElementById('result').innerHTML = 'Result: ' + result; 95 } 96 </script> 97 </body> 98</html>