docs: function splitByRangeAndEnum(maybeUniverse, rangeToBeSplit) {
  	var enumSet;
  
  	// If it's an AND
  	if (rangeToBeSplit instanceof is.And) {
  		// recursively split each value
  		var sets = rangeToBeSplit.values.map(function(setInAnd) {
  			return splitByRangeAndEnum(maybeUniverse, setInAnd);
  		});
  		// take the intersections
  		return sets.reduce(function(last, maybe) {
  			return {
  				range: set.intersection(last.range, maybe.range),
  				enum: set.intersection(last.enum, maybe.enum)
  			};
  		}, {
  			range: set.UNIVERSAL,
  			enum: maybeUniverse
  		});
  
  	} else if (rangeToBeSplit instanceof is.In) {
  
  		var shouldBeInValues = rangeToBeSplit.values.filter(function(value) {
  			return maybeUniverse.isMember(value);
  		});
  		if (shouldBeInValues.length) {
  			var valuesCopy = rangeToBeSplit.values.slice(0);
  			canReflect.removeValues(valuesCopy, shouldBeInValues);
  
  			return {
  				enum: new is.In(shouldBeInValues),
  				range: valuesCopy.length ? new is.In(valuesCopy) : set.EMPTY
  			};
  		} else {
  			return {
  				enum: set.EMPTY,
  				range: rangeToBeSplit
  			};
  		}
  	} else if (rangeToBeSplit instanceof is.NotIn) {
  
  		// Gets the 'maybe' values in the range
  		enumSet = set.intersection(maybeUniverse, rangeToBeSplit);
  
  		// We should remove all the values within $in matching an in values.
  		var rangeValues = rangeToBeSplit.values.filter(function(value) {
  			return !maybeUniverse.isMember(value);
  		});
  		return {
  			range: rangeValues.length ? new is.NotIn(rangeValues) : set.UNIVERSAL,
  			enum: enumSet
  		};
  	} else {
  		return {
  			enum: set.EMPTY,
  			range: rangeToBeSplit
  		};
  	}
  }