Browse Source

added Map and haxe.ds.IntMap

Simon Krajewski 12 years ago
parent
commit
d76a85d4be

+ 28 - 0
std/Map.hx

@@ -0,0 +1,28 @@
+typedef IMap < K, V > = {
+	public function get(k:K):V;
+	public function set(k:K, v:V):Void;
+	public function exists(k:K):Null<V>;
+	public function remove(k:K):Bool;
+	public function keys():Iterator<K>;
+	public function iterator():Iterator<V>;
+}
+
+@:generic
+abstract Map(IMap < K, V > )<K,V> {
+	public function new();
+
+	@:to static inline public function toHash(t:IMap < String, V > ):Hash<V> {
+		return new Hash<V>();
+	}
+
+	@:to static inline public function toIntHash(t:IMap < Int, V > ):haxe.ds.IntMap<V> {
+		return new haxe.ds.IntMap<V>();
+	}
+
+	public inline function set(k:K, v:V) this.set(k, v)
+	public inline function get(k:K) return this.get(k)
+	public inline function exists(k:K) return this.exists(k)
+	public inline function remove(k:K) return this.remove(k)
+	public inline function keys() return this.keys()
+	public inline function iterator() return this.iterator()
+}

+ 73 - 0
std/cpp/_std/haxe/ds/IntMap.hx

@@ -0,0 +1,73 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package haxe.ds;
+
+@:coreApi class IntMap<T> {
+
+	private var h : Dynamic;
+
+	public function new() : Void {
+		h = untyped __global__.__int_hash_create();
+	}
+
+	public function set( key : Int, value : T ) : Void {
+		untyped __global__.__int_hash_set(h,key,value);
+	}
+
+	public function get( key : Int ) : Null<T> {
+		return untyped __global__.__int_hash_get(h,key);
+	}
+
+	public function exists( key : Int ) : Bool {
+		return untyped __global__.__int_hash_exists(h,key);
+	}
+
+	public function remove( key : Int ) : Bool {
+		return untyped __global__.__int_hash_remove(h,key);
+	}
+
+	public function keys() : Iterator<Int> {
+		var a:Array<Int> = untyped __global__.__int_hash_keys(h);
+		return a.iterator();
+	}
+
+	public function iterator() : Iterator<T> {
+		var a:Array<Dynamic> = untyped __global__.__int_hash_values(h);
+		return a.iterator();
+	}
+
+	public function toString() : String {
+		var s = new StringBuf();
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(i);
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+
+}

+ 455 - 0
std/cs/_std/haxe/ds/IntMap.hx

@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+package haxe.ds;
+import cs.NativeArray;
+
+/*
+ * This IntMap implementation is based on khash (https://github.com/attractivechaos/klib/blob/master/khash.h)
+ * Copyright goes to Attractive Chaos <[email protected]> and his contributors
+ *
+ * Thanks also to Jonas Malaco Filho for his Haxe-written IntMap code inspired by Python tables.
+ * (https://jonasmalaco.com/fossil/test/jonas-haxe/artifact/887b53126e237d6c68951111d594033403889304)
+ */
+@:coreApi class IntMap<T>
+{
+	private static inline var HASH_UPPER = 0.7;
+
+	private var flags:NativeArray<Int>;
+	private var _keys:NativeArray<Int>;
+	private var vals:NativeArray<T>;
+
+	private var nBuckets:Int;
+	private var size:Int;
+	private var nOccupied:Int;
+	private var upperBound:Int;
+
+	private var cachedKey:Int;
+	private var cachedIndex:Int;
+
+	public function new() : Void
+	{
+		cachedIndex = -1;
+	}
+
+	public function set( key : Int, value : T ) : Void
+	{
+		var x:Int;
+		if (nOccupied >= upperBound)
+		{
+			if (nBuckets > (size << 1))
+				resize(nBuckets - 1); //clear "deleted" elements
+			else
+				resize(nBuckets + 1);
+		}
+
+		var flags = flags, _keys = _keys;
+		{
+			var mask = nBuckets - 1;
+			var site = x = nBuckets;
+			var k = hash(key);
+			var i = k & mask;
+
+			//for speed up
+			if (flagIsEmpty(flags, i)) {
+				x = i;
+			} else {
+				var inc = getInc(k, mask);
+				var last = i;
+				while (! (isEither(flags, i) || _keys[i] == key) )
+				{
+					i = (i + inc) & mask;
+#if DEBUG_HASHTBL
+					if (i == last)
+					{
+						throw "assert";
+					}
+#end
+				}
+				x = i;
+			}
+		}
+
+		if (flagIsEmpty(flags, x))
+		{
+			_keys[x] = key;
+			vals[x] = value;
+			setIsBothFalse(flags, x);
+			size++;
+			nOccupied++;
+		} else if (flagIsDel(flags, x)) {
+			_keys[x] = key;
+			vals[x] = value;
+			setIsBothFalse(flags, x);
+			size++;
+		} else {
+			assert(_keys[x] == key);
+			vals[x] = value;
+		}
+	}
+
+	@:final private function lookup( key : Int ) : Int
+	{
+		if (nBuckets != 0)
+		{
+			var flags = flags, _keys = _keys;
+
+			var mask = nBuckets - 1, k = hash(key);
+			var i = k & mask;
+			var inc = getInc(k, mask); /* inc == 1 for linear probing */
+			var last = i;
+			while (!flagIsEmpty(flags, i) && (flagIsDel(flags, i) || _keys[i] != key))
+			{
+				i = (i + inc) & mask;
+				if (i == last)
+					return -1;
+			}
+			return isEither(flags, i) ? -1 : i;
+		}
+
+		return -1;
+	}
+
+	public function get( key : Int ) : Null<T>
+	{
+		var idx = -1;
+		if (cachedKey == key && ( (idx = cachedIndex) != -1 ))
+		{
+			return vals[idx];
+		}
+
+		idx = lookup(key);
+		if (idx != -1)
+		{
+			cachedKey = key;
+			cachedIndex = idx;
+
+			return vals[idx];
+		}
+
+		return null;
+	}
+
+	private function getDefault( key : Int, def : T ) : T
+	{
+		var idx = -1;
+		if (cachedKey == key && ( (idx = cachedIndex) != -1 ))
+		{
+			return vals[idx];
+		}
+
+		idx = lookup(key);
+		if (idx != -1)
+		{
+			cachedKey = key;
+			cachedIndex = idx;
+
+			return vals[idx];
+		}
+
+		return def;
+	}
+
+	public function exists( key : Int ) : Bool
+	{
+		var idx = -1;
+		if (cachedKey == key && ( (idx = cachedIndex) != -1 ))
+		{
+			return true;
+		}
+
+		idx = lookup(key);
+		if (idx != -1)
+		{
+			cachedKey = key;
+			cachedIndex = idx;
+
+			return true;
+		}
+
+		return false;
+	}
+
+	public function remove( key : Int ) : Bool
+	{
+		var idx = -1;
+		if (! (cachedKey == key && ( (idx = cachedIndex) != -1 )))
+		{
+			idx = lookup(key);
+		}
+
+		if (idx == -1)
+		{
+			return false;
+		} else {
+			if (cachedKey == key)
+				cachedIndex = -1;
+
+			if (!isEither(flags, idx))
+			{
+				setIsDelTrue(flags, idx);
+				--size;
+
+				vals[idx] = null;
+				_keys[idx] = 0;
+			}
+
+			return true;
+		}
+	}
+
+	@:final private function resize(newNBuckets:Int) : Void
+	{
+		//This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets.
+		var newFlags = null;
+		var j = 1;
+		{
+			newNBuckets = roundUp(newNBuckets);
+			if (newNBuckets < 4) newNBuckets = 4;
+			if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */
+			{
+				j = 0;
+			} else { /* hash table size to be changed (shrink or expand); rehash */
+				var nfSize = flagsSize(newNBuckets);
+				newFlags = new NativeArray( nfSize );
+				for (i in 0...nfSize)
+					newFlags[i] = 0xaaaaaaaa;
+				if (nBuckets < newNBuckets) //expand
+				{
+					var k = new NativeArray(newNBuckets);
+					if (_keys != null)
+						arrayCopy(_keys, 0, k, 0, nBuckets);
+					_keys = k;
+
+					var v = new NativeArray(newNBuckets);
+					if (vals != null)
+						arrayCopy(vals, 0, v, 0, nBuckets);
+					vals = v;
+				} //otherwise shrink
+			}
+		}
+
+		if (j != 0)
+		{ //rehashing is required
+			//resetting cache
+			cachedKey = 0;
+			cachedIndex = -1;
+
+			j = -1;
+			var nBuckets = nBuckets, _keys = _keys, vals = vals, flags = flags;
+
+			var newMask = newNBuckets - 1;
+			while (++j < nBuckets)
+			{
+				if (!isEither(flags, j))
+				{
+					var key = _keys[j];
+					var val = vals[j];
+
+					setIsDelTrue(flags, j);
+					while (true) /* kick-out process; sort of like in Cuckoo hashing */
+					{
+						var k = hash(key);
+						var inc = getInc(k, newMask);
+						var i = k & newMask;
+						while (!flagIsEmpty(newFlags, i))
+							i = (i + inc) & newMask;
+						setIsEmptyFalse(newFlags, i);
+
+						if (i < nBuckets && !isEither(flags, i)) /* kick out the existing element */
+						{
+							{
+								var tmp = _keys[i];
+								_keys[i] = key;
+								key = tmp;
+							}
+							{
+								var tmp = vals[i];
+								vals[i] = val;
+								val = tmp;
+							}
+
+							setIsDelTrue(flags, i); /* mark it as deleted in the old hash table */
+						} else { /* write the element and jump out of the loop */
+							_keys[i] = key;
+							vals[i] = val;
+							break;
+						}
+					}
+				}
+			}
+
+			if (nBuckets > newNBuckets) /* shrink the hash table */
+			{
+				{
+					var k = new NativeArray(newNBuckets);
+					arrayCopy(_keys, 0, k, 0, newNBuckets);
+					this._keys = k;
+				}
+				{
+					var v = new NativeArray(newNBuckets);
+					arrayCopy(vals, 0, v, 0, newNBuckets);
+					this.vals = v;
+				}
+			}
+
+			this.flags = newFlags;
+			this.nBuckets = newNBuckets;
+			this.nOccupied = size;
+			this.upperBound = Std.int(newNBuckets * HASH_UPPER + .5);
+		}
+	}
+
+	/**
+		Returns an iterator of all keys in the hashtable.
+		Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration
+	**/
+	public function keys() : Iterator<Int>
+	{
+		var i = 0;
+		var len = nBuckets;
+		return {
+			hasNext: function() {
+				for (j in i...len)
+				{
+					if (!isEither(flags, j))
+					{
+						i = j;
+						return true;
+					}
+				}
+				return false;
+			},
+			next: function() {
+				var ret = _keys[i];
+				cachedIndex = i;
+				cachedKey = ret;
+
+				i = i + 1;
+				return ret;
+			}
+		};
+	}
+
+	/**
+		Returns an iterator of all values in the hashtable.
+		Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration
+	**/
+	public function iterator() : Iterator<T>
+	{
+		var i = 0;
+		var len = nBuckets;
+		return {
+			hasNext: function() {
+				for (j in i...len)
+				{
+					if (!isEither(flags, j))
+					{
+						i = j;
+						return true;
+					}
+				}
+				return false;
+			},
+			next: function() {
+				var ret = vals[i];
+				i = i + 1;
+				return ret;
+			}
+		};
+	}
+
+	/**
+		Returns an displayable representation of the hashtable content.
+	**/
+
+	public function toString() : String {
+		var s = new StringBuf();
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(i);
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+
+	private static inline function assert(x:Bool):Void
+	{
+		#if debug
+		if (!x) throw "assert failed";
+		#end
+	}
+
+	private static inline function defaultK():Int return 0
+
+	private static inline function arrayCopy(sourceArray:cs.system.Array, sourceIndex:Int, destinationArray:cs.system.Array, destinationIndex:Int, length:Int):Void
+		cs.system.Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length)
+
+	private static inline function getInc(k:Int, mask:Int):Int
+		return (((k) >> 3 ^ (k) << 3) | 1) & (mask)
+
+	private static inline function hash(i:Int):Int
+		return i
+
+	private static inline function flagIsEmpty(flag:NativeArray<Int>, i:Int):Bool
+		return ( (flag[i >> 4] >>> ((i & 0xf) << 1)) & 2 ) != 0
+
+	private static inline function flagIsDel(flag:NativeArray<Int>, i:Int):Bool
+		return ((flag[i >> 4] >>> ((i & 0xf) << 1)) & 1) != 0
+
+	private static inline function isEither(flag:NativeArray<Int>, i:Int):Bool
+		return ((flag[i >> 4] >>> ((i & 0xf) << 1)) & 3) != 0
+
+	private static inline function setIsDelFalse(flag:NativeArray<Int>, i:Int):Void
+		flag[i >> 4] &= ~(1 << ((i & 0xf) << 1))
+
+	private static inline function setIsEmptyFalse(flag:NativeArray<Int>, i:Int):Void
+		flag[i >> 4] &= ~(2 << ((i & 0xf) << 1))
+
+	private static inline function setIsBothFalse(flag:NativeArray<Int>, i:Int):Void
+		flag[i >> 4] &= ~(3 << ((i & 0xf) << 1))
+
+	private static inline function setIsDelTrue(flag:NativeArray<Int>, i:Int):Void
+		flag[i >> 4] |= 1 << ((i & 0xf) << 1)
+
+	private static inline function roundUp(x:Int):Int
+	{
+		--x;
+		x |= (x) >>> 1;
+		x |= (x) >>> 2;
+		x |= (x) >>> 4;
+		x |= (x) >>> 8;
+		x |= (x) >>> 16;
+		return ++x;
+	}
+
+	private static inline function flagsSize(m:Int):Int
+		return ((m) < 16? 1 : (m) >> 4)
+}

+ 78 - 0
std/flash/_std/haxe/ds/IntMap.hx

@@ -0,0 +1,78 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package haxe.ds;
+
+@:coreApi class IntMap<T> {
+
+	private var h : flash.utils.Dictionary;
+
+	public function new() : Void {
+		h = new flash.utils.Dictionary();
+	}
+
+	public function set( key : Int, value : T ) : Void {
+		untyped h[key] = value;
+	}
+
+	public function get( key : Int ) : Null<T> {
+		return untyped h[key];
+	}
+
+	public function exists( key : Int ) : Bool {
+		return untyped h.hasOwnProperty(key);
+	}
+
+	public function remove( key : Int ) : Bool {
+		if( untyped !h.hasOwnProperty(key) ) return false;
+		untyped __delete__(h,key);
+		return true;
+	}
+
+	public function keys() : Iterator<Int> {
+		return untyped (__keys__(h)).iterator();
+	}
+
+	public function iterator() : Iterator<T> {
+		return untyped {
+			ref : h,
+			it : keys(),
+			hasNext : function() { return __this__.it.hasNext(); },
+			next : function() { var i = __this__.it.next(); return __this__.ref[i]; }
+		};
+	}
+
+	public function toString() : String {
+		var s = new StringBuf();
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(i);
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+
+}

+ 81 - 0
std/flash8/_std/haxe/ds/IntMap.hx

@@ -0,0 +1,81 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package haxe.ds;
+
+@:coreApi class IntMap<T> {
+
+	private var h : Dynamic;
+
+	public function new() : Void {
+		h = untyped __new__(_global["Object"]);
+	}
+
+	public function set( key : Int, value : T ) : Void {
+		h[key] = value;
+	}
+
+	public function get( key : Int ) : Null<T> {
+		return h[key];
+	}
+
+	public function exists( key : Int ) : Bool {
+		return untyped h["hasOwnProperty"](key);
+	}
+
+	public function remove( key : Int ) : Bool {
+		if( untyped !h["hasOwnProperty"](key) ) return false;
+		untyped __delete__(h,key);
+		return true;
+	}
+
+	public function keys() : Iterator<Int> {
+		var l : Array<Int> = untyped __keys__(h);
+		for( x in 0...l.length )
+			l[x] = Std.int(l[x]);
+		return l.iterator();
+	}
+
+	public function iterator() : Iterator<T> {
+		return untyped {
+			ref : h,
+			it : keys(),
+			hasNext : function() { return __this__.it[__unprotect__("hasNext")](); },
+			next : function() { var i = __this__.it[__unprotect__("next")](); return __this__.ref[i]; }
+		};
+	}
+
+	public function toString() : String {
+		var s = new StringBuf();
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(i);
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+
+}

+ 1 - 1
std/haxe/Json.hx

@@ -457,7 +457,7 @@ class Json {
 				case "Date" : return Std.string(val); //.split(" ").join("T"); //better with "T"?
 				case "Date" : return Std.string(val); //.split(" ").join("T"); //better with "T"?
 				case "HList" : arr = php.Lib.toPhpArray(Lambda.array(val)); //convert List to array?
 				case "HList" : arr = php.Lib.toPhpArray(Lambda.array(val)); //convert List to array?
 				case "_hx_enum" : return Type.enumIndex(val);
 				case "_hx_enum" : return Type.enumIndex(val);
-				case "Hash", "IntHash" : arr = php.Lib.associativeArrayOfHash(val);
+				case "Hash", "IntMap" : arr = php.Lib.associativeArrayOfHash(val);
 				default : arr = php.Lib.associativeArrayOfObject(val);
 				default : arr = php.Lib.associativeArrayOfObject(val);
 			}
 			}
 		}
 		}

