| 
									
										
										
										
											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') | 
					
						
							| 
									
										
										
										
											2022-07-06 00:13:09 +03:00
										 |  |  | var stoppable = require('ig-stoppable') | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // NOTE: this is used in a similar fashion to Python's StopIteration...
 | 
					
						
							|  |  |  | var STOP = | 
					
						
							|  |  |  | module.STOP = | 
					
						
							| 
									
										
										
										
											2022-07-06 00:13:09 +03:00
										 |  |  | 	stoppable.STOP | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // The generator hierarchy in JS is a bit complicated.
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // Consider the following:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		// this is the generator function (i.e. the constructor)
 | 
					
						
							|  |  |  | // 		var Iter = function*(lst){
 | 
					
						
							|  |  |  | // 			for(var e of lst){
 | 
					
						
							|  |  |  | // 				yield e }}
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2021-01-05 04:37:47 +03:00
										 |  |  | // 		// this is the generator instance (constructed instance)...
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | // 		var iter = Iter([1,2,3])
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // In this module we need to add methods to be visible from either Iter
 | 
					
						
							| 
									
										
										
										
											2021-01-05 04:37:47 +03:00
										 |  |  | // or iter from the above example, so we need to access the prototypes 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | // of each of them.
 | 
					
						
							| 
									
										
										
										
											2021-01-05 04:37:47 +03:00
										 |  |  | // So, below we will define:
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2022-07-05 22:57:35 +03:00
										 |  |  | // 	Generator.prototype 
 | 
					
						
							| 
									
										
										
										
											2021-01-05 04:37:47 +03:00
										 |  |  | // 		prototype of the generator constructors (i.e. Iter(..) from the 
 | 
					
						
							|  |  |  | // 		above example)
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2022-07-05 22:57:35 +03:00
										 |  |  | // 	Generator.prototype.prototype
 | 
					
						
							| 
									
										
										
										
											2021-01-05 04:37:47 +03:00
										 |  |  | // 		generator instance prototype (i.e. iter for the above code)
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Also the following applies:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		iter instanceof Iter		// -> true
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		Iter instanceof Generator
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2021-03-24 18:57:02 +03:00
										 |  |  | // NOTE: there appears to be no way to test if iter is instance of some 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | // 		generic Generator...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Generator =  | 
					
						
							|  |  |  | module.Generator = | 
					
						
							|  |  |  | 	(function*(){}).constructor | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-15 16:44:16 +03:00
										 |  |  | var AsyncGenerator = | 
					
						
							|  |  |  | module.AsyncGenerator = | 
					
						
							|  |  |  | 	(async function*(){}).constructor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-29 15:17:06 +03:00
										 |  |  | // base iterator prototypes...
 | 
					
						
							|  |  |  | var ITERATOR_PROTOTYPES = [ | 
					
						
							|  |  |  | 	Array, | 
					
						
							|  |  |  | 	Set, | 
					
						
							|  |  |  | 	Map, | 
					
						
							|  |  |  | ].map(function(e){  | 
					
						
							|  |  |  | 	return (new e()).values().__proto__ }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | // generic generator wrapper...
 | 
					
						
							| 
									
										
										
										
											2022-06-23 13:37:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // helper...
 | 
					
						
							|  |  |  | var __iter =  | 
					
						
							|  |  |  | module.__iter = | 
					
						
							|  |  |  | function*(lst=[]){ | 
					
						
							| 
									
										
										
										
											2022-06-24 05:50:10 +03:00
										 |  |  | 	if(typeof(lst) == 'object'  | 
					
						
							|  |  |  | 			&& Symbol.iterator in lst){ | 
					
						
							| 
									
										
										
										
											2022-06-23 13:37:46 +03:00
										 |  |  | 		yield* lst  | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		yield lst } } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | // handle stops is onstop(..) is defined...
 | 
					
						
							|  |  |  | var __onstop = | 
					
						
							|  |  |  | function(res, _, ...args){ | 
					
						
							|  |  |  | 	var onstop = args.at(-1) | 
					
						
							|  |  |  | 	typeof(onstop) == 'function' | 
					
						
							|  |  |  | 		&& onstop.call(this,  | 
					
						
							|  |  |  | 			...(res === STOP ?  | 
					
						
							|  |  |  | 				[]  | 
					
						
							|  |  |  | 				: [res])) } | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-23 13:37:46 +03:00
										 |  |  | // XXX updatae Array.js' version for compatibility...
 | 
					
						
							|  |  |  | // XXX DOCS!!!
 | 
					
						
							| 
									
										
										
										
											2020-11-10 03:04:04 +03:00
										 |  |  | var iter =  | 
					
						
							|  |  |  | module.iter =  | 
					
						
							| 
									
										
										
										
											2021-05-19 16:16:17 +03:00
										 |  |  | Generator.iter = | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | 	stoppable( | 
					
						
							|  |  |  | 		function(lst=[]){ | 
					
						
							|  |  |  | 			// handler -> generator-constructor...
 | 
					
						
							|  |  |  | 			if(typeof(lst) == 'function'){ | 
					
						
							|  |  |  | 				// we need to be callable...
 | 
					
						
							|  |  |  | 				var that = this instanceof Function ? | 
					
						
							|  |  |  | 					this | 
					
						
							|  |  |  | 					// generic root generator...
 | 
					
						
							|  |  |  | 					: module.__iter | 
					
						
							|  |  |  | 				return function*(){ | 
					
						
							|  |  |  | 					yield* that(...arguments).iter(lst) } } | 
					
						
							|  |  |  | 			// no handler -> generator instance...
 | 
					
						
							|  |  |  | 			return module.__iter(lst) }, | 
					
						
							|  |  |  | 		__onstop) | 
					
						
							| 
									
										
										
										
											2022-06-23 13:37:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // NOTE: we need .iter(..) to both return generators if passed an iterable
 | 
					
						
							|  |  |  | // 		and genereator constructos if passed a function...
 | 
					
						
							| 
									
										
										
										
											2022-07-05 22:57:35 +03:00
										 |  |  | iter.__proto__ = Generator.prototype | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2022-07-05 22:57:35 +03:00
										 |  |  | // Generator.prototype "class" methods...
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2021-01-05 04:37:47 +03:00
										 |  |  | // the following are effectively the same:
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | // 	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( .. )
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2021-01-05 04:37:47 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | // Helpers...
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // 	makeGenerator(<name>)
 | 
					
						
							| 
									
										
										
										
											2022-06-22 10:26:04 +03:00
										 |  |  | // 	makeGenerator(<name>, <handler>)
 | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | // 		-> <func>
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2022-06-22 10:26:04 +03:00
										 |  |  | // 	makeGenerator('async', <name>)
 | 
					
						
							|  |  |  | // 	makeGenerator('async', <name>, <handler>)
 | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | // 		-> <func>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	<func>(...args)
 | 
					
						
							|  |  |  | // 		-> <Generator>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	<Generator>(...inputs)
 | 
					
						
							|  |  |  | // 		-> <generator>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	<handler>(args, ...inputs)
 | 
					
						
							|  |  |  | // 		-> args
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | // XXX this needs to be of the correct type... (???)
 | 
					
						
							| 
									
										
										
										
											2021-05-18 02:07:08 +03:00
										 |  |  | // XXX need to accept generators as handlers...
 | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | var makeGenerator = function(name, pre){ | 
					
						
							| 
									
										
										
										
											2022-06-22 10:26:04 +03:00
										 |  |  | 	var sync = true | 
					
						
							|  |  |  | 	if(name == 'async'){ | 
					
						
							|  |  |  | 		sync = false | 
					
						
							|  |  |  | 		var [name, pre] = [...arguments].slice(1) } | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 	return function(...args){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 		return Object.assign( | 
					
						
							| 
									
										
										
										
											2022-06-22 10:26:04 +03:00
										 |  |  | 			// NOTE: the two branches here are identical, the only 
 | 
					
						
							|  |  |  | 			// 		difference is the async keyword...
 | 
					
						
							|  |  |  | 			sync ? | 
					
						
							|  |  |  | 				function*(){ | 
					
						
							|  |  |  | 					var a = pre ?  | 
					
						
							|  |  |  | 						pre.call(this, args, ...arguments) | 
					
						
							|  |  |  | 						: args | 
					
						
							|  |  |  | 					yield* that(...arguments)[name](...a) } | 
					
						
							|  |  |  | 				: async function*(){ | 
					
						
							|  |  |  | 					var a = pre ?  | 
					
						
							|  |  |  | 						pre.call(this, args, ...arguments) | 
					
						
							|  |  |  | 						: args | 
					
						
							|  |  |  | 					yield* that(...arguments)[name](...a) },  | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | 			{ toString: function(){ | 
					
						
							|  |  |  | 				return [ | 
					
						
							|  |  |  | 					that.toString(),  | 
					
						
							|  |  |  | 					// XXX need to normalize args better...
 | 
					
						
							|  |  |  | 					`.${ name }(${ args.join(', ') })`, | 
					
						
							|  |  |  | 				].join('\n    ') }, }) } } | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 17:40:32 +03:00
										 |  |  | // XXX do a better doc...
 | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | var makeProxy = function(name){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	return function(...args){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return function(){ | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 			return that(...arguments)[name](...args) } } } | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | var GeneratorMixin = | 
					
						
							|  |  |  | module.GeneratorMixin = | 
					
						
							|  |  |  | object.Mixin('GeneratorMixin', 'soft', { | 
					
						
							| 
									
										
										
										
											2021-05-25 18:44:09 +03:00
										 |  |  | 	STOP: object.STOP, | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-23 13:37:46 +03:00
										 |  |  | 	iter: module.iter, | 
					
						
							| 
									
										
										
										
											2021-06-23 09:05:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 	gat: makeGenerator('gat'), | 
					
						
							|  |  |  | 	at: function(i){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return Object.assign( | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				return that(...arguments).at(i) }, | 
					
						
							|  |  |  | 			{ toString: function(){ | 
					
						
							|  |  |  | 				return that.toString()  | 
					
						
							|  |  |  | 					+ '\n    .at('+ i +')'}, }) }, | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	slice: makeGenerator('slice'), | 
					
						
							|  |  |  | 	flat: makeGenerator('flat'), | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	map: makeGenerator('map'), | 
					
						
							|  |  |  | 	filter: makeGenerator('filter'), | 
					
						
							|  |  |  | 	reduce: makeGenerator('reduce'), | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 	reduceRight: makeGenerator('reduceRight'), | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 01:48:59 +03:00
										 |  |  | 	// XXX
 | 
					
						
							|  |  |  | 	smap: makeGenerator('smap'), | 
					
						
							|  |  |  | 	sfilter: makeGenerator('sfilter'), | 
					
						
							|  |  |  | 	sreduce: makeGenerator('sreduce'), | 
					
						
							|  |  |  | 	sreduceRight: makeGenerator('sreduceRight'), | 
					
						
							|  |  |  | 	sforEach: makeGenerator('sforEach'), | 
					
						
							|  |  |  | 	//*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-14 11:15:54 +03:00
										 |  |  | 	between: makeGenerator('between'), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 11:25:10 +03:00
										 |  |  | 	// XXX EXPERIMENTAL
 | 
					
						
							|  |  |  | 	// XXX add .toString(..) to this???
 | 
					
						
							| 
									
										
										
										
											2022-08-08 21:51:06 +03:00
										 |  |  | 	forEach: function(func){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return function(){ | 
					
						
							|  |  |  | 			return that(...arguments).forEach(func) } }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	// non-generators...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	toArray: function(){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return Object.assign( | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				return that(...arguments).toArray() }, | 
					
						
							|  |  |  | 			{ toString: function(){ | 
					
						
							|  |  |  | 				return that.toString()  | 
					
						
							| 
									
										
										
										
											2022-07-27 14:11:01 +03:00
										 |  |  | 					+ '\n    .toArray()'}, }) }, | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 	gpop: makeGenerator('gpop'), | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	pop: function(){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return Object.assign( | 
					
						
							|  |  |  | 			function(){ | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 				//return that(...arguments).toArray().pop() },
 | 
					
						
							|  |  |  | 				return that(...arguments).pop() }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 			{ toString: function(){ | 
					
						
							|  |  |  | 				return that.toString()  | 
					
						
							| 
									
										
										
										
											2022-07-27 14:11:01 +03:00
										 |  |  | 					+ '\n    .pop()'}, }) }, | 
					
						
							| 
									
										
										
										
											2021-06-26 10:51:49 +03:00
										 |  |  | 	push: makeGenerator('push'), | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 	gshift: makeGenerator('gshift'), | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	shift: function(){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return Object.assign( | 
					
						
							|  |  |  | 			function(){ | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 				//return that(...arguments).toArray().shift() }, 
 | 
					
						
							|  |  |  | 				return that(...arguments).shift() },  | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 			{ toString: function(){ | 
					
						
							|  |  |  | 				return that.toString()  | 
					
						
							| 
									
										
										
										
											2022-07-27 14:11:01 +03:00
										 |  |  | 					+ '\n    .shift()'}, }) }, | 
					
						
							| 
									
										
										
										
											2021-06-26 10:51:49 +03:00
										 |  |  | 	unshift: makeGenerator('unshift'), | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// promises...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 	// NOTE: .then(..) and friends are intentionally not defined here to
 | 
					
						
							|  |  |  | 	// 		prevent control deadlocks when awaiting for a generator that
 | 
					
						
							|  |  |  | 	// 		expects manual unwinding e.g.:
 | 
					
						
							|  |  |  | 	// 			g = function*(){}
 | 
					
						
							|  |  |  | 	// 			await g				// will hang waiting for g to resolve
 | 
					
						
							|  |  |  | 	unwind: makeProxy('unwind'), | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// combinators...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	chain: makeGenerator('chain'), | 
					
						
							|  |  |  | 	concat: makeGenerator('concat',  | 
					
						
							|  |  |  | 		// initialize arguments...
 | 
					
						
							|  |  |  | 		function(next, ...args){ | 
					
						
							|  |  |  | 			return next | 
					
						
							|  |  |  | 				.map(function(e){ | 
					
						
							|  |  |  | 					return (e instanceof Generator | 
					
						
							|  |  |  | 							|| typeof(e) == 'function') ? | 
					
						
							|  |  |  | 						e(...args) | 
					
						
							|  |  |  | 						: e }) }), | 
					
						
							|  |  |  | 	//zip: makeGenerator('zip'),
 | 
					
						
							| 
									
										
										
										
											2022-07-05 16:43:28 +03:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	enumerate: makeGenerator('enumerate'), | 
					
						
							| 
									
										
										
										
											2022-07-27 14:11:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// XXX should this have a .gjoin(..) companion...
 | 
					
						
							|  |  |  | 	join: function(){ | 
					
						
							|  |  |  | 		var args = [...arguments] | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return Object.assign( | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				//return that(...arguments).toArray().shift() }, 
 | 
					
						
							|  |  |  | 				return that(...arguments).join(...args) },  | 
					
						
							|  |  |  | 			{ toString: function(){ | 
					
						
							|  |  |  | 				return that.toString()  | 
					
						
							|  |  |  | 					+ '\n    .join()'}, }) }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var GeneratorProtoMixin = | 
					
						
							|  |  |  | module.GeneratorProtoMixin = | 
					
						
							|  |  |  | object.Mixin('GeneratorProtoMixin', 'soft', { | 
					
						
							| 
									
										
										
										
											2022-06-23 13:37:46 +03:00
										 |  |  | 	// XXX use module.iter(..) ???
 | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | 	iter: stoppable( | 
					
						
							|  |  |  | 		function*(handler, onerror){  | 
					
						
							|  |  |  | 			try{ | 
					
						
							|  |  |  | 				if(handler){ | 
					
						
							|  |  |  | 					var i = 0 | 
					
						
							|  |  |  | 					for(var elem of this){ | 
					
						
							|  |  |  | 						var res = handler.call(this, elem, i)  | 
					
						
							|  |  |  | 						// expand iterables...
 | 
					
						
							|  |  |  | 						if(typeof(res) == 'object'  | 
					
						
							|  |  |  | 								&& Symbol.iterator in res){ | 
					
						
							|  |  |  | 							yield* res | 
					
						
							|  |  |  | 						// as-is...
 | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							yield res }} | 
					
						
							|  |  |  | 				// no handler...
 | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					yield* this }  | 
					
						
							|  |  |  | 			}catch(err){ | 
					
						
							|  |  |  | 				if(onerror){ | 
					
						
							|  |  |  | 					if(!(err === STOP  | 
					
						
							|  |  |  | 							|| err instanceof STOP)){ | 
					
						
							|  |  |  | 						var res = onerror(err) | 
					
						
							|  |  |  | 						if(res){ | 
					
						
							|  |  |  | 							yield res | 
					
						
							|  |  |  | 							return } } } | 
					
						
							|  |  |  | 				throw err }}, | 
					
						
							|  |  |  | 		__onstop), | 
					
						
							| 
									
										
										
										
											2022-06-23 13:37:46 +03:00
										 |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2021-06-23 09:05:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 	at: function(i){ | 
					
						
							|  |  |  | 		return this.gat(i).next().value }, | 
					
						
							|  |  |  | 	// XXX this needs the value to be iterable... why???
 | 
					
						
							|  |  |  | 	gat: function*(i){ | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 		// sanity check...
 | 
					
						
							|  |  |  | 		if(i < 0){ | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 			throw new Error('.gat(..): ' | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 				+'generator index can\'t be a negative value.')} | 
					
						
							|  |  |  | 		for(var e of this){ | 
					
						
							|  |  |  | 			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 
 | 
					
						
							| 
									
										
										
										
											2021-05-07 02:50:08 +03:00
										 |  |  | 	// 		to judge the length of a generator until it is fully done...
 | 
					
						
							| 
									
										
										
										
											2021-06-17 20:15:29 +03:00
										 |  |  | 	slice: function*(from=0, to=Infinity){ | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 		// sanity check...
 | 
					
						
							|  |  |  | 		if(from < 0 || to < 0){ | 
					
						
							|  |  |  | 			throw new Error('.slice(..): ' | 
					
						
							|  |  |  | 				+'generator form/to indexes can\'t be negative values.')} | 
					
						
							|  |  |  | 		var i = 0 | 
					
						
							|  |  |  | 		for(var e of this){ | 
					
						
							|  |  |  | 			// stop at end of seq...
 | 
					
						
							|  |  |  | 			if(i >= to){ | 
					
						
							|  |  |  | 				return } | 
					
						
							|  |  |  | 			// only yield from from...
 | 
					
						
							|  |  |  | 			if(i >= from){ | 
					
						
							|  |  |  | 				yield e } | 
					
						
							|  |  |  | 			i++ } }, | 
					
						
							|  |  |  | 	// XXX do we need a version that'll expand generators???
 | 
					
						
							|  |  |  | 	flat: function*(depth=1){ | 
					
						
							|  |  |  | 		if(depth == 0){ | 
					
						
							|  |  |  | 			return this } | 
					
						
							|  |  |  | 		for(var e of this){ | 
					
						
							|  |  |  | 			// expand array...
 | 
					
						
							|  |  |  | 			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] } } | 
					
						
							|  |  |  | 			// item as-is...
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				yield e } } }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-18 02:07:08 +03:00
										 |  |  | 	// NOTE: if func is instanceof Generator then it's result (iterator) 
 | 
					
						
							|  |  |  | 	// 		will be expanded...
 | 
					
						
							| 
									
										
										
										
											2021-05-18 12:24:31 +03:00
										 |  |  | 	// NOTE: there is no point to add generator-handler support to either 
 | 
					
						
							|  |  |  | 	// 		.filter(..)  or .reduce(..)
 | 
					
						
							| 
									
										
										
										
											2021-05-25 18:21:30 +03:00
										 |  |  | 	map: stoppable( | 
					
						
							|  |  |  | 		function*(func){ | 
					
						
							|  |  |  | 			var i = 0 | 
					
						
							|  |  |  | 			if(func instanceof Generator){ | 
					
						
							|  |  |  | 				for(var e of this){ | 
					
						
							|  |  |  | 					yield* func(e, i++, this) }  | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				for(var e of this){ | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | 					yield func(e, i++, this) } } }, | 
					
						
							|  |  |  | 		__onstop), | 
					
						
							| 
									
										
										
										
											2023-02-08 01:48:59 +03:00
										 |  |  | 	smap: function*(func){ | 
					
						
							|  |  |  | 		yield* this.map(...arguments) }, | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | 	filter: stoppable( | 
					
						
							|  |  |  | 		function*(func){ | 
					
						
							| 
									
										
										
										
											2021-05-25 18:21:30 +03:00
										 |  |  | 			var i = 0 | 
					
						
							|  |  |  | 			try{ | 
					
						
							|  |  |  | 				for(var e of this){ | 
					
						
							|  |  |  | 					if(func(e, i++, this)){ | 
					
						
							|  |  |  | 						yield e } }  | 
					
						
							|  |  |  | 			// normalize the stop value...
 | 
					
						
							|  |  |  | 			} catch(err){ | 
					
						
							|  |  |  | 				if(err instanceof STOP){ | 
					
						
							|  |  |  | 					if(!err.value){ | 
					
						
							|  |  |  | 						throw STOP } | 
					
						
							|  |  |  | 					err.value = e } | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | 				throw err } }, | 
					
						
							|  |  |  | 		__onstop), | 
					
						
							| 
									
										
										
										
											2023-02-08 01:48:59 +03:00
										 |  |  | 	sfilter: function*(func){ | 
					
						
							|  |  |  | 		yield* this.filter(...arguments) }, | 
					
						
							| 
									
										
										
										
											2021-05-25 18:21:30 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | 	reduce: stoppable( | 
					
						
							|  |  |  | 		function(func, res){ | 
					
						
							|  |  |  | 			var i = 0 | 
					
						
							|  |  |  | 			for(var e of this){ | 
					
						
							|  |  |  | 				res = func(res, e, i++, this) } | 
					
						
							|  |  |  | 			return res }, | 
					
						
							|  |  |  | 		// NOTE: we need to wrap __onstop(..) here to prevent res if it 
 | 
					
						
							|  |  |  | 		// 		was passed a function from ever being treated as onstop(..)...
 | 
					
						
							|  |  |  | 		function(res, f, _, onstop){ | 
					
						
							|  |  |  | 			return __onstop.call(this, res, onstop) }), | 
					
						
							| 
									
										
										
										
											2023-02-08 01:48:59 +03:00
										 |  |  | 	sreduce: function*(func, res){ | 
					
						
							|  |  |  | 		yield* this.reduce(...arguments) }, | 
					
						
							| 
									
										
										
										
											2021-05-25 18:21:30 +03:00
										 |  |  | 	greduce: function*(func, res){ | 
					
						
							|  |  |  | 		yield this.reduce(...arguments) }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | 	between: stoppable( | 
					
						
							|  |  |  | 		function*(func){ | 
					
						
							|  |  |  | 			var i = 0 | 
					
						
							|  |  |  | 			var j = 0 | 
					
						
							|  |  |  | 			var prev | 
					
						
							|  |  |  | 			for(var e of this){ | 
					
						
							|  |  |  | 				if(i > 0){ | 
					
						
							|  |  |  | 					yield typeof(func) == 'function' ? | 
					
						
							|  |  |  | 						func.call(this, [prev, e], i-1, i + j++, this) | 
					
						
							|  |  |  | 						: func } | 
					
						
							|  |  |  | 				prev = e | 
					
						
							|  |  |  | 				yield e | 
					
						
							|  |  |  | 				i++ } }, | 
					
						
							|  |  |  | 		__onstop), | 
					
						
							| 
									
										
										
										
											2022-08-14 11:15:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 21:51:06 +03:00
										 |  |  | 	// NOTE: this is a special case in that it will unwind the generator...
 | 
					
						
							|  |  |  | 	// NOTE: this is different from <array>.forEach(..) in that this will
 | 
					
						
							|  |  |  | 	// 		return the resulting array.
 | 
					
						
							| 
									
										
										
										
											2022-08-09 11:25:10 +03:00
										 |  |  | 	// XXX EXPERIMENTAL
 | 
					
						
							| 
									
										
										
										
											2022-08-08 21:51:06 +03:00
										 |  |  | 	forEach: function(func){ | 
					
						
							|  |  |  | 		return [...this].map(func) }, | 
					
						
							| 
									
										
										
										
											2023-02-08 01:48:59 +03:00
										 |  |  | 	sforEach: function(func){ | 
					
						
							|  |  |  | 		return this.forEach(func) }, | 
					
						
							| 
									
										
										
										
											2022-08-08 21:51:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	pop: function(){ | 
					
						
							|  |  |  | 		return [...this].pop() }, | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 	// XXX this needs the value to be iterable...
 | 
					
						
							|  |  |  | 	gpop: function*(){ | 
					
						
							|  |  |  | 		yield [...this].pop() }, | 
					
						
							| 
									
										
										
										
											2021-06-26 10:51:49 +03:00
										 |  |  | 	push: function*(value){ | 
					
						
							|  |  |  | 		yield* this | 
					
						
							|  |  |  | 		yield value }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	shift: function(){ | 
					
						
							| 
									
										
										
										
											2021-03-26 02:12:55 +03:00
										 |  |  | 		return this.next().value }, | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 	// XXX this needs the value to be iterable...
 | 
					
						
							|  |  |  | 	gshift: function*(){ | 
					
						
							|  |  |  | 		yield this.next().value }, | 
					
						
							| 
									
										
										
										
											2021-06-26 10:51:49 +03:00
										 |  |  | 	unshift: function*(value){ | 
					
						
							|  |  |  | 		yield value | 
					
						
							|  |  |  | 		yield* this }, | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// non-generators...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	toArray: function(){ | 
					
						
							|  |  |  | 		return [...this] }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// promises...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 	// NOTE: this will unwind the generator...
 | 
					
						
							|  |  |  | 	unwind: function(onresolve, onreject){ | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2022-06-21 13:41:06 +03:00
										 |  |  | 		var p = new Promise( | 
					
						
							|  |  |  | 			function(resolve){ | 
					
						
							|  |  |  | 				resolve([...that]) })  | 
					
						
							|  |  |  | 		p = (onresolve || onreject) ? | 
					
						
							|  |  |  | 			p.then(...arguments) | 
					
						
							|  |  |  | 			: p | 
					
						
							|  |  |  | 		return p }, | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 	then: function(...args){ | 
					
						
							|  |  |  | 		return this.unwind(...args) }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	catch: function(func){ | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 		return this.unwind().catch(...arguments) }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	finally: function(func){ | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 		return this.unwind.finally(...arguments) }, | 
					
						
							| 
									
										
										
										
											2021-03-24 02:10:55 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 	// combinators...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	chain: function*(...next){ | 
					
						
							|  |  |  | 		yield* next | 
					
						
							|  |  |  | 			.reduce(function(cur, next){ | 
					
						
							|  |  |  | 				return next(cur) }, this) }, | 
					
						
							|  |  |  | 	concat: function*(...next){ | 
					
						
							|  |  |  | 		yield* this | 
					
						
							|  |  |  | 		for(var e of next){ | 
					
						
							|  |  |  | 			yield* e } }, | 
					
						
							| 
									
										
										
										
											2021-03-24 02:10:55 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 	/* XXX not sure how to do this yet... | 
					
						
							|  |  |  | 	tee: function*(...next){ | 
					
						
							|  |  |  | 		// XXX take the output of the current generator and feed it into 
 | 
					
						
							|  |  |  | 		// 		each of the next generators... (???)
 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	zip: function*(...items){ | 
					
						
							|  |  |  | 		// XXX
 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2022-07-05 16:43:28 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	enumerate: function*(){ | 
					
						
							|  |  |  | 		var i = 0 | 
					
						
							|  |  |  | 		for(var e of this){ | 
					
						
							|  |  |  | 			yield [i++, e] } }, | 
					
						
							| 
									
										
										
										
											2022-07-27 14:11:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	join: function(){ | 
					
						
							|  |  |  | 		return [...this] | 
					
						
							|  |  |  | 			.join(...arguments) }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-05 22:57:35 +03:00
										 |  |  | GeneratorMixin(Generator.prototype) | 
					
						
							|  |  |  | GeneratorProtoMixin(Generator.prototype.prototype) | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-29 15:17:06 +03:00
										 |  |  | // Extend base iterators...
 | 
					
						
							|  |  |  | ITERATOR_PROTOTYPES | 
					
						
							|  |  |  | 	.forEach(function(proto){ | 
					
						
							|  |  |  | 		GeneratorProtoMixin(proto) }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-15 16:44:16 +03:00
										 |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | // XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var AsyncGeneratorMixin = | 
					
						
							|  |  |  | module.AsyncGeneratorMixin = | 
					
						
							|  |  |  | object.Mixin('AsyncGeneratorMixin', 'soft', { | 
					
						
							| 
									
										
										
										
											2022-06-22 10:26:04 +03:00
										 |  |  | 	// XXX TEST...
 | 
					
						
							|  |  |  | 	iter: makeGenerator('async', 'iter'), | 
					
						
							| 
									
										
										
										
											2022-06-23 13:37:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-22 10:26:04 +03:00
										 |  |  | 	map: makeGenerator('async', 'map'), | 
					
						
							|  |  |  | 	filter: makeGenerator('async', 'filter'), | 
					
						
							|  |  |  | 	reduce: makeGenerator('async', 'reduce'), | 
					
						
							| 
									
										
										
										
											2022-08-14 11:15:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// XXX TEST...
 | 
					
						
							|  |  |  | 	between: makeGenerator('async', 'between'), | 
					
						
							| 
									
										
										
										
											2022-06-15 16:44:16 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var AsyncGeneratorProtoMixin = | 
					
						
							|  |  |  | module.AsyncGeneratorProtoMixin = | 
					
						
							|  |  |  | object.Mixin('AsyncGeneratorProtoMixin', 'soft', { | 
					
						
							| 
									
										
										
										
											2022-06-22 10:26:04 +03:00
										 |  |  | 	// promise...
 | 
					
						
							| 
									
										
										
										
											2022-06-17 12:01:04 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: this will unwind the generator...
 | 
					
						
							| 
									
										
										
										
											2022-06-20 00:11:06 +03:00
										 |  |  | 	// XXX create an iterator promise???
 | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 	unwind: function(onresolve, onreject){ | 
					
						
							| 
									
										
										
										
											2022-06-17 12:01:04 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 		var p = new Promise(async function(resolve){ | 
					
						
							| 
									
										
										
										
											2022-06-17 12:01:04 +03:00
										 |  |  | 			var res = [] | 
					
						
							|  |  |  | 			for await(var elem of that){ | 
					
						
							|  |  |  | 				res.push(elem) } | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 			resolve(res) })  | 
					
						
							|  |  |  | 		p = (onresolve || onreject) ? | 
					
						
							| 
									
										
										
										
											2022-06-21 13:49:50 +03:00
										 |  |  | 			p.then(...arguments) | 
					
						
							|  |  |  | 			: p | 
					
						
							| 
									
										
										
										
											2022-06-17 12:01:04 +03:00
										 |  |  | 		return p }, | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 	then: function(...args){ | 
					
						
							|  |  |  | 		return this.unwind(...args) }, | 
					
						
							| 
									
										
										
										
											2022-06-21 13:49:50 +03:00
										 |  |  | 	catch: function(func){ | 
					
						
							| 
									
										
										
										
											2022-09-14 11:22:00 +03:00
										 |  |  | 		return this.unwind().catch(...arguments) }, | 
					
						
							|  |  |  | 	finally: function(func){ | 
					
						
							|  |  |  | 		return this.unwind.finally(...arguments) }, | 
					
						
							| 
									
										
										
										
											2022-06-17 12:01:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-20 00:11:06 +03:00
										 |  |  | 	// XXX might be a good idea to use this approach above...
 | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | 	iter: stoppable( | 
					
						
							|  |  |  | 		async function*(handler=undefined, onerror=undefined){ | 
					
						
							|  |  |  | 			try{ | 
					
						
							|  |  |  | 				var i = 0 | 
					
						
							|  |  |  | 				if(handler){ | 
					
						
							|  |  |  | 					for await(var e of this){ | 
					
						
							|  |  |  | 						var res = handler.call(this, e, i++) | 
					
						
							|  |  |  | 						if(typeof(res) == 'object'  | 
					
						
							|  |  |  | 								&& Symbol.iterator in res){ | 
					
						
							|  |  |  | 							yield* res | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							yield res } } | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					yield* this }  | 
					
						
							|  |  |  | 			}catch(err){ | 
					
						
							|  |  |  | 				if(onerror){ | 
					
						
							|  |  |  | 					if(!(err === STOP || err instanceof STOP)){ | 
					
						
							|  |  |  | 						var res = onerror(err)  | 
					
						
							|  |  |  | 						if(res !== undefined){ | 
					
						
							|  |  |  | 							yield handler ? | 
					
						
							|  |  |  | 								handler(res) | 
					
						
							|  |  |  | 								: res }  | 
					
						
							|  |  |  | 						return } } | 
					
						
							|  |  |  | 				throw err } }, | 
					
						
							|  |  |  | 		__onstop), | 
					
						
							| 
									
										
										
										
											2022-06-20 00:11:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	map: async function*(func){ | 
					
						
							|  |  |  | 		yield* this.iter(function(elem, i){ | 
					
						
							|  |  |  | 			return [func.call(this, elem, i)] }) }, | 
					
						
							|  |  |  | 	filter: async function*(func){ | 
					
						
							|  |  |  | 		yield* this.iter(function(elem, i){ | 
					
						
							|  |  |  | 			return func.call(this, elem, i) ? | 
					
						
							|  |  |  | 	   			[elem] | 
					
						
							|  |  |  | 				: [] }) }, | 
					
						
							| 
									
										
										
										
											2022-06-23 13:37:46 +03:00
										 |  |  | 	// NOTE: there is not much point in .reduceRight(..) in an async 
 | 
					
						
							|  |  |  | 	// 		generator as we'll need to fully unwind it then go from the 
 | 
					
						
							|  |  |  | 	// 		end...
 | 
					
						
							| 
									
										
										
										
											2022-06-20 00:11:06 +03:00
										 |  |  | 	reduce: async function(func, state){ | 
					
						
							|  |  |  | 		this.iter(function(elem, i){ | 
					
						
							|  |  |  | 			state = func.call(this, state, elem, i)  | 
					
						
							|  |  |  | 			return [] }) | 
					
						
							|  |  |  | 		return state }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-14 11:15:54 +03:00
										 |  |  | 	// XXX BETWEEN...
 | 
					
						
							| 
									
										
										
										
											2022-08-14 13:38:37 +03:00
										 |  |  | 	between: async function*(func){ | 
					
						
							| 
									
										
										
										
											2022-08-14 13:46:22 +03:00
										 |  |  | 		var i = 0 | 
					
						
							|  |  |  | 		var j = 0 | 
					
						
							|  |  |  | 		var prev | 
					
						
							|  |  |  | 		yield* this.iter(function(e){ | 
					
						
							|  |  |  | 			return i++ > 0 ? | 
					
						
							|  |  |  | 				[ | 
					
						
							|  |  |  | 					typeof(func) == 'function' ? | 
					
						
							| 
									
										
										
										
											2022-08-14 19:40:00 +03:00
										 |  |  | 						func.call(this, [prev, e], i, i + j++, this) | 
					
						
							| 
									
										
										
										
											2022-08-14 13:46:22 +03:00
										 |  |  | 						: func,	 | 
					
						
							|  |  |  | 					e, | 
					
						
							|  |  |  | 				] | 
					
						
							|  |  |  | 				: [e] }) }, | 
					
						
							| 
									
										
										
										
											2022-08-14 11:15:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 13:41:06 +03:00
										 |  |  | 	// XXX TEST...
 | 
					
						
							|  |  |  | 	chain: async function*(...next){ | 
					
						
							|  |  |  | 		yield* next | 
					
						
							|  |  |  | 			.reduce(function(cur, next){ | 
					
						
							|  |  |  | 				return next(cur) }, this) }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 07:49:03 +03:00
										 |  |  | 	flat: async function*(){ | 
					
						
							|  |  |  | 		for await(var e of this){ | 
					
						
							|  |  |  | 			if(e instanceof Array){ | 
					
						
							|  |  |  | 				yield* e | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				yield e }}}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-20 00:11:06 +03:00
										 |  |  | 	concat: async function*(other){ | 
					
						
							|  |  |  | 		yield* this | 
					
						
							|  |  |  | 		yield* other }, | 
					
						
							|  |  |  | 	push: async function*(elem){ | 
					
						
							|  |  |  | 		yield* this | 
					
						
							|  |  |  | 		yield elem }, | 
					
						
							|  |  |  | 	unsift: async function*(elem){ | 
					
						
							|  |  |  | 		yield elem  | 
					
						
							|  |  |  | 		yield* this }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 14:11:01 +03:00
										 |  |  | 	join: async function(){ | 
					
						
							|  |  |  | 		return [...(await this)] | 
					
						
							|  |  |  | 			.join(...arguments) }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-20 00:11:06 +03:00
										 |  |  | 	// XXX
 | 
					
						
							| 
									
										
										
										
											2022-06-22 10:26:04 +03:00
										 |  |  | 	// 	slice -- not sure if we need this...
 | 
					
						
							| 
									
										
										
										
											2022-06-20 00:11:06 +03:00
										 |  |  | 	// 	...
 | 
					
						
							| 
									
										
										
										
											2022-06-15 16:44:16 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-05 22:57:35 +03:00
										 |  |  | AsyncGeneratorMixin(AsyncGenerator.prototype) | 
					
						
							|  |  |  | AsyncGeneratorProtoMixin(AsyncGenerator.prototype.prototype) | 
					
						
							| 
									
										
										
										
											2022-06-15 16:44:16 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-29 15:17:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Generators...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NOTE: step can be 0, this will repeat the first element infinitely...
 | 
					
						
							|  |  |  | var range = | 
					
						
							|  |  |  | module.range = | 
					
						
							|  |  |  | function*(from, to, step){ | 
					
						
							|  |  |  | 	if(to == null){ | 
					
						
							|  |  |  | 		to = from | 
					
						
							|  |  |  | 		from = 0 } | 
					
						
							|  |  |  | 	step = step ?? (from > to ? -1 : 1) | 
					
						
							|  |  |  | 	while(step > 0 ?  | 
					
						
							|  |  |  | 			from < to  | 
					
						
							|  |  |  | 			: from > to){ | 
					
						
							|  |  |  | 		yield from  | 
					
						
							|  |  |  | 		from += step } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var repeat = | 
					
						
							|  |  |  | module.repeat = | 
					
						
							|  |  |  | function*(value=true, stop){ | 
					
						
							|  |  |  | 	while( typeof(stop) == 'function' && stop(value) ){ | 
					
						
							|  |  |  | 		yield value } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var produce = | 
					
						
							|  |  |  | module.produce = | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | stoppable( | 
					
						
							|  |  |  | 	function*(func){ | 
					
						
							|  |  |  | 		while(true){ | 
					
						
							|  |  |  | 			yield func() } }, | 
					
						
							|  |  |  | 	__onstop) | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |