--- /dev/null
+SEEK_ABSOLUTE = 0
+SEEK_RELATIVE = 1
+SEEK_FROM_EOF = 2
+
+
+# Binary representation of the number
+bin = (n) ->
+ do
+ s = (if n % 2 then '1' else '0') + (s or '')
+ n >>= 1
+ while n
+ s
+
+# Number of bits needed to represent the absolute value of n.
+binlen = (n) ->
+ bin Math.abs n .length
+
+# Returns a run of 1s of size n.
+mask = (n) ->
+ (1 << n) - 1
+
+chr = -> String.fromCharCode it
+ord = -> String(it).charCodeAt 0
+
+
+
+
+/**
+ * File-like object for reading/writing bits.
+ * @class
+ */
+class BitString
+ # Array<UInt8>
+ buf : null
+
+ # Byte position of read/write cursor (-1 for end).
+ _pos : -1
+
+ # Spill cache for bits smaller than a byte waiting to write.
+ _spill : 0
+
+ # Number of bits in the spill cache.
+ _spillen : 0
+
+ # Peek cache for read requests smaller than a byte.
+ _peek : 0
+
+ # Number of bits in the peek cache.
+ _peeklen : 0
+
+
+
+ (source='', buf=[]) ->
+ @buf = buf.slice()
+ for i til source.length
+ @_bufwrite source.charCodeAt i
+
+ size: ->
+ @buf.length + if @_spillen then 1 else 0
+
+ bitsize: ->
+ @buf.length*8 + @_spillen
+
+ _bufwrite: (b) ->
+ if @_pos is -1
+ @buf.push b
+ else
+ @buf[@_pos] = b
+ @_pos = -1 if ++@_pos >= @buf.length
+ this
+
+ # Writes bits to the stream; bits must be supplied as a number. Supplying n=0 will write one bit.
+ # Supplying the optional parameter length treats the bits as a field with the given length.
+ writebits: (n, size) ->
+ size = size or binlen n
+ bits = (@_spill << size) | n
+ size += @_spillen # handles _spill=0 but _spillen > 0
+ while size >= 8
+ size -= 8
+ b = bits >> size
+ bits &= mask size
+ @_bufwrite b
+ @_spill = bits
+ @_spillen = size
+ this
+
+ # Flushes any pending bits to the stream.
+ flush: ->
+ b = @_spill
+ if @_spillen
+ b <<= 8 - @_spillen
+ @_bufwrite b
+ @_spill = 0
+ @_spillen = 0
+ this
+
+ # Truncates the stream to zero bits.
+ truncate: ->
+ @buf = []
+ @_pos = -1
+ @_spill = 0
+ @_spillen = 0
+ @_peek = 0
+ @_peeklen = 0
+ this
+
+ # Move buffer cursor to given byte-offset. mode: 0 = absolute, 1 = relative, 2 = relative EOF
+ _bufseek: (n, mode=SEEK_ABSOLUTE) ->
+ switch mode
+ case 1 # relative
+ pos = @_pos + n
+ case 2
+ pos = @buf.length + n
+ default # absolute
+ pos = n
+ @_pos = if pos >= @buf.length then -1 else Math.max 0, pos
+ this
+
+ # Flushes the bit-buffer and moves to the given byte-offset. mode: 0 = absolute, 1 = relative, 2 = relative EOF
+ seek: (n, mode=SEEK_ABSOLUTE) ->
+ @flush()
+ @_peek = 0
+ @_peeklen = 0
+ @_bufseek n, mode
+ this
+
+ # Returns the current position of the cursor as a *byte* offset from the start of the stream.
+ tell: ->
+ if @_pos is -1 then @buf.length else @_pos
+
+
+ _nextbyte: ->
+ return null if @_pos is -1
+ byte = @buf[ @_pos++ ]
+ @_pos = -1 if @_pos >= @buf.length
+ byte
+
+
+ # Reads n bits from the stream.
+ readbits: (n) ->
+ return 0 if n == 0
+
+ size = @_peeklen
+ bits = @_peek
+
+ while size < n
+ byte = @_nextbyte()
+ break unless byte?
+ size += 8
+ bits = (bits << 8) | byte
+
+ if size > n
+ @_peeklen = size - n
+ @_peek = bits & mask(@_peeklen)
+ bits >>= @_peeklen
+ else
+ @_peeklen = 0
+ @_peek = 0
+
+ return if size then bits else null
+
+
+ # Reads the next n bits without moving the cursor.
+ peek: (n) ->
+ offset = 0
+ size = @_peeklen
+ bits = @_peek
+
+ while size < n
+ byte = @_nextbyte()
+ break unless byte?
+ offset += 1
+ size += 8
+ bits = (bits << 8) | byte
+
+ if size == 0
+ return null
+
+ if size > n
+ bits >>= size - n
+
+ if offset
+ @_bufseek -offset, SEEK_RELATIVE
+ bits
+
+
+ # True if there is more data to read.
+ hasMore: ->
+ @peek(1)?
+
+
+ ### XXX: Should .each(), .map(), .reduce() flush?
+
+ # forEach of bytes
+ each: (fn, cxt=this) ->
+ @buf.forEach fn, cxt
+
+ # map over bytes
+ map: (fn, cxt=this) ->
+ @buf.map fn, cxt
+
+ # reduce over bytes
+ reduce: (fn, acc, cxt=this) ->
+ fn .= bind this
+ @buf.reduce fn, acc
+
+
+ # Returns the stream as a bytearray.
+ bytearray: ->
+ @flush().buf.slice()
+
+ # Dumps the stream as a binary string. Unlike __index__(), bin() will not cause int overflow.
+ bin: (byte_sep='') ->
+ @flush().buf.map(bin).join(byte_sep)
+
+ # Returns the stream as a hex string.
+ hex: ->
+ @flush().buf.map(hex).join('')
+
+ # Returns the buffer as a number. Use this with obvious caution. Called by builtins bin(), int(), long(), etc.
+ number: ->
+ @flush()
+ @reduce (n, byte) -> (n << 8) | byte
+
+
+ # Dumps the stream as a string; does not flush or change cursor position.
+ dump: ->
+ @buf.map(chr).join('') + if @_spillen then chr @_spill << (8 - @_spillen) else ''
+
+ repr: (dump_buf=true) ->
+ s = if dump_buf then "buf=#{@dump()}" else "len(buf)=#{@buf.length}"
+ return "BitString(#s,
+ spill[#{@_spillen}]=#{bin @_spill},
+ tell=#{@tell()},
+ peek[#{@_peeklen}]=#{bin @_peek})
+ "
+
+ # Dumps the stream as a string; flushes the bit-buffer but leaves cursor position unchanged.
+ toString: ->
+ @flush().dump()
+
+
+exports = module.exports = BitString
+
+exports.SEEK_ABSOLUTE = SEEK_ABSOLUTE
+exports.SEEK_RELATIVE = SEEK_RELATIVE
+exports.SEEK_FROM_EOF = SEEK_FROM_EOF
--- /dev/null
+
+crc32 = exports.crc32 = (s, last_crc=0) ->
+ s = utf8Encode s
+ crc = last_crc ^ (-1)
+ for i til s.length
+ y = (crc ^ s.charCodeAt i) & 0xFF
+ x = "0x" + TABLE.substr y*9, 8
+ crc = (crc >>> 8) ^ x
+ crc ^ (-1)
+
+
+utf8Encode = exports.utf8Encode = (s) ->
+ s = s.replace /\r\n/g, '\n'
+ u = ''
+ for n til s.length
+ c = s.charCodeAt n
+ if c < 128
+ u += String.fromCharCode c
+ else if 127 < c < 2048
+ u += String.fromCharCode (c >> 6) | 192
+ u += String.fromCharCode (c & 63) | 128
+ else
+ u += String.fromCharCode (c >> 12) | 224
+ u += String.fromCharCode ((c >> 6) & 63) | 128
+ u += String.fromCharCode (c & 63) | 128
+ u
+
+
+# static precompiled hashes
+TABLE = '''
+ 00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4
+ E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE
+ 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9
+ FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B
+ 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A
+ C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924
+ 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F
+ 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01
+ 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950
+ 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2
+ 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5
+ AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F
+ 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6
+ 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8
+ E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB
+ 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5
+ D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C
+ 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236
+ CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31
+ 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713
+ 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242
+ 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C
+ 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7
+ 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9
+ BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8
+ 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D
+'''
+
--- /dev/null
+_ = require 'underscore'
+
+
+/**
+ * A Set class, implemented using the `__id__` property on non-primitive objects it is passed.
+ * Arrays are hashed based on their contents. If an object lacks `__id__`, an exception will be
+ * thrown. This class does not keep values in sorted order.
+ *
+ * Underscore provides an easy way to generate unique IDs with the (surprise!) `_.uniqueId()`
+ * function.
+ * @see http://documentcloud.github.com/underscore/#uniqueId
+ *
+ * @class
+ */
+class HashSet
+ /**
+ * Objects by Id.
+ * @private
+ */
+ _byId : {}
+
+ /**
+ * Set contents.
+ * @private
+ */
+ _o : []
+
+ /**
+ * Number of elements in the set.
+ * @property {Number}
+ */
+ length : 0
+
+
+ /**
+ * Accepts any number of collections to be added to the set.
+ * @constructor
+ */
+ ->
+ @_byId = {}
+ @_o = []
+ @update ...arguments if arguments.length
+
+
+
+ /**
+ * Determine unique identifier for the given value.
+ * @private
+ * @returns {String} Id for this value.
+ */
+ _getIdSafe : (v) ->
+ t = typeof v
+
+ switch t
+ case 'undefined'
+ return 'u'
+ case 'boolean' 'string' 'number'
+ return "#{t.charAt 0}:#v"
+ if v is null
+ return 'n'
+ if '__id__' in v
+ return 'o:' + v.__id__
+ if _.isArray v
+ return 'a:' + v.map @_getIdSafe, this .join ','
+
+ /**
+ * Determine unique identifier for the given value, throwing an exception otherwise.
+ * @private
+ * @returns {String} Id for this value.
+ */
+ _getId : (v) ->
+ id = @_getIdSafe v
+ unless id?
+ throw new Error "HashSet elements must be hashable (#v)"
+ id
+
+
+
+ /**
+ * Aliases: HashSet#has
+ * @param {Any} v Value to test.
+ * @returns {Boolean} Whether HashSet contains value.
+ */
+ contains : (v) ->
+ @_getIdSafe(v) in @_byId
+
+
+ /**
+ * @private
+ * @returns {this}
+ */
+ _addOne : (v) ->
+ id = @_getId v
+ unless id in @_byId
+ @_byId[id] = v
+ @_o.push(v)
+ @length = @_o.length
+ this
+
+
+ /**
+ * Add values to the HashSet.
+ * Aliases: HashSet#push HashSet#unshift
+ * @param {Any} values... Values to add.
+ * @returns {this}
+ */
+ add : (...values) ->
+ _.each arguments, @_addOne, this
+ this
+
+ /**
+ * @private
+ * @returns {this}
+ */
+ _removeOne : (v) ->
+ id = @_getId v
+ if id in @_byId
+ delete @_byId[id]
+ @_o.splice @_o.indexOf(v), 1
+ @length = @_o.length
+ this
+
+
+ /**
+ * Remove values from the HashSet.
+ * Aliases: HashSet#without
+ * @param {Any} values... Values to remove.
+ * @returns {this}
+ */
+ remove : (...values) ->
+ _.each arguments, @_removeOne, this
+ this
+
+
+ /**
+ * Update this HashSet (in-place) with other collections.
+ * Aliases: HashSet#extend HashSet#concat
+ * @param {Array|Object} it... Collection to add.
+ * @returns {this}
+ */
+ update : (vs) ->
+ _.each arguments, ~> _.each it, @_addOne, this
+ this
+
+
+ /**
+ * Remove and return an element from the set.
+ * Aliases: HashSet#shift
+ * @returns {Any} An element from the set.
+ */
+ pop : ->
+ return unless @_o.length
+ v = @_o.shift()
+ id = @_getIdSafe v
+ delete @_byId[id]
+ return v
+
+
+ /**
+ * Returns but does not remove the an element from the set.
+ * @returns {Any} An element from the set.
+ */
+ element : ->
+ @_o[0]
+
+
+ /**
+ * Clones the set, returning a new object.
+ * @returns {HashSet}
+ */
+ clone : ->
+ new HashSet @_o
+
+
+ /**
+ * Removes all elements from the set.
+ * Aliases: HashSet#empty
+ * @returns {this}
+ */
+ clear: ->
+ @_byId = {}
+ @_o = []
+ @length = 0
+ this
+
+
+
+ ### Collection Operations
+
+ /**
+ * Transforms the collection into a single value, front-to-back.
+ * Aliases: HashSet#inject HashSet#fold HashSet#foldl HashSet#foldr
+ * @param {Function} fn Reducer function.
+ * @param {Any} [acc] Starting accumulator value.
+ * @param {Object} [cxt=this] Context; defaults to this HashSet.
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
+ * @returns {Any}
+ */
+ reduce: (fn, acc, cxt) ->
+ _.reduce @_o, fn, acc, cxt or this
+
+ /**
+ * Applies a function to each element.
+ * Aliases: HashSet#each
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach
+ * @returns {this}
+ */
+ forEach: (fn, cxt) ->
+ _.forEach @_o, fn, cxt or this
+ this
+
+ /**
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
+ * @return {HashSet} A new HashSet of elements produced by applying the transform across each element.
+ */
+ map: (fn, cxt) ->
+ new HashSet _.map @_o, fn, cxt or this
+
+
+ /**
+ * Aliases: HashSet#select
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
+ * @return {HashSet} A new HashSet of only the elements passing the filter.
+ */
+ filter: (fn, cxt) ->
+ new HashSet _.filter @_o, fn, cxt or this
+
+ /**
+ * Like `HashSet.filter()`, but instead keeps values for which the filter returns false.
+ * @see HashSet#filter
+ * @return {HashSet} A new HashSet of only the elements for which the filter returns false.
+ */
+ reject: (fn, cxt) ->
+ new HashSet _.reject @_o, fn, cxt or this
+
+
+ /**
+ * Aliases: HashSet#any
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
+ * @return {Boolean}
+ */
+ some: (fn, cxt) ->
+ _.some @_o, fn, cxt or this
+
+ /**
+ * Aliases: HashSet#all
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
+ * @return {Boolean}
+ */
+ every: (fn, cxt) ->
+ _.every @_o, fn, cxt or this
+
+
+ /**
+ * Iterates through the HashSet, returning the first value for which `fn` returns truth-y.
+ * Aliases: HashSet#detect
+ * @returns {Any}
+ */
+ find: (fn, cxt) ->
+ _.find @_o, fn, cxt or this
+
+
+ /**
+ * @returns {Array} List of all values at property `prop`.
+ */
+ pluck : (prop) ->
+ _.pluck @_o, prop
+
+
+ /**
+ * Invokes the named method on each element in the set, returning a list of the results.
+ * @param {String} methodName Name of the method on each element to call.
+ * @param {Any...} [args...] Optional arguments to call pass to method call.
+ * @returns {Array} List of results.
+ */
+ invoke : (methodName) ->
+ _.invoke @_o, ...arguments
+
+
+ /**
+ * @returns {Array} List of the unique identifiers for each element of the set.
+ */
+ keys : ->
+ _.keys @_byId
+
+ /**
+ * Converts this HashSet to an Array.
+ * Aliases: HashSet#toArray
+ * @returns {Array}
+ */
+ values : ->
+ @_o.slice()
+
+
+
+ ### Comparators and HashSet Operations
+
+ /**
+ * Tests if `a` is a Collection and has all elements in common with the set.
+ * Sets are equal if and only if their intersection has the same size as both sets.
+ * @param {Collection} a
+ * @returns {Boolean}
+ */
+ equals : (a) ->
+ return false unless a
+ L = @_o.length
+ return L is a.length and L is @intersect(a).length
+
+
+ /**
+ * Tests if the set has no elements in common with `a`.
+ * Sets are disjoint if and only if their intersection is the empty set.
+ * @param {Collection} a
+ * @returns {Boolean}
+ */
+ isDisjoint : (a) ->
+ return true unless a
+ return not _.some a, @contains, this
+
+
+ /**
+ * Test whether every element in the set is in `a`.
+ * @param {Collection} a
+ * @returns {Boolean}
+ */
+ isSubset : (a) ->
+ return false unless a
+ A = _ if _.isArray a then a else _.values a
+ @every A.contains, A
+
+
+ /**
+ * Test whether every element in `a` is in the set.
+ * @param {Array|Object} a
+ * @returns {Boolean}
+ */
+ isSuperset : (a) ->
+ return false unless a
+ _.every a, @contains, this
+
+
+ /**
+ * HashSet Intersection (A ^ B)
+ * Intersects this YArray with another collection, returning a new YArray.
+ * The membership test uses _(a).contains(), so it is possible to intersect collections of different types.
+ * For YArray and YObject, .contains() uses strict equality (is) via .indexOf().
+ *
+ * @param {Array|Object} a Comparison collection.
+ * @returns {HashSet} A new YArray of all elements of {this} found in the supplied collection.
+ *
+ * @example
+ * foo = /foo/
+ * A = [foo, 'A', 1, 2, 3, 'C', /foo/]
+ * B = [foo, 'B', 3, 'A', 1, /foo/]
+ * ins = _(A).intersect(B)
+ * ins.toString() is "HashSet([/foo/,A,1,3])"; # true
+ * ins.get(0) is foo; # true
+ */
+ intersect : (a) ->
+ new HashSet _.intersect @_o, _.map arguments, _.values
+
+
+ /**
+ * HashSet Union (A v B)
+ * Aliases: HashSet#extend HashSet#concat
+ * @param {Array|Object} a Other collection(s).
+ * @returns {HashSet} A new HashSet of all elements of both collections, without duplicates.
+ */
+ union : (a) ->
+ _.reduce arguments, ((out, it) -> out.update it), @clone()
+
+
+ /**
+ * HashSet Difference (A - B)
+ * @param {Array|Object} a Comparison collection(s).
+ * @returns {HashSet} A new HashSet of only elements of this HashSet not in supplied collection(s).
+ */
+ difference : (a) ->
+ new HashSet _.difference @_o, _.map arguments, _.values
+
+
+ /**
+ * Symmetric Difference (A - B) v (B - A)
+ * @returns {HashSet}
+ */
+ xor : (a) ->
+ a = _.values a
+ @difference a .union _.difference a, @_o
+
+
+ toString : ->
+ "HashSet([#{@_o}])"
+
+
+
+### Aliases
+
+pt = HashSet::
+
+pt.push = pt.unshift = pt.add
+pt.shift = pt.pop
+pt.without = pt.remove
+pt.empty = pt.clear
+pt.has = pt.include = pt.contains
+
+pt.fold = pt.foldl = pt.foldr = pt.inject = pt.reduce
+pt.each = pt.forEach
+pt.select = pt.filter
+pt.all = pt.every
+pt.any = pt.some
+
+pt.detect = pt.find
+pt.toArray = pt.values
+pt.extend = pt.concat = pt.union
+
+
+exports = module.exports = HashSet
+
--- /dev/null
+_ = require 'kraken/underscore'
+
+root = do -> this
+root.console or= _ <[ log info warn error dir table group groupCollapsed groupEnd ]> .synthesize -> [it, nop]
+
+root.jQuery?.fn.invoke = (method, ...args) ->
+ for el, idx of this
+ el = jQuery(el)
+ el[method] ...args
+
+op = require 'kraken/util/op'
+# HashSet = require 'kraken/util/hashset'
+# BitString = require 'kraken/util/bitstring'
+# {crc32} = require 'kraken/util/crc'
+
+
+exports import { root, _, op, }
+# exports import { root, _, op, HashSet, BitString, crc32, }
--- /dev/null
+
+FALSEY = /^\s*(?:no|off|false)\s*$/i
+parseBool = (s) ->
+ i = parseInt(s or 0)
+ !! if isNaN(i) then not FALSEY.test(s) else i
+
+module.exports = op =
+
+ I : (x) -> x
+ K : (k) -> -> k
+ nop : ->
+ kThis : -> this
+ kObject : -> {}
+ kArray : -> []
+
+ # values
+ val : (def,o) -> o ? def
+ ok : (o) -> o?
+
+ first : (a) -> a
+ second : (_,a) -> a
+ nth : (n) ->
+ switch n
+ case 0 then op.first
+ case 1 then op.second
+ default -> arguments[n]
+
+ flip : (fn) ->
+ (a, b) ->
+ arguments[0] = b
+ arguments[1] = a
+ fn.apply this, arguments
+
+ # reduce-ordered values & accessors
+ khas : (k,o) -> k in o
+ kget : (k,o) -> o[k]
+ defkget : (def,k,o) -> if k in o then o[k] else def
+ thisget : (k) -> this[k]
+ vkset : (o,v,k) -> o[k] = v if o and k?; o
+
+ # curry-ordered values & accessors
+ has : (o,k) -> k in o
+ get : (o,k) -> o[k]
+ getdef : (o,k,def) -> if k in o then o[k] else def
+ kvset : (o,k,v) -> o[k] = v if o and k?; o
+ thiskvset : (k,v) -> @[k] = v if k?; this
+
+ prop : (k) -> (o) -> o[k]
+ method : (name, ...args) ->
+ (obj, ..._args) ->
+ obj[name] ...args.concat(_args) if obj?[name]
+ isK : (k) -> (v) -> v is k
+
+ # type coercion (w/ limited parameters for mapping)
+ parseBool : parseBool
+ toBool : (v) -> !! v
+ toInt : (v) -> parseInt v
+ toFloat : (v) -> parseFloat v
+ toStr : (v) -> String v
+
+ # comparison
+ cmp : (x,y) -> if x < y then -1 else (if x > y then 1 else 0)
+ eq : (x,y) -> x == y
+ ne : (x,y) -> x != y
+ gt : (x,y) -> x > y
+ ge : (x,y) -> x >= y
+ lt : (x,y) -> x < y
+ le : (x,y) -> x <= y
+
+ # math
+ add : (x,y) -> x + y
+ sub : (x,y) -> x - y
+ mul : (x,y) -> x * y
+ div : (x,y) -> x / y
+ flrdiv : (x,y) -> Math.floor(x / y)
+ mod : (x,y) -> x % y
+ neg : (x) -> -x
+ log2 : (n) -> Math.log n / Math.LN2
+
+
+ # logic
+ is : (x,y) -> x is y
+ isnt : (x,y) -> x is not y
+ and : (x,y) -> x and y
+ or : (x,y) -> x or y
+ not : (x) -> not x
+
+ # bitwise
+ bitnot : (x) -> ~x
+ bitand : (x,y) -> x & y
+ bitor : (x,y) -> x | y
+ bitxor : (x,y) -> x ^ y
+ lshift : (x,y) -> x << y
+ rshift : (x,y) -> x >> y
+ # zrshift : (x,y) -> x >>> y
+
+ # binary
+
+ # Binary representation of the number.
+ bin : (n) ->
+ do
+ s = (if n % 2 then '1' else '0') + (s or '')
+ n >>= 1
+ while n
+ s
+
+ # Number of bits needed to represent the absolute value of n.
+ binlen : (n) ->
+ bin Math.abs n .length
+
+ # Returns a run of 1s of size n.
+ mask : (n) ->
+ (1 << n) - 1
+
+ # strings
+ chr : -> String.fromCharCode it
+ ord : -> String(it).charCodeAt 0
+ encode : -> it and $ "<div>#it</div>" .html().replace /"/g, '"'
+ decode : -> it and $ "<div>#it</div>" .text()
+
+
+
- underscore.array
- underscore.object
- index
- # - scaffold
- # - graph
+ - util:
+ - op
+ - index
+ - scaffold
+ - graph
# - suffix: .js
# paths: