2
0
Эх сурвалжийг харах

[cpp] Use cpp::Int64 for haxe.Int64 instead of a class (#9935)

* Generate variables, functions, and ClassOf with ::cpp::Int64 for haxe.Int64

* cpp haxe.Int64 abstract implements functions required by the api

* Use standard maths operators where possible

* Disallow type checks using the haxe.Int64 abstract

* Add functions for getting and setting Int64 values in map types

* Use maths helper functions for bitwise ops

* Increase hxcpp api version

* Remove earlier gencpp changes as they're not needed when abstracting around cpp.Int64

* Bump api version

* Add a new cpp specific Int64Map type

* use extern functions for Int64 operators

* Add implicit from for cpp Int64Map

* Add Int64Map check for cppia get and set calls

* Intercept Class<cpp.Int64> calls and insert the correct path

* Add cpp.Int64Map to cppia host classes array

* Fix incorrect signature from copy and pasting

* add int64 get and set functions for map specialisations on cppia

* Prevent enums with Int64s being boxed or down casted to ints
Aidan Lee 2 жил өмнө
parent
commit
bc50a04855

+ 1 - 1
src/compiler/haxe.ml

@@ -51,4 +51,4 @@ set_binary_mode_out stdout true;
 set_binary_mode_out stderr true;
 set_binary_mode_out stderr true;
 let sctx = ServerCompilationContext.create false in
 let sctx = ServerCompilationContext.create false in
 Server.process sctx (Communication.create_stdio ()) args;
 Server.process sctx (Communication.create_stdio ()) args;
-other()
+other()

+ 11 - 1
src/generators/gencpp.ml

@@ -2083,6 +2083,7 @@ let cpp_variant_type_of t = match t with
    | TCppScalar "Int"
    | TCppScalar "Int"
    | TCppScalar "bool"
    | TCppScalar "bool"
    | TCppScalar "Float"  -> t
    | TCppScalar "Float"  -> t
+   | TCppScalar "::cpp::Int64" -> TCppScalar("Int64")
    | TCppScalar "double"
    | TCppScalar "double"
    | TCppScalar "float" -> TCppScalar("Float")
    | TCppScalar "float" -> TCppScalar("Float")
    | TCppScalar _  -> TCppScalar("int")
    | TCppScalar _  -> TCppScalar("int")
@@ -2273,6 +2274,7 @@ let is_array_splice_call obj member =
 let is_map_get_call obj member =
 let is_map_get_call obj member =
    member.cf_name="get" &&
    member.cf_name="get" &&
    (match obj.cpptype  with
    (match obj.cpptype  with
+   | TCppInst({cl_path=(["cpp"],"Int64Map")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"IntMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"IntMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"StringMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"StringMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"ObjectMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"ObjectMap")}, _) -> true
@@ -2283,6 +2285,7 @@ let is_map_get_call obj member =
 let is_map_set_call obj member =
 let is_map_set_call obj member =
    member.cf_name="set" &&
    member.cf_name="set" &&
    (match obj.cpptype  with
    (match obj.cpptype  with
+   | TCppInst({cl_path=(["cpp"],"Int64Map")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"IntMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"IntMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"StringMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"StringMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"ObjectMap")}, _) -> true
    | TCppInst({cl_path=(["haxe";"ds"],"ObjectMap")}, _) -> true
@@ -2767,6 +2770,7 @@ let retype_expression ctx request_type function_args function_type expression_tr
                   let fname, cppType = match return_type with
                   let fname, cppType = match return_type with
                   | TCppVoid | TCppScalar("bool")  -> (if forCppia then "getBool" else "get_bool"), return_type
                   | TCppVoid | TCppScalar("bool")  -> (if forCppia then "getBool" else "get_bool"), return_type
                   | TCppScalar("int")  -> (if forCppia then "getInt" else "get_int"), return_type
                   | TCppScalar("int")  -> (if forCppia then "getInt" else "get_int"), return_type
+                  | TCppScalar("::cpp::Int64") -> (if forCppia then "getInt64" else "get_int64"), return_type
                   | TCppScalar("Float")  -> (if forCppia then "getFloat" else "get_float"), return_type
                   | TCppScalar("Float")  -> (if forCppia then "getFloat" else "get_float"), return_type
                   | TCppString  -> (if forCppia then "getString" else "get_string"), return_type
                   | TCppString  -> (if forCppia then "getString" else "get_string"), return_type
                   | _ -> "get", TCppDynamic
                   | _ -> "get", TCppDynamic
@@ -2786,6 +2790,7 @@ let retype_expression ctx request_type function_args function_type expression_tr
                   let fname = match retypedArgs with
                   let fname = match retypedArgs with
                   | [_;{cpptype=TCppScalar("bool")}]  -> "setBool"
                   | [_;{cpptype=TCppScalar("bool")}]  -> "setBool"
                   | [_;{cpptype=TCppScalar("int")}]  -> "setInt"
                   | [_;{cpptype=TCppScalar("int")}]  -> "setInt"
+                  | [_;{cpptype=TCppScalar("::cpp::Int64")}]  -> "setInt64"
                   | [_;{cpptype=TCppScalar("Float")}]  -> "setFloat"
                   | [_;{cpptype=TCppScalar("Float")}]  -> "setFloat"
                   | [_;{cpptype=TCppString}]  -> "setString"
                   | [_;{cpptype=TCppString}]  -> "setString"
                   | _ -> "set"
                   | _ -> "set"
@@ -2947,7 +2952,12 @@ let retype_expression ctx request_type function_args function_type expression_tr
                arrayExpr, elemType
                arrayExpr, elemType
 
 
          | TTypeExpr module_type ->
          | TTypeExpr module_type ->
-            let path = t_path module_type in
+            (* If we try and use the coreType / runtimeValue cpp.Int64 abstract with Class<T> then we get a class decl of the abstract *)
+            (* as that abstract has functions in its declaration *)
+            (* Intercept it and replace it with the path of the actual int64 type so the generated cpp is correct *)
+            let path = match module_type with
+            | TClassDecl ({ cl_path = ["cpp";"_Int64"],"Int64_Impl_" }) -> ["cpp"],"Int64"
+            | _ -> t_path module_type in
             CppClassOf(path, is_native_gen_module module_type), TCppClass
             CppClassOf(path, is_native_gen_module module_type), TCppClass
 
 
          | TBinop (op,left,right) ->
          | TBinop (op,left,right) ->

+ 154 - 0
std/cpp/Int64Map.hx

@@ -0,0 +1,154 @@
+/*
+ * Copyright (C)2005-2019 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 cpp;
+
+import haxe.Int64;
+
+@:headerClassCode("
+  inline void set(cpp::Int64 key, ::null value) { __int64_hash_set(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, bool value) { __int64_hash_set(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, char value) { __int64_hash_set_int(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, unsigned char value) { __int64_hash_set_int(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, signed char value) { __int64_hash_set_int(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, short value) { __int64_hash_set_int(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, unsigned short value) { __int64_hash_set_int(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, int value) { __int64_hash_set_int(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, unsigned int value) { __int64_hash_set_int(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, float value) { __int64_hash_set_float(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, double value) { __int64_hash_set_float(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, ::String value) { __int64_hash_set_string(HX_MAP_THIS,key,value); }
+  inline void set(cpp::Int64 key, cpp::Int64 value) { __int64_hash_set_int64(HX_MAP_THIS,key,value); }
+
+  template<typename V, typename H>
+  inline void set(cpp::Int64 key, const ::cpp::Struct<V,H> &value) {__int64_hash_set(HX_MAP_THIS,key,value); }
+  template<typename F>
+  inline void set(cpp::Int64 key, const ::cpp::Function<F> &value) {__int64_hash_set(HX_MAP_THIS,key,value); }
+  template<typename V>
+  inline void set(cpp::Int64 key, const ::cpp::Pointer<V> &value) {__int64_hash_set(HX_MAP_THIS,key,(Dynamic)value ); }
+
+  template<typename VALUE>
+  inline void set(Dynamic &key, const VALUE &value) { set( (cpp::Int64)key, value ); }
+
+  inline bool get_bool(cpp::Int64 key) { return __int64_hash_get_bool(h,key); }
+  inline int get_int(cpp::Int64 key) { return __int64_hash_get_int(h,key); }
+  inline Float get_float(cpp::Int64 key) { return __int64_hash_get_float(h,key); }
+  inline String get_string(cpp::Int64 key) { return __int64_hash_get_string(h,key); }
+  inline cpp::Int64 get_int64(cpp::Int64 key) { return __int64_hash_get_int64(h,key); }
+")
+@:coreApi class Int64Map<T> implements haxe.Constraints.IMap<Int64, T> {
+	@:ifFeature("cpp.Int64Map.*")
+	private var h:Dynamic;
+
+	public function new():Void {}
+
+	public function set(key:Int64, value:T):Void {
+		untyped __global__.__int64_hash_set(__cpp__("HX_MAP_THIS"), key, value);
+	}
+
+	public function get(key:Int64):Null<T> {
+		return untyped __global__.__int64_hash_get(h, key);
+	}
+
+	public function exists(key:Int64):Bool {
+		return untyped __global__.__int64_hash_exists(h, key);
+	}
+
+	public function remove(key:Int64):Bool {
+		return untyped __global__.__int64_hash_remove(h, key);
+	}
+
+	public function keys():Iterator<Int64> {
+		var a:Array<Int64> = untyped __global__.__int64_hash_keys(h);
+		return a.iterator();
+	}
+
+	public function iterator():Iterator<T> {
+		var a:Array<Dynamic> = untyped __global__.__int64_hash_values(h);
+		return a.iterator();
+	}
+
+	@:runtime public inline function keyValueIterator():KeyValueIterator<Int64, T> {
+		return new haxe.iterators.MapKeyValueIterator(this);
+	}
+
+	public function copy():Int64Map<T> {
+		var copied = new Int64Map();
+		for (key in keys())
+			copied.set(key, get(key));
+		return copied;
+	}
+
+	public function toString():String {
+		return untyped __global__.__int64_hash_to_string(h);
+	}
+
+	public function clear():Void {
+		#if (hxcpp_api_level >= 400)
+		return untyped __global__.__int64_hash_clear(h);
+		#else
+		h = null;
+		#end
+	}
+
+	#if (scriptable)
+	private function setString(key:Int64, val:String):Void {
+		untyped __int64_hash_set_string(__cpp__("HX_MAP_THIS"), key, val);
+	}
+
+	private function setInt(key:Int64, val:Int):Void {
+		untyped __int64_hash_set_int(__cpp__("HX_MAP_THIS"), key, val);
+	}
+
+	private function setBool(key:Int64, val:Bool):Void {
+		untyped __int64_hash_set_int(__cpp__("HX_MAP_THIS"), key, val);
+	}
+
+	private function setFloat(key:Int64, val:Float):Void {
+		untyped __int64_hash_set_float(__cpp__("HX_MAP_THIS"), key, val);
+	}
+
+	private function setInt64(key:Int64, val:Int64):Void {
+		untyped __int64_hash_set_int64(__cpp__("HX_MAP_THIS"), key, val);
+	}
+
+	private function getString(key:Int64):String {
+		return untyped __int64_hash_get_string(h, key);
+	}
+
+	private function getInt(key:Int64):Int {
+		return untyped __int64_hash_get_int(h, key);
+	}
+
+	private function getBool(key:Int64):Bool {
+		return untyped __int64_hash_get_bool(h, key);
+	}
+
+	private function getFloat(key:Int64):Float {
+		return untyped __int64_hash_get_float(h, key);
+	}
+
+	private function getInt64(key:Int64):Int64 {
+		return untyped __int64_hash_get_int64(h, key);
+	}
+	#end
+}

+ 48 - 48
std/cpp/_std/haxe/Int64.hx

@@ -22,13 +22,8 @@
 
 
 package haxe;
 package haxe;
 
 
-import haxe.Int64Helper;
-
-@:notNull
 @:include("cpp/Int64.h")
 @:include("cpp/Int64.h")
-@:native("cpp::Int64Struct")
-private extern class ___Int64 {
-
+private extern class NativeInt64Helper {
 	@:native("_hx_int64_make")
 	@:native("_hx_int64_make")
 	static function make(high:Int32, low:Int32):__Int64;
 	static function make(high:Int32, low:Int32):__Int64;
 
 
@@ -132,21 +127,21 @@ private extern class ___Int64 {
 	static function low(a:__Int64):Int32;
 	static function low(a:__Int64):Int32;
 }
 }
 
 
-private typedef __Int64 = ___Int64;
+private typedef __Int64 = cpp.Int64;
 
 
 @:coreApi
 @:coreApi
 @:transitive
 @:transitive
-abstract Int64(__Int64) from __Int64 to __Int64 {
+@:notNull
+abstract Int64(__Int64) from __Int64 from Int to __Int64 {
 	public #if !cppia inline #end function copy():Int64
 	public #if !cppia inline #end function copy():Int64
 		return this;
 		return this;
 
 
 	public static #if !cppia inline #end function make(high:Int32, low:Int32):Int64 {
 	public static #if !cppia inline #end function make(high:Int32, low:Int32):Int64 {
-		return __Int64.make(high, low);
+		return NativeInt64Helper.make(high, low);
 	}
 	}
 
 
-	@:from
 	public static #if !cppia inline #end function ofInt(x:Int):Int64 {
 	public static #if !cppia inline #end function ofInt(x:Int):Int64 {
-		return __Int64.ofInt(x);
+		return x;
 	}
 	}
 
 
 	public static #if !cppia inline #end function toInt(x:Int64):Int {
 	public static #if !cppia inline #end function toInt(x:Int64):Int {
@@ -158,11 +153,11 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 
 
 	@:deprecated('haxe.Int64.is() is deprecated. Use haxe.Int64.isInt64() instead')
 	@:deprecated('haxe.Int64.is() is deprecated. Use haxe.Int64.isInt64() instead')
 	inline public static function is(val:Dynamic):Bool {
 	inline public static function is(val:Dynamic):Bool {
-		return isInt64(val);
+		return val is cpp.Int64;
 	}
 	}
 
 
 	public static #if !cppia inline #end function isInt64(val:Dynamic):Bool
 	public static #if !cppia inline #end function isInt64(val:Dynamic):Bool
-		return __Int64.isInt64(val);
+		return val is cpp.Int64;
 
 
 	@:deprecated("Use high instead")
 	@:deprecated("Use high instead")
 	public static #if !cppia inline #end function getHigh(x:Int64):Int32
 	public static #if !cppia inline #end function getHigh(x:Int64):Int32
@@ -173,22 +168,22 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 		return x.low;
 		return x.low;
 
 
 	public static #if !cppia inline #end function isNeg(x:Int64):Bool
 	public static #if !cppia inline #end function isNeg(x:Int64):Bool
-		return __Int64.isNeg(x);
+		return NativeInt64Helper.isNeg(x);
 
 
 	public static #if !cppia inline #end function isZero(x:Int64):Bool
 	public static #if !cppia inline #end function isZero(x:Int64):Bool
-		return __Int64.isZero(x);
+		return NativeInt64Helper.isZero(x);
 
 
 	public static #if !cppia inline #end function compare(a:Int64, b:Int64):Int
 	public static #if !cppia inline #end function compare(a:Int64, b:Int64):Int
-		return __Int64.compare(a, b);
+		return NativeInt64Helper.compare(a, b);
 
 
 	public static #if !cppia inline #end function ucompare(a:Int64, b:Int64):Int
 	public static #if !cppia inline #end function ucompare(a:Int64, b:Int64):Int
-		return __Int64.ucompare(a, b);
+		return NativeInt64Helper.ucompare(a, b);
 
 
 	public static #if !cppia inline #end function toStr(x:Int64):String
 	public static #if !cppia inline #end function toStr(x:Int64):String
-		return x.toString();
+		return cast x.val;
 
 
 	private #if !cppia inline #end function toString():String
 	private #if !cppia inline #end function toString():String
-		return __Int64.toString(this);
+		return cast this;
 
 
 	public static function parseString(sParam:String):Int64 {
 	public static function parseString(sParam:String):Int64 {
 		return Int64Helper.parseString(sParam);
 		return Int64Helper.parseString(sParam);
@@ -201,7 +196,7 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 	public static function divMod(dividend:Int64, divisor:Int64):{quotient:Int64, modulus:Int64} {
 	public static function divMod(dividend:Int64, divisor:Int64):{quotient:Int64, modulus:Int64} {
 		var q = dividend / divisor;
 		var q = dividend / divisor;
 
 
-		if (isZero(divisor))
+		if (divisor == 0)
 			throw "divide by zero";
 			throw "divide by zero";
 
 
 		var m = dividend - q * divisor;
 		var m = dividend - q * divisor;
@@ -209,16 +204,16 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 		return {quotient: q, modulus: m};
 		return {quotient: q, modulus: m};
 	}
 	}
 
 
-	@:op(-A)
+@:op(-A)
 	public static #if !cppia inline #end function neg(x:Int64):Int64
 	public static #if !cppia inline #end function neg(x:Int64):Int64
-		return __Int64.neg(x);
+		return NativeInt64Helper.neg(x);
 
 
 	@:op(++A) private inline function preIncrement():Int64 {
 	@:op(++A) private inline function preIncrement():Int64 {
 		#if cppia
 		#if cppia
 		this = this + make(0, 1);
 		this = this + make(0, 1);
 		return this;
 		return this;
 		#else
 		#else
-		return __Int64.preIncrement(this);
+		return NativeInt64Helper.preIncrement(this);
 		#end
 		#end
 	}
 	}
 
 
@@ -228,7 +223,7 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 		this = this + make(0, 1);
 		this = this + make(0, 1);
 		return result;
 		return result;
 		#else
 		#else
-		return __Int64.postIncrement(this);
+		return NativeInt64Helper.postIncrement(this);
 		#end
 		#end
 	}
 	}
 
 
@@ -237,7 +232,7 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 		untyped this = this - make(0, 1);
 		untyped this = this - make(0, 1);
 		return this;
 		return this;
 		#else
 		#else
-		return __Int64.preDecrement(this);
+		return NativeInt64Helper.preDecrement(this);
 		#end
 		#end
 	}
 	}
 
 
@@ -247,35 +242,35 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 		this = this - make(0, 1);
 		this = this - make(0, 1);
 		return result;
 		return result;
 		#else
 		#else
-		return __Int64.postDecrement(this);
+		return NativeInt64Helper.postDecrement(this);
 		#end
 		#end
 	}
 	}
 
 
 	@:op(A + B)
 	@:op(A + B)
 	public static #if !cppia inline #end function add(a:Int64, b:Int64):Int64
 	public static #if !cppia inline #end function add(a:Int64, b:Int64):Int64
-		return __Int64.add(a, b);
+		return NativeInt64Helper.add(a, b);
 
 
 	@:op(A + B)
 	@:op(A + B)
 	@:commutative
 	@:commutative
 	private static #if !cppia inline #end function addInt(a:Int64, b:Int):Int64
 	private static #if !cppia inline #end function addInt(a:Int64, b:Int):Int64
-		return __Int64.addInt(a, b);
+		return NativeInt64Helper.addInt(a, b);
 
 
 	@:op(A - B)
 	@:op(A - B)
 	public static #if !cppia inline #end function sub(a:Int64, b:Int64):Int64 {
 	public static #if !cppia inline #end function sub(a:Int64, b:Int64):Int64 {
-		return __Int64.sub(a, b);
+		return NativeInt64Helper.sub(a, b);
 	}
 	}
 
 
 	@:op(A - B)
 	@:op(A - B)
 	private static #if !cppia inline #end function subInt(a:Int64, b:Int):Int64
 	private static #if !cppia inline #end function subInt(a:Int64, b:Int):Int64
-		return __Int64.subInt(a, b);
+		return NativeInt64Helper.subInt(a, b);
 
 
 	@:op(A - B)
 	@:op(A - B)
 	private static #if !cppia inline #end function intSub(a:Int, b:Int64):Int64
 	private static #if !cppia inline #end function intSub(a:Int, b:Int64):Int64
-		return __Int64.intSub(a, b);
+		return NativeInt64Helper.intSub(a, b);
 
 
 	@:op(A * B)
 	@:op(A * B)
 	public static #if !cppia inline #end function mul(a:Int64, b:Int64):Int64
 	public static #if !cppia inline #end function mul(a:Int64, b:Int64):Int64
-		return __Int64.mul(a, b);
+		return NativeInt64Helper.mul(a, b);
 
 
 	@:op(A * B)
 	@:op(A * B)
 	@:commutative
 	@:commutative
@@ -284,9 +279,9 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 
 
 	@:op(A / B)
 	@:op(A / B)
 	public static #if !cppia inline #end function div(a:Int64, b:Int64):Int64 {
 	public static #if !cppia inline #end function div(a:Int64, b:Int64):Int64 {
-		if (__Int64.isZero(b))
+		if (NativeInt64Helper.isZero(b))
 			throw "divide by zero";
 			throw "divide by zero";
-		return __Int64.div(a, b);
+		return NativeInt64Helper.div(a, b);
 	}
 	}
 
 
 	@:op(A / B)
 	@:op(A / B)
@@ -299,9 +294,9 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 
 
 	@:op(A % B)
 	@:op(A % B)
 	public static #if !cppia inline #end function mod(a:Int64, b:Int64):Int64 {
 	public static #if !cppia inline #end function mod(a:Int64, b:Int64):Int64 {
-		if (__Int64.isZero(b))
+		if (NativeInt64Helper.isZero(b))
 			throw "divide by zero";
 			throw "divide by zero";
-		return __Int64.mod(a, b);
+		return NativeInt64Helper.mod(a, b);
 	}
 	}
 
 
 	@:op(A % B)
 	@:op(A % B)
@@ -314,16 +309,16 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 
 
 	@:op(A == B)
 	@:op(A == B)
 	public static #if !cppia inline #end function eq(a:Int64, b:Int64):Bool
 	public static #if !cppia inline #end function eq(a:Int64, b:Int64):Bool
-		return __Int64.eq(a, b);
+		return NativeInt64Helper.eq(a, b);
 
 
 	@:op(A == B)
 	@:op(A == B)
 	@:commutative
 	@:commutative
 	private static #if !cppia inline #end function eqInt(a:Int64, b:Int):Bool
 	private static #if !cppia inline #end function eqInt(a:Int64, b:Int):Bool
-		return __Int64.eqInt(a, b);
+		return NativeInt64Helper.eqInt(a, b);
 
 
 	@:op(A != B)
 	@:op(A != B)
 	public static #if !cppia inline #end function neq(a:Int64, b:Int64):Bool
 	public static #if !cppia inline #end function neq(a:Int64, b:Int64):Bool
-		return __Int64.neq(a, b);
+		return NativeInt64Helper.neq(a, b);
 
 
 	@:op(A != B)
 	@:op(A != B)
 	@:commutative
 	@:commutative
@@ -380,39 +375,44 @@ abstract Int64(__Int64) from __Int64 to __Int64 {
 
 
 	@:op(~A)
 	@:op(~A)
 	private static #if !cppia inline #end function complement(a:Int64):Int64
 	private static #if !cppia inline #end function complement(a:Int64):Int64
-		return __Int64.complement(a);
+		return NativeInt64Helper.complement(a);
 
 
 	@:op(A & B)
 	@:op(A & B)
 	public static #if !cppia inline #end function and(a:Int64, b:Int64):Int64
 	public static #if !cppia inline #end function and(a:Int64, b:Int64):Int64
-		return __Int64.bitAnd(a, b);
+		return NativeInt64Helper.bitAnd(a, b);
 
 
 	@:op(A | B)
 	@:op(A | B)
 	public static #if !cppia inline #end function or(a:Int64, b:Int64):Int64
 	public static #if !cppia inline #end function or(a:Int64, b:Int64):Int64
-		return __Int64.bitOr(a, b);
+		return NativeInt64Helper.bitOr(a, b);
 
 
 	@:op(A ^ B)
 	@:op(A ^ B)
 	public static #if !cppia inline #end function xor(a:Int64, b:Int64):Int64
 	public static #if !cppia inline #end function xor(a:Int64, b:Int64):Int64
-		return __Int64.bitXor(a, b);
+		return NativeInt64Helper.bitXor(a, b);
 
 
 	@:op(A << B)
 	@:op(A << B)
 	public static #if !cppia inline #end function shl(a:Int64, b:Int):Int64
 	public static #if !cppia inline #end function shl(a:Int64, b:Int):Int64
-		return __Int64.shl(a, b);
+		return NativeInt64Helper.shl(a, b);
 
 
 	@:op(A >> B)
 	@:op(A >> B)
 	public static #if !cppia inline #end function shr(a:Int64, b:Int):Int64
 	public static #if !cppia inline #end function shr(a:Int64, b:Int):Int64
-		return __Int64.shr(a, b);
+		return NativeInt64Helper.shr(a, b);
 
 
 	@:op(A >>> B)
 	@:op(A >>> B)
 	public static #if !cppia inline #end function ushr(a:Int64, b:Int):Int64
 	public static #if !cppia inline #end function ushr(a:Int64, b:Int):Int64
-		return __Int64.ushr(a, b);
+		return NativeInt64Helper.ushr(a, b);
 
 
 	public var high(get, never):Int32;
 	public var high(get, never):Int32;
 
 
 	private #if !cppia inline #end function get_high():Int32
 	private #if !cppia inline #end function get_high():Int32
-		return __Int64.high(this);
+		return NativeInt64Helper.high(this);
 
 
 	public var low(get, never):Int32;
 	public var low(get, never):Int32;
 
 
 	private #if !cppia inline #end function get_low():Int32
 	private #if !cppia inline #end function get_low():Int32
-		return __Int64.low(this);
+		return NativeInt64Helper.low(this);
+
+	private var val(get, never):__Int64;
+
+	private #if !cppia inline #end function get_val():__Int64
+		return this;
 }
 }

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

@@ -35,6 +35,7 @@ package haxe.ds;
   inline void set(int key, float value) { __int_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(int key, float value) { __int_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(int key, double value) { __int_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(int key, double value) { __int_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(int key, ::String value) { __int_hash_set_string(HX_MAP_THIS,key,value); }
   inline void set(int key, ::String value) { __int_hash_set_string(HX_MAP_THIS,key,value); }
+  inline void set(int key, cpp::Int64 value) { __int_hash_set_int64(HX_MAP_THIS,key,value); }
 
 
   template<typename V, typename H>
   template<typename V, typename H>
   inline void set(int key, const ::cpp::Struct<V,H> &value) {__int_hash_set(HX_MAP_THIS,key,value); }
   inline void set(int key, const ::cpp::Struct<V,H> &value) {__int_hash_set(HX_MAP_THIS,key,value); }
@@ -50,6 +51,7 @@ package haxe.ds;
   inline int get_int(int key) { return __int_hash_get_int(h,key); }
   inline int get_int(int key) { return __int_hash_get_int(h,key); }
   inline Float get_float(int key) { return __int_hash_get_float(h,key); }
   inline Float get_float(int key) { return __int_hash_get_float(h,key); }
   inline String get_string(int key) { return __int_hash_get_string(h,key); }
   inline String get_string(int key) { return __int_hash_get_string(h,key); }
+  inline cpp::Int64 get_int64(int key) { return __int_hash_get_int64(h,key); }
 ")
 ")
 @:coreApi class IntMap<T> implements haxe.Constraints.IMap<Int, T> {
 @:coreApi class IntMap<T> implements haxe.Constraints.IMap<Int, T> {
 	@:ifFeature("haxe.ds.IntMap.*")
 	@:ifFeature("haxe.ds.IntMap.*")
@@ -123,6 +125,10 @@ package haxe.ds;
 		untyped __int_hash_set_float(__cpp__("HX_MAP_THIS"), key, val);
 		untyped __int_hash_set_float(__cpp__("HX_MAP_THIS"), key, val);
 	}
 	}
 
 
+	private function setInt64(key:Int, val:haxe.Int64):Void {
+		untyped __int_hash_set_int64(__cpp__("HX_MAP_THIS"), key, val);
+	}
+
 	private function getString(key:Int):String {
 	private function getString(key:Int):String {
 		return untyped __int_hash_get_string(h, key);
 		return untyped __int_hash_get_string(h, key);
 	}
 	}
@@ -138,5 +144,9 @@ package haxe.ds;
 	private function getFloat(key:Int):Float {
 	private function getFloat(key:Int):Float {
 		return untyped __int_hash_get_float(h, key);
 		return untyped __int_hash_get_float(h, key);
 	}
 	}
+
+	private function getInt64(key:Int):haxe.Int64 {
+		return untyped __int_hash_get_int64(h, key);
+	}
 	#end
 	#end
 }
 }

+ 207 - 0
std/cpp/_std/haxe/ds/Map.hx

@@ -0,0 +1,207 @@
+/*
+ * Copyright (C)2005-2019 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 haxe.Int64;
+import haxe.ds.StringMap;
+import haxe.ds.IntMap;
+import haxe.ds.HashMap;
+import haxe.ds.ObjectMap;
+import haxe.ds.WeakMap;
+import haxe.ds.EnumValueMap;
+import haxe.Constraints.IMap;
+import cpp.Int64Map;
+
+/**
+	Map allows key to value mapping for arbitrary value types, and many key
+	types.
+
+	This is a multi-type abstract, it is instantiated as one of its
+	specialization types depending on its type parameters.
+
+	A Map can be instantiated without explicit type parameters. Type inference
+	will then determine the type parameters from the usage.
+
+	Maps can also be created with `[key1 => value1, key2 => value2]` syntax.
+
+	Map is an abstract type, it is not available at runtime.
+
+	@see https://haxe.org/manual/std-Map.html
+**/
+@:transitive
+@:multiType(@:followWithAbstracts K)
+abstract Map<K, V>(IMap<K, V>) {
+	/**
+		Creates a new Map.
+
+		This becomes a constructor call to one of the specialization types in
+		the output. The rules for that are as follows:
+
+		1. if `K` is a `String`, `haxe.ds.StringMap` is used
+		2. if `K` is an `Int`, `haxe.ds.IntMap` is used
+		3. if `K` is an `EnumValue`, `haxe.ds.EnumValueMap` is used
+		4. if `K` is any other class or structure, `haxe.ds.ObjectMap` is used
+		5. if `K` is any other type, it causes a compile-time error
+
+		(Cpp) Map does not use weak keys on `ObjectMap` by default.
+	**/
+	public function new();
+
+	/**
+		Maps `key` to `value`.
+
+		If `key` already has a mapping, the previous value disappears.
+
+		If `key` is `null`, the result is unspecified.
+	**/
+	public inline function set(key:K, value:V)
+		this.set(key, value);
+
+	/**
+		Returns the current mapping of `key`.
+
+		If no such mapping exists, `null` is returned.
+
+		Note that a check like `map.get(key) == null` can hold for two reasons:
+
+		1. the map has no mapping for `key`
+		2. the map has a mapping with a value of `null`
+
+		If it is important to distinguish these cases, `exists()` should be
+		used.
+
+		If `key` is `null`, the result is unspecified.
+	**/
+	@:arrayAccess public inline function get(key:K)
+		return this.get(key);
+
+	/**
+		Returns true if `key` has a mapping, false otherwise.
+
+		If `key` is `null`, the result is unspecified.
+	**/
+	public inline function exists(key:K)
+		return this.exists(key);
+
+	/**
+		Removes the mapping of `key` and returns true if such a mapping existed,
+		false otherwise.
+
+		If `key` is `null`, the result is unspecified.
+	**/
+	public inline function remove(key:K)
+		return this.remove(key);
+
+	/**
+		Returns an Iterator over the keys of `this` Map.
+
+		The order of keys is undefined.
+	**/
+	public inline function keys():Iterator<K> {
+		return this.keys();
+	}
+
+	/**
+		Returns an Iterator over the values of `this` Map.
+
+		The order of values is undefined.
+	**/
+	public inline function iterator():Iterator<V> {
+		return this.iterator();
+	}
+
+	/**
+		Returns an Iterator over the keys and values of `this` Map.
+
+		The order of values is undefined.
+	**/
+	public inline function keyValueIterator():KeyValueIterator<K, V> {
+		return this.keyValueIterator();
+	}
+
+	/**
+		Returns a shallow copy of `this` map.
+
+		The order of values is undefined.
+	**/
+	public inline function copy():Map<K, V> {
+		return cast this.copy();
+	}
+
+	/**
+		Returns a String representation of `this` Map.
+
+		The exact representation depends on the platform and key-type.
+	**/
+	public inline function toString():String {
+		return this.toString();
+	}
+
+	/**
+		Removes all keys from `this` Map.
+	**/
+	public inline function clear():Void {
+		this.clear();
+	}
+
+	@:arrayAccess @:noCompletion public inline function arrayWrite(k:K, v:V):V {
+		this.set(k, v);
+		return v;
+	}
+
+	@:to static inline function toStringMap<K:String, V>(t:IMap<K, V>):StringMap<V> {
+		return new StringMap<V>();
+	}
+
+	@:to static inline function toIntMap<K:Int, V>(t:IMap<K, V>):IntMap<V> {
+		return new IntMap<V>();
+	}
+
+    @:to static inline function toInt64Map<K:Int64, V>(t:IMap<K, V>):Int64Map<V> {
+		return new Int64Map<V>();
+	}
+
+	@:to static inline function toEnumValueMapMap<K:EnumValue, V>(t:IMap<K, V>):EnumValueMap<K, V> {
+		return new EnumValueMap<K, V>();
+	}
+
+	@:to static inline function toObjectMap<K:{}, V>(t:IMap<K, V>):ObjectMap<K, V> {
+		return new ObjectMap<K, V>();
+	}
+
+	@:from static inline function fromStringMap<V>(map:StringMap<V>):Map<String, V> {
+		return cast map;
+	}
+
+	@:from static inline function fromIntMap<V>(map:IntMap<V>):Map<Int, V> {
+		return cast map;
+	}
+
+	@:from static inline function fromInt64Map<V>(map:Int64Map<V>):Map<Int64, V> {
+		return cast map;
+	}
+
+	@:from static inline function fromObjectMap<K:{}, V>(map:ObjectMap<K, V>):Map<K, V> {
+		return cast map;
+	}
+}

+ 10 - 1
std/cpp/_std/haxe/ds/ObjectMap.hx

@@ -35,6 +35,7 @@ package haxe.ds;
   inline void set(Dynamic key, float value) { __object_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(Dynamic key, float value) { __object_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(Dynamic key, double value) { __object_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(Dynamic key, double value) { __object_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(Dynamic key, ::String value) { __object_hash_set_string(HX_MAP_THIS,key,value); }
   inline void set(Dynamic key, ::String value) { __object_hash_set_string(HX_MAP_THIS,key,value); }
+  inline void set(Dynamic key, cpp::Int64 value) { __object_hash_set_int64(HX_MAP_THIS,key,value); }
 
 
 
 
   template<typename V, typename H>
   template<typename V, typename H>
@@ -48,7 +49,7 @@ package haxe.ds;
   inline int get_int(Dynamic key) { return __object_hash_get_int(h,key); }
   inline int get_int(Dynamic key) { return __object_hash_get_int(h,key); }
   inline Float get_float(Dynamic key) { return __object_hash_get_float(h,key); }
   inline Float get_float(Dynamic key) { return __object_hash_get_float(h,key); }
   inline String get_string(Dynamic key) { return __object_hash_get_string(h,key); }
   inline String get_string(Dynamic key) { return __object_hash_get_string(h,key); }
-
+  inline cpp::Int64 get_int64(Dynamic key) { return __object_hash_get_int64(h,key); }
 ")
 ")
 @:coreApi
 @:coreApi
 class ObjectMap<K:{}, V> implements haxe.Constraints.IMap<K, V> {
 class ObjectMap<K:{}, V> implements haxe.Constraints.IMap<K, V> {
@@ -123,6 +124,10 @@ class ObjectMap<K:{}, V> implements haxe.Constraints.IMap<K, V> {
 		untyped __object_hash_set_float(__cpp__("HX_MAP_THIS"), key, val);
 		untyped __object_hash_set_float(__cpp__("HX_MAP_THIS"), key, val);
 	}
 	}
 
 
+	private function setInt64(key:Dynamic, val:haxe.Int64):Void {
+		untyped __object_hash_set_int64(__cpp__("HX_MAP_THIS"), key, val);
+	}
+
 	private function getString(key:Dynamic):String {
 	private function getString(key:Dynamic):String {
 		return untyped __object_hash_get_string(h, key);
 		return untyped __object_hash_get_string(h, key);
 	}
 	}
@@ -138,5 +143,9 @@ class ObjectMap<K:{}, V> implements haxe.Constraints.IMap<K, V> {
 	private function getFloat(key:Dynamic):Float {
 	private function getFloat(key:Dynamic):Float {
 		return untyped __object_hash_get_float(h, key);
 		return untyped __object_hash_get_float(h, key);
 	}
 	}
+
+	private function getInt64(key:Dynamic):haxe.Int64 {
+		return untyped __object_hash_get_int64(h, key);
+	}
 	#end
 	#end
 }
 }

+ 10 - 0
std/cpp/_std/haxe/ds/StringMap.hx

@@ -35,6 +35,7 @@ package haxe.ds;
   inline void set(String key, float value) { __string_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(String key, float value) { __string_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(String key, double value) { __string_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(String key, double value) { __string_hash_set_float(HX_MAP_THIS,key,value); }
   inline void set(String key, ::String value) { __string_hash_set_string(HX_MAP_THIS,key,value); }
   inline void set(String key, ::String value) { __string_hash_set_string(HX_MAP_THIS,key,value); }
+  inline void set(String key, cpp::Int64 value) { __string_hash_set_int64(HX_MAP_THIS,key,value); }
 
 
   template<typename V, typename H>
   template<typename V, typename H>
   inline void set(String key, const ::cpp::Struct<V,H> &value) {__string_hash_set(HX_MAP_THIS,key,value); }
   inline void set(String key, const ::cpp::Struct<V,H> &value) {__string_hash_set(HX_MAP_THIS,key,value); }
@@ -50,6 +51,7 @@ package haxe.ds;
   inline int get_int(String key) { return __string_hash_get_int(h,key); }
   inline int get_int(String key) { return __string_hash_get_int(h,key); }
   inline Float get_float(String key) { return __string_hash_get_float(h,key); }
   inline Float get_float(String key) { return __string_hash_get_float(h,key); }
   inline String get_string(String key) { return __string_hash_get_string(h,key); }
   inline String get_string(String key) { return __string_hash_get_string(h,key); }
+  inline cpp::Int64 get_int64(String key) { return __string_hash_get_int64(h,key); }
 ")
 ")
 @:coreApi class StringMap<T> implements haxe.Constraints.IMap<String, T> {
 @:coreApi class StringMap<T> implements haxe.Constraints.IMap<String, T> {
 	@:ifFeature("haxe.ds.StringMap.*")
 	@:ifFeature("haxe.ds.StringMap.*")
@@ -123,6 +125,10 @@ package haxe.ds;
 		untyped __string_hash_set_float(__cpp__("HX_MAP_THIS"), key, val);
 		untyped __string_hash_set_float(__cpp__("HX_MAP_THIS"), key, val);
 	}
 	}
 
 
+	private function setInt64(key:String, val:haxe.Int64):Void {
+		untyped __string_hash_set_int64(__cpp__("HX_MAP_THIS"), key, val);
+	}
+
 	private function getString(key:String):String {
 	private function getString(key:String):String {
 		return untyped __string_hash_get_string(h, key);
 		return untyped __string_hash_get_string(h, key);
 	}
 	}
@@ -138,5 +144,9 @@ package haxe.ds;
 	private function getFloat(key:String):Float {
 	private function getFloat(key:String):Float {
 		return untyped __string_hash_get_float(h, key);
 		return untyped __string_hash_get_float(h, key);
 	}
 	}
+
+	private function getInt64(key:String):haxe.Int64 {
+		return untyped __string_hash_get_int64(h, key);
+	}
 	#end
 	#end
 }
 }

+ 1 - 0
std/cpp/_std/haxe/ds/WeakMap.hx

@@ -35,6 +35,7 @@ package haxe.ds;
   inline void set(Dynamic key, float value) { __object_hash_set_float(HX_MAP_THIS,key,value,true); }
   inline void set(Dynamic key, float value) { __object_hash_set_float(HX_MAP_THIS,key,value,true); }
   inline void set(Dynamic key, double value) { __object_hash_set_float(HX_MAP_THIS,key,value,true); }
   inline void set(Dynamic key, double value) { __object_hash_set_float(HX_MAP_THIS,key,value,true); }
   inline void set(Dynamic key, ::String value) { __object_hash_set_string(HX_MAP_THIS,key,value,true); }
   inline void set(Dynamic key, ::String value) { __object_hash_set_string(HX_MAP_THIS,key,value,true); }
+  inline void set(Dynamic key, cpp::Int64 value) { __object_hash_set_int64(HX_MAP_THIS,key,value,true); }
 
 
   template<typename V, typename H>
   template<typename V, typename H>
   inline void set(Dynamic key, const ::cpp::Struct<V,H> &value) {__object_hash_set(HX_MAP_THIS,key,value,true); }
   inline void set(Dynamic key, const ::cpp::Struct<V,H> &value) {__object_hash_set(HX_MAP_THIS,key,value,true); }

+ 1 - 0
std/cpp/cppia/HostClasses.hx

@@ -55,6 +55,7 @@ class HostClasses {
 		"cpp.vm.WeakRef",
 		"cpp.vm.WeakRef",
 		"cpp.Object",
 		"cpp.Object",
 		"cpp.Int64",
 		"cpp.Int64",
+		"cpp.Int64Map",
 		"cpp.Finalizable",
 		"cpp.Finalizable",
 		"Std",
 		"Std",
 		"StringBuf",
 		"StringBuf",