| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************/  /* c8 ignore next 2 */ | 
					
						
							|  |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | var object = require('ig-object') | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | // The generator hirearchy in JS is a bit complicated.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Consider the following:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		// this is the generator function (i.e. the constructor)
 | 
					
						
							|  |  |  | // 		var Iter = function*(lst){
 | 
					
						
							|  |  |  | // 			for(var e of lst){
 | 
					
						
							|  |  |  | // 				yield e }}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		// this is the generator instance (constructod instance)...
 | 
					
						
							|  |  |  | // 		var iter = Iter([1,2,3])
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // In this module we need to add methods to be visible from either Iter
 | 
					
						
							|  |  |  | // or iter from the above example, so we need the access the prototypes 
 | 
					
						
							|  |  |  | // of each of them.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	GeneratorPrototype 
 | 
					
						
							|  |  |  | // 		is the prototype of the generator construcotrs (i.e. Iter(..) 
 | 
					
						
							|  |  |  | // 		from the above example)
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	GeneratorPrototype.prototype
 | 
					
						
							|  |  |  | // 		is the generator instance prototype (i.e. iter for the above 
 | 
					
						
							|  |  |  | // 		code)
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Also the following applies:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		iter instanceof Iter		// -> true
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		Iter instanceof Generator
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: there appears no way to test if iter is instnace of some 
 | 
					
						
							|  |  |  | // 		generic Generator...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var GeneratorPrototype = | 
					
						
							|  |  |  | 	(function*(){}).constructor.prototype | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Generator =  | 
					
						
							|  |  |  | module.Generator = | 
					
						
							|  |  |  | 	(function*(){}).constructor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // generic generator wrapper...
 | 
					
						
							|  |  |  | var iter =  | 
					
						
							|  |  |  | module.iter =  | 
					
						
							| 
									
										
										
										
											2020-11-12 17:35:41 +03:00
										 |  |  | 	function*(lst=[]){ | 
					
						
							|  |  |  | 		for(var e of lst){ | 
					
						
							|  |  |  | 			yield e } } | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | // GeneratorPrototype "class" methods...
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // the following are the same:
 | 
					
						
							|  |  |  | // 	1) Wrapper
 | 
					
						
							|  |  |  | // 		var combined = function(...args){
 | 
					
						
							|  |  |  | // 			return someGenerator(...args)
 | 
					
						
							|  |  |  | // 				.filter(function(e){ ... })
 | 
					
						
							|  |  |  | // 				.map(function(e){ ... }) }
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		combined( .. )
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	2) Static generator methods...
 | 
					
						
							|  |  |  | // 		var combined = someGenerator
 | 
					
						
							|  |  |  | // 			.filter(function(e){ ... })
 | 
					
						
							|  |  |  | // 			.map(function(e){ ... })
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		combined( .. )
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | // XXX this needs to be of the correct type... (???)
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | var makeGenerator = function(name){ | 
					
						
							|  |  |  | 	return function(...args){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 		return Object.assign( | 
					
						
							|  |  |  | 			function*(){ | 
					
						
							|  |  |  | 				yield* that(...arguments)[name](...args) },  | 
					
						
							|  |  |  | 			{ toString: function(){ | 
					
						
							|  |  |  | 				return [ | 
					
						
							|  |  |  | 					that.toString(),  | 
					
						
							|  |  |  | 					// XXX need to normalize args better...
 | 
					
						
							|  |  |  | 					`.${ name }(${ args.join(', ') })`, | 
					
						
							|  |  |  | 				].join('\n    ') }, }) } } | 
					
						
							|  |  |  | // XXX do a better doc...
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | var makePromise = function(name){ | 
					
						
							|  |  |  | 	return function(...args){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return function(){ | 
					
						
							|  |  |  | 			return that(...arguments)[name](func) } } } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | // XXX should this be a generator???
 | 
					
						
							|  |  |  | GeneratorPrototype.at = makeGenerator('at') | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.slice = makeGenerator('slice') | 
					
						
							|  |  |  | GeneratorPrototype.flat = makeGenerator('flat') | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | GeneratorPrototype.map = makeGenerator('map') | 
					
						
							|  |  |  | GeneratorPrototype.filter = makeGenerator('filter') | 
					
						
							|  |  |  | GeneratorPrototype.reduce = makeGenerator('reduce') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // non-generators...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.toArray = function(){ | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 	var that = this | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 	return Object.assign( | 
					
						
							|  |  |  | 		function(){ | 
					
						
							|  |  |  | 			return that(...arguments).toArray() }, | 
					
						
							|  |  |  | 		{ toString: function(){ | 
					
						
							|  |  |  | 			return that.toString()  | 
					
						
							|  |  |  | 				+ '\n    .toString()'}, }) }  | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.pop = function(){ | 
					
						
							|  |  |  | 	var that = this | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 	return Object.assign( | 
					
						
							|  |  |  | 		function(){ | 
					
						
							|  |  |  | 			return that(...arguments).toArray().pop() }, | 
					
						
							|  |  |  | 		{ toString: function(){ | 
					
						
							|  |  |  | 			return that.toString()  | 
					
						
							|  |  |  | 				+ '\n    .pop()'}, }) }  | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.shift = function(){ | 
					
						
							|  |  |  | 	var that = this | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 	return Object.assign( | 
					
						
							|  |  |  | 		function(){ | 
					
						
							|  |  |  | 			return that(...arguments).toArray().shift() },  | 
					
						
							|  |  |  | 		{ toString: function(){ | 
					
						
							|  |  |  | 			return that.toString()  | 
					
						
							|  |  |  | 				+ '\n    .shift()'}, }) }  | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | // promises...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.then = makePromise('then') | 
					
						
							|  |  |  | GeneratorPrototype.catch = makePromise('catch') | 
					
						
							|  |  |  | GeneratorPrototype.finally = makePromise('finally') | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | // GeneratorPrototype instance methods...
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | // XXX should this be a generator???
 | 
					
						
							|  |  |  | GeneratorPrototype.prototype.at = function*(i){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	// sanity check...
 | 
					
						
							|  |  |  | 	if(i < 0){ | 
					
						
							|  |  |  | 		throw new Error('.at(..): ' | 
					
						
							|  |  |  | 			+'generator index can\'t be a negative value.')} | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 	for(var e of this){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 		if(i-- == 0){ | 
					
						
							|  |  |  | 			yield e  | 
					
						
							|  |  |  | 			return } } }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NOTE: this is different from Array's .slice(..) in that it does not 
 | 
					
						
							|  |  |  | // 		support negative indexes -- this is done because there is no way 
 | 
					
						
							|  |  |  | // 		to judge the length of a generator untill it is fully done...
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.prototype.slice = function*(from=0, to=Infity){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	// sanity check...
 | 
					
						
							|  |  |  | 	if(from < 0 || to < 0){ | 
					
						
							|  |  |  | 		throw new Error('.slice(..): ' | 
					
						
							|  |  |  | 			+'generator form/to indexes can\'t be negative values.')} | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 	var i = 0 | 
					
						
							|  |  |  | 	for(var e of this){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 		// stop at end of seq...
 | 
					
						
							|  |  |  | 		if(i >= to){ | 
					
						
							|  |  |  | 			return } | 
					
						
							|  |  |  | 		// only yield from from...
 | 
					
						
							|  |  |  | 		if(i >= from){ | 
					
						
							|  |  |  | 			yield e } | 
					
						
							|  |  |  | 		i++ } }, | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | // XXX do we need a version that'll expand generators???
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.prototype.flat = function*(depth=1){ | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 	if(depth == 0){ | 
					
						
							|  |  |  | 		return this } | 
					
						
							|  |  |  | 	for(var e of this){ | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 		// expand array...
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 		if(e instanceof Array){ | 
					
						
							|  |  |  | 			for(var i=0; i < e.length; i++){ | 
					
						
							|  |  |  | 				if(depth <= 1){ | 
					
						
							|  |  |  | 					yield e[i] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					yield* typeof(e[i].flat) == 'function' ? | 
					
						
							|  |  |  | 						e[i].flat(depth-1) | 
					
						
							|  |  |  | 						: e[i] } } | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 		// item as-is...
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			yield e } } } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.prototype.map = function*(func){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	var i = 0 | 
					
						
							|  |  |  | 	for(var e of this){ | 
					
						
							|  |  |  | 		yield func(e, i++, this) } } | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.prototype.filter = function*(func){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	var i = 0 | 
					
						
							|  |  |  | 	for(var e of this){ | 
					
						
							|  |  |  | 		if(func(e, i++, this)){ | 
					
						
							|  |  |  | 			yield e } } } | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.prototype.reduce = function*(func, res){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	var i = 0 | 
					
						
							|  |  |  | 	for(var e of this){ | 
					
						
							|  |  |  | 		res = func(res, e, i++, this) }  | 
					
						
							|  |  |  | 	yield res } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | // non-generators...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | GeneratorPrototype.prototype.toArray = function(){ | 
					
						
							|  |  |  | 	return [...this] } | 
					
						
							|  |  |  | GeneratorPrototype.prototype.pop = function(){ | 
					
						
							|  |  |  | 	return [...this].pop() } | 
					
						
							|  |  |  | GeneratorPrototype.prototype.shift = function(){ | 
					
						
							|  |  |  | 	return [...this].shift() } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // promises...
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // XXX how do we handle reject(..) / .catch(..)???
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.prototype.promise = function(){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	var that = this | 
					
						
							|  |  |  | 	return new Promise(function(resolve){ | 
					
						
							|  |  |  | 			resolve([...that]) }) } | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.prototype.then = function(func){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	return this.promise().then(func) } | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.prototype.catch = function(func){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	return this.promise().catch(func) } | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | GeneratorPrototype.prototype.finally = function(func){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	return this.promise().finally(func) } | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |