JS.Hash=new JS.Class('Hash',{include:JS.Enumerable||{},extend:{Pair:new JS.Class({include:JS.Comparable||{},setKey:function(a){this[0]=this.key=a},hasKey:function(a){var b=this.key;return b.equals?b.equals(a):b===a},setValue:function(a){this[1]=this.value=a},hasValue:function(a){var b=this.value;return b.equals?b.equals(a):b===a},compareTo:function(a){return this.key.compareTo?this.key.compareTo(a.key):(this.keya.key?1:0))},hash:function(){var a=JS.Hash.codeFor(this.key),b=JS.Hash.codeFor(this.value);return[a,b].sort().join('')}}),codeFor:function(a){if(typeof a!=='object')return String(a);return JS.isFn(a.hash)?a.hash():a.toString()}},initialize:function(a){this.clear();if(!JS.isType(a,Array))return this.setDefault(a);for(var b=0,c=a.length;b-1)return c[d];if(!b)return null;this.size+=1;this.length+=1;e=new this.klass.Pair;e.setKey(a);c.push(e);return e},rassoc:function(a){var b=this.key(a);return b?this.assoc(b):null},clear:function(){this._0={};this.length=this.size=0},compareByIdentity:function(){this._1=true},comparesByIdentity:function(){return!!this._1},setDefault:function(a){this._2=a;return this},getDefault:function(a){return JS.isFn(this._2)?this._2(this,a):(this._2||null)},equals:function(c){if(!JS.isType(c,JS.Hash)||this.length!==c.length)return false;var d=true;this.forEach(function(a){if(!d)return;var b=c.assoc(a.key);if(b===null||!b.hasValue(a.value))d=false});return d},hash:function(){var b=[];this.forEach(function(a){b.push(a.hash())});return b.sort().join('')},fetch:function(a,b){var c=this.assoc(a);if(c)return c.value;if(b===undefined)throw new Error('key not found');if(JS.isFn(b))return b(a);return b},forEachKey:function(b,c){if(!b)return this.enumFor('forEachKey');b=JS.Enumerable.toFn(b);this.forEach(function(a){b.call(c||null,a.key)});return this},forEachPair:function(b,c){if(!b)return this.enumFor('forEachPair');b=JS.Enumerable.toFn(b);this.forEach(function(a){b.call(c||null,a.key,a.value)});return this},forEachValue:function(b,c){if(!b)return this.enumFor('forEachValue');b=JS.Enumerable.toFn(b);this.forEach(function(a){b.call(c||null,a.value)});return this},get:function(a){var b=this.assoc(a);return b?b.value:this.getDefault(a)},hasKey:function(a){return!!this.assoc(a)},hasValue:function(b){var c=false,d=!!this._1;this.forEach(function(a){if((b.equals&&!d)?b.equals(a.value):b===a.value)c=true});return c},invert:function(){var b=new this.klass;this.forEach(function(a){b.store(a.value,a.key)});return b},isEmpty:function(){for(var a in this._0){if(this._0.hasOwnProperty(a)&&this._0[a].length>0)return false}return true},key:function(b){var c=null;this.forEach(function(a){if(b.equals?b.equals(a.value):(b===a.value))c=a.key});return c},keys:function(){var b=[];this.forEach(function(a){b.push(a.key)});return b},merge:function(a,b,c){var d=new this.klass;d.update(this);d.update(a,b,c);return d},rehash:function(){var a=new this.klass;a._0=this._0;this.clear();this.update(a)},remove:function(a,b){if(b===undefined)b=null;var c,d,e;c=this._3(a);if(!c)return JS.isFn(b)?this.fetch(a,b):this.getDefault(a);d=this._4(c,a);if(d<0)return JS.isFn(b)?this.fetch(a,b):this.getDefault(a);e=c[d].value;c.splice(d,1);this.size-=1;this.length-=1;if(c.length===0)delete this._0[this.klass.codeFor(a)];return e},removeIf:function(b,c){if(!b)return this.enumFor('removeIf');b=JS.Enumerable.toFn(b);this.forEach(function(a){if(b.call(c||null,a))this.remove(a.key)},this);return this},replace:function(a){this.clear();this.update(a)},shift:function(){var a=this.keys();if(a.length===0)return this.getDefault();var b=this.assoc(a[0]);this.remove(b.key);return b},store:function(a,b){this.assoc(a,true).setValue(b);return b},update:function(d,e,f){var g=JS.isFn(e);d.forEach(function(a){var b=a.key,c=a.value;if(g&&this.hasKey(b))c=e.call(f||null,b,this.get(b),c);this.store(b,c)},this)},values:function(){var b=[];this.forEach(function(a){b.push(a.value)});return b},valuesAt:function(){var a=arguments.length,b=[];while(a--)b.push(this.get(arguments[a]));return b}});JS.Hash.include({includes:JS.Hash.instanceMethod('hasKey'),index:JS.Hash.instanceMethod('key'),put:JS.Hash.instanceMethod('store')},true);