UNPKG

mercury-lang

Version:

Parser for the mercury live coding language

801 lines (798 loc) 19.1 kB
const Gen = require('total-serialism').Generative; const Algo = require('total-serialism').Algorithmic; const Mod = require('total-serialism').Transform; const Rand = require('total-serialism').Stochastic; const Stat = require('total-serialism').Statistic; const TL = require('total-serialism').Translate; const Util = require('total-serialism').Utility; const functionMap = { // All the Array transformation/generation methods // From the total-serialism Node package // // Generative Methods // // generate an array of ints between specified range 'spread' : (...v) => { return Gen.spread(...v); }, // generate an array of floats between range 'spreadFloat' : (...v) => { return Gen.spreadFloat(...v); }, 'spreadF' : (...v) => { return Gen.spreadFloat(...v); }, // generate an array of ints between specified range (inclusive) 'spreadInclusive' : (...v) => { return Gen.spreadInclusive(...v); }, 'spreadInc' : (...v) => { return Gen.spreadInclusive(...v); }, // generate an array of floats between range (inclusive) 'spreadInclusiveFloat' : (...v) => { return Gen.spreadInclusiveFloat(...v); }, 'spreadInclusiveF' : (...v) => { return Gen.spreadInclusiveFloat(...v); }, 'spreadIncF' : (...v) => { return Gen.spreadInclusiveFloat(...v); }, // generate an array between range (exponentially) 'spreadExp' : (...v) => { return Gen.spreadExp(...v); }, 'spreadExpFloat' : (...v) => { return Gen.spreadExpFloat(...v); }, 'spreadExpF' : (...v) => { return Gen.spreadExpFloat(...v); }, 'spreadInclusiveExp' : (...v) => { return Gen.spreadInclusiveExp(...v); }, 'spreadIncExp' : (...v) => { return Gen.spreadInclusiveExp(...v); }, 'spreadInclusiveExpFloat' : (...v) => { return Gen.spreadInclusiveExpFloat(...v); }, 'spreadIncExpF' : (...v) => { return Gen.spreadInclusiveExpFloat(...v); }, // fill an array with duplicates of a value 'fill' : (...v) => { return Gen.fill(...v); }, // generate an array from a sinewave function 'sine' : (...v) => { return Gen.sine(...v); }, 'sineFloat' : (...v) => { return Gen.sineFloat(...v); }, 'sineF' : (...v) => { return Gen.sineFloat(...v); }, 'sinF' : (...v) => { return Gen.sineFloat(...v); }, // generate an array from a cosine function 'cosine' : (...v) => { return Gen.cosine(...v); }, 'cosineFloat' : (...v) => { return Gen.cosineFloat(...v); }, 'cosineF' : (...v) => { return Gen.cosineFloat(...v); }, 'cosF' : (...v) => { return Gen.cosineFloat(...v); }, // generate an array from a sawtooth function 'saw' : (...v) => { return Gen.saw(...v); }, 'sawFloat' : (...v) => { return Gen.sawFloat(...v); }, 'sawF' : (...v) => { return Gen.sawFloat(...v); }, // generate an array from a squarewave function 'square' : (...v) => { return Gen.square(...v); }, 'rect' : (...v) => { return Gen.square(...v); }, 'squareFloat' : (...v) => { return Gen.squareFloat(...v); }, 'squareF' : (...v) => { return Gen.squareFloat(...v); }, 'rectF' : (...v) => { return Gen.squareFloat(...v); }, 'binaryBeat' : (...v) => { return Gen.binaryBeat(...v); }, 'binary' : (...v) => { return Gen.binaryBeat(...v); }, 'spacingBeat' : (...v) => { return Gen.spacingBeat(...v); }, 'spacing' : (...v) => { return Gen.spacingBeat(...v); }, // // Algorithmic Methods // // generate a euclidean rhythm evenly spacing n-beats amongst n-steps // switched to fastEuclid method 'euclid' : (...v) => { // return Algo.euclid(...v); return Algo.fastEuclid(...v); }, 'euclidean' : (...v) => { // return Algo.euclid(...v); return Algo.fastEuclid(...v); }, // generate a rhythm based on a hexadecimal string (0-f) 'hexBeat' : (...v) => { // console.log("@hexBeat", v); return Algo.hexBeat(v[0]); }, 'hex' : (...v) => { return Algo.hexBeat(v[0]); }, // generate a sequence of numbers from the collatz conjecture // thread lightly, can grow large with large input numbers 'collatz' : (...v) => { return Algo.collatz(v[0]); }, 'collatzMod' : (...v) => { return Algo.collatzMod(...v); }, // generate the numbers in the fibonacci sequence 'fibonacci' : (...v) => { return Algo.fibonacci(...v); }, // generate the pisano periods from the fibonacci sequence 'pisano' : (...v) => { return Algo.pisano(...v); }, 'fibonacciMod' : (...v) => { return functionMap.pisano(v); }, // generate the numbers in the fibonacci sequence 'pell' : (...v) => { return Algo.pell(...v); }, // generate the numbers in the fibonacci sequence 'lucas' : (...v) => { return Algo.lucas(...v); }, // generate the numbers in the fibonacci sequence 'threeFibonacci' : (...v) => { return Algo.threeFibonacci(...v); }, // Per Nørgards Inifity series 'infinitySeries' : (...v) => { return Algo.infinitySeries(...v); }, 'infSeries' : (...v) => { return functionMap.infinitySeries(v); }, // // Stochastic Methods // // set the random number generator seed 'randomSeed' : (...v) => { return Rand.seed(v[0]); }, // get the random number generator seed 'getSeed' : () => { return Rand.getSeed(); }, // generate an array of random integers in range 'random' : (...v) => { return Rand.random(...v); }, 'rand' : (...v) => { return Rand.random(...v); }, // generate an array of random floats 'randomFloat' : (...v) => { return Rand.randomFloat(...v); }, 'randomF' : (...v) => { return Rand.randomFloat(...v); }, 'randF' : (...v) => { return Rand.randomFloat(...v); }, // generate a random walk (drunk) 'drunk' : (...v) => { return Rand.drunk(...v); }, 'drunkFloat' : (...v) => { return Rand.drunkFloat(...v); }, 'drunkF' : (...v) => { return Rand.drunkFloat(...v); }, // generate random values picked from an urn 'urn' : (...v) => { return Rand.urn(...v); }, // generate an array of coin tosses 'coin' : (...v) => { return Rand.coin(v[0]); }, // generate an array of dice rolls 'dice' : (...v) => { return Rand.dice(v[0]); }, // generate random clave patterns 'clave' : (...v) => { return Rand.clave(...v); }, // generate an array of twelveTone notes 'twelveTone' : () => { return Rand.twelveTone(); }, // choose values at random from a ring provided 'choose' : (...v) => { return Rand.choose(...v); }, // pick values randomly from a ring provided and remove chosen 'pick' : (...v) => { return Rand.pick(...v); }, // shuffle the items in an array, influenced by the random seed 'shuffle' : (v) => { return Rand.shuffle(v); }, 'scramble' : (v) => { return Rand.shuffle(v); }, // expand an array based upon the pattern within an array // arbitrarily choosing the next 'expand' : (...v) => { // check if arguments are correct v[0] = (Array.isArray(v[0])) ? v[0] : [v[0]]; v[1] = Math.max(2, (Array.isArray(v[1])) ? v[1][0] : v[1]); return Rand.expand(v[0], v[1]); }, // markov chain methods // combine the markovTrain with markovChain // first train the model based on a list // then generate a list output from the chain 'markovTrain' : (...v) => { // generate markovchain from the incoming list let markov = new Rand.DeepMarkovChain(...v); // create string of data let data = markov.stringify(); // clear data and delete markov.clear(); markov = null; // output the table as a string array to use for generating return [ data ]; }, 'markov' : (...v) => { return functionMap['markovTrain'](...v); }, 'markovChain' : (...v) => { // train from a markov table and generate a chain let markov = new Rand.DeepMarkovChain(); markov.parse(v[1]); // set the seed based on the global seed markov.seed(Rand.getSeed()); let gen = markov.chain(v[0]); // clear the data and remove markov markov.clear(); markov = null; // return generated array return gen; }, 'chain' : (...v) => { return functionMap['markovChain'](...v); }, // // Transformational Methods // // duplicate an array with an offset added to every value 'clone' : (...v) => { return Mod.clone(...v); }, // combine multiple numbers/arrays into one 'combine' : (...v) => { return Mod.combine(...v); }, 'concat' : (...v) => { return Mod.combine(...v); }, 'join' : (...v) => { return Mod.combine(...v); }, // duplicate an array certain amount of times 'duplicate' : (...v) => { return Mod.duplicate(...v); }, 'dup' : (...v) => { return Mod.duplicate(...v); }, 'copy' : (...v) => { return Mod.duplicate(...v); }, // Pad an array with zeroes (or any other value) up to the length specified. 'pad' : (...v) => { return Mod.pad(...v); }, // add zeroes to a rhythm to make it play once over a certain amount of bars 'every' : (...v) => { return Mod.every(...v); }, // flatten a multidimensional array to 1D (or specified) 'flatten' : (...v) => { return Util.flatten(...v); }, 'flat' : (...v) => { return functionMap.flatten(v); }, // invert an array around a center point 'invert' : (...v) => { return Mod.invert(...v); }, 'inverse' : (...v) => { return Mod.invert(...v); }, 'flip' : (...v) => { return Mod.invert(...v); }, 'inv' : (...v) => { return Mod.invert(...v); }, // filter items from an array 'filter' : (...v) => { return Mod.filter(v[0], v.slice(1, v.length)); }, // lookup the values from an array based on another array 'lookup' : (...v) => { return Mod.lookup(...v); }, 'get' : (...v) => { return Mod.lookup(...v); }, // interleave multiple arrays into one 'lace' : (...v) => { return Mod.lace(...v); }, 'zip' : (...v) => { return Mod.lace(...v); }, // merge arrays into a 2D-array 'merge' : (...v) => { return Mod.merge(...v); }, // 'mix' : (...v) => { // return Mod.merge(...v); // }, // generate a palindrome of an array 'palindrome' : (...v) => { return Mod.palindrome(...v); }, 'palin' : (...v) => { return Mod.palindrome(...v); }, 'pinky' : (...v) => { return Mod.pinkyUp(...v); }, 'pinkyUp' : (...v) => { return Mod.pinkyUp(...v); }, 'pinkyDown' : (...v) => { return Mod.pinkyDown(...v); }, 'pinkyUpDown' : (...v) => { return Mod.pinkyUpDown(...v); }, 'mirror' : (...v) => { return Mod.palindrome(...v); }, // repeat the individual values of an array by a certain amount 'repeat' : (...v) => { return Mod.repeat(...v); }, // reverse an array 'reverse' : (...v) => { return Mod.reverse(...v); }, 'rev' : (...v) => { return Mod.reverse(...v); }, 'retrograde' : (...v) => { return Mod.reverse(...v); }, // rotate an array in positive or negative direction 'rotate' : (...v) => { return Mod.rotate(...v); }, 'rot' : (...v) => { return Mod.rotate(...v); }, 'turn' : (...v) => { return Mod.rotate(...v); }, // sort an array in ascending or descending order 'sort' : (...v) => { return Stat.sort(...v); }, // spray values on the non-zero places of another array 'spray' : (...v) => { return Mod.spray(...v); }, // slice an array into one or multiple parts 'slice' : (...v) => { return Mod.slice(...v); }, // split an array recursively till the end 'split' : (...v) => { return Mod.split(...v); }, 'thumb' : (...v) => { return Mod.thumbUp(...v); }, 'thumbUp' : (...v) => { return Mod.thumbUp(...v); }, 'thumbDown' : (...v) => { return Mod.thumbDown(...v); }, 'thumbUpDown' : (...v) => { return Mod.thumbUpDown(...v); }, // cut a piece of the array and return 'cut' : (...v) => { return Mod.slice(...v)[0]; }, // cut a piece of the array and return the last part 'cutLast' : (...v) => { return Mod.slice(...v).pop(); }, // stretch an array to a specified length, interpolating values 'stretch' : (...v) => { return Util.trunc(functionMap['stretchFloat'](...v)); }, 'stretchF' : (...v) => { return functionMap['stretchFloat'](...v); }, 'stretchFloat' : (...v) => { // swap because of implementation in total-serialism v[0] = (Array.isArray(v[0])) ? v[0] : [v[0]]; v[1] = Math.max(2, (Array.isArray(v[1])) ? v[1][0] : v[1]); return Mod.stretch(...v); }, // remove duplicates from an array, leave order intact 'unique' : (...v) => { return Mod.unique(...v); }, 'thin' : (...v) => { return Mod.unique(...v); }, // // Translate Methods // 'tempo' : (...v) => { TL.setTempo(v[0]); return TL.getTempo(); }, 'getTempo' : () => { return TL.getTempo(); }, 'scale' : (...v) => { TL.setScale(...v); return TL.getSettings().map; }, 'getScale' : () => { return TL.getSettings().scale; }, 'getRoot' : () => { return TL.getSettings().root; }, 'getScaleMap' : () => { return TL.getSettings().map; }, 'scaleNames' : (...v) => { return TL.getScales(); }, 'tuning' : (...v) => { console.log('set tuning', v); }, 'root' : (v) => { TL.setRoot(v[0]); return TL.getSettings().root; }, // tempo translate methods // divisionToMs 'divisionToMs' : (...v) => { return TL.divisionToMs(...v); }, 'dtoms' : (...v) => { return TL.divisionToMs(...v); }, // divisionToRatio 'divisionToRatio' : (...v) => { return TL.divisionToRatio(...v); }, 'dtor' : (...v) => { return TL.divisionToRatio(...v); }, // ratioToMs 'ratioToMs' : (...v) => { return TL.ratioToMs(...v); }, 'rtoms' : (...v) => { return TL.ratioToMs(...v); }, // timeToRatio 'timeToRatio' : (...v) => { return TL.timevalueToRatio(...v); }, 'ttor' : (...v) => { return TL.timevalueToRatio(...v); }, // pitch translate methods // midiToNote 'midiToNote' : (...v) => { return TL.midiToNote(...v); }, 'mton' : (...v) => { return TL.midiToNote(...v); }, // midiToFreq 'midiToFreq' : (...v) => { return TL.midiToFreq(...v); }, 'mtof' : (...v) => { return TL.midiToFreq(...v); }, // freqToMidi 'freqToMidi' : (...v) => { return TL.freqToMidi(...v); }, 'ftom' : (...v) => { return TL.freqToMidi(...v); }, // freqToNote 'freqToNote' : (...v) => { return TL.freqToNote(...v); }, 'fton' : (...v) => { return TL.freqToNote(...v); }, // noteToMidi 'noteToMidi' : (...v) => { return TL.ntom(...v); }, 'ntom' : (...v) => { return TL.ntom(...v); }, // noteToFreq 'noteToFreq' : (...v) => { return TL.noteToFreq(...v); }, 'ntof' : (...v) => { return TL.noteToFreq(...v); }, // chromaToRelative 'chromaToRelative' : (...v) => { return TL.chromaToRelative(...v); }, 'ctor' : (...v) => { return TL.chromaToRelative(...v); }, // relativeToMidi 'relativeToMidi' : (...v) => { return TL.relativeToMidi(...v); }, 'rtom' : (...v) => { return TL.relativeToMidi(...v); }, // relativeToFreq 'relativeToFreq' : (...v) => { return TL.relativeToFreq(...v); }, 'rtof' : (...v) => { return TL.relativeToFreq(...v); }, // mapToScale functions 'toScale' : (...v) => { return TL.toScale(...v); }, // ratio to cent 'ratioToCent' : (...v) => { return TL.ratioToCent(...v); }, 'rtoc' : (...v) => { return TL.ratioToCent(...v); }, // chords generation 'chordsFromNumerals' : (...v) => { return TL.chordsFromNumerals(v); }, 'makeChords' : (...v) => { return functionMap.chordsFromNumerals(v); }, 'chordsFigured' : (...v) => { return functionMap.chordsFromNumerals(v); }, 'chordsFromNames' : (...v) => { return TL.chordsFromNames(...v); }, 'chordsNamed' : (...v) => { return functionMap.chordsFromNames(v); }, // translate text to ASCII 'textCode' : (...v) => { return TL.textCode(...v); }, // // Statistic Methods // // IMPLEMENTATION NEEDED // maximum // minimum // mean / average // median / center // mode / common // // Utility Methods // // wrap values between a low and high range 'wrap' : (...v) => { return Util.wrap(...v); }, // fold values between a low and high range 'fold' : (...v) => { return Util.fold(...v); }, // clip values between a low and high range 'clip' : (...v) => { return Util.constrain(...v); }, 'constrain' : (...v) => { return Util.constrain(...v); }, // scale values from an input range to an output range 'map' : (...v) => { return Util.map(...v); }, // sum the values from an array into one number 'sum' : (...v) => { return Util.sum(...v); }, 'reduce' : (...v) => { return Util.sum(...v); }, // return the size of an array 'size' : (v) => { return Util.size(v); }, // length unsupported because overwritten by function map to env // 'length' : (v) => { // return Util.size(v); // }, // add 1 or more values to an array 'add' : (...v) => { return Util.add(...v); }, // subtract 1 or more values from an array 'subtract' : (...v) => { return Util.subtract(...v); }, 'sub' : (...v) => { return Util.subtract(...v); }, // multiply 1 or more values to an array 'multiply' : (...v) => { return Util.multiply(...v); }, 'mult' : (...v) => { return Util.multiply(...v); }, 'mul' : (...v) => { return Util.multiply(...v); }, // divide 1 or more values from an array 'divide' : (...v) => { return Util.divide(...v); }, 'div' : (...v) => { return Util.divide(...v); }, // normalize an array to 0-1 range 'normalize' : (...v) => { return Util.normalize(...v); }, 'norm' : (...v) => { return Util.normalize(...v); }, // signed normalize an array to -1 1 range 'signedNormalize' : (...v) => { return Util.add(Util.mult(Util.norm(...v), 2), -1); }, 'snorm' : (...v) => { return functionMap.signedNormalize(...v); }, // take the modulus of an array 'modulo' : (...v) => { return Util.mod(...v); }, 'mod' : (...v) => { return Util.mod(...v); }, // convert floats to integers by truncating 'int' : (v) => { return Util.arrayCalc(v, 0, (a) => Math.trunc(a)); }, // round down floats 'floor' : (v) => { return Util.arrayCalc(v, 0, (a) => Math.floor(a)); }, // round floats to nearest integer 'round' : (v) => { return Util.arrayCalc(v, 0, (a) => Math.round(a)); }, 'ceil' : (v) => { return Util.arrayCalc(v, 0, (a) => Math.ceil(a)); }, // compare two lists for equals 'equals' : (...v) => { return Util.arrayCalc(v[0], v[1], (a,b) => Number(a === b)); }, 'eq' : (...v) => { return functionMap.equals(...v); }, // compare two lists for not equal 'notEquals' : (...v) => { return Util.arrayCalc(v[0], v[1], (a,b) => Number(a !== b)); }, 'neq' : (...v) => { return functionMap.notEquals(...v); }, // compare left for greater than right list 'greater' : (...v) => { return Util.arrayCalc(v[0], v[1], (a,b) => Number(a > b)); }, 'gt' : (...v) => { return functionMap.greater(...v); }, // compare left for greater than or equal to right list 'greaterEquals' : (...v) => { return Util.arrayCalc(v[0], v[1], (a,b) => Number(a >= b)); }, 'gte' : (...v) => { return functionMap.greaterEquals(...v); }, // compare left for less than right list 'less' : (...v) => { return Util.arrayCalc(v[0], v[1], (a,b) => Number(a < b)); }, 'lt' : (...v) => { return functionMap.less(...v); }, // compare left for less than or equal to right list 'lessEquals' : (...v) => { return Util.arrayCalc(v[0], v[1], (a,b) => Number(a <= b)); }, 'lte' : (...v) => { return functionMap.lessEquals(...v); }, } exports.functionMap = functionMap;