+ 20 - 20
std/haxe/Serializer.hx

@@ -24,17 +24,17 @@ package haxe;
 /**
 /**
 	The Serializer class can be used to encode values and objects into a String,
 	The Serializer class can be used to encode values and objects into a String,
 	from which the Unserializer class can recreate the original representation.
 	from which the Unserializer class can recreate the original representation.
-	
+
 	This class can be used in two ways:
 	This class can be used in two ways:
 		- create a new Serializer() instance, call its serialize() method with
 		- create a new Serializer() instance, call its serialize() method with
 		any argument and finally retrieve the String representation from
 		any argument and finally retrieve the String representation from
 		toString()
 		toString()
 		- call Serializer.run() to obtain the serialized representation of a
 		- call Serializer.run() to obtain the serialized representation of a
 		single argument
 		single argument
-		
+
 	Serialization is guaranteed to work for all haxe-defined classes, but may
 	Serialization is guaranteed to work for all haxe-defined classes, but may
 	or may not work for instances of external/native classes.
 	or may not work for instances of external/native classes.
-	
+
 	The specification of the serialization format can be found here:
 	The specification of the serialization format can be found here:
 		http://haxe.org/manual/serialization/format
 		http://haxe.org/manual/serialization/format
 **/
 **/
@@ -44,10 +44,10 @@ class Serializer {
 		If the values you are serializing can contain circular references or
 		If the values you are serializing can contain circular references or
 		objects repetitions, you should set USE_CACHE to true to prevent
 		objects repetitions, you should set USE_CACHE to true to prevent
 		infinite loops.
 		infinite loops.
-		
+
 		This may also reduce the size of serialization Strings at the expense of
 		This may also reduce the size of serialization Strings at the expense of
 		performance.
 		performance.
-		
+
 		This value can be changed for individual instances of Serializer by
 		This value can be changed for individual instances of Serializer by
 		setting their useCache field.
 		setting their useCache field.
 	**/
 	**/
@@ -55,11 +55,11 @@ class Serializer {
 
 
 	/**
 	/**
 		Use constructor indexes for enums instead of names.
 		Use constructor indexes for enums instead of names.
-		
+
 		This may reduce the size of serialization Strings, but makes them less
 		This may reduce the size of serialization Strings, but makes them less
 		suited for long-term storage: If constructors are removed or added from
 		suited for long-term storage: If constructors are removed or added from
 		the enum, the indices may no longer match.
 		the enum, the indices may no longer match.
-		
+
 		This value can be changed for individual instances of Serializer by
 		This value can be changed for individual instances of Serializer by
 		setting their useEnumIndex field.
 		setting their useEnumIndex field.
 	**/
 	**/
@@ -71,28 +71,28 @@ class Serializer {
 	var cache : Array<Dynamic>;
 	var cache : Array<Dynamic>;
 	var shash : Hash<Int>;
 	var shash : Hash<Int>;
 	var scount : Int;
 	var scount : Int;
-	
+
 	/**
 	/**
 		The individual cache setting for [this] Serializer instance.
 		The individual cache setting for [this] Serializer instance.
-		
+
 		See USE_CACHE for a complete description.
 		See USE_CACHE for a complete description.
 	**/
 	**/
 	public var useCache : Bool;
 	public var useCache : Bool;
-	
+
 	/**
 	/**
 		The individual enum index setting for [this] Serializer instance.
 		The individual enum index setting for [this] Serializer instance.
-		
+
 		See USE_ENUM_INDEX for a complete description.
 		See USE_ENUM_INDEX for a complete description.
 	**/
 	**/
 	public var useEnumIndex : Bool;
 	public var useEnumIndex : Bool;
 
 
 	/**
 	/**
 		Creates a new Serializer instance.
 		Creates a new Serializer instance.
-		
+
 		Subsequent calls to [this].serialize() will append values to the
 		Subsequent calls to [this].serialize() will append values to the
 		internal buffer of this String. Once complete, the contents can be
 		internal buffer of this String. Once complete, the contents can be
 		retrieved through a call to [this].toString() .
 		retrieved through a call to [this].toString() .
-		
+
 		Each Serializer instance maintains its own cache if [this].useCache is
 		Each Serializer instance maintains its own cache if [this].useCache is
 		true.
 		true.
 	**/
 	**/
@@ -107,7 +107,7 @@ class Serializer {
 
 
 	/**
 	/**
 		Return the String representation of [this] Serializer.
 		Return the String representation of [this] Serializer.
-		
+
 		The exact format specification can be found here:
 		The exact format specification can be found here:
 		http://haxe.org/manual/serialization/format
 		http://haxe.org/manual/serialization/format
 	**/
 	**/
@@ -132,7 +132,7 @@ class Serializer {
 		n : null
 		n : null
 		o : object
 		o : object
 		p : +Inf
 		p : +Inf
-		q : inthash
+		q : haxe.ds.IntMap
 		r : reference
 		r : reference
 		s : bytes (base64)
 		s : bytes (base64)
 		t : true
 		t : true
@@ -211,11 +211,11 @@ class Serializer {
 
 
 	/**
 	/**
 		Serializes [v].
 		Serializes [v].
-		
+
 		All haxe-defined values and objects with the exception of functions can
 		All haxe-defined values and objects with the exception of functions can
 		be serialized. Serialization of external/native objects is not
 		be serialized. Serialization of external/native objects is not
 		guaranteed to work.
 		guaranteed to work.
-		
+
 		The values of [this].useCache and [this].useEnumIndex may affect
 		The values of [this].useCache and [this].useEnumIndex may affect
 		serialization output.
 		serialization output.
 	**/
 	**/
@@ -299,9 +299,9 @@ class Serializer {
 					serialize(v.get(k));
 					serialize(v.get(k));
 				}
 				}
 				buf.add("h");
 				buf.add("h");
-			case #if (neko || cs) "IntHash" #else cast IntHash #end:
+			case #if (neko || cs) "haxe.ds.IntMap" #else cast haxe.ds.IntMap #end:
 				buf.add("q");
 				buf.add("q");
-				var v : IntHash<Dynamic> = v;
+				var v : haxe.ds.IntMap<Dynamic> = v;
 				for( k in v.keys() ) {
 				for( k in v.keys() ) {
 					buf.add(":");
 					buf.add(":");
 					buf.add(k);
 					buf.add(k);
@@ -496,7 +496,7 @@ class Serializer {
 
 
 	/**
 	/**
 		Serializes [v] and returns the String representation.
 		Serializes [v] and returns the String representation.
-		
+
 		This is a convenience function for creating a new instance of
 		This is a convenience function for creating a new instance of
 		Serializer, serialize [v] into it and obtain the result through a call
 		Serializer, serialize [v] into it and obtain the result through a call
 		to toString().
 		to toString().

+ 16 - 16
std/haxe/Unserializer.hx

@@ -29,7 +29,7 @@ typedef TypeResolver = {
 /**
 /**
 	The Unserializer class is the complement to the Serializer class. It parses
 	The Unserializer class is the complement to the Serializer class. It parses
 	a serialization String and creates objects from the contained data.
 	a serialization String and creates objects from the contained data.
-	
+
 	This class can be used in two ways:
 	This class can be used in two ways:
 		- create a new Unserializer() instance with a given serialization
 		- create a new Unserializer() instance with a given serialization
 		String, then call its unserialize() method until all values are
 		String, then call its unserialize() method until all values are
@@ -41,16 +41,16 @@ class Unserializer {
 
 
 	/**
 	/**
 		This value can be set to use custom type resolvers.
 		This value can be set to use custom type resolvers.
-		
+
 		A type resolver finds a Class or Enum instance from a given String. By
 		A type resolver finds a Class or Enum instance from a given String. By
 		default, the haxe Type Api is used.
 		default, the haxe Type Api is used.
-		
+
 		A type resolver must provide two methods:
 		A type resolver must provide two methods:
 			resolveClass(name:String):Class<Dynamic> is called to determine a
 			resolveClass(name:String):Class<Dynamic> is called to determine a
 				Class from a class name
 				Class from a class name
 			resolveEnum(name:String):Enum<Dynamic> is called to determine an
 			resolveEnum(name:String):Enum<Dynamic> is called to determine an
 				Enum from an enum name
 				Enum from an enum name
-		
+
 		This value is applied when a new Unserializer instance is created.
 		This value is applied when a new Unserializer instance is created.
 		Changing it afterwards has no effect on previously created instances.
 		Changing it afterwards has no effect on previously created instances.
 	**/
 	**/
@@ -87,10 +87,10 @@ class Unserializer {
 	/**
 	/**
 		Creates a new Unserializer instance, with its internal buffer
 		Creates a new Unserializer instance, with its internal buffer
 		initialized to [buf].
 		initialized to [buf].
-		
+
 		This does not parse [buf] immediately. It is parsed only when calls to
 		This does not parse [buf] immediately. It is parsed only when calls to
 		[this].unserialize are made.
 		[this].unserialize are made.
-		
+
 		Each Unserializer instance maintains its own cache.
 		Each Unserializer instance maintains its own cache.
 	**/
 	**/
  	public function new( buf : String ) {
  	public function new( buf : String ) {
@@ -112,10 +112,10 @@ class Unserializer {
 
 
 	/**
 	/**
 		Sets the type resolver of [this] Unserializer instance to [r].
 		Sets the type resolver of [this] Unserializer instance to [r].
-		
+
 		If [r] is null, a special resolver is used which returns null for all
 		If [r] is null, a special resolver is used which returns null for all
 		input values.
 		input values.
-		
+
 		See DEFAULT_RESOLVER for more information on type resolvers.
 		See DEFAULT_RESOLVER for more information on type resolvers.
 	**/
 	**/
  	public function setResolver( r ) {
  	public function setResolver( r ) {
@@ -130,7 +130,7 @@ class Unserializer {
 
 
 	/**
 	/**
 		Gets the type resolver of [this] Unserializer instance.
 		Gets the type resolver of [this] Unserializer instance.
-		
+
 		See DEFAULT_RESOLVER for more information on type resolvers.
 		See DEFAULT_RESOLVER for more information on type resolvers.
 	**/
 	**/
  	public function getResolver() {
  	public function getResolver() {
@@ -196,20 +196,20 @@ class Unserializer {
 	/**
 	/**
 		Unserializes the next part of [this] Unserializer instance and returns
 		Unserializes the next part of [this] Unserializer instance and returns
 		the according value.
 		the according value.
-		
+
 		This function may call [this].resolver.resolveClass to determine a
 		This function may call [this].resolver.resolveClass to determine a
 		Class from a String, and [this].resolver.resolveEnum to determine an
 		Class from a String, and [this].resolver.resolveEnum to determine an
 		Enum from a String.
 		Enum from a String.
-		
+
 		If [this] Unserializer instance contains no more or invalid data, an
 		If [this] Unserializer instance contains no more or invalid data, an
 		exception is thrown.
 		exception is thrown.
-		
+
 		This operation may fail on structurally valid data if a type cannot be
 		This operation may fail on structurally valid data if a type cannot be
 		resolved or if a field cannot be set. This can happen when unserializing
 		resolved or if a field cannot be set. This can happen when unserializing
 		Strings that were serialized on a different haxe target, in which the
 		Strings that were serialized on a different haxe target, in which the
 		serialization side has to make sure not to include platform-specific
 		serialization side has to make sure not to include platform-specific
 		data.
 		data.
-		
+
 		Classes are created from Type.createEmptyInstance, which means their
 		Classes are created from Type.createEmptyInstance, which means their
 		constructors are not called.
 		constructors are not called.
 	**/
 	**/
@@ -335,7 +335,7 @@ class Unserializer {
 			pos++;
 			pos++;
 			return h;
 			return h;
 		case "q".code:
 		case "q".code:
-			var h = new IntHash();
+			var h = new haxe.ds.IntMap();
 			cache.push(h);
 			cache.push(h);
 			var buf = buf;
 			var buf = buf;
 			var c = get(pos++);
 			var c = get(pos++);
@@ -345,7 +345,7 @@ class Unserializer {
 				c = get(pos++);
 				c = get(pos++);
 			}
 			}
 			if( c != "h".code )
 			if( c != "h".code )
-				throw "Invalid IntHash format";
+				throw "Invalid IntMap format";
 			return h;
 			return h;
 		case "v".code:
 		case "v".code:
 			var d = Date.fromString(buf.substr(pos,19));
 			var d = Date.fromString(buf.substr(pos,19));
@@ -412,7 +412,7 @@ class Unserializer {
 
 
 	/**
 	/**
 		Unserializes [v] and returns the according value.
 		Unserializes [v] and returns the according value.
-		
+
 		This is a convenience function for creating a new instance of
 		This is a convenience function for creating a new instance of
 		Unserializer with [v] as buffer and calling its unserialize() method
 		Unserializer with [v] as buffer and calling its unserialize() method
 		once.
 		once.

+ 72 - 0
std/haxe/ds/IntMap.hx

@@ -0,0 +1,72 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package haxe.ds;
+
+/**
+	Hashtable over a set of elements, using [Int] as keys.
+	On Flash and Javascript, the underlying structure is an Object.
+**/
+extern class IntMap<T> {
+
+	/**
+		Creates a new empty hashtable.
+	**/
+	public function new() : Void;
+
+	/**
+		Set a value for the given key.
+	**/
+	public function set( key : Int, value : T ) : Void;
+	/**
+		Get a value for the given key.
+	**/
+	public function get( key : Int ) : Null<T>;
+
+	/**
+		Tells if a value exists for the given key.
+		In particular, it's useful to tells if a key has
+		a [null] value versus no value.
+	**/
+	public function exists( key : Int ) : Bool;
+
+	/**
+		Removes a hashtable entry. Returns [true] if
+		there was such entry.
+	**/
+	public function remove( key : Int ) : Bool;
+
+	/**
+		Returns an iterator of all keys in the hashtable.
+	**/
+	public function keys() : Iterator<Int>;
+
+	/**
+		Returns an iterator of all values in the hashtable.
+	**/
+	public function iterator() : Iterator<T>;
+
+	/**
+		Returns an displayable representation of the hashtable content.
+	**/
+	public function toString() : String;
+
+}

+ 2 - 2
std/haxe/remoting/LocalConnection.hx

@@ -28,7 +28,7 @@ class LocalConnection implements AsyncConnection, implements Dynamic<AsyncConnec
 	var __path : Array<String>;
 	var __path : Array<String>;
 	var __data : {
 	var __data : {
 		ctx : Context,
 		ctx : Context,
-		results : IntHash<{ error : Dynamic -> Void, result : Dynamic -> Void }>,
+		results : haxe.ds.IntMap<{ error : Dynamic -> Void, result : Dynamic -> Void }>,
 		error : Dynamic -> Void,
 		error : Dynamic -> Void,
 		target : String,
 		target : String,
 		#if flash9
 		#if flash9
@@ -116,7 +116,7 @@ class LocalConnection implements AsyncConnection, implements Dynamic<AsyncConnec
 		var c = new LocalConnection({
 		var c = new LocalConnection({
 			ctx : ctx,
 			ctx : ctx,
 			error : function(e) throw e,
 			error : function(e) throw e,
-			results : new IntHash(),
+			results : new haxe.ds.IntMap(),
 			cnx : l,
 			cnx : l,
 			target : recv,
 			target : recv,
 		},[]);
 		},[]);

+ 2 - 2
std/haxe/zip/Huffman.hx

@@ -73,7 +73,7 @@ class HuffTools {
 		}
 		}
 	}
 	}
 
 
-	function treeMake( bits : IntHash<Int>, maxbits : Int, v : Int, len : Int ) {
+	function treeMake( bits : haxe.ds.IntMap<Int>, maxbits : Int, v : Int, len : Int ) {
 		if( len > maxbits ) throw "Invalid huffman";
 		if( len > maxbits ) throw "Invalid huffman";
 		var idx = (v << 5) | len;
 		var idx = (v << 5) | len;
 		if( bits.exists(idx) )
 		if( bits.exists(idx) )
@@ -101,7 +101,7 @@ class HuffTools {
 			code = (code + counts[i]) << 1;
 			code = (code + counts[i]) << 1;
 			tmp[i] = code;
 			tmp[i] = code;
 		}
 		}
-		var bits = new IntHash();
+		var bits = new haxe.ds.IntMap();
 		for( i in 0...nlengths ) {
 		for( i in 0...nlengths ) {
 			var l = lengths[i + pos];
 			var l = lengths[i + pos];
 			if( l != 0 ) {
 			if( l != 0 ) {

+ 453 - 0
std/java/_std/haxe/ds/IntMap.hx

@@ -0,0 +1,453 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package haxe.ds;
+
+import java.NativeArray;
+
+/*
+ * This IntMap implementation is based on khash (https://github.com/attractivechaos/klib/blob/master/khash.h)
+ * Copyright goes to Attractive Chaos <[email protected]> and his contributors
+ *
+ * Thanks also to Jonas Malaco Filho for his Haxe-written IntMap code inspired by Python tables.
+ * (https://jonasmalaco.com/fossil/test/jonas-haxe/artifact/887b53126e237d6c68951111d594033403889304)
+ */
+
+@:coreApi class IntMap<T>
+{
+	private static inline var HASH_UPPER = 0.7;
+
+	private var flags:NativeArray<Int>;
+	private var _keys:NativeArray<Int>;
+	private var vals:NativeArray<T>;
+
+	private var nBuckets:Int;
+	private var size:Int;
+	private var nOccupied:Int;
+	private var upperBound:Int;
+
+	private var cachedKey:Int;
+	private var cachedIndex:Int;
+
+	public function new() : Void
+	{
+		cachedIndex = -1;
+	}
+
+	public function set( key : Int, value : T ) : Void
+	{
+		var x:Int;
+		if (nOccupied >= upperBound)
+		{
+			if (nBuckets > (size << 1))
+				resize(nBuckets - 1); //clear "deleted" elements
+			else
+				resize(nBuckets + 1);
+		}
+
+		var flags = flags, _keys = _keys;
+		{
+			var mask = nBuckets - 1;
+			var site = x = nBuckets;
+			var k = hash(key);
+			var i = k & mask;
+
+			//for speed up
+			if (flagIsEmpty(flags, i)) {
+				x = i;
+			} else {
+				var inc = getInc(k, mask);
+				var last = i;
+				while (! (isEither(flags, i) || _keys[i] == key) )
+				{
+					i = (i + inc) & mask;
+#if DEBUG_HASHTBL
+					if (i == last)
+					{
+						throw "assert";
+					}
+#end
+				}
+				x = i;
+			}
+		}
+
+		if (flagIsEmpty(flags, x))
+		{
+			_keys[x] = key;
+			vals[x] = value;
+			setIsBothFalse(flags, x);
+			size++;
+			nOccupied++;
+		} else if (flagIsDel(flags, x)) {
+			_keys[x] = key;
+			vals[x] = value;
+			setIsBothFalse(flags, x);
+			size++;
+		} else {
+			assert(_keys[x] == key);
+			vals[x] = value;
+		}
+	}
+
+	@:final private function lookup( key : Int ) : Int
+	{
+		if (nBuckets != 0)
+		{
+			var flags = flags, _keys = _keys;
+
+			var mask = nBuckets - 1, k = hash(key);
+			var i = k & mask;
+			var inc = getInc(k, mask); /* inc == 1 for linear probing */
+			var last = i;
+			while (!flagIsEmpty(flags, i) && (flagIsDel(flags, i) || _keys[i] != key))
+			{
+				i = (i + inc) & mask;
+				if (i == last)
+					return -1;
+			}
+			return isEither(flags, i) ? -1 : i;
+		}
+
+		return -1;
+	}
+
+	public function get( key : Int ) : Null<T>
+	{
+		var idx = -1;
+		if (cachedKey == key && ( (idx = cachedIndex) != -1 ))
+		{
+			return vals[idx];
+		}
+
+		idx = lookup(key);
+		if (idx != -1)
+		{
+			cachedKey = key;
+			cachedIndex = idx;
+
+			return vals[idx];
+		}
+
+		return null;
+	}
+
+	private function getDefault( key : Int, def : T ) : T
+	{
+		var idx = -1;
+		if (cachedKey == key && ( (idx = cachedIndex) != -1 ))
+		{
+			return vals[idx];
+		}
+
+		idx = lookup(key);
+		if (idx != -1)
+		{
+			cachedKey = key;
+			cachedIndex = idx;
+
+			return vals[idx];
+		}
+
+		return def;
+	}
+
+	public function exists( key : Int ) : Bool
+	{
+		var idx = -1;
+		if (cachedKey == key && ( (idx = cachedIndex) != -1 ))
+		{
+			return true;
+		}
+
+		idx = lookup(key);
+		if (idx != -1)
+		{
+			cachedKey = key;
+			cachedIndex = idx;
+
+			return true;
+		}
+
+		return false;
+	}
+
+	public function remove( key : Int ) : Bool
+	{
+		var idx = -1;
+		if (! (cachedKey == key && ( (idx = cachedIndex) != -1 )))
+		{
+			idx = lookup(key);
+		}
+
+		if (idx == -1)
+		{
+			return false;
+		} else {
+			if (cachedKey == key)
+				cachedIndex = -1;
+
+			if (!isEither(flags, idx))
+			{
+				setIsDelTrue(flags, idx);
+				--size;
+
+				vals[idx] = null;
+				_keys[idx] = 0;
+			}
+
+			return true;
+		}
+	}
+
+	@:final private function resize(newNBuckets:Int) : Void
+	{
+		//This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets.
+		var newFlags = null;
+		var j = 1;
+		{
+			newNBuckets = roundUp(newNBuckets);
+			if (newNBuckets < 4) newNBuckets = 4;
+			if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */
+			{
+				j = 0;
+			} else { /* hash table size to be changed (shrink or expand); rehash */
+				var nfSize = flagsSize(newNBuckets);
+				newFlags = new NativeArray( nfSize );
+				for (i in 0...nfSize)
+					newFlags[i] = 0xaaaaaaaa;
+				if (nBuckets < newNBuckets) //expand
+				{
+					var k = new NativeArray(newNBuckets);
+					if (_keys != null)
+						arrayCopy(_keys, 0, k, 0, nBuckets);
+					_keys = k;
+
+					var v = new NativeArray(newNBuckets);
+					if (vals != null)
+						arrayCopy(vals, 0, v, 0, nBuckets);
+					vals = v;
+				} //otherwise shrink
+			}
+		}
+
+		if (j != 0)
+		{ //rehashing is required
+			//resetting cache
+			cachedKey = 0;
+			cachedIndex = -1;
+
+			j = -1;
+			var nBuckets = nBuckets, _keys = _keys, vals = vals, flags = flags;
+
+			var newMask = newNBuckets - 1;
+			while (++j < nBuckets)
+			{
+				if (!isEither(flags, j))
+				{
+					var key = _keys[j];
+					var val = vals[j];
+
+					setIsDelTrue(flags, j);
+					while (true) /* kick-out process; sort of like in Cuckoo hashing */
+					{
+						var k = hash(key);
+						var inc = getInc(k, newMask);
+						var i = k & newMask;
+						while (!flagIsEmpty(newFlags, i))
+							i = (i + inc) & newMask;
+						setIsEmptyFalse(newFlags, i);
+
+						if (i < nBuckets && !isEither(flags, i)) /* kick out the existing element */
+						{
+							{
+								var tmp = _keys[i];
+								_keys[i] = key;
+								key = tmp;
+							}
+							{
+								var tmp = vals[i];
+								vals[i] = val;
+								val = tmp;
+							}
+
+							setIsDelTrue(flags, i); /* mark it as deleted in the old hash table */
+						} else { /* write the element and jump out of the loop */
+							_keys[i] = key;
+							vals[i] = val;
+							break;
+						}
+					}
+				}
+			}
+
+			if (nBuckets > newNBuckets) /* shrink the hash table */
+			{
+				{
+					var k = new NativeArray(newNBuckets);
+					arrayCopy(_keys, 0, k, 0, newNBuckets);
+					this._keys = k;
+				}
+				{
+					var v = new NativeArray(newNBuckets);
+					arrayCopy(vals, 0, v, 0, newNBuckets);
+					this.vals = v;
+				}
+			}
+
+			this.flags = newFlags;
+			this.nBuckets = newNBuckets;
+			this.nOccupied = size;
+			this.upperBound = Std.int(newNBuckets * HASH_UPPER + .5);
+		}
+	}
+
+	/**
+		Returns an iterator of all keys in the hashtable.
+		Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration
+	**/
+	public function keys() : Iterator<Int>
+	{
+		var i = 0;
+		var len = nBuckets;
+		return {
+			hasNext: function() {
+				for (j in i...len)
+				{
+					if (!isEither(flags, j))
+					{
+						i = j;
+						return true;
+					}
+				}
+				return false;
+			},
+			next: function() {
+				var ret = _keys[i];
+				cachedIndex = i;
+				cachedKey = ret;
+
+				i = i + 1;
+				return ret;
+			}
+		};
+	}
+
+	/**
+		Returns an iterator of all values in the hashtable.
+		Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration
+	**/
+	public function iterator() : Iterator<T>
+	{
+		var i = 0;
+		var len = nBuckets;
+		return {
+			hasNext: function() {
+				for (j in i...len)
+				{
+					if (!isEither(flags, j))
+					{
+						i = j;
+						return true;
+					}
+				}
+				return false;
+			},
+			next: function() {
+				var ret = vals[i];
+				i = i + 1;
+				return ret;
+			}
+		};
+	}
+
+	/**
+		Returns an displayable representation of the hashtable content.
+	**/
+
+	public function toString() : String {
+		var s = new StringBuf();
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(i);
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+
+	private static inline function assert(x:Bool):Void
+	{
+		#if debug
+		if (!x) throw "assert failed";
+		#end
+	}
+
+	private static inline function defaultK():Int return 0
+
+	private static inline function arrayCopy(sourceArray:Dynamic, sourceIndex:Int, destinationArray:Dynamic, destinationIndex:Int, length:Int):Void
+		java.lang.System.arraycopy(sourceArray, sourceIndex, destinationArray, destinationIndex, length)
+
+	private static inline function getInc(k:Int, mask:Int):Int
+		return (((k) >> 3 ^ (k) << 3) | 1) & (mask)
+
+	private static inline function hash(i:Int):Int
+		return i
+
+	private static inline function flagIsEmpty(flag:NativeArray<Int>, i:Int):Bool
+		return ( (flag[i >> 4] >>> ((i & 0xf) << 1)) & 2 ) != 0
+
+	private static inline function flagIsDel(flag:NativeArray<Int>, i:Int):Bool
+		return ((flag[i >> 4] >>> ((i & 0xf) << 1)) & 1) != 0
+
+	private static inline function isEither(flag:NativeArray<Int>, i:Int):Bool
+		return ((flag[i >> 4] >>> ((i & 0xf) << 1)) & 3) != 0
+
+	private static inline function setIsDelFalse(flag:NativeArray<Int>, i:Int):Void
+		flag[i >> 4] &= ~(1 << ((i & 0xf) << 1))
+
+	private static inline function setIsEmptyFalse(flag:NativeArray<Int>, i:Int):Void
+		flag[i >> 4] &= ~(2 << ((i & 0xf) << 1))
+
+	private static inline function setIsBothFalse(flag:NativeArray<Int>, i:Int):Void
+		flag[i >> 4] &= ~(3 << ((i & 0xf) << 1))
+
+	private static inline function setIsDelTrue(flag:NativeArray<Int>, i:Int):Void
+		flag[i >> 4] |= 1 << ((i & 0xf) << 1)
+
+	private static inline function roundUp(x:Int):Int
+	{
+		--x;
+		x |= (x) >>> 1;
+		x |= (x) >>> 2;
+		x |= (x) >>> 4;
+		x |= (x) >>> 8;
+		x |= (x) >>> 16;
+		return ++x;
+	}
+
+	private static inline function flagsSize(m:Int):Int
+		return ((m) < 16? 1 : (m) >> 4)
+}

+ 85 - 0
std/js/_std/haxe/ds/IntMap.hx

@@ -0,0 +1,85 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package haxe.ds;
+
+@:coreApi class IntMap<T> {
+
+	private var h : Dynamic;
+
+	public function new() : Void {
+		h = {};
+	}
+
+	public function set( key : Int, value : T ) : Void {
+		untyped h[key] = value;
+	}
+
+	public function get( key : Int ) : Null<T> {
+		return untyped h[key];
+	}
+
+	public function exists( key : Int ) : Bool {
+		return untyped h.hasOwnProperty(key);
+	}
+
+	public function remove( key : Int ) : Bool {
+		if( untyped !h.hasOwnProperty(key) ) return false;
+		untyped  __js__("delete")(h[key]);
+		return true;
+	}
+
+	public function keys() : Iterator<Int> {
+		var a = [];
+		untyped {
+			__js__("for( var key in this.h ) {");
+				if( h.hasOwnProperty(key) )
+					a.push(key|0);
+			__js__("}");
+		}
+		return a.iterator();
+	}
+
+	public function iterator() : Iterator<T> {
+		return untyped {
+			ref : h,
+			it : keys(),
+			hasNext : function() { return __this__.it.hasNext(); },
+			next : function() { var i = __this__.it.next(); return __this__.ref[i]; }
+		};
+	}
+
+	public function toString() : String {
+		var s = new StringBuf();
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(i);
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+
+}

+ 75 - 0
std/neko/_std/haxe/ds/IntMap.hx

@@ -0,0 +1,75 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package haxe.ds;
+
+@:coreApi class IntMap<T> {
+
+	private var h : Dynamic;
+
+	public function new() : Void {
+		h = untyped __dollar__hnew(0);
+	}
+
+	public inline function set( key : Int, value : T ) : Void {
+		untyped __dollar__hset(h,key,value,null);
+	}
+
+	public function get( key : Int ) : Null<T> {
+		return untyped __dollar__hget(h,key,null);
+	}
+
+	public inline function exists( key : Int ) : Bool {
+		return untyped __dollar__hmem(h,key,null);
+	}
+
+	public inline function remove( key : Int ) : Bool {
+		return untyped __dollar__hremove(h,key,null);
+	}
+
+	public function keys() : Iterator<Int> {
+		var l = new List<Int>();
+		untyped __dollar__hiter(h,function(k,_) { l.push(k); });
+		return l.iterator();
+	}
+
+	public function iterator() : Iterator<T> {
+		var l = new List<T>();
+		untyped __dollar__hiter(h,function(_,v) { l.push(v); });
+		return l.iterator();
+	}
+
+	public function toString() : String {
+		var s = new StringBuf();
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(i);
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+
+}

+ 82 - 0
std/php/_std/haxe/ds/IntMap.hx

@@ -0,0 +1,82 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package haxe.ds;
+
+@:coreApi class IntMap<T> implements php.IteratorAggregate<T> {
+	private var h : ArrayAccess<Int>;
+	public function new() : Void {
+		h = untyped __call__('array');
+	}
+
+	public function set( key : Int, value : T ) : Void {
+		untyped h[key] = value;
+	}
+
+	public function get( key : Int ) : Null<T> {
+		if (untyped __call__("array_key_exists", key, h))
+			return untyped h[key];
+		else
+			return null;
+	}
+
+	public function exists( key : Int ) : Bool {
+		return untyped __call__("array_key_exists", key, h);
+	}
+
+	public function remove( key : Int ) : Bool {
+		if (untyped __call__("array_key_exists", key, h)) {
+			untyped __call__("unset", h[key]);
+			return true;
+		} else
+			return false;
+	}
+
+	public function keys() : Iterator<Int> {
+		return untyped __call__("new _hx_array_iterator", __call__("array_keys", h));
+	}
+
+	public function iterator() : Iterator<T> {
+		return untyped __call__("new _hx_array_iterator", __call__("array_values", h));
+	}
+
+	public function toString() : String {
+		var s = "{";
+		var it = keys();
+		for( i in it ) {
+			s += i;
+			s += " => ";
+			s += Std.string(get(i));
+			if( it.hasNext() )
+				s += ", ";
+		}
+		return s + "}";
+	}
+
+	/**
+		Implement IteratorAggregate for native php iteration
+	**/
+	#if php
+	function getIterator() : Iterator<T> {
+		return iterator();
+	}
+	#end
+}

+ 10 - 42
tests/unit/MyAbstract.hx

@@ -20,14 +20,14 @@ abstract TemplateWrap(haxe.Template) {
 	public inline function new(x) {
 	public inline function new(x) {
 		this = new haxe.Template(x);
 		this = new haxe.Template(x);
 	}
 	}
-	
+
 	public inline function get()
 	public inline function get()
 		return this
 		return this
-	
+
 	@:from static inline public function fromString(s:String) {
 	@:from static inline public function fromString(s:String) {
 		return new TemplateWrap(s);
 		return new TemplateWrap(s);
 	}
 	}
-	
+
 	@:to inline function toString() {
 	@:to inline function toString() {
 		return this.execute( { t: "really works!"});
 		return this.execute( { t: "really works!"});
 	}
 	}
@@ -36,10 +36,10 @@ abstract TemplateWrap(haxe.Template) {
 abstract Meter(Float) from Float to Float {
 abstract Meter(Float) from Float to Float {
 	public inline function new(f)
 	public inline function new(f)
 		this = f
 		this = f
-	
+
 	public inline function get()
 	public inline function get()
 		return this
 		return this
-		
+
 	@:to public inline function toString()
 	@:to public inline function toString()
 		return this + "m"
 		return this + "m"
 }
 }
@@ -47,10 +47,10 @@ abstract Meter(Float) from Float to Float {
 abstract Kilometer(Float) from Float to Float {
 abstract Kilometer(Float) from Float to Float {
 	public inline function new(f)
 	public inline function new(f)
 		this = f
 		this = f
-		
+
 	@:to public inline function toString()
 	@:to public inline function toString()
 		return this + "km"
 		return this + "km"
-		
+
 	@:from static public inline function fromMeter(m:Meter)
 	@:from static public inline function fromMeter(m:Meter)
 		return new Kilometer(m.get() / 1000.)
 		return new Kilometer(m.get() / 1000.)
 }
 }
@@ -66,7 +66,7 @@ abstract MyHash(Hash<V>)<V> {
 		return this.get(k)
 		return this.get(k)
 	public inline function toString()
 	public inline function toString()
 		return this.toString()
 		return this.toString()
-		
+
 	@:from static public function fromStringArray(arr:Array<String>) {
 	@:from static public function fromStringArray(arr:Array<String>) {
 		var hash = new MyHash();
 		var hash = new MyHash();
 		var i = 0;
 		var i = 0;
@@ -77,7 +77,7 @@ abstract MyHash(Hash<V>)<V> {
 		}
 		}
 		return hash;
 		return hash;
 	}
 	}
-	
+
 	@:from static public function fromArray<K>(arr:Array<K>) {
 	@:from static public function fromArray<K>(arr:Array<K>) {
 		var hash = new MyHash();
 		var hash = new MyHash();
 		var i = 0;
 		var i = 0;
@@ -102,40 +102,8 @@ abstract AbstractZ(AbstractBase<T>)<T> from AbstractBase<T> {
 	@:to public static function toFoo(a:AbstractBase<Int>):Int {
 	@:to public static function toFoo(a:AbstractBase<Int>):Int {
 		return a.value;
 		return a.value;
 	}
 	}
-	
+
 	@:to public static function toString(a:AbstractBase<String>):String {
 	@:to public static function toString(a:AbstractBase<String>):String {
 		return a.value;
 		return a.value;
 	}
 	}
-}
-
-typedef IMap < K, V > = {
-	public function keys():Iterator<K>;
-	public function set(k:K, v:V):Void;
-	public function get(k:K):V;
-}
-
-class PseudoObjectHash < K: { }, V > {
-	public function new() { }
-	public function get(k:K):V return null
-	public function set(k:K, v:V) { }
-}
-
-@:generic
-abstract MyMap(IMap < K, V > ) < K, V > {
-	public function new();
-	
-	@:to static inline public function toHash(t:IMap < String, V > ):Hash<V> {
-		return new Hash<V>();
-	}
-		
-	@:to static inline public function toObjectHash<K:{}>(t:IMap < K, V > ):PseudoObjectHash<K,V> {
-		return new PseudoObjectHash<K, V>();
-	}
-	
-	@:to static inline public function toIntHash(t:IMap < Int, V > ):IntHash<V> {
-		return new IntHash<V>();
-	}
-	
-	public inline function set(k:K, v:V) this.set(k, v)
-	public inline function get(k:K) return this.get(k)
 }
 }

+ 18 - 18
tests/unit/TestBasetypes.hx

@@ -208,8 +208,8 @@ class TestBasetypes extends Test {
 		f( h.remove("x") );
 		f( h.remove("x") );
 	}
 	}
 
 
-	function testIntHash() {
-		var h = new IntHash<Null<Int>>();
+	function testIntMap() {
+		var h = new haxe.ds.IntMap<Null<Int>>();
 		h.set(0, -1);
 		h.set(0, -1);
 		h.set(-4815, 8546);
 		h.set(-4815, 8546);
 		eq( h.get(0), -1);
 		eq( h.get(0), -1);
@@ -238,7 +238,7 @@ class TestBasetypes extends Test {
 		t( h.remove(65) );
 		t( h.remove(65) );
 		f( h.remove(65) );
 		f( h.remove(65) );
 
 
-		var h = new IntHash();
+		var h = new haxe.ds.IntMap();
 		h.set(1, ['a', 'b']);
 		h.set(1, ['a', 'b']);
 		t( h.exists(1) );
 		t( h.exists(1) );
 		t( h.remove(1) );
 		t( h.remove(1) );
@@ -272,7 +272,7 @@ class TestBasetypes extends Test {
 		eq('a${x}b', "a5b");
 		eq('a${x}b', "a5b");
 		eq('${x}${y}', "5[]");
 		eq('${x}${y}', "5[]");
 	}
 	}
-	
+
 	function testAbstract() {
 	function testAbstract() {
 		var a = new MyAbstract(33);
 		var a = new MyAbstract(33);
 		t( Std.is(a, Int) );
 		t( Std.is(a, Int) );
@@ -290,71 +290,71 @@ class TestBasetypes extends Test {
 		t(Std.is(tpl, haxe.Template));
 		t(Std.is(tpl, haxe.Template));
 		t(Std.is(tpl.get(), haxe.Template));
 		t(Std.is(tpl.get(), haxe.Template));
 		eq(tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
 		eq(tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
-		
+
 		//var to
 		//var to
 		var str:String = tpl;
 		var str:String = tpl;
 		t(Std.is(str, String));
 		t(Std.is(str, String));
 		eq(str, "Abstract casting really works!");
 		eq(str, "Abstract casting really works!");
-		
+
 		// assign from
 		// assign from
 		var tpl:unit.MyAbstract.TemplateWrap;
 		var tpl:unit.MyAbstract.TemplateWrap;
 		tpl = s;
 		tpl = s;
 		t(Std.is(tpl, haxe.Template));
 		t(Std.is(tpl, haxe.Template));
 		t(Std.is(tpl.get(), haxe.Template));
 		t(Std.is(tpl.get(), haxe.Template));
 		eq(tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
 		eq(tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
-		
+
 		//assign to
 		//assign to
 		var str:String;
 		var str:String;
 		str = tpl;
 		str = tpl;
 		t(Std.is(str, String));
 		t(Std.is(str, String));
 		eq(str, "Abstract casting really works!");
 		eq(str, "Abstract casting really works!");
-		
+
 		// call arg from
 		// call arg from
 		function from(tpl:unit.MyAbstract.TemplateWrap) {
 		function from(tpl:unit.MyAbstract.TemplateWrap) {
 			eq(tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
 			eq(tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
 		}
 		}
 		from(s);
 		from(s);
-		
+
 		// call arg to
 		// call arg to
 		function from(s:String) {
 		function from(s:String) {
 			eq(s, "Abstract casting really works!");
 			eq(s, "Abstract casting really works!");
 		}
 		}
 		from(tpl);
 		from(tpl);
-		
+
 		// object decl from variant
 		// object decl from variant
 		var obj: { tpl:unit.MyAbstract.TemplateWrap } = { tpl:s };
 		var obj: { tpl:unit.MyAbstract.TemplateWrap } = { tpl:s };
 		eq(obj.tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
 		eq(obj.tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
-		
+
 		// object decl from
 		// object decl from
 		var obj: { tpl:unit.MyAbstract.TemplateWrap };
 		var obj: { tpl:unit.MyAbstract.TemplateWrap };
 		obj = { tpl:s };
 		obj = { tpl:s };
 		eq(obj.tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
 		eq(obj.tpl.get().execute( { t:"works!" } ), "Abstract casting works!");
-		
+
 		// object decl to variant
 		// object decl to variant
 		var obj: { s:String } = { s:tpl };
 		var obj: { s:String } = { s:tpl };
 		eq(obj.s, "Abstract casting really works!");
 		eq(obj.s, "Abstract casting really works!");
-		
+
 		// object decl to
 		// object decl to
 		var obj: { s:String };
 		var obj: { s:String };
 		obj = { s:tpl };
 		obj = { s:tpl };
 		eq(obj.s, "Abstract casting really works!");
 		eq(obj.s, "Abstract casting really works!");
-		
+
 		// array from
 		// array from
 		var arr:Array<unit.MyAbstract.TemplateWrap> = [s, "foo"];
 		var arr:Array<unit.MyAbstract.TemplateWrap> = [s, "foo"];
 		eq(arr[0].get().execute( { t:"works!" } ), "Abstract casting works!");
 		eq(arr[0].get().execute( { t:"works!" } ), "Abstract casting works!");
 		eq(arr[1].get().execute( { } ), "foo");
 		eq(arr[1].get().execute( { } ), "foo");
-		
+
 		// array to
 		// array to
 		var arr:Array<String> = [tpl];
 		var arr:Array<String> = [tpl];
 		eq(arr[0], "Abstract casting really works!");
 		eq(arr[0], "Abstract casting really works!");
 	}
 	}
-	
+
 	function testAbstractToAbstractCast() {
 	function testAbstractToAbstractCast() {
 		var m:unit.MyAbstract.Meter = 122.2;
 		var m:unit.MyAbstract.Meter = 122.2;
 		var km:unit.MyAbstract.Kilometer = m;
 		var km:unit.MyAbstract.Kilometer = m;
 		feq(km, 0.1222);
 		feq(km, 0.1222);
 	}
 	}
-	
+
 	#if !cpp
 	#if !cpp
 	function testAbstractTypeParameters() {
 	function testAbstractTypeParameters() {
 		var hash1:unit.MyAbstract.MyHash<String> = ["k1", "v1", "k2", "v2"];
 		var hash1:unit.MyAbstract.MyHash<String> = ["k1", "v1", "k2", "v2"];
@@ -365,7 +365,7 @@ class TestBasetypes extends Test {
 		eq(4, hash1.get("_s3"));
 		eq(4, hash1.get("_s3"));
 	}
 	}
 	#end
 	#end
-	
+
 	function testAbstractToString() {
 	function testAbstractToString() {
 		var km:unit.MyAbstract.Kilometer = 12.5;
 		var km:unit.MyAbstract.Kilometer = 12.5;
 		var m:unit.MyAbstract.Meter = 12.5;
 		var m:unit.MyAbstract.Meter = 12.5;

+ 4 - 4
tests/unit/TestSerialize.hx

@@ -63,12 +63,12 @@ class TestSerialize extends Test {
 		eq( h2.get("kéyb"), -465 );
 		eq( h2.get("kéyb"), -465 );
 		eq( Lambda.count(h2), 2 );
 		eq( Lambda.count(h2), 2 );
 
 
-		// inthash
-		var h = new IntHash();
+		// IntMap
+		var h = new haxe.ds.IntMap();
 		h.set(55,2);
 		h.set(55,2);
 		h.set(-101,-465);
 		h.set(-101,-465);
 		var h2 = id(h);
 		var h2 = id(h);
-		t( Std.is(h2,IntHash) );
+		t( Std.is(h2,haxe.ds.IntMap) );
 		eq( h2.get(55), 2 );
 		eq( h2.get(55), 2 );
 		eq( h2.get(-101), -465 );
 		eq( h2.get(-101), -465 );
 		eq( Lambda.count(h2), 2 );
 		eq( Lambda.count(h2), 2 );
@@ -96,7 +96,7 @@ class TestSerialize extends Test {
 		#if !cpp
 		#if !cpp
 		exc(function() haxe.Unserializer.run(null));
 		exc(function() haxe.Unserializer.run(null));
 		#end
 		#end
-		
+
 		exc(function() haxe.Unserializer.run(""));
 		exc(function() haxe.Unserializer.run(""));
 
 
 	}
 	}

+ 15 - 15
tests/unit/TestType.hx

@@ -363,7 +363,7 @@ class TestType extends Test {
 		typedAs(c.contravariant, b);
 		typedAs(c.contravariant, b);
 		typedAs(cast (c, Ctrv1).contravariant, c1);
 		typedAs(cast (c, Ctrv1).contravariant, c1);
 	}
 	}
-	
+
 	function testInlineCast() {
 	function testInlineCast() {
 		var s = new InlineCastB().test().quote();
 		var s = new InlineCastB().test().quote();
 		eq(s, "I am the greatest.");
 		eq(s, "I am the greatest.");
@@ -660,7 +660,7 @@ class TestType extends Test {
 		eq(c.test(), "test2");
 		eq(c.test(), "test2");
 		eq(c.fProp(9), "test09");
 		eq(c.fProp(9), "test09");
 	}
 	}
-	
+
 	function testVoidFunc() {
 	function testVoidFunc() {
 		exc(function() { throw null; return 1; } );
 		exc(function() { throw null; return 1; } );
 		exc(function() { throw null; return "foo"; } );
 		exc(function() { throw null; return "foo"; } );
@@ -669,7 +669,7 @@ class TestType extends Test {
 		exc(function() { throw null; return null; } );
 		exc(function() { throw null; return null; } );
 		exc(function() { throw null; return { foo: 1}; } );
 		exc(function() { throw null; return { foo: 1}; } );
 	}
 	}
-	
+
 	function testAbstractCastConstraints() {
 	function testAbstractCastConstraints() {
 		var z:unit.MyAbstract.AbstractZ<String> = new unit.MyAbstract.AbstractBase("foo");
 		var z:unit.MyAbstract.AbstractZ<String> = new unit.MyAbstract.AbstractBase("foo");
 		var s:String = z;
 		var s:String = z;
@@ -677,7 +677,7 @@ class TestType extends Test {
 			var i:Int = z;
 			var i:Int = z;
 		}));
 		}));
 		eq("foo", s);
 		eq("foo", s);
-		
+
 		var z:unit.MyAbstract.AbstractZ<Int> = new unit.MyAbstract.AbstractBase(12);
 		var z:unit.MyAbstract.AbstractZ<Int> = new unit.MyAbstract.AbstractBase(12);
 		var i:Int = z;
 		var i:Int = z;
 		eq(12, i);
 		eq(12, i);
@@ -685,20 +685,20 @@ class TestType extends Test {
 			var s:String = z;
 			var s:String = z;
 		}));
 		}));
 	}
 	}
-	
+
 	function testAbstractGeneric() {
 	function testAbstractGeneric() {
-		var map = new unit.MyAbstract.MyMap();
+		var map = new Map();
 		map.set("foo", 1);
 		map.set("foo", 1);
 		t(Std.is(map, Hash));
 		t(Std.is(map, Hash));
 
 
-		var map = new unit.MyAbstract.MyMap();
+		var map = new Map();
 		_mapMe(map); // infer from function call
 		_mapMe(map); // infer from function call
-		t(Std.is(map, IntHash));
+		t(Std.is(map, haxe.ds.IntMap));
+
+		//var map = new unit.MyAbstract.MyMap();
+		//map.set(new haxe.Template("foo"), 99);
+		//t(Std.is(map, unit.MyAbstract.PseudoObjectHash));
 
 
-		var map = new unit.MyAbstract.MyMap();
-		map.set(new haxe.Template("foo"), 99);
-		t(Std.is(map, unit.MyAbstract.PseudoObjectHash));
-		
 		// all these cause a compilation error, but we cannot typeError test that because it happens
 		// all these cause a compilation error, but we cannot typeError test that because it happens
 		// during a post-process check
 		// during a post-process check
 		//var map = new Map(); // Could not determine type for IMap<Float, Int>
 		//var map = new Map(); // Could not determine type for IMap<Float, Int>
@@ -706,9 +706,9 @@ class TestType extends Test {
 
 
 		//var map = new Map(); // Could not determine type for IMap<x : String -> String, Int>
 		//var map = new Map(); // Could not determine type for IMap<x : String -> String, Int>
 		//map.set(function(x:String) return x, 1);
 		//map.set(function(x:String) return x, 1);
-		
+
 		//var map = new Map(); // Could not determine type for IMap<Unknown<0>, Unknown<1>>
 		//var map = new Map(); // Could not determine type for IMap<Unknown<0>, Unknown<1>>
 	}
 	}
-	
-	static function _mapMe(map:unit.MyAbstract.MyMap < Int, String > ) { }
+
+	static function _mapMe(map:Map < Int, String > ) { }
 }
 }