diff --git a/packages/hs2js/src/hs2js.mjs b/packages/hs2js/src/hs2js.mjs index 4161b0e6..227a42b2 100644 --- a/packages/hs2js/src/hs2js.mjs +++ b/packages/hs2js/src/hs2js.mjs @@ -52,6 +52,9 @@ function curry(patterns, body, scope, ops) { export function run(node, scope, ops = {}) { let runInScope = (node, scp = scope) => run(node, scp, ops); //console.log("node", node.type, node.text); + if (ops[node.type]) { + return ops[node.type](node); + } switch (node.type) { case 'ERROR': throw new Error(`invalid syntax: "${node.text}"`); diff --git a/packages/tidal/tidal.mjs b/packages/tidal/tidal.mjs index 00a32021..2c3c8900 100644 --- a/packages/tidal/tidal.mjs +++ b/packages/tidal/tidal.mjs @@ -1,6 +1,5 @@ import { reify } from '@strudel/core'; -import { miniAllStrings } from '@strudel/mini'; -import { evaluate, loadParser } from 'hs2js'; +import { loadParser, run, parse } from 'hs2js'; function getInfixOperators() { let operators = { @@ -29,12 +28,15 @@ function getInfixOperators() { ops['~>'] = (l, r) => reify(l).late(reify(r)); ops['<~'] = (l, r) => reify(l).early(reify(r)); ops['<$>'] = (l, r) => reify(r).fmap(l).outerJoin(); // is this right? + ops['string'] = (node) => { + const str = node.text.slice(1, -1); + return m(str, 1); + }; return ops; } const ops = getInfixOperators(); export async function initTidal() { - miniAllStrings(); // TODO: get rid of this and implement custom string parser in hs2js // TODO: implement this in regular land window.d1 = (pat) => pat.p('d1'); window.d2 = (pat) => pat.p('d2'); @@ -45,6 +47,10 @@ export async function initTidal() { window.d7 = (pat) => pat.p('d7'); window.d8 = (pat) => pat.p('d8'); window.d9 = (pat) => pat.p('d9'); + window.minicurry = (str) => (loc) => { + console.log('minicurry', str, loc); + return m(str, loc); + }; return loadParser(); } @@ -52,5 +58,50 @@ export function tidal(code) { if (Array.isArray(code)) { code = code.join(''); } - return evaluate(code, window, ops); + let ast = parse(code).rootNode; + // ast = transpile(ast); + console.log('ast', ast); + return run(ast, window, ops); +} + +function edit(ast, options) { + if (!ast || ast.skip) { + return ast; + } + const { enter, leave } = options; + ast = enter?.(ast); + if (!ast.skip && ast.children) { + const children = ast.children.map((child) => edit(child, options)); + ast = { type: ast.type, text: ast.text, children }; + } + leave?.(ast); + return ast; +} + +function transpile(ast) { + return edit(ast, { + enter: (node) => { + if (node.type === 'literal' && node.children[0].type === 'string') { + return miniWithLocation(node.text, 1); + } + return node; + }, + }); +} + +function miniWithLocation(string, loc) { + return { + type: 'apply', + children: [ + { + type: 'apply', + skip: true, + children: [ + { type: 'variable', text: 'minicurry', children: [] }, + { type: 'string', text: string, children: [] }, + ], + }, + { type: 'float', text: loc + '', children: [] }, + ], + }; }