'use strict'

function isString(s) { return 'string' === typeof s }

function isNumber(n) { return !isNaN(+n) }

function isBoolean (b) { return 'boolean' === typeof b }

function isBasic (p) { return isString(p) || isNumber(p) || isBoolean(p) }

function isFunction (f) { return 'function' === typeof f }

var isArray = Array.isArray

function isObject (o) { return o && 'object' === typeof o && !isArray(o) }

function has(o, k) {
  return Object.hasOwnProperty.call(o, k)
}

function isExact (v) {
  if(isBasic(v)) return true
  if(isArray(v))
    return v.every(isExact)
  return isObject(v) && has(v, '$eq')
}

function isLtgt (v) {
  return has(v, '$lt') || has(v, '$gt') || has(v, '$lte') || has(v, '$gte')
}

function isRange (v) {
  if(v == null) return false
//  if(!isObject(v)) return false
  if(v.$prefix) return true
  if(isArray(v)) return find(v, isRange)
  return isLtgt(v)
}

function find (ary, test) {
  for(var i = 0; i < ary.length; i++)
    if(test(ary[i], i, ary)) return true
  return false
}

function lower (v) {
  if(isBasic(v)) return v
  if(isObject(v)) {
    if(isArray(v.$prefix)) return v.$prefix.concat(exports.HI)
    if(isString(v.$prefix)) return v.$prefix
    if(has(v, '$gt')) return v.$gt
    if(has(v, '$gte')) return v.$gte
  }
  if(isArray(v)) return v.map(lower)
}

function upper (v) {
  if(isBasic(v)) return v
  if(isObject(v)) {
    if(isArray(v.$prefix)) return v.$prefix.concat(exports.LO)
    if(isString(v.$prefix)) return v.$prefix+'\uffff'
    if(has(v, '$le')) return v.$lt
    if(has(v, '$lte')) return v.$lte
  }
  if(isArray(v)) return v.map(upper)
}

function get(obj, path) {
  if(isString(path)) return obj[path]
  if(isArray(path)) {
    for(var i = 0; i < path.length; i++) {
      if(obj == null) return undefined
      obj = obj[path[i]]
    }
    return obj
  }
  if(path === true) return obj
  return undefined
}

function map(obj, iter, o) {
  if(Array.isArray(obj)) return obj.map(iter)
  o = o || {}
  for(var k in obj)
    o[k] = iter(obj[k], k, obj)
  return o
}


function mapa(obj, iter) {
  if(Array.isArray(obj)) return obj.map(iter)
  var a = []
  for(var k in obj) {
    var v = iter(obj[k], k, obj)
    if(v !== undefined) a.push(v)
  }
  return a

}

function each(obj, iter) {
  if(Array.isArray(obj)) return obj.forEach(iter)
  else if(isObject(obj))
    for(var k in obj) iter(obj[k], k, obj)
  else
    iter(obj)
}

function project (value, map, isObj) {
  isObj = isObj || isObject
  if(!isObj(value))
    return map(value)
  else {
    var o
    for(var k in value) {
      var v = project(value[k], map, isObj)
      if(v !== undefined)
        (o = o || {})[k] = v
    }
    return o
  }
}

//get all paths within an object
//this can probably be optimized to create less arrays!
function paths (object, test) {
  var p = []
  if(test(object)) return []
  for(var key in object) {
    var value = object[key]
    if(test(value)) p.push(key)
    else if(isObject(value))
      p = p.concat(paths(value, test).map(function (path) {
        return [key].concat(path)
      }))
  }
  return p
}

exports.isString = isString
exports.isNumber = isNumber
exports.isBasic = isBasic
exports.isArray = isArray
exports.isObject = isObject
exports.isRange = isRange
exports.isExact = isExact
exports.isLtgt = isLtgt
exports.isFunction = isFunction

exports.has     = has
exports.get     = get
exports.map     = map
exports.mapa    = mapa
exports.project = project
exports.paths   = paths
exports.each    = each

exports.upper = upper
exports.lower = lower

exports.HI = undefined
exports.LO = null










@@ -102,24 +102,58 @@
 sNaN(+n) %7D%0A%0A
+var isInteger = Number.isInteger%0A%0A
 function isB
@@ -435,24 +435,101 @@
 Array(o) %7D%0A%0A
+// %5B%5D or %7B%7D%0Afunction isContainer (o) %7B%0A  return o && 'object' == typeof o%0A%7D%0A%0A
 function has
@@ -3201,16 +3201,19 @@
 sString 
+   
 = isStri
@@ -3232,16 +3232,19 @@
 sNumber 
+   
 = isNumb
@@ -3246,16 +3246,48 @@
 sNumber%0A
+exports.isInteger   = isInteger%0A
 exports.
@@ -3294,16 +3294,20 @@
 isBasic 
+    
 = isBasi
@@ -3324,16 +3324,20 @@
 isArray 
+    
 = isArra
@@ -3355,16 +3355,19 @@
 sObject 
+   
 = isObje
@@ -3365,24 +3365,58 @@
  = isObject%0A
+exports.isContainer = isContainer%0A
 exports.isRa
@@ -3419,16 +3419,20 @@
 isRange 
+    
 = isRang
@@ -3449,16 +3449,20 @@
 isExact 
+    
 = isExac
@@ -3478,16 +3478,21 @@
 .isLtgt 
+     
 = isLtgt
@@ -3511,16 +3511,17 @@
 unction 
+ 
 = isFunc
@@ -3757,16 +3757,16 @@
 defined%0A
+
 exports.
@@ -3777,15 +3777,8 @@
  null%0A%0A%0A
-%0A%0A%0A%0A%0A%0A%0A

add isInteger and isContainer