| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // NOTE: this is used in a similar fashion to Python's StopIteration...
 | 
					
						
							|  |  |  | var STOP = | 
					
						
							|  |  |  | module.STOP = | 
					
						
							|  |  |  | 	object.STOP | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // 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
										 |  |  | //
 | 
					
						
							|  |  |  | // 	GeneratorPrototype 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | //
 | 
					
						
							|  |  |  | // 	GeneratorPrototype.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 GeneratorPrototype = | 
					
						
							|  |  |  | 	(function*(){}).constructor.prototype | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Generator =  | 
					
						
							|  |  |  | module.Generator = | 
					
						
							|  |  |  | 	(function*(){}).constructor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // generic generator wrapper...
 | 
					
						
							|  |  |  | var iter =  | 
					
						
							|  |  |  | module.iter =  | 
					
						
							| 
									
										
										
										
											2021-05-19 16:16:17 +03:00
										 |  |  | Generator.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
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											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>)
 | 
					
						
							|  |  |  | // 		-> <func>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	makeGenerator(<name>, <handler>)
 | 
					
						
							|  |  |  | // 		-> <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){ | 
					
						
							| 
									
										
										
										
											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( | 
					
						
							|  |  |  | 			function*(){ | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 				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...
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | var stoppable =  | 
					
						
							|  |  |  | module.stoppable = | 
					
						
							|  |  |  | function(func){ | 
					
						
							|  |  |  | 	return Object.assign( | 
					
						
							|  |  |  | 		func instanceof Generator ? | 
					
						
							|  |  |  | 			function*(){ | 
					
						
							|  |  |  | 				try{ | 
					
						
							|  |  |  | 					yield* func.call(this, ...arguments) | 
					
						
							|  |  |  | 				} catch(err){ | 
					
						
							|  |  |  | 					if(err === STOP){ | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} else if(err instanceof STOP){ | 
					
						
							| 
									
										
										
										
											2021-05-25 18:21:30 +03:00
										 |  |  | 						yield err.value | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +03:00
										 |  |  | 						return } | 
					
						
							|  |  |  | 					throw err } } | 
					
						
							|  |  |  | 			: function(){ | 
					
						
							|  |  |  | 				try{ | 
					
						
							|  |  |  | 					return func.call(this, ...arguments) | 
					
						
							|  |  |  | 				} catch(err){ | 
					
						
							|  |  |  | 					if(err === STOP){ | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} else if(err instanceof STOP){ | 
					
						
							|  |  |  | 						return err.value } | 
					
						
							|  |  |  | 					throw err } }, | 
					
						
							|  |  |  | 		{ toString: function(){ | 
					
						
							|  |  |  | 			return func.toString() }, }) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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'), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// non-generators...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	toArray: function(){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return Object.assign( | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				return that(...arguments).toArray() }, | 
					
						
							|  |  |  | 			{ toString: function(){ | 
					
						
							|  |  |  | 				return that.toString()  | 
					
						
							|  |  |  | 					+ '\n    .toString()'}, }) }, | 
					
						
							| 
									
										
										
										
											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()  | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 					+ '\n    .gpop()'}, }) }, | 
					
						
							|  |  |  | 	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()  | 
					
						
							| 
									
										
										
										
											2021-05-12 00:03:31 +03:00
										 |  |  | 					+ '\n    .gshift()'}, }) }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// promises...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	then: makePromise('then'), | 
					
						
							|  |  |  | 	catch: makePromise('catch'), | 
					
						
							|  |  |  | 	finally: makePromise('finally'), | 
					
						
							| 
									
										
										
										
											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'),
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var GeneratorProtoMixin = | 
					
						
							|  |  |  | module.GeneratorProtoMixin = | 
					
						
							|  |  |  | object.Mixin('GeneratorProtoMixin', 'soft', { | 
					
						
							| 
									
										
										
										
											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...
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 	slice: function*(from=0, to=Infity){ | 
					
						
							|  |  |  | 		// 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){ | 
					
						
							|  |  |  | 					yield func(e, i++, this) } } }), | 
					
						
							| 
									
										
										
										
											2021-05-25 17:21:40 +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 } | 
					
						
							|  |  |  | 				throw err } }), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	reduce: stoppable(function(func, res){ | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 		var i = 0 | 
					
						
							|  |  |  | 		for(var e of this){ | 
					
						
							| 
									
										
										
										
											2021-05-18 02:07:08 +03:00
										 |  |  | 			res = func(res, e, i++, this) } | 
					
						
							| 
									
										
										
										
											2021-05-25 18:21:30 +03:00
										 |  |  | 		return res }), | 
					
						
							|  |  |  | 	greduce: function*(func, res){ | 
					
						
							|  |  |  | 		yield this.reduce(...arguments) }, | 
					
						
							| 
									
										
										
										
											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() }, | 
					
						
							| 
									
										
										
										
											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 }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// non-generators...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	toArray: function(){ | 
					
						
							|  |  |  | 		return [...this] }, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// promises...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX how do we handle reject(..) / .catch(..)???
 | 
					
						
							|  |  |  | 	promise: function(){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return new Promise(function(resolve){ | 
					
						
							|  |  |  | 				resolve([...that]) }) }, | 
					
						
							|  |  |  | 	then: function(func){ | 
					
						
							|  |  |  | 		return this.promise().then(func) }, | 
					
						
							|  |  |  | 	catch: function(func){ | 
					
						
							|  |  |  | 		return this.promise().catch(func) }, | 
					
						
							|  |  |  | 	finally: function(func){ | 
					
						
							|  |  |  | 		return this.promise().finally(func) }, | 
					
						
							| 
									
										
										
										
											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
 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GeneratorMixin(GeneratorPrototype) | 
					
						
							|  |  |  | GeneratorProtoMixin(GeneratorPrototype.prototype) | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +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 = | 
					
						
							|  |  |  | stoppable(function*(func){ | 
					
						
							|  |  |  | 	while(true){ | 
					
						
							|  |  |  | 		yield func() } }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |