UNPKG

genish.js

Version:
118 lines (89 loc) 3.62 kB
'use strict' let gen = require('./gen.js') let proto = { basename:'accum', gen() { let code, inputs = gen.getInputs( this ), genName = 'gen.' + this.name, functionBody gen.requestMemory( this.memory ) gen.memory.heap[ this.memory.value.idx ] = this.initialValue functionBody = this.callback( genName, inputs[0], inputs[1], `memory[${this.memory.value.idx}]` ) //gen.closures.add({ [ this.name ]: this }) gen.memo[ this.name ] = this.name + '_value' return [ this.name + '_value', functionBody ] }, callback( _name, _incr, _reset, valueRef ) { let diff = this.max - this.min, out = '', wrap = '' /* three different methods of wrapping, third is most expensive: * * 1: range {0,1}: y = x - (x | 0) * 2: log2(this.max) == integer: y = x & (this.max - 1) * 3: all others: if( x >= this.max ) y = this.max -x * */ // must check for reset before storing value for output if( !(typeof this.inputs[1] === 'number' && this.inputs[1] < 1) ) { if( this.resetValue !== this.min ) { out += ` if( ${_reset} >=1 ) ${valueRef} = ${this.resetValue}\n\n` //out += ` if( ${_reset} >=1 ) ${valueRef} = ${this.min}\n\n` }else{ out += ` if( ${_reset} >=1 ) ${valueRef} = ${this.min}\n\n` //out += ` if( ${_reset} >=1 ) ${valueRef} = ${this.initialValue}\n\n` } } out += ` var ${this.name}_value = ${valueRef}\n` if( this.shouldWrap === false && this.shouldClamp === true ) { out += ` if( ${valueRef} < ${this.max } ) ${valueRef} += ${_incr}\n` }else{ out += ` ${valueRef} += ${_incr}\n` // store output value before accumulating } if( this.max !== Infinity && this.shouldWrapMax ) wrap += ` if( ${valueRef} >= ${this.max} ) ${valueRef} -= ${diff}\n` if( this.min !== -Infinity && this.shouldWrapMin ) wrap += ` if( ${valueRef} < ${this.min} ) ${valueRef} += ${diff}\n` //if( this.min === 0 && this.max === 1 ) { // wrap = ` ${valueRef} = ${valueRef} - (${valueRef} | 0)\n\n` //} else if( this.min === 0 && ( Math.log2( this.max ) | 0 ) === Math.log2( this.max ) ) { // wrap = ` ${valueRef} = ${valueRef} & (${this.max} - 1)\n\n` //} else if( this.max !== Infinity ){ // wrap = ` if( ${valueRef} >= ${this.max} ) ${valueRef} -= ${diff}\n\n` //} out = out + wrap + '\n' return out }, defaults : { min:0, max:1, resetValue:0, initialValue:0, shouldWrap:true, shouldWrapMax: true, shouldWrapMin:true, shouldClamp:false } } module.exports = ( incr, reset=0, properties ) => { const ugen = Object.create( proto ) Object.assign( ugen, { uid: gen.getUID(), inputs: [ incr, reset ], memory: { value: { length:1, idx:null } } }, proto.defaults, properties ) if( properties !== undefined && properties.shouldWrapMax === undefined && properties.shouldWrapMin === undefined ) { if( properties.shouldWrap !== undefined ) { ugen.shouldWrapMin = ugen.shouldWrapMax = properties.shouldWrap } } if( properties !== undefined && properties.resetValue === undefined ) { ugen.resetValue = ugen.min } if( ugen.initialValue === undefined ) ugen.initialValue = ugen.min Object.defineProperty( ugen, 'value', { get() { //console.log( 'gen:', gen, gen.memory ) return gen.memory.heap[ this.memory.value.idx ] }, set(v) { gen.memory.heap[ this.memory.value.idx ] = v } }) ugen.name = `${ugen.basename}${ugen.uid}` return ugen }