Created
June 13, 2016 19:35
-
-
Save petsel/043349f345e990d002d532c06cb66f3d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
composable("composites.Range", function (require, global) { | |
"use strict"; | |
require("environment_extended_introspective_core"); | |
var | |
environment = require("environment"), | |
environment_introspective = environment.introspective, | |
environment_helpers = environment.helpers, | |
Object = global.Object, | |
String = global.String, | |
Number = global.Number, | |
Math = global.Math, | |
isFinite = global.isFinite, | |
isObject = environment_introspective.isObject, | |
isFunction = environment_introspective.isFunction, | |
isBoolean = environment_introspective.isBoolean, | |
isNumber = environment_introspective.isNumber, | |
isString = environment_introspective.isString, | |
compareTypes = environment_helpers.compareTypes, | |
object_keys = Object.keys, | |
object_isEqual = Object.isEqual, | |
isPrototypeOf = Object.isPrototypeOf, | |
fromCharCode = String.fromCharCode, | |
floor = Math.floor, | |
INTEGER_MINIMUM = Math.pow(-2, 53), // (Math.pow(-2, 53) - 1) === (Math.pow(-2, 53)) // true // (Math.pow(-2, 53) + 1) === (Math.pow(-2, 53)) // false | |
INTEGER_MAXIMUM = Math.pow(2, 53), // - see [http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html] | |
// - via [http://stackoverflow.com/questions/307179/what-is-javascripts-max-int-whats-the-highest-integer-value-a-number-can-go-to#answer-4375743] | |
UNDEFINED_VALUE, | |
REGX_RANGELIKE = (/\[[^.]+\.{2}[^.]+\]/), | |
getSanitizedInteger = function (type) { | |
return (isFinite(type = Number(type)) && ((type = floor(type)) <= INTEGER_MAXIMUM) && (type >= INTEGER_MINIMUM)) ? type : UNDEFINED_VALUE; | |
}, | |
isEqualType = function (typeA, typeB) { | |
var | |
isEqual = false | |
; | |
if (isFunction(typeA.equals)) { | |
isEqual = typeA.equals(typeB); | |
} else if (isFunction(typeB.equals)) { | |
isEqual = typeB.equals(typeA); | |
} | |
if (!isEqual) { | |
isEqual = object_isEqual(typeA, typeB); | |
} | |
return isEqual; | |
}, | |
isIteratorItemLike = function (type) { | |
return ( | |
('value' in type) | |
&& (isBoolean(type.done)) | |
&& (object_keys(type).length === 2) | |
); | |
} | |
; | |
function compareNumbers(a, b) { | |
return (a - b); | |
} | |
function compareStrings(a, b) { | |
return (((a < b) && -1) || ((a > b) && 1) || 0); | |
} | |
function getNextInteger(int) { | |
var | |
currVal = getSanitizedInteger(int), | |
nextVal = (currVal + 1) | |
; | |
//Math.pow(2, 53) === Math.pow(2, 53) // true | |
//Math.pow(2, 53) + 1 === Math.pow(2, 53) // true | |
//Math.pow(2, 53) + 2 === Math.pow(2, 53) // false | |
return ((isFinite(nextVal) && (nextVal !== currVal)) ? nextVal : UNDEFINED_VALUE); | |
} | |
function getNextIntegerInRange(int, intEnd) { | |
return { | |
value : (int = getNextInteger(int)), | |
done : ((int === UNDEFINED_VALUE) || (compareNumbers(int, intEnd) >= 0)) | |
}; | |
} | |
function getNextCharacter(char) { | |
var | |
currVal = ("" + char), | |
nextVal | |
; | |
if (currVal.length == 1) { // this definitely is a character. | |
/** | |
* as for >> (currVal === "") << ... | |
* ... there is nothing like a "next" character | |
* that could be a successor of an empty string. | |
*/ | |
nextVal = fromCharCode(currVal.charCodeAt(0) + 1); | |
/* | |
* either "nextVal" gets assigned a valid character ... | |
* ... or assignement of "nextVal" falls back again to the [undefined] value. | |
*/ | |
nextVal = ((nextVal !== "") && (nextVal !== currVal)) ? nextVal : UNDEFINED_VALUE; | |
} | |
return nextVal; | |
} | |
function getNextCharacterInRange(char, charEnd) { | |
return { | |
value : (char = getNextCharacter(char)), | |
done : ((char === UNDEFINED_VALUE) || (compareStrings(char, charEnd) >= 0)) | |
}; | |
} | |
function hasNextGenericItemInRange(typeA, typeB) { // fallback via build in default comparison. | |
return ( | |
(compareTypes(typeA, typeB) < 0) | |
|| (!isEqualType(typeA, typeB)) | |
); | |
} | |
function getNextGenericItemInRange(type, typeEnd, hasNext) { | |
var | |
tupel | |
; | |
type = type.next(); | |
if (isIteratorItemLike(type)) { | |
tupel = type; | |
} else { | |
tupel = { | |
value : type, | |
done : !hasNext(type, typeEnd) | |
} | |
} | |
return tupel; | |
} | |
function toString(type, typeEnd, tupel) { | |
return [ | |
'{[ ' | |
, type | |
, ' .. ' | |
, typeEnd | |
, ' ], { value: ' | |
, tupel.value | |
, ', done: ' | |
, tupel.done | |
, ' }}' | |
].join(""); | |
} | |
function toValue(tupel) { | |
return { | |
value : tupel.value, | |
done : tupel.done | |
}; | |
} | |
function isRangeLike(type) { | |
return ( | |
isFunction(type.next) | |
&& REGX_RANGELIKE.test(type.toString()) | |
); | |
} | |
function isRange(type) { | |
return ((type instanceof Range) || isRangeLike(type)); | |
} | |
function Range(type, typeEnd, hasNext, getNext, isInitiallyDone) { // Constructor. | |
var | |
tupel = { | |
value : type, | |
done : !!isInitiallyDone | |
}, | |
range = this | |
; | |
range.next = function () { | |
if (!tupel.done) { | |
tupel = getNext(tupel.value, typeEnd, hasNext); | |
} | |
return tupel; | |
}; | |
range.toString = function () { | |
return toString(type, typeEnd, tupel); | |
}; | |
range.valueOf = function () { | |
return toValue(tupel); | |
}; | |
} | |
function createRange(config) { // Factory. | |
var | |
typeBegin = config.begin, | |
typeEnd = config.end, | |
compare = config.compare, // custom. | |
equals = config.equals, // custom. | |
hasNext = hasNextGenericItemInRange, // default. | |
range | |
; | |
if (isObject(typeBegin) && isObject(typeEnd)) { | |
if ( | |
isFunction(typeBegin.next) | |
&& isFunction(typeEnd.next) | |
&& (isPrototypeOf(typeBegin) === isPrototypeOf(typeEnd)) | |
) { | |
if (isFunction(compare)) { | |
hasNext = (function (compare) { | |
return function (typeA, typeB) { | |
return (compare(typeA, typeB) < 0); | |
}; | |
}(compare)); | |
} else if (isFunction(equals)) { | |
hasNext = (function (equals) { | |
return function (typeA, typeB) { | |
return (!equals(typeA, typeB)); | |
}; | |
}(equals)); | |
} | |
range = (new Range(typeBegin, typeEnd, hasNext, getNextGenericItemInRange)); | |
} | |
} else if ( | |
isString(typeBegin) | |
&& (typeBegin.length === 1) | |
&& ((typeEnd = ("" + typeEnd)) && (typeEnd.length === 1)) | |
&& (compareStrings(typeBegin, typeEnd) < 0) | |
) { | |
range = (new Range(typeBegin, typeEnd, hasNext, getNextCharacterInRange)); | |
} else if ( | |
isNumber(typeBegin) | |
&& ((typeBegin = getSanitizedInteger(typeBegin)) !== UNDEFINED_VALUE) | |
&& ((typeEnd = getSanitizedInteger(typeEnd)) !== UNDEFINED_VALUE) | |
&& (compareNumbers(typeBegin, typeEnd) < 0) | |
) { | |
range = (new Range(typeBegin, typeEnd, hasNext, getNextIntegerInRange)); | |
} | |
return (range || (new Range(typeBegin, typeEnd, hasNext, getNextGenericItemInRange, true))); | |
} | |
return { // (Factory) Module. | |
create : createRange, | |
isRange : isRange | |
}; | |
}); | |
/* | |
[http://closure-compiler.appspot.com/home] | |
- Simple - 1716 byte | |
composable("composites.Range",function(r,k){function y(a,c){var b=n(a),d=b+1;return{value:a=t(d)&&d!==b?d:g,done:a===g||0<=a-c}}function z(a,c){var b=""+a,d;1==b.length&&(d=A(b.charCodeAt(0)+1),d=""!==d&&d!==b?d:g);return{value:a=d,done:a===g||0<=(a<c&&-1||a>c&&1||0)}}function B(a,c){var b;(b=0>C(a,c))||(b=!1,h(a.equals)?b=a.equals(c):h(c.equals)&&(b=c.equals(a)),b||(b=D(a,c)),b=!b);return b}function u(a,c,b){var d=a=a.next();return"value"in d&&E(d.done)&&2===F(d).length?a:{value:a,done:!b(a,c)}}function l(a,c,b,d,f){var e={value:a,done:!!f};this.next=function(){e.done||(e=d(e.value,c,b));return e};this.toString=function(){return["{[ ",a," .. ",c," ], { value: ",e.value,", done: ",e.done," }}"].join("")};this.valueOf=function(){return{value:e.value,done:e.done}}}r("environment_extended_introspective_core");var v=r("environment"),m=v.introspective,p=k.Object,G=k.Number,q=k.Math,t=k.isFinite,w=m.isObject,h=m.isFunction,E=m.isBoolean,H=m.isNumber,I=m.isString,C=v.helpers.compareTypes,F=p.keys,D=p.isEqual,x=p.isPrototypeOf,A=k.String.fromCharCode,J=q.floor,K=q.pow(-2,53),L=q.pow(2,53),g,M=/\[[^.]+\.{2}[^.]+\]/,n=function(a){return t(a=G(a))&&(a=J(a))<=L&&a>=K?a:g};return{create:function(a){var c=a.begin,b=a.end,d=a.compare;a=a.equals;var f=B,e;w(c)&&w(b)?h(c.next)&&h(b.next)&&x(c)===x(b)&&(h(d)?f=function(a){return function(b,c){return 0>a(b,c)}}(d):h(a)&&(f=function(a){return function(b,c){return!a(b,c)}}(a)),e=new l(c,b,f,u)):I(c)&&1===c.length&&(b=""+b)&&1===b.length&&0>(c<b&&-1||c>b&&1||0)?e=new l(c,b,f,z):H(c)&&(c=n(c))!==g&&(b=n(b))!==g&&0>c-b&&(e=new l(c,b,f,y));return e||new l(c,b,f,u,!0)},isRange:function(a){var c;(c=a instanceof l)||(c=h(a.next)&&M.test(a.toString()));return c}}}); | |
*/ | |
/* | |
var | |
r, o, | |
TypeRange = composable.require("composites.Range") | |
; | |
r = TypeRange.create({begin: 1, end: 0}); | |
while(!(o = r.next()).done) { | |
console.log("[1 .. 0].next() : ", o); | |
} | |
console.log("[1 .. 0].next() : ", o); | |
r = TypeRange.create({begin: 4, end: 20}); | |
while(!(o = r.next()).done) { | |
console.log("[4 .. 20].next() : ", o); | |
} | |
console.log("[4 .. 20].next() : ", o); | |
r = TypeRange.create({begin: -4, end: "12"}); | |
while(!(o = r.next()).done) { | |
console.log("[-4 .. '12'].next() : ", o); | |
} | |
console.log("[-4 .. '12'].next() : ", o); | |
r = TypeRange.create({begin: "_", end: "N"}); | |
while(!(o = r.next()).done) { | |
console.log("['_' .. 'N'].next() : ", o); | |
} | |
console.log("['_' .. 'N'].next() : ", o); | |
r = TypeRange.create({begin: "N", end: "_"}); | |
while(!(o = r.next()).done) { | |
console.log("['N' .. '_'].next() : ", o); | |
} | |
console.log("['N' .. '_'].next() : ", o); | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment