From 27be90358ffdac5dd7cd75152082dcebbbbc411c Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 6 Feb 2022 20:59:41 +0100 Subject: [PATCH] add many more krill operators --- repl/package-lock.json | 623 +++++++++++++++++++++++++++++++++++++++-- repl/package.json | 1 + repl/src/App.tsx | 8 +- repl/src/mini.ts | 55 ---- repl/src/parse.d.ts | 18 ++ repl/src/parse.ts | 101 +++++++ repl/src/tunes.ts | 36 ++- repl/src/types.d.ts | 1 + 8 files changed, 758 insertions(+), 85 deletions(-) delete mode 100644 repl/src/mini.ts create mode 100644 repl/src/parse.d.ts create mode 100644 repl/src/parse.ts diff --git a/repl/package-lock.json b/repl/package-lock.json index a08c11c7..2003efbc 100644 --- a/repl/package-lock.json +++ b/repl/package-lock.json @@ -5,8 +5,10 @@ "packages": { "": { "dependencies": { + "@tonaljs/tonal": "^4.6.5", "react": "^17.0.2", "react-dom": "^17.0.2", + "tonal": "^2.2.2", "tone": "^14.7.77" }, "devDependencies": { @@ -26,7 +28,6 @@ "autoprefixer": "^10.4.2", "chai": "^4.3.4", "peggy": "^1.2.0", - "pegjs": "^0.10.0", "postcss": "^8.4.6", "prettier": "^2.2.1", "snowpack": "^3.3.7", @@ -1084,6 +1085,205 @@ "react-dom": "*" } }, + "node_modules/@tonaljs/abc-notation": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/abc-notation/-/abc-notation-4.6.5.tgz", + "integrity": "sha512-1S0Jnx0NfDLgyhkQOMEHqOacELL6RUdPcWWUP+nAnsOsb9owvB9RKYLSzp5odd16FVUR7U8c/JLc2yxIRvSeJw==", + "dependencies": { + "@tonaljs/core": "^4.6.5" + } + }, + "node_modules/@tonaljs/array": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/array/-/array-4.6.5.tgz", + "integrity": "sha512-7A3DbBQ+qIQ134FqE518b4tJ8V2a15Sn303JjHzgnqZqKrNh/s3wqwkL60F7LKcd09tcp+vIKQP/MYt4xMcRAA==", + "dependencies": { + "@tonaljs/core": "^4.6.5" + } + }, + "node_modules/@tonaljs/chord": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/chord/-/chord-4.6.5.tgz", + "integrity": "sha512-Pjdel4aDVv4kcx9PW6Qozt5BB9nAt13AOExfzKztpgPmlBSy0SKHse7Jp1cA4MGAuLHU8dzVssTFYpCskEFw3w==", + "dependencies": { + "@tonaljs/chord-detect": "^4.6.5", + "@tonaljs/chord-type": "^4.6.5", + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5", + "@tonaljs/pcset": "^4.6.5", + "@tonaljs/scale-type": "^4.6.5" + } + }, + "node_modules/@tonaljs/chord-detect": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/chord-detect/-/chord-detect-4.6.5.tgz", + "integrity": "sha512-4xu53UP4kNTfdTNpAAVijhXcQ+ypJqmeMnsST08ZXSjoYfJUhmf5rWDWfz36KOTtNdCA6AbYgdtTYV/Xw0nd/w==", + "dependencies": { + "@tonaljs/chord-type": "^4.6.5", + "@tonaljs/core": "^4.6.5", + "@tonaljs/pcset": "^4.6.5" + } + }, + "node_modules/@tonaljs/chord-type": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/chord-type/-/chord-type-4.6.5.tgz", + "integrity": "sha512-Ol4DDopqpZCF9odosO2i8I+plud3Ul7VWJGNvL+PPCf4Qnwuz87q3aJQDLNoRUz4VyW0u66mq3LyVh6A8kb6Ug==", + "dependencies": { + "@tonaljs/core": "^4.6.5", + "@tonaljs/pcset": "^4.6.5" + } + }, + "node_modules/@tonaljs/collection": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@tonaljs/collection/-/collection-4.6.2.tgz", + "integrity": "sha512-bfPCotLJNB/tG1NrdbsQPLDKZB5jlMs7uPQ6RYKiNkaena3345ZKkbCGl5pj6YTXeDm/oblXiSbFAn7SlLRZdQ==" + }, + "node_modules/@tonaljs/core": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/core/-/core-4.6.5.tgz", + "integrity": "sha512-t7Vx0+L3j/ubQj2AhI1H45D/K745np4DwJjJjXNi5FlGD+TL2wyw50dCwkHKGHsrLDqup1qqP6yN7LBpC6UwNg==" + }, + "node_modules/@tonaljs/duration-value": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@tonaljs/duration-value/-/duration-value-4.6.2.tgz", + "integrity": "sha512-zrXT0L/qsDQ6251Mlqz54vcUbYUB9xb6uJhlxUzc6VauXOt8UOfrdTULubRTXTaBwWt1h8J5n9pXTQmNGzNI9A==" + }, + "node_modules/@tonaljs/interval": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/interval/-/interval-4.6.5.tgz", + "integrity": "sha512-7EDWhqZ7Nnh9oD4ahRYJHLc799ACGxYL4hDHwMKD16B2MgXqPvDeDvwQ31qUuO0ruGz8tMb3FDlgg0Hplowcbw==", + "dependencies": { + "@tonaljs/core": "^4.6.5" + } + }, + "node_modules/@tonaljs/key": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/key/-/key-4.6.5.tgz", + "integrity": "sha512-ZdZWb5IStx6CLRmdEjawR66CqNpoW3EVUua2nVZBMdgnNebWxt4nvgH/ZNvGlCQGFZkUZzRhCfTwqsS6e3OmSA==", + "dependencies": { + "@tonaljs/core": "^4.6.5", + "@tonaljs/note": "^4.6.5", + "@tonaljs/roman-numeral": "^4.6.5" + } + }, + "node_modules/@tonaljs/midi": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/midi/-/midi-4.6.5.tgz", + "integrity": "sha512-fJEZtNvV3M6yW1w+Tep60Rbv5PvuKszQcQzaJS1Loq5mHOKAzdmRfuJSpEpZBiaKEZ1WAMh1QKXYyOd+imyGQg==", + "dependencies": { + "@tonaljs/core": "^4.6.5" + } + }, + "node_modules/@tonaljs/mode": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/mode/-/mode-4.6.5.tgz", + "integrity": "sha512-54iaON1rJ6q8fV5iuei8RGDxYhKBGGxZz3rjAxGSqdTUwBRVOdPqtzOkofThf9gRGYOMhzPp1BMbxbV+UCAPsA==", + "dependencies": { + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5", + "@tonaljs/interval": "^4.6.5", + "@tonaljs/pcset": "^4.6.5", + "@tonaljs/scale-type": "^4.6.5" + } + }, + "node_modules/@tonaljs/note": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/note/-/note-4.6.5.tgz", + "integrity": "sha512-Y0/eTzcReXzfcSLLG4k/dLLayqbvh/XYIkybG/QMDyR0BREuJq0Sw+NavbzhTtO0dadIQb/qfe0GFq4k2xS+NQ==", + "dependencies": { + "@tonaljs/core": "^4.6.5", + "@tonaljs/midi": "^4.6.5" + } + }, + "node_modules/@tonaljs/pcset": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/pcset/-/pcset-4.6.5.tgz", + "integrity": "sha512-oWAKflP3cREnUfScqsBzg2LLKNevxSnpDtrq8CPtwOAsrAa8PjQG07NQfhqIiFMjPUdgkDiER3qVA1n8dDwAJA==", + "dependencies": { + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5" + } + }, + "node_modules/@tonaljs/progression": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/progression/-/progression-4.6.5.tgz", + "integrity": "sha512-ijYEgMFQG4izHYUw5cRtBRNBuoYzmpGvb/tRiykhJNI6XIjekZEMiMsOMfb1u5q+EGvnVNXRmrluMRDIz2rmRw==", + "dependencies": { + "@tonaljs/chord": "^4.6.5", + "@tonaljs/core": "^4.6.5", + "@tonaljs/roman-numeral": "^4.6.5" + } + }, + "node_modules/@tonaljs/range": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/range/-/range-4.6.5.tgz", + "integrity": "sha512-99cOvVJ3l4X0UJuTSa6qE87JriREnnWIsi3xo1/n7RoqFxnfi8YPh4SfJJyysvHcT18X4EfcTNde9ancMBVu6A==", + "dependencies": { + "@tonaljs/collection": "^4.6.2", + "@tonaljs/midi": "^4.6.5" + } + }, + "node_modules/@tonaljs/roman-numeral": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/roman-numeral/-/roman-numeral-4.6.5.tgz", + "integrity": "sha512-bWYQNZWKmYDDcmbQQNwcWAHfTWanpzmvI0wplrMnGd4x0op5etwUEv+Yzjg0B1ef+E+zcU02Sl0WwRJhaDK3hg==", + "dependencies": { + "@tonaljs/core": "^4.6.5" + } + }, + "node_modules/@tonaljs/scale": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/scale/-/scale-4.6.5.tgz", + "integrity": "sha512-isYDamelOBtcd5bEnJ8QV0Js7jKRwZ0FlFVE/+bUN3wsyo9u6KLL5gMyfH9RKdx74m8lE13JXYTXgKqe+AOa4A==", + "dependencies": { + "@tonaljs/chord-type": "^4.6.5", + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5", + "@tonaljs/note": "^4.6.5", + "@tonaljs/pcset": "^4.6.5", + "@tonaljs/scale-type": "^4.6.5" + } + }, + "node_modules/@tonaljs/scale-type": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/scale-type/-/scale-type-4.6.5.tgz", + "integrity": "sha512-rwcDOYf2UifjLJhmuQ8f8bJSeOCMDQJ1lB7lzlqdFxes03OeQhdOEfrT0nPtW8BhBEvq4GMM2NA6CLxX8MTwOQ==", + "dependencies": { + "@tonaljs/core": "^4.6.5", + "@tonaljs/pcset": "^4.6.5" + } + }, + "node_modules/@tonaljs/time-signature": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@tonaljs/time-signature/-/time-signature-4.6.2.tgz", + "integrity": "sha512-OlZY4gdLd21WpMeAI1nS9E9zWcYU6oAzh6ptAUndqmVnFIrIWIWKCkWapdFx8dWdqrX8jqya3m4T33wmeo7w5Q==" + }, + "node_modules/@tonaljs/tonal": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/tonal/-/tonal-4.6.5.tgz", + "integrity": "sha512-lmsWinI9dy7nQyzCEgDVeVAwJtsk4ey05cJZd6oa4QVuSFD+CR8ebaEiwT4/Na+W0kHrKicT3h0uYc2PJIvx5Q==", + "dependencies": { + "@tonaljs/abc-notation": "^4.6.5", + "@tonaljs/array": "^4.6.5", + "@tonaljs/chord": "^4.6.5", + "@tonaljs/chord-type": "^4.6.5", + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5", + "@tonaljs/duration-value": "^4.6.2", + "@tonaljs/interval": "^4.6.5", + "@tonaljs/key": "^4.6.5", + "@tonaljs/midi": "^4.6.5", + "@tonaljs/mode": "^4.6.5", + "@tonaljs/note": "^4.6.5", + "@tonaljs/pcset": "^4.6.5", + "@tonaljs/progression": "^4.6.5", + "@tonaljs/range": "^4.6.5", + "@tonaljs/roman-numeral": "^4.6.5", + "@tonaljs/scale": "^4.6.5", + "@tonaljs/scale-type": "^4.6.5", + "@tonaljs/time-signature": "^4.6.2" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -6081,18 +6281,6 @@ "node": ">=10" } }, - "node_modules/pegjs": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", - "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=", - "dev": true, - "bin": { - "pegjs": "bin/pegjs" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -7878,6 +8066,108 @@ "node": ">=0.6" } }, + "node_modules/tonal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal/-/tonal-2.2.2.tgz", + "integrity": "sha512-Ze2bQc6KhAf3FKM9HzEsQ4z8hZh4WYCOsCrryONqf/THGOrOpL9Cc8Uc0dq0OA2yK2JbD5FhZckEXNYyD9946A==", + "dependencies": { + "tonal-array": "^2.2.2", + "tonal-chord": "^2.2.2", + "tonal-dictionary": "^2.2.2", + "tonal-distance": "^2.2.2", + "tonal-interval": "^2.2.2", + "tonal-key": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-pcset": "^2.2.2", + "tonal-scale": "^2.2.2" + } + }, + "node_modules/tonal-array": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-array/-/tonal-array-2.2.2.tgz", + "integrity": "sha512-h6YIq20L0EEU4EsDoKHAjl5kD2EQn467VfV79QHAuybvNCJpqqRNsQ3QNvoQyir1BgDXaDUIN9FEmQJNiaaCKA==", + "dependencies": { + "tonal-note": "^2.2.2" + } + }, + "node_modules/tonal-chord": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-chord/-/tonal-chord-2.2.2.tgz", + "integrity": "sha512-gOIXapi6Gx3ISRKdEJKEQjhDBiwjhaalyWSrN5rijGrSyyFFNZ+EVOfzcqLtnVAF9BgeO9Ca0eXCor3XpHdEJg==", + "dependencies": { + "tonal-dictionary": "^2.2.2", + "tonal-distance": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-pcset": "^2.2.2" + } + }, + "node_modules/tonal-dictionary": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-dictionary/-/tonal-dictionary-2.2.2.tgz", + "integrity": "sha512-283ppJl/0lohhlVPMI6t5C6XwaP5Wx0egu9qfG9TLCT2tn4pRwYpXkzGufd9icvkJTgOylOum3+RxWmywUIPIg==", + "dependencies": { + "tonal-array": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-pcset": "^2.2.2" + } + }, + "node_modules/tonal-distance": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-distance/-/tonal-distance-2.2.2.tgz", + "integrity": "sha512-ktA6OapCxaetXJb/JuXD5QwfyB7/G3y3ONby7Kkbezyffc57cnNfjdhlTR9XBR7eSFIY/J1KuhLwMx/qrffT4g==", + "dependencies": { + "tonal-interval": "^2.2.2", + "tonal-note": "^2.2.2" + } + }, + "node_modules/tonal-interval": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-interval/-/tonal-interval-2.2.2.tgz", + "integrity": "sha512-lrtDU8lH5IAX7YE63OhGGDRpVb4OoGxaN0wDu5XC3sUhXBwjSgNYpHY2D9JI2aWQ/Er9jhQbnw9b0ffkLy34+Q==" + }, + "node_modules/tonal-key": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-key/-/tonal-key-2.2.2.tgz", + "integrity": "sha512-KIc0b8yPl2ATDxF/65P52tIIempNsAQrug0idpD0zFvs5F5cb1hp7Rh7JJ4gECwC/6a3Hgdd1jomI+TnJ7K98w==", + "dependencies": { + "tonal-array": "^2.2.2", + "tonal-distance": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-roman-numeral": "^2.2.2" + } + }, + "node_modules/tonal-note": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-note/-/tonal-note-2.2.2.tgz", + "integrity": "sha512-RNK3Nb8PxBEW9yYGStcoczgE8bCYFZ5zfLvYJjvuzLWiwTQmqWOhTzONVobVCGFZ/jgDNwpBEKe/bngL3g3Xfw==" + }, + "node_modules/tonal-pcset": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-pcset/-/tonal-pcset-2.2.2.tgz", + "integrity": "sha512-PSqhkxzckO6J27W0GxawHYln4wvfDJ7puDmccksyFOBo97UhLnpxiyvBekhiYpkuaMtoZLQC/KALAkEj7lcb+A==", + "dependencies": { + "tonal-array": "^2.2.2", + "tonal-interval": "^2.2.2", + "tonal-note": "^2.2.2" + } + }, + "node_modules/tonal-roman-numeral": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-roman-numeral/-/tonal-roman-numeral-2.2.2.tgz", + "integrity": "sha512-+auQNObpW3OvsSqlo+Cc+0otrlEhtbEgpzkPoKbTtkCva0P9oSkSz0OZ9fI73KQM5MsBs1XbB+olxppWkzYTFw==" + }, + "node_modules/tonal-scale": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-scale/-/tonal-scale-2.2.2.tgz", + "integrity": "sha512-tDb3YCoTF50XOXq9kNhGB1JkInk7qAGN6GQnP/3xkGxkreFFRZyI58jfHlmWf/AH4+IKb/exsOmL6G8Ok/PCRw==", + "dependencies": { + "tonal-array": "^2.2.2", + "tonal-dictionary": "^2.2.2", + "tonal-distance": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-pcset": "^2.2.2" + } + }, "node_modules/tone": { "version": "14.7.77", "resolved": "https://registry.npmjs.org/tone/-/tone-14.7.77.tgz", @@ -9250,6 +9540,205 @@ "@testing-library/dom": "^7.28.1" } }, + "@tonaljs/abc-notation": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/abc-notation/-/abc-notation-4.6.5.tgz", + "integrity": "sha512-1S0Jnx0NfDLgyhkQOMEHqOacELL6RUdPcWWUP+nAnsOsb9owvB9RKYLSzp5odd16FVUR7U8c/JLc2yxIRvSeJw==", + "requires": { + "@tonaljs/core": "^4.6.5" + } + }, + "@tonaljs/array": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/array/-/array-4.6.5.tgz", + "integrity": "sha512-7A3DbBQ+qIQ134FqE518b4tJ8V2a15Sn303JjHzgnqZqKrNh/s3wqwkL60F7LKcd09tcp+vIKQP/MYt4xMcRAA==", + "requires": { + "@tonaljs/core": "^4.6.5" + } + }, + "@tonaljs/chord": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/chord/-/chord-4.6.5.tgz", + "integrity": "sha512-Pjdel4aDVv4kcx9PW6Qozt5BB9nAt13AOExfzKztpgPmlBSy0SKHse7Jp1cA4MGAuLHU8dzVssTFYpCskEFw3w==", + "requires": { + "@tonaljs/chord-detect": "^4.6.5", + "@tonaljs/chord-type": "^4.6.5", + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5", + "@tonaljs/pcset": "^4.6.5", + "@tonaljs/scale-type": "^4.6.5" + } + }, + "@tonaljs/chord-detect": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/chord-detect/-/chord-detect-4.6.5.tgz", + "integrity": "sha512-4xu53UP4kNTfdTNpAAVijhXcQ+ypJqmeMnsST08ZXSjoYfJUhmf5rWDWfz36KOTtNdCA6AbYgdtTYV/Xw0nd/w==", + "requires": { + "@tonaljs/chord-type": "^4.6.5", + "@tonaljs/core": "^4.6.5", + "@tonaljs/pcset": "^4.6.5" + } + }, + "@tonaljs/chord-type": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/chord-type/-/chord-type-4.6.5.tgz", + "integrity": "sha512-Ol4DDopqpZCF9odosO2i8I+plud3Ul7VWJGNvL+PPCf4Qnwuz87q3aJQDLNoRUz4VyW0u66mq3LyVh6A8kb6Ug==", + "requires": { + "@tonaljs/core": "^4.6.5", + "@tonaljs/pcset": "^4.6.5" + } + }, + "@tonaljs/collection": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@tonaljs/collection/-/collection-4.6.2.tgz", + "integrity": "sha512-bfPCotLJNB/tG1NrdbsQPLDKZB5jlMs7uPQ6RYKiNkaena3345ZKkbCGl5pj6YTXeDm/oblXiSbFAn7SlLRZdQ==" + }, + "@tonaljs/core": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/core/-/core-4.6.5.tgz", + "integrity": "sha512-t7Vx0+L3j/ubQj2AhI1H45D/K745np4DwJjJjXNi5FlGD+TL2wyw50dCwkHKGHsrLDqup1qqP6yN7LBpC6UwNg==" + }, + "@tonaljs/duration-value": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@tonaljs/duration-value/-/duration-value-4.6.2.tgz", + "integrity": "sha512-zrXT0L/qsDQ6251Mlqz54vcUbYUB9xb6uJhlxUzc6VauXOt8UOfrdTULubRTXTaBwWt1h8J5n9pXTQmNGzNI9A==" + }, + "@tonaljs/interval": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/interval/-/interval-4.6.5.tgz", + "integrity": "sha512-7EDWhqZ7Nnh9oD4ahRYJHLc799ACGxYL4hDHwMKD16B2MgXqPvDeDvwQ31qUuO0ruGz8tMb3FDlgg0Hplowcbw==", + "requires": { + "@tonaljs/core": "^4.6.5" + } + }, + "@tonaljs/key": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/key/-/key-4.6.5.tgz", + "integrity": "sha512-ZdZWb5IStx6CLRmdEjawR66CqNpoW3EVUua2nVZBMdgnNebWxt4nvgH/ZNvGlCQGFZkUZzRhCfTwqsS6e3OmSA==", + "requires": { + "@tonaljs/core": "^4.6.5", + "@tonaljs/note": "^4.6.5", + "@tonaljs/roman-numeral": "^4.6.5" + } + }, + "@tonaljs/midi": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/midi/-/midi-4.6.5.tgz", + "integrity": "sha512-fJEZtNvV3M6yW1w+Tep60Rbv5PvuKszQcQzaJS1Loq5mHOKAzdmRfuJSpEpZBiaKEZ1WAMh1QKXYyOd+imyGQg==", + "requires": { + "@tonaljs/core": "^4.6.5" + } + }, + "@tonaljs/mode": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/mode/-/mode-4.6.5.tgz", + "integrity": "sha512-54iaON1rJ6q8fV5iuei8RGDxYhKBGGxZz3rjAxGSqdTUwBRVOdPqtzOkofThf9gRGYOMhzPp1BMbxbV+UCAPsA==", + "requires": { + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5", + "@tonaljs/interval": "^4.6.5", + "@tonaljs/pcset": "^4.6.5", + "@tonaljs/scale-type": "^4.6.5" + } + }, + "@tonaljs/note": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/note/-/note-4.6.5.tgz", + "integrity": "sha512-Y0/eTzcReXzfcSLLG4k/dLLayqbvh/XYIkybG/QMDyR0BREuJq0Sw+NavbzhTtO0dadIQb/qfe0GFq4k2xS+NQ==", + "requires": { + "@tonaljs/core": "^4.6.5", + "@tonaljs/midi": "^4.6.5" + } + }, + "@tonaljs/pcset": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/pcset/-/pcset-4.6.5.tgz", + "integrity": "sha512-oWAKflP3cREnUfScqsBzg2LLKNevxSnpDtrq8CPtwOAsrAa8PjQG07NQfhqIiFMjPUdgkDiER3qVA1n8dDwAJA==", + "requires": { + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5" + } + }, + "@tonaljs/progression": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/progression/-/progression-4.6.5.tgz", + "integrity": "sha512-ijYEgMFQG4izHYUw5cRtBRNBuoYzmpGvb/tRiykhJNI6XIjekZEMiMsOMfb1u5q+EGvnVNXRmrluMRDIz2rmRw==", + "requires": { + "@tonaljs/chord": "^4.6.5", + "@tonaljs/core": "^4.6.5", + "@tonaljs/roman-numeral": "^4.6.5" + } + }, + "@tonaljs/range": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/range/-/range-4.6.5.tgz", + "integrity": "sha512-99cOvVJ3l4X0UJuTSa6qE87JriREnnWIsi3xo1/n7RoqFxnfi8YPh4SfJJyysvHcT18X4EfcTNde9ancMBVu6A==", + "requires": { + "@tonaljs/collection": "^4.6.2", + "@tonaljs/midi": "^4.6.5" + } + }, + "@tonaljs/roman-numeral": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/roman-numeral/-/roman-numeral-4.6.5.tgz", + "integrity": "sha512-bWYQNZWKmYDDcmbQQNwcWAHfTWanpzmvI0wplrMnGd4x0op5etwUEv+Yzjg0B1ef+E+zcU02Sl0WwRJhaDK3hg==", + "requires": { + "@tonaljs/core": "^4.6.5" + } + }, + "@tonaljs/scale": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/scale/-/scale-4.6.5.tgz", + "integrity": "sha512-isYDamelOBtcd5bEnJ8QV0Js7jKRwZ0FlFVE/+bUN3wsyo9u6KLL5gMyfH9RKdx74m8lE13JXYTXgKqe+AOa4A==", + "requires": { + "@tonaljs/chord-type": "^4.6.5", + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5", + "@tonaljs/note": "^4.6.5", + "@tonaljs/pcset": "^4.6.5", + "@tonaljs/scale-type": "^4.6.5" + } + }, + "@tonaljs/scale-type": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/scale-type/-/scale-type-4.6.5.tgz", + "integrity": "sha512-rwcDOYf2UifjLJhmuQ8f8bJSeOCMDQJ1lB7lzlqdFxes03OeQhdOEfrT0nPtW8BhBEvq4GMM2NA6CLxX8MTwOQ==", + "requires": { + "@tonaljs/core": "^4.6.5", + "@tonaljs/pcset": "^4.6.5" + } + }, + "@tonaljs/time-signature": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@tonaljs/time-signature/-/time-signature-4.6.2.tgz", + "integrity": "sha512-OlZY4gdLd21WpMeAI1nS9E9zWcYU6oAzh6ptAUndqmVnFIrIWIWKCkWapdFx8dWdqrX8jqya3m4T33wmeo7w5Q==" + }, + "@tonaljs/tonal": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@tonaljs/tonal/-/tonal-4.6.5.tgz", + "integrity": "sha512-lmsWinI9dy7nQyzCEgDVeVAwJtsk4ey05cJZd6oa4QVuSFD+CR8ebaEiwT4/Na+W0kHrKicT3h0uYc2PJIvx5Q==", + "requires": { + "@tonaljs/abc-notation": "^4.6.5", + "@tonaljs/array": "^4.6.5", + "@tonaljs/chord": "^4.6.5", + "@tonaljs/chord-type": "^4.6.5", + "@tonaljs/collection": "^4.6.2", + "@tonaljs/core": "^4.6.5", + "@tonaljs/duration-value": "^4.6.2", + "@tonaljs/interval": "^4.6.5", + "@tonaljs/key": "^4.6.5", + "@tonaljs/midi": "^4.6.5", + "@tonaljs/mode": "^4.6.5", + "@tonaljs/note": "^4.6.5", + "@tonaljs/pcset": "^4.6.5", + "@tonaljs/progression": "^4.6.5", + "@tonaljs/range": "^4.6.5", + "@tonaljs/roman-numeral": "^4.6.5", + "@tonaljs/scale": "^4.6.5", + "@tonaljs/scale-type": "^4.6.5", + "@tonaljs/time-signature": "^4.6.2" + } + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -13145,12 +13634,6 @@ "integrity": "sha512-PQ+NKpAobImfMprYQtc4Egmyi29bidRGEX0kKjCU5uuW09s0Cthwqhfy7mLkwcB4VcgacE5L/ZjruD/kOPCUUw==", "dev": true }, - "pegjs": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", - "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=", - "dev": true - }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -14481,6 +14964,108 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, + "tonal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal/-/tonal-2.2.2.tgz", + "integrity": "sha512-Ze2bQc6KhAf3FKM9HzEsQ4z8hZh4WYCOsCrryONqf/THGOrOpL9Cc8Uc0dq0OA2yK2JbD5FhZckEXNYyD9946A==", + "requires": { + "tonal-array": "^2.2.2", + "tonal-chord": "^2.2.2", + "tonal-dictionary": "^2.2.2", + "tonal-distance": "^2.2.2", + "tonal-interval": "^2.2.2", + "tonal-key": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-pcset": "^2.2.2", + "tonal-scale": "^2.2.2" + } + }, + "tonal-array": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-array/-/tonal-array-2.2.2.tgz", + "integrity": "sha512-h6YIq20L0EEU4EsDoKHAjl5kD2EQn467VfV79QHAuybvNCJpqqRNsQ3QNvoQyir1BgDXaDUIN9FEmQJNiaaCKA==", + "requires": { + "tonal-note": "^2.2.2" + } + }, + "tonal-chord": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-chord/-/tonal-chord-2.2.2.tgz", + "integrity": "sha512-gOIXapi6Gx3ISRKdEJKEQjhDBiwjhaalyWSrN5rijGrSyyFFNZ+EVOfzcqLtnVAF9BgeO9Ca0eXCor3XpHdEJg==", + "requires": { + "tonal-dictionary": "^2.2.2", + "tonal-distance": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-pcset": "^2.2.2" + } + }, + "tonal-dictionary": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-dictionary/-/tonal-dictionary-2.2.2.tgz", + "integrity": "sha512-283ppJl/0lohhlVPMI6t5C6XwaP5Wx0egu9qfG9TLCT2tn4pRwYpXkzGufd9icvkJTgOylOum3+RxWmywUIPIg==", + "requires": { + "tonal-array": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-pcset": "^2.2.2" + } + }, + "tonal-distance": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-distance/-/tonal-distance-2.2.2.tgz", + "integrity": "sha512-ktA6OapCxaetXJb/JuXD5QwfyB7/G3y3ONby7Kkbezyffc57cnNfjdhlTR9XBR7eSFIY/J1KuhLwMx/qrffT4g==", + "requires": { + "tonal-interval": "^2.2.2", + "tonal-note": "^2.2.2" + } + }, + "tonal-interval": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-interval/-/tonal-interval-2.2.2.tgz", + "integrity": "sha512-lrtDU8lH5IAX7YE63OhGGDRpVb4OoGxaN0wDu5XC3sUhXBwjSgNYpHY2D9JI2aWQ/Er9jhQbnw9b0ffkLy34+Q==" + }, + "tonal-key": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-key/-/tonal-key-2.2.2.tgz", + "integrity": "sha512-KIc0b8yPl2ATDxF/65P52tIIempNsAQrug0idpD0zFvs5F5cb1hp7Rh7JJ4gECwC/6a3Hgdd1jomI+TnJ7K98w==", + "requires": { + "tonal-array": "^2.2.2", + "tonal-distance": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-roman-numeral": "^2.2.2" + } + }, + "tonal-note": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-note/-/tonal-note-2.2.2.tgz", + "integrity": "sha512-RNK3Nb8PxBEW9yYGStcoczgE8bCYFZ5zfLvYJjvuzLWiwTQmqWOhTzONVobVCGFZ/jgDNwpBEKe/bngL3g3Xfw==" + }, + "tonal-pcset": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-pcset/-/tonal-pcset-2.2.2.tgz", + "integrity": "sha512-PSqhkxzckO6J27W0GxawHYln4wvfDJ7puDmccksyFOBo97UhLnpxiyvBekhiYpkuaMtoZLQC/KALAkEj7lcb+A==", + "requires": { + "tonal-array": "^2.2.2", + "tonal-interval": "^2.2.2", + "tonal-note": "^2.2.2" + } + }, + "tonal-roman-numeral": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-roman-numeral/-/tonal-roman-numeral-2.2.2.tgz", + "integrity": "sha512-+auQNObpW3OvsSqlo+Cc+0otrlEhtbEgpzkPoKbTtkCva0P9oSkSz0OZ9fI73KQM5MsBs1XbB+olxppWkzYTFw==" + }, + "tonal-scale": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tonal-scale/-/tonal-scale-2.2.2.tgz", + "integrity": "sha512-tDb3YCoTF50XOXq9kNhGB1JkInk7qAGN6GQnP/3xkGxkreFFRZyI58jfHlmWf/AH4+IKb/exsOmL6G8Ok/PCRw==", + "requires": { + "tonal-array": "^2.2.2", + "tonal-dictionary": "^2.2.2", + "tonal-distance": "^2.2.2", + "tonal-note": "^2.2.2", + "tonal-pcset": "^2.2.2" + } + }, "tone": { "version": "14.7.77", "resolved": "https://registry.npmjs.org/tone/-/tone-14.7.77.tgz", diff --git a/repl/package.json b/repl/package.json index e6c8dc39..e5d71892 100644 --- a/repl/package.json +++ b/repl/package.json @@ -8,6 +8,7 @@ "peggy": "peggy -o krill-parser.js --format es ./krill.pegjs" }, "dependencies": { + "@tonaljs/tonal": "^4.6.5", "react": "^17.0.2", "react-dom": "^17.0.2", "tone": "^14.7.77" diff --git a/repl/src/App.tsx b/repl/src/App.tsx index 0ad4653e..ee032037 100644 --- a/repl/src/App.tsx +++ b/repl/src/App.tsx @@ -6,12 +6,12 @@ import * as Tone from 'tone'; import useCycle from './useCycle'; import type { Hap, Pattern } from './types'; import * as tunes from './tunes'; -import _mini from './mini'; +import * as krill from './parse'; -const { tetris, tetrisMini } = tunes; +const { tetris, tetrisMini, tetrisHaskell } = tunes; const { sequence, pure, reify, slowcat, fastcat, cat, stack, silence } = strudel; // make available to eval -const mini = _mini; // for eval (direct import wont work somehow) +const { mini, h } = krill; // for eval (direct import wont work somehow) const parse = (code: string): Pattern => eval(code); const synth = new Tone.PolySynth().toDestination(); @@ -23,7 +23,7 @@ synth.set({ }); function App() { - const [code, setCode] = useState(tetrisMini); + const [code, setCode] = useState(tetrisHaskell); const [log, setLog] = useState(''); const logBox = useRef(); const [error, setError] = useState(); diff --git a/repl/src/mini.ts b/repl/src/mini.ts deleted file mode 100644 index 40e31b8a..00000000 --- a/repl/src/mini.ts +++ /dev/null @@ -1,55 +0,0 @@ -import * as krill from '../krill-parser'; -import * as strudel from '../../strudel.mjs'; - -const { sequence, stack, silence } = strudel; - -export function patternifyAST(ast: any): any { - switch (ast.type_) { - case 'pattern': - if (ast.arguments_.alignment === 'v') { - return stack(...ast.source_.map(patternifyAST)); - } - return sequence(...ast.source_.map(patternifyAST)); - case 'element': - if (ast.source_ === '~') { - return silence; - } - if (typeof ast.source_ !== 'object') { - return ast.source_; - } - return patternifyAST(ast.source_); - } - // *3 => options_.operator.arguments_.amount = 1/3 -} -/* export default (str: string) => patternifyAST(krill.parse(`"${str}"`)); */ - -export default (...strings: string[]) => { - const pattern = sequence( - ...strings.map((str) => { - const ast = krill.parse(`"${str}"`); - // console.log('ast', ast); - return patternifyAST(ast); - }) - ); - // console.log('mini pattern', pattern); - return pattern; -}; - -/* -TODO: -export interface Arguments { - alignment: string; -} - -export interface ElementStub { - type_: string; - source_: string; - options_?: any; -} - -export interface PatternStub { - type_: string; // pattern - arguments_: Arguments; - source_: ElementStub[]; -} - */ diff --git a/repl/src/parse.d.ts b/repl/src/parse.d.ts new file mode 100644 index 00000000..be24374b --- /dev/null +++ b/repl/src/parse.d.ts @@ -0,0 +1,18 @@ +/* +TODO: +export interface Arguments { + alignment: string; +} + +export interface ElementStub { + type_: string; + source_: string; + options_?: any; +} + +export interface PatternStub { + type_: string; // pattern + arguments_: Arguments; + source_: ElementStub[]; +} + */ diff --git a/repl/src/parse.ts b/repl/src/parse.ts new file mode 100644 index 00000000..64228006 --- /dev/null +++ b/repl/src/parse.ts @@ -0,0 +1,101 @@ +import * as krill from '../krill-parser'; +import * as strudel from '../../strudel.mjs'; +import { Scale, Note, Interval } from '@tonaljs/tonal'; + +const { sequence, stack, silence, Fraction, pure } = strudel; + +function reify(thing: any) { + if (thing?.constructor?.name === 'Pattern') { + return thing; + } + return pure(thing); +} + +const applyOptions = (parent: any) => (pat: any, i: number) => { + const ast = parent.source_[i]; + const options = ast.options_; + const operator = options?.operator; + if (operator) { + switch (operator.type_) { + case 'stretch': + const speed = new Fraction(operator.arguments_.amount).inverse().valueOf(); + return reify(pat).fast(speed); + // case 'fixed-step': "%" // https://github.com/Mdashdotdashn/krill#patterns---a-more-traditional-approach + } + console.warn(`operator "${operator.type_}" not implemented`); + } + // TODO: options.weight = "@" + // TODO: bjorklund e.g. "c3(5,8)" + const unimplemented = Object.keys(options || {}).filter((key) => key !== 'operator'); + if (unimplemented.length) { + console.warn( + `option${unimplemented.length > 1 ? 's' : ''} ${unimplemented.map((o) => `"${o}"`).join(', ')} not implemented` + ); + } + return pat; +}; + +export function patternifyAST(ast: any): any { + switch (ast.type_) { + case 'pattern': + const children = ast.source_.map(patternifyAST).map(applyOptions(ast)); + if (ast.arguments_.alignment === 'v') { + return stack(...children); + } + return sequence(...children); + case 'element': + if (ast.source_ === '~') { + return silence; + } + if (typeof ast.source_ !== 'object') { + return ast.source_; + } + return patternifyAST(ast.source_); + case 'stretch': + return patternifyAST(ast.source_).slow(ast.arguments_.amount); + case 'scale': + let [tonic, scale] = Scale.tokenize(ast.arguments_.scale); + const intervals = Scale.get(scale).intervals; + const pattern = patternifyAST(ast.source_); + tonic = tonic || 'C4'; + // console.log('scale', ast, pattern, tonic, scale); + console.log('tonic', tonic); + return pattern.fmap((step: any) => { + step = Number(step); + if (isNaN(step)) { + console.warn(`scale step "${step}" not a number`); + return step; + } + const octaves = Math.floor(step / intervals.length); + const mod = (n: number, m: number): number => (n < 0 ? mod(n + m, m) : n % m); + const index = mod(step, intervals.length); // % with negative numbers. e.g. -1 % 3 = 2 + const interval = Interval.add(intervals[index], Interval.fromSemitones(octaves * 12)); + return Note.transpose(tonic, interval || '1P'); + }); + /* case 'struct': + // TODO: + return silence; */ + default: + console.warn(`node type "${ast.type_}" not implemented -> returning silence`); + return silence; + } +} + +// mini notation only (wraps in "") +export const mini = (...strings: string[]) => { + const pattern = sequence( + ...strings.map((str) => { + const ast = krill.parse(`"${str}"`); + // console.log('ast', ast); + return patternifyAST(ast); + }) + ); + return pattern; +}; + +// includes haskell style (raw krill parsing) +export const h = (string: string) => { + const ast = krill.parse(string); + console.log('ast', ast); + return patternifyAST(ast); +}; diff --git a/repl/src/tunes.ts b/repl/src/tunes.ts index 5c5df672..2f195d54 100644 --- a/repl/src/tunes.ts +++ b/repl/src/tunes.ts @@ -55,16 +55,38 @@ export const tetrisMini = `mini(\`[[e5 [b4 c5] d5 [c5 b4]] [e5 [~ c5] e5 [d5 c5]] [b4 [b4 c5] d5 e5] [c5 a4 a4 ~]], -[[e2 e3 e2 e3 e2 e3 e2 e3] -[a2 a3 a2 a3 a2 a3 a2 a3] -[g#2 g#3 g#2 g#3 e2 e3 e2 e3] +[[e2 e3]*4] +[[a2 a3]*4] +[[g#2 g#3]*2 [e2 e3]*2] [a2 a3 a2 a3 a2 a3 b1 c2] -[d2 d3 d2 d3 d2 d3 d2 d3] -[c2 c3 c2 c3 c2 c3 c2 c3] -[b1 b2 b1 b2 e2 e3 e2 e3] -[a1 a2 a1 a2 a1 a2 a1 a2]]\`)._slow(16); +[[d2 d3]*4] +[[c2 c3]*4] +[[b1 b2]*2 [e2 e3]*2] +[[a1 a2]*4]\`)._slow(16); `; +export const tetrisHaskell = `h(\`slow 16 $ "[[e5 [b4 c5] d5 [c5 b4]] +[a4 [a4 c5] e5 [d5 c5]] +[b4 [~ c5] d5 e5] +[c5 a4 a4 ~] +[[~ d5] [~ f5] a5 [g5 f5]] +[e5 [~ c5] e5 [d5 c5]] +[b4 [b4 c5] d5 e5] +[c5 a4 a4 ~]], +[[e2 e3]*4] +[[a2 a3]*4] +[[g#2 g#3]*2 [e2 e3]*2] +[a2 a3 a2 a3 a2 a3 b1 c2] +[[d2 d3]*4] +[[c2 c3]*4] +[[b1 b2]*2 [e2 e3]*2] +[[a1 a2]*4]"\`) +`; + +/* +export const tetrisHaskell = `h(\`slow 16 $ "[[e5 [b4 c5] d5 [c5 b4]] [a4 [a4 c5] e5 [d5 c5]] [b4 [~ c5] d5 e5] [c5 a4 a4 ~] [[~ d5] [~ f5] a5 [g5 f5]] [e5 [~ c5] e5 [d5 c5]] [b4 [b4 c5] d5 e5] [c5 a4 a4 ~]], [[e2 e3]*4] [[a2 a3]*4] [[g#2 g#3]*2 [e2 e3]*2] [a2 a3 a2 a3 a2 a3 b1 c2] [[d2 d3]*4] [[c2 c3]*4] [[b1 b2]*2 [e2 e3]*2] [[a1 a2]*4]"\`)`; +*/ + // "sequence('c3', 'eb3', sequence('g3', 'f3'))" // /* `sequence( stack('c4','eb4','g4'), diff --git a/repl/src/types.d.ts b/repl/src/types.d.ts index 6854f74e..8252d201 100644 --- a/repl/src/types.d.ts +++ b/repl/src/types.d.ts @@ -19,4 +19,5 @@ export declare interface Hap { } export declare interface Pattern { query: (span: TimeSpan) => Hap[]; + fmap: (v: T) => T; }