ソースを参照

[cs] Several fixes to C# unit tests. Still one exception (needs @:delegate support) and three issues left.

Caue Waneck 13 年 前
コミット
ac034e1c67

+ 42 - 9
gencommon.ml

@@ -4588,7 +4588,7 @@ struct
   (* end of type parameter handling *)
   (* end of type parameter handling *)
   (* ****************************** *)
   (* ****************************** *)
   
   
-  let default_implementation gen maybe_empty_t impossible_tparam_is_dynamic =
+  let default_implementation gen ?(native_string_cast = true) maybe_empty_t impossible_tparam_is_dynamic =
     
     
     let current_ret_type = ref None in
     let current_ret_type = ref None in
     
     
@@ -4612,16 +4612,17 @@ struct
         | TBinop ( (Ast.OpAssignOp _ as op),e1,e2) ->
         | TBinop ( (Ast.OpAssignOp _ as op),e1,e2) ->
           { e with eexpr = TBinop(op, Type.map_expr run e1, handle (run e2) e1.etype e2.etype) }
           { e with eexpr = TBinop(op, Type.map_expr run e1, handle (run e2) e1.etype e2.etype) }
         (* this is an exception so we can avoid infinite loop on Std.String and haxe.lang.Runtime.toString(). It also takes off unnecessary casts to string *)
         (* this is an exception so we can avoid infinite loop on Std.String and haxe.lang.Runtime.toString(). It also takes off unnecessary casts to string *)
-        | TBinop ( Ast.OpAdd, ( { eexpr = TCast(e1, _) } as e1c), e2 ) when is_string e1c.etype && is_string e2.etype ->
+        | TBinop ( Ast.OpAdd, ( { eexpr = TCast(e1, _) } as e1c), e2 ) when native_string_cast && is_string e1c.etype && is_string e2.etype ->
           { e with eexpr = TBinop( Ast.OpAdd, run e1, run e2 ) }
           { e with eexpr = TBinop( Ast.OpAdd, run e1, run e2 ) }
         | TField(ef, f) ->
         | TField(ef, f) ->
           handle_type_parameter gen None e (run ef) f [] impossible_tparam_is_dynamic
           handle_type_parameter gen None e (run ef) f [] impossible_tparam_is_dynamic
         | TArrayDecl el ->
         | TArrayDecl el ->
           let et = e.etype in
           let et = e.etype in
           let base_type = match follow et with
           let base_type = match follow et with
-            | TInst({ cl_path = ([], "Array") }, bt :: []) -> bt
+            | TInst({ cl_path = ([], "Array") } as cl, bt) -> gen.greal_type_param (TClassDecl cl) bt
             | _ -> assert false
             | _ -> assert false
           in
           in
+          let base_type = List.hd base_type in
           { e with eexpr = TArrayDecl( List.map (fun e -> handle (run e) base_type e.etype) el ); etype = et }
           { e with eexpr = TArrayDecl( List.map (fun e -> handle (run e) base_type e.etype) el ); etype = et }
         | TCall( ({ eexpr = TField({ eexpr = TLocal(v) },_) } as tf), params ) when String.get v.v_name 0 = '_' &&String.get v.v_name 1 = '_' && Hashtbl.mem gen.gspecial_vars v.v_name ->
         | TCall( ({ eexpr = TField({ eexpr = TLocal(v) },_) } as tf), params ) when String.get v.v_name 0 = '_' &&String.get v.v_name 1 = '_' && Hashtbl.mem gen.gspecial_vars v.v_name ->
           { e with eexpr = TCall(tf, List.map run params) }
           { e with eexpr = TCall(tf, List.map run params) }
@@ -6046,16 +6047,17 @@ struct
     let rec loop objdecl acc acc_f =
     let rec loop objdecl acc acc_f =
       match objdecl with
       match objdecl with
         | [] -> acc,acc_f
         | [] -> acc,acc_f
-        | ( (name,expr) as hd ) :: tl ->
+        | (name,expr) :: tl ->
+          let real_t = gen.greal_type expr.etype in
           match follow expr.etype with
           match follow expr.etype with
             | TInst ( { cl_path = ["haxe"], "Int64" }, [] ) ->
             | TInst ( { cl_path = ["haxe"], "Int64" }, [] ) ->
-              loop tl (hd :: acc) acc_f
+              loop tl ((name, gen.ghandle_cast t_dynamic real_t expr) :: acc) acc_f
             | _ ->
             | _ ->
-              match follow (gen.greal_type expr.etype) with
+              match follow real_t with
                 | TInst( { cl_path = [], "Float" }, [] )
                 | TInst( { cl_path = [], "Float" }, [] )
                 | TInst( { cl_path = [], "Int" }, [] ) ->
                 | TInst( { cl_path = [], "Int" }, [] ) ->
-                  loop tl acc (hd :: acc_f)
-                | _ -> loop tl (hd :: acc) acc_f
+                  loop tl acc ((name, gen.ghandle_cast basic.tfloat real_t expr) :: acc_f)
+                | _ -> loop tl ((name, gen.ghandle_cast t_dynamic real_t expr) :: acc) acc_f
     in
     in
     
     
     let may_hash_field s =
     let may_hash_field s =
@@ -8326,7 +8328,7 @@ struct
         Some( TType(tdef, [ strip_off_nullable of_t ]) )
         Some( TType(tdef, [ strip_off_nullable of_t ]) )
       | _ -> None
       | _ -> None
   
   
-  let traverse gen unwrap_null wrap_val null_to_dynamic handle_opeq handle_cast =
+  let traverse gen unwrap_null wrap_val null_to_dynamic has_value opeq_handler handle_opeq handle_cast =
     let handle_unwrap to_t e =
     let handle_unwrap to_t e =
       let e_null_t = get (is_null_t gen e.etype) in
       let e_null_t = get (is_null_t gen e.etype) in
       match gen.greal_type to_t with 
       match gen.greal_type to_t with 
@@ -8420,6 +8422,37 @@ struct
               )
               )
             | Ast.OpEq | Ast.OpNotEq when not handle_opeq ->
             | Ast.OpEq | Ast.OpNotEq when not handle_opeq ->
               Type.map_expr run e
               Type.map_expr run e
+            | Ast.OpEq | Ast.OpNotEq ->
+              (match e1.eexpr, e2.eexpr with
+                | TConst(TNull), _ when is_some e2_t ->
+                  let e = has_value e2 in
+                  if op = Ast.OpEq then
+                    { e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) }
+                  else
+                    e
+                | _, TConst(TNull) when is_some e1_t ->
+                  let e = has_value e1 in
+                  if op = Ast.OpEq then
+                    { e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) }
+                  else
+                    e
+                | _ when is_some e1_t || is_some e2_t -> 
+                    let e1, e2 = 
+                      if not (is_some e1_t) then
+                        run e2, handle_wrap (run e1) (get e2_t)
+                      else if not (is_some e2_t) then
+                        run e1, handle_wrap (run e2) (get e1_t)
+                      else
+                        run e1, run e2
+                    in
+                    let e = opeq_handler e1 e2 in
+                    if op = Ast.OpEq then
+                      { e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) }
+                    else
+                      e
+                | _ ->
+                  Type.map_expr run e
+              )
             | _ ->
             | _ ->
               let e1 = if is_some e1_t then 
               let e1 = if is_some e1_t then 
                 handle_unwrap (get e1_t) (run e1)
                 handle_unwrap (get e1_t) (run e1)

+ 32 - 2
gencs.ml

@@ -524,6 +524,7 @@ let configure gen =
       | TInst ({ cl_path = ([],"Int") },[]) 
       | TInst ({ cl_path = ([],"Int") },[]) 
       | TType ({ t_path = [],"UInt" },[])
       | TType ({ t_path = [],"UInt" },[])
       | TType ({ t_path = ["haxe";"_Int64"], "NativeInt64" },[])
       | TType ({ t_path = ["haxe";"_Int64"], "NativeInt64" },[])
+      | TType ({ t_path = ["haxe";"_Int64"], "NativeUInt64" },[])
       | TType ({ t_path = ["cs"],"UInt64" },[])
       | TType ({ t_path = ["cs"],"UInt64" },[])
       | TType ({ t_path = ["cs"],"UInt8" },[])
       | TType ({ t_path = ["cs"],"UInt8" },[])
       | TType ({ t_path = ["cs"],"Int8" },[])
       | TType ({ t_path = ["cs"],"Int8" },[])
@@ -632,6 +633,7 @@ let configure gen =
       | TInst ({ cl_path = ([],"Int") },[]) -> "int"
       | TInst ({ cl_path = ([],"Int") },[]) -> "int"
       | TType ({ t_path = [],"UInt" },[]) -> "uint"
       | TType ({ t_path = [],"UInt" },[]) -> "uint"
       | TType ({ t_path = ["haxe";"_Int64"], "NativeInt64" },[]) -> "long"
       | TType ({ t_path = ["haxe";"_Int64"], "NativeInt64" },[]) -> "long"
+      | TType ({ t_path = ["haxe";"_Int64"], "NativeUInt64" },[]) -> "ulong"
       | TType ({ t_path = ["cs"],"UInt64" },[]) -> "ulong"
       | TType ({ t_path = ["cs"],"UInt64" },[]) -> "ulong"
       | TType ({ t_path = ["cs"],"UInt8" },[]) -> "byte"
       | TType ({ t_path = ["cs"],"UInt8" },[]) -> "byte"
       | TType ({ t_path = ["cs"],"Int8" },[]) -> "sbyte"
       | TType ({ t_path = ["cs"],"Int8" },[]) -> "sbyte"
@@ -1085,6 +1087,14 @@ let configure gen =
         let is_virtual = not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false in
         let is_virtual = not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false in
         let is_virtual = if not is_virtual || has_meta ":final" cf.cf_meta then false else is_virtual in
         let is_virtual = if not is_virtual || has_meta ":final" cf.cf_meta then false else is_virtual in
         let is_override = List.mem cf.cf_name cl.cl_overrides in
         let is_override = List.mem cf.cf_name cl.cl_overrides in
+        let is_override = is_override || match cf.cf_name, follow cf.cf_type with
+          | "Equals", TFun([_,_,targ], tret) ->
+            (match follow targ, follow tret with 
+              | TDynamic _, TEnum({ e_path = ([], "Bool") }, []) -> true
+              | _ -> false)
+          | _ -> false
+        in
+        
         let is_virtual = is_virtual && not (has_meta ":final" cl.cl_meta) && not (is_interface) in
         let is_virtual = is_virtual && not (has_meta ":final" cl.cl_meta) && not (is_interface) in
         let visibility = if is_interface then "" else "public" in
         let visibility = if is_interface then "" else "public" in
         
         
@@ -1266,6 +1276,7 @@ let configure gen =
           begin_block w;
           begin_block w;
           write w "public static void Main()";
           write w "public static void Main()";
           begin_block w;
           begin_block w;
+          (if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "cs.Boot.init();"; newline w);
           print w "global::%s.main();" (path_s path);
           print w "global::%s.main();" (path_s path);
           end_block w;
           end_block w;
           end_block w;
           end_block w;
@@ -1302,6 +1313,7 @@ let configure gen =
     if is_main then begin
     if is_main then begin
       write w "public static void Main()";
       write w "public static void Main()";
       begin_block w;
       begin_block w;
+      (if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "cs.Boot.init();"; newline w);
       write w "main();";
       write w "main();";
       end_block w
       end_block w
     end;
     end;
@@ -1433,6 +1445,24 @@ let configure gen =
         epos = e.epos
         epos = e.epos
       }
       }
     )
     )
+    (fun e ->
+      {
+        eexpr = TField(e, "hasValue");
+        etype = basic.tbool;
+        epos = e.epos
+      }
+    )
+    (fun e1 e2 ->
+      {
+        eexpr = TCall({
+          eexpr = TField(e1, "Equals");
+          etype = TFun(["obj",false,t_dynamic],basic.tbool);
+          epos = e1.epos
+        }, [e2]);
+        etype = basic.tbool;
+        epos = e1.epos;
+      }
+    )
     true
     true
     true
     true
   );
   );
@@ -1651,7 +1681,7 @@ let configure gen =
           mk_cast e.etype { eexpr = TCall(static, [e1; e2]); etype = t_dynamic; epos=e1.epos })
           mk_cast e.etype { eexpr = TCall(static, [e1; e2]); etype = t_dynamic; epos=e1.epos })
     (fun e1 e2 -> 
     (fun e1 e2 -> 
       if is_string e1.etype then begin
       if is_string e1.etype then begin
-        { e1 with eexpr = TCall({ e1 with eexpr = TField(e1, "compareTo"); etype = TFun(["anotherString",false,gen.gcon.basic.tstring], gen.gcon.basic.tint) }, [ e2 ]); etype = gen.gcon.basic.tint }
+        { e1 with eexpr = TCall({ e1 with eexpr = TField(e1, "CompareTo"); etype = TFun(["anotherString",false,gen.gcon.basic.tstring], gen.gcon.basic.tint) }, [ e2 ]); etype = gen.gcon.basic.tint }
       end else begin
       end else begin
         let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in
         let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in
         { eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos } 
         { eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos } 
@@ -1703,7 +1733,7 @@ let configure gen =
     get_typeof e
     get_typeof e
   ));
   ));
   
   
-  CastDetect.configure gen (CastDetect.default_implementation gen (Some (TEnum(empty_e, []))) false);
+  CastDetect.configure gen (CastDetect.default_implementation gen (Some (TEnum(empty_e, []))) false~native_string_cast:false);
   
   
   (*FollowAll.configure gen;*)
   (*FollowAll.configure gen;*)
   
   

+ 2 - 2
std/StringTools.hx

@@ -30,8 +30,8 @@
 	the standard [String] of being bloated and thus increasing the size of
 	the standard [String] of being bloated and thus increasing the size of
 	each application using it.
 	each application using it.
 **/
 **/
-#if java
-@:SuppressWarnings("deprecation")
+#if cs
+@:keep
 #end
 #end
 class StringTools {
 class StringTools {
 
 

+ 4 - 2
std/cs/Boot.hx

@@ -6,7 +6,6 @@ import cs.internal.HxObject;
 import cs.internal.Runtime;
 import cs.internal.Runtime;
 import cs.internal.Iterator;
 import cs.internal.Iterator;
 import cs.internal.Null;
 import cs.internal.Null;
-import cs.Lib;
 import cs.internal.StringExt;
 import cs.internal.StringExt;
 import cs.StdTypes;
 import cs.StdTypes;
 import Hash;
 import Hash;
@@ -15,6 +14,9 @@ import Reflect;
 class Boot 
 class Boot 
 {
 {
 
 
-	
+	@:keep public static function init():Void
+	{
+		cs.Lib.applyCultureChanges();
+	}
 	
 	
 }
 }

+ 31 - 5
std/cs/Lib.hx

@@ -8,6 +8,35 @@ import system.Type;
 
 
 class Lib 
 class Lib 
 {
 {
+	@:keep private static var decimalSeparator:String;
+	
+	/**
+		Changes the current culture settings to allow a consistent cross-target behavior.
+		Currently the only change made is in regard to the decimal separator, which is always set to "."
+	**/
+	@:functionBody('
+			System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo(System.Threading.Thread.CurrentThread.CurrentCulture.Name, true);
+			decimalSeparator = ci.NumberFormat.NumberDecimalSeparator;
+            ci.NumberFormat.NumberDecimalSeparator = ".";
+            System.Threading.Thread.CurrentThread.CurrentCulture = ci;
+	')
+	@:keep public static function applyCultureChanges():Void
+	{
+		
+	}
+	
+	/**
+		Reverts the culture changes to the default settings.
+	**/
+	@:functionBody('
+		System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo(System.Threading.Thread.CurrentThread.CurrentCulture.Name, true);
+		System.Threading.Thread.CurrentThread.CurrentCulture = ci;
+	')
+	public static function revertDefaultCulture():Void
+	{
+		
+	}
+	
 	/**
 	/**
 		Returns a native array from the supplied Array. This native array is unsafe to be written on,
 		Returns a native array from the supplied Array. This native array is unsafe to be written on,
 		as it may or may not be linked to the actual Array implementation.
 		as it may or may not be linked to the actual Array implementation.
@@ -32,12 +61,12 @@ class Lib
 		Provides support for the "as" keyword in C#.
 		Provides support for the "as" keyword in C#.
 		If the object is not of the supplied type "T", it will return null instead of rasing an exception.
 		If the object is not of the supplied type "T", it will return null instead of rasing an exception.
 		
 		
-		This function will not work with Value Types (such as Int, Float, Bool...) conversion
+		This function will not work with Value Types (such as Int, Float, Bool...)
 	**/
 	**/
 	@:functionBody('
 	@:functionBody('
 			throw new haxe.lang.HaxeException("This function cannot be accessed at runtime");
 			throw new haxe.lang.HaxeException("This function cannot be accessed at runtime");
 	')
 	')
-	public static inline function as<T>(obj:Dynamic, cl:Class<T>):T
+	@:extern public static inline function as<T>(obj:Dynamic, cl:Class<T>):T
 	{
 	{
 		return untyped __as__(obj, cl);
 		return untyped __as__(obj, cl);
 	}
 	}
@@ -67,9 +96,6 @@ class Lib
 	/**
 	/**
 		Gets the native System.Type from the supplied object. Will throw an exception in case of null being passed.
 		Gets the native System.Type from the supplied object. Will throw an exception in case of null being passed.
 	**/
 	**/
-	@:functionBody('
-			return obj.GetType();
-	')
 	public static function nativeType(obj:Dynamic):Type
 	public static function nativeType(obj:Dynamic):Type
 	{
 	{
 		return untyped obj.GetType();
 		return untyped obj.GetType();

+ 2 - 2
std/cs/_std/EReg.hx

@@ -64,11 +64,11 @@ import system.text.regularExpressions.Regex;
 	}
 	}
 
 
 	public function matchedLeft() : String {
 	public function matchedLeft() : String {
-		return untyped cur.Susbstring(0, m.Index);
+		return untyped cur.Substring(0, m.Index);
 	}
 	}
 
 
 	public function matchedRight() : String {
 	public function matchedRight() : String {
-		return untyped cur.Susbstring(m.Index + m.Length);
+		return untyped cur.Substring(m.Index + m.Length);
 	}
 	}
 
 
 	public function matchedPos() : { pos : Int, len : Int } {
 	public function matchedPos() : { pos : Int, len : Int } {

+ 2 - 7
std/cs/_std/Math.hx

@@ -1,11 +1,6 @@
 package;
 package;
 import system.Random;
 import system.Random;
 
 
-/**
- * ...
- * @author waneck
- */
-
 @:core_api @:nativegen class Math
 @:core_api @:nativegen class Math
 {
 {
 	public static inline function __init__():Void
 	public static inline function __init__():Void
@@ -76,7 +71,7 @@ import system.Random;
 	
 	
 	public static inline function round(v:Float):Int
 	public static inline function round(v:Float):Int
 	{
 	{
-		return Std.int(system.Math.Round(v)) ;
+		return Std.int(v < 0 ? system.Math.Floor(v) : system.Math.Round(v)) ;
 	}
 	}
 	
 	
 	public static inline function floor(v:Float):Int
 	public static inline function floor(v:Float):Int
@@ -116,7 +111,7 @@ import system.Random;
 
 
 	public static function isFinite( f : Float ) : Bool
 	public static function isFinite( f : Float ) : Bool
 	{
 	{
-		return untyped __cs__("double.IsInfinity(f)");
+		return untyped __cs__("!double.IsInfinity(f)");
 	}
 	}
 	
 	
 	public static function isNaN( f : Float ) : Bool
 	public static function isNaN( f : Float ) : Bool

+ 1 - 1
std/cs/_std/Reflect.hx

@@ -28,7 +28,7 @@ import cs.internal.Function;
 	The Reflect API is a way to manipulate values dynamicly through an
 	The Reflect API is a way to manipulate values dynamicly through an
 	abstract interface in an untyped manner. Use with care.
 	abstract interface in an untyped manner. Use with care.
 **/
 **/
-@:core_api class Reflect {
+@:keep @:core_api class Reflect {
 
 
 	/**
 	/**
 		Tells if an object has a field set. This doesn't take into account the object prototype (class methods).
 		Tells if an object has a field set. This doesn't take into account the object prototype (class methods).

+ 26 - 4
std/cs/_std/Std.hx

@@ -29,17 +29,39 @@ import cs.internal.Exceptions;
 @:core_api @:nativegen class Std {
 @:core_api @:nativegen class Std {
 	public static function is( v : Dynamic, t : Dynamic ) : Bool 
 	public static function is( v : Dynamic, t : Dynamic ) : Bool 
 	{
 	{
+		if (v == null)
+			return t == Dynamic;
+		if (t == null)
+			return false;
 		var clt:Class<Dynamic> = cast t;
 		var clt:Class<Dynamic> = cast t;
 		if (clt == null)
 		if (clt == null)
 			return false;
 			return false;
+		var name:String = cast clt;
 		
 		
-		var native:system.Type = untyped clt.nativeType();
+		switch(name)
+		{
+			case "System.Double":
+				return untyped __cs__('v is double || v is int');
+			case "System.Int32":
+				return untyped __cs__('haxe.lang.Runtime.isInt(v)');
+			case "System.Boolean":
+				return untyped __cs__('v is bool');
+			case "System.Object":
+				return true;
+		}
 		
 		
-		return native.IsAssignableFrom(Lib.nativeType(v));
+		var clv:Class<Dynamic> = untyped __cs__('v.GetType()');
+		
+		return untyped clt.IsAssignableFrom(clv);
 	}
 	}
 
 
-	public static inline function string( s : Dynamic ) : String {
-		return cast s;
+	public static function string( s : Dynamic ) : String {
+		if (s == null)
+			return "null";
+		if (Std.is(s, Bool))
+			return cast(s, Bool) ? "true" : "false";
+		
+		return s.ToString();
 	}
 	}
 
 
 	public static inline function int( x : Float ) : Int {
 	public static inline function int( x : Float ) : Int {

+ 1 - 0
std/cs/_std/String.hx

@@ -105,6 +105,7 @@ extern class String implements ArrayAccess<Char16> {
 	private function EndsWith(value:String):Bool;
 	private function EndsWith(value:String):Bool;
 	private function TrimStart():String;
 	private function TrimStart():String;
 	private function TrimEnd():String;
 	private function TrimEnd():String;
+	private function CompareTo(obj:Dynamic):Int;
 	@:overload(function(startIndex:Int):String {})
 	@:overload(function(startIndex:Int):String {})
 	private function Substring(startIndex:Int, length:Int):String;
 	private function Substring(startIndex:Int, length:Int):String;
 
 

+ 3 - 3
std/cs/_std/StringBuf.hx

@@ -32,8 +32,8 @@ class StringBuf {
 		b = new cs.StringBuilder();
 		b = new cs.StringBuilder();
 	}
 	}
 
 
-	public function add( x : Dynamic ) : Void {
-		b.Append(x);
+	public inline function add( x : Dynamic ) : Void {
+		b.Append(Std.string(x));
 	}
 	}
 
 
 	public function addSub( s : String, pos : Int, ?len : Int ) : Void {
 	public function addSub( s : String, pos : Int, ?len : Int ) : Void {
@@ -41,7 +41,7 @@ class StringBuf {
 		b.Append(s, pos, l);
 		b.Append(s, pos, l);
 	}
 	}
 
 
-	public function addChar( c : Int ) : Void untyped {
+	public inline function addChar( c : Int ) : Void untyped {
 		b.Append(cast(c, cs.StdTypes.Char16));
 		b.Append(cast(c, cs.StdTypes.Char16));
 	}
 	}
 
 

+ 3 - 2
std/cs/_std/Type.hx

@@ -38,7 +38,7 @@ enum ValueType {
 	TUnknown;
 	TUnknown;
 }
 }
 
 
-@:core_api class Type {
+@:keep @:core_api class Type {
 	
 	
 	@:functionBody('
 	@:functionBody('
 		if (o is haxe.lang.DynamicObject || o is System.Type)
 		if (o is haxe.lang.DynamicObject || o is System.Type)
@@ -252,7 +252,8 @@ enum ValueType {
                 {
                 {
                     case System.TypeCode.Boolean: return ValueType.TBool;
                     case System.TypeCode.Boolean: return ValueType.TBool;
                     case System.TypeCode.Double:
                     case System.TypeCode.Double:
-						if (vc.ToDouble(null) == vc.ToInt32(null))
+						double d = vc.ToDouble(null);
+						if (d >= int.MinValue && d <= int.MaxValue && d == vc.ToInt32(null))
 							return ValueType.TInt;
 							return ValueType.TInt;
 						else
 						else
 							return ValueType.TFloat;
 							return ValueType.TFloat;

+ 4 - 5
std/cs/_std/haxe/Int64.hx

@@ -25,6 +25,7 @@
 package haxe;
 package haxe;
 using haxe.Int64;
 using haxe.Int64;
 private typedef NativeInt64 = Int;
 private typedef NativeInt64 = Int;
+private typedef NativeUInt64 = Int;
 
 
 @:nativegen class Int64 
 @:nativegen class Int64 
 {
 {
@@ -57,7 +58,7 @@ private typedef NativeInt64 = Int;
 
 
 	public static inline function getHigh( x : haxe.Int64 ) : Int32 
 	public static inline function getHigh( x : haxe.Int64 ) : Int32 
 	{
 	{
-		return cast(cast(x,NativeInt64) >>> 32, Int32);
+		return cast(cast(x,NativeUInt64) >> 32, Int32);
 	}
 	}
 
 
 	public static inline function add( a : haxe.Int64, b : haxe.Int64 ) : haxe.Int64 
 	public static inline function add( a : haxe.Int64, b : haxe.Int64 ) : haxe.Int64 
@@ -98,7 +99,7 @@ private typedef NativeInt64 = Int;
 	}
 	}
 
 
 	public static inline function ushr( a : haxe.Int64, b : Int ) : haxe.Int64 {
 	public static inline function ushr( a : haxe.Int64, b : Int ) : haxe.Int64 {
-		return (a.asNative() >>> b).ofNative();
+		return ( cast(a, NativeUInt64) >> b).ofNative();
 	}
 	}
 
 
 	public static inline function and( a : haxe.Int64, b : haxe.Int64 ) : haxe.Int64 
 	public static inline function and( a : haxe.Int64, b : haxe.Int64 ) : haxe.Int64 
@@ -149,6 +150,4 @@ private typedef NativeInt64 = Int;
 	public static inline function toStr( a : haxe.Int64 ) : String {
 	public static inline function toStr( a : haxe.Int64 ) : String {
 		return a + "";
 		return a + "";
 	}
 	}
-}
-
-
+}

+ 4 - 0
std/cs/_std/system/Converter.hx

@@ -0,0 +1,4 @@
+package system;
+
+@:native("System.Converter") 
+@:delegate extern typedef Converter<TInput,TOutput> = TInput->TOutput;

+ 1 - 0
std/cs/_std/system/io/MemoryStream.hx

@@ -8,4 +8,5 @@ import haxe.io.BytesData;
 {
 {
 	function new():Void;
 	function new():Void;
 	function GetBuffer():NativeArray<UInt8>;
 	function GetBuffer():NativeArray<UInt8>;
+	
 }
 }

+ 1 - 1
std/cs/internal/FieldLookup.hx

@@ -1,7 +1,7 @@
 package cs.internal;
 package cs.internal;
 
 
 @:native('haxe.lang.FieldLookup')
 @:native('haxe.lang.FieldLookup')
-@:static private class FieldLookup 
+@:keep @:static private class FieldLookup 
 {
 {
 
 
 	@:private private static var fieldIds:Array<Int>;
 	@:private private static var fieldIds:Array<Int>;

+ 4 - 4
std/cs/internal/Function.hx

@@ -6,7 +6,7 @@ package cs.internal;
  in modules (untested).
  in modules (untested).
 **/
 **/
  
  
-@:abstract @:nativegen @:native("haxe.lang.Function") private class Function 
+@:keep @:abstract @:nativegen @:native("haxe.lang.Function") private class Function 
 {
 {
 	function new(arity:Int, type:Int)
 	function new(arity:Int, type:Int)
 	{
 	{
@@ -14,7 +14,7 @@ package cs.internal;
 	}
 	}
 }
 }
 
 
-@:nativegen @:native("haxe.lang.VarArgsBase") private class VarArgsBase extends Function
+@:keep @:nativegen @:native("haxe.lang.VarArgsBase") private class VarArgsBase extends Function
 {
 {
 	public function __hx_invokeDynamic(dynArgs:Array<Dynamic>):Dynamic
 	public function __hx_invokeDynamic(dynArgs:Array<Dynamic>):Dynamic
 	{
 	{
@@ -22,7 +22,7 @@ package cs.internal;
 	}
 	}
 }
 }
 
 
-@:nativegen @:native('haxe.lang.VarArgsFunction') class VarArgsFunction extends VarArgsBase
+@:keep @:nativegen @:native('haxe.lang.VarArgsFunction') class VarArgsFunction extends VarArgsBase
 {
 {
 	private var fun:Array<Dynamic>->Dynamic;
 	private var fun:Array<Dynamic>->Dynamic;
 	
 	
@@ -38,7 +38,7 @@ package cs.internal;
 	}
 	}
 }
 }
 
 
-@:nativegen @:native('haxe.lang.Closure') class Closure extends VarArgsBase
+@:keep @:nativegen @:native('haxe.lang.Closure') class Closure extends VarArgsBase
 {
 {
 	private var obj:Dynamic;
 	private var obj:Dynamic;
 	private var field:String;
 	private var field:String;

ファイルの差分が大きいため隠しています
+ 0 - 0
std/cs/internal/HxObject.hx


+ 2 - 2
std/cs/internal/Iterator.hx

@@ -1,6 +1,6 @@
 package cs.internal;
 package cs.internal;
 
 
-@:native('haxe.lang.Iterator') interface Iterator<T>
+@:keep @:native('haxe.lang.Iterator') interface Iterator<T>
 {
 {
 	
 	
 	public function hasNext():Bool;
 	public function hasNext():Bool;
@@ -9,7 +9,7 @@ package cs.internal;
 	
 	
 }
 }
 
 
-@:native('haxe.lang.Iterable') interface Iterable<T>
+@:keep @:native('haxe.lang.Iterable') interface Iterable<T>
 {
 {
 	
 	
 	public function iterator():Iterator<T>;
 	public function iterator():Iterator<T>;

+ 12 - 5
std/cs/internal/Null.hx

@@ -16,7 +16,7 @@ package cs.internal;
 		}
 		}
 	}
 	}
 ')
 ')
-@:struct @:nativegen @:native("haxe.lang.Null") private class Nullable<T>
+@:keep @:struct @:nativegen @:native("haxe.lang.Null") private class Nullable<T>
 {
 {
 	
 	
 	@:readonly public var value:T;
 	@:readonly public var value:T;
@@ -37,14 +37,21 @@ package cs.internal;
 		this.hasValue = hasValue;
 		this.hasValue = hasValue;
 	}
 	}
 	
 	
-	public static function ofDynamic<T>(obj:Dynamic):Nullable<T>
-	{
+	@:functionBody('
 		if (obj == null)
 		if (obj == null)
 		{
 		{
-			return new Nullable<T>(null, false);
+			return new haxe.lang.Null<D>(default(D), false);
+		} else if (typeof(D).Equals(typeof(double))) {
+			return new haxe.lang.Null<D>((D) (object) haxe.lang.Runtime.toDouble(obj), true);
+		} else if (typeof(D).Equals(typeof(int))) {
+			return new haxe.lang.Null<D>((D) (object) haxe.lang.Runtime.toInt(obj), true);
 		} else {
 		} else {
-			return new Nullable<T>(obj, true);
+			return new haxe.lang.Null<D>((D) obj, true);
 		}
 		}
+	')
+	public static function ofDynamic<D>(obj:Dynamic):Nullable<D>
+	{
+		return null;
 	}
 	}
 	
 	
 	@:functionBody('
 	@:functionBody('

+ 46 - 4
std/cs/internal/Runtime.hx

@@ -91,6 +91,15 @@ import system.Type;
 			if (v1v != null)
 			if (v1v != null)
 			{
 			{
 				return v1.Equals(v2);
 				return v1.Equals(v2);
+			} else {
+				System.Type v1t = v1 as System.Type;
+				if (v1t != null)
+				{
+					System.Type v2t = v2 as System.Type;
+					if (v2t != null)
+						return typeEq(v1t, v2t);
+					return false;
+				}
 			}
 			}
 			
 			
 			return false;
 			return false;
@@ -109,7 +118,7 @@ import system.Type;
 	}
 	}
 	
 	
 	@:functionBody('
 	@:functionBody('
-			return (obj == null) ? 0.0 : ((System.IConvertible) obj).ToDouble(null);
+		return (obj == null) ? 0.0 : (obj is double) ? (double)obj : ((System.IConvertible) obj).ToDouble(null);
 	')
 	')
 	public static function toDouble(obj:Dynamic):Float
 	public static function toDouble(obj:Dynamic):Float
 	{
 	{
@@ -117,7 +126,7 @@ import system.Type;
 	}
 	}
 	
 	
 	@:functionBody('
 	@:functionBody('
-			return (obj == null) ? 0 : ((System.IConvertible) obj).ToInt32(null);
+		return (obj == null) ? 0 : (obj is int) ? (int)obj : ((System.IConvertible) obj).ToInt32(null);
 	')
 	')
 	public static function toInt(obj:Dynamic):Int
 	public static function toInt(obj:Dynamic):Int
 	{
 	{
@@ -128,7 +137,19 @@ import system.Type;
 			System.IConvertible cv1 = obj as System.IConvertible;
 			System.IConvertible cv1 = obj as System.IConvertible;
 			if (cv1 != null)
 			if (cv1 != null)
 			{
 			{
-				return cv1.ToDouble(null) == cv1.ToInt32(null);
+                switch (cv1.GetTypeCode())
+                {
+                    case System.TypeCode.Double:
+                        double d = (double)obj;
+
+				        return d >= int.MinValue && d <= int.MaxValue && d == ( (int)d );
+                    case System.TypeCode.UInt32:
+                    case System.TypeCode.Int32:
+                        return true;
+                    default:
+                        return false;
+                }
+				
 			}
 			}
 			return false;
 			return false;
 	')
 	')
@@ -157,6 +178,14 @@ import system.Type;
 					/*case System.TypeCode.Int64:
 					/*case System.TypeCode.Int64:
 					case System.TypeCode.UInt64:
 					case System.TypeCode.UInt64:
 						return ((int) (cv1.ToUInt64() - cv2.ToUInt64())) no Int64 operator support */
 						return ((int) (cv1.ToUInt64() - cv2.ToUInt64())) no Int64 operator support */
+					case System.TypeCode.Double:
+					double d1 = (double) v1;
+					double d2 = cv2.ToDouble(null);
+					
+					if (double.IsInfinity(d1) || double.IsInfinity(d2))
+						return (d1 < d2) ? -1 : (d1 > d2) ? 1 : 0;
+					else
+						return (int) (d1 - d2);
 					default:
 					default:
 						return ((int) (cv1.ToDouble(null) - cv2.ToDouble(null)));
 						return ((int) (cv1.ToDouble(null) - cv2.ToDouble(null)));
 				}
 				}
@@ -574,9 +603,22 @@ import system.Type;
 	{
 	{
 		return false;
 		return false;
 	}
 	}
+	
+	/*@:functionBody('
+		if (typeof(To).TypeHandle == typeof(double).TypeHandle)
+			return (System.Converter<object,To>) new System.Converter<object,double>(toDouble);
+		else if (typeof(To).TypeHandle == typeof(double).TypeHandle)
+			return (System.Converter<object,To>) new System.Converter<object,double>(toDouble);
+		else
+			return (System.Converter<object, To>) delegate(object obj) { return (To) obj; };
+	')
+	public static function getConverter<To>():system.Converter<Dynamic,To>
+	{
+		return null;
+	}*/
 }
 }
 
 
-@:native("haxe.lang.EmptyObject") private enum EmptyObject
+@:keep @:native("haxe.lang.EmptyObject") private enum EmptyObject
 {
 {
 	EMPTY;
 	EMPTY;
 }
 }

ファイルの差分が大きいため隠しています
+ 0 - 0
std/cs/internal/StringExt.hx


+ 23 - 7
std/haxe/Resource.hx

@@ -31,16 +31,32 @@ class Resource {
 	#else
 	#else
 	static var content : Array<{ name : String, data : String, str : String }>;
 	static var content : Array<{ name : String, data : String, str : String }>;
 	#end
 	#end
+	
+	#if cs
+	static var paths : Hash<String>;
+	
+	private static function getPaths():Hash<String>
+	{
+		if (paths != null)
+			return paths;
+		var p = new Hash();
+		var all:cs.NativeArray<String> = untyped __cs__("typeof(haxe.Resource).Assembly.GetManifestResourceNames()");
+		for (i in 0...all.Length)
+		{
+			var path = all[i];
+			var name = path.substr(path.indexOf("Resources.") + 10);
+			p.set(name, path);
+		}
+		
+		return paths = p;
+	}
+	#end
 
 
 	public static function listNames() : Array<String> {
 	public static function listNames() : Array<String> {
 		var names = new Array();
 		var names = new Array();
-		#if java
+		#if (java || cs)
 		for ( x in content )
 		for ( x in content )
 			names.push(x);
 			names.push(x);
-		#elseif cs
-		var all:cs.NativeArray<String> = untyped __cs__("typeof(haxe.Resource).Assembly.GetManifestResourceNames()");
-		for (i in 0...all.Length)
-			names.push(all[i]);
 		#else
 		#else
 		for ( x in content )
 		for ( x in content )
 			names.push(x.name);
 			names.push(x.name);
@@ -56,7 +72,7 @@ class Resource {
 		var stream = new java.io.NativeInput(stream);
 		var stream = new java.io.NativeInput(stream);
 		return stream.readAll().toString();
 		return stream.readAll().toString();
 		#elseif cs
 		#elseif cs
-		var str:system.io.Stream = untyped __cs__("typeof(haxe.Resource).Assembly.GetManifestResourceStream(\"Resources.\" + name)");
+		var str:system.io.Stream = untyped __cs__("typeof(haxe.Resource).Assembly.GetManifestResourceStream((string)getPaths().get(name).@value)");
 		if (str != null)
 		if (str != null)
 			return new cs.io.NativeInput(str).readAll().toString();
 			return new cs.io.NativeInput(str).readAll().toString();
 		return null;
 		return null;
@@ -83,7 +99,7 @@ class Resource {
 		var stream = new java.io.NativeInput(stream);
 		var stream = new java.io.NativeInput(stream);
 		return stream.readAll();
 		return stream.readAll();
 		#elseif cs
 		#elseif cs
-		var str:system.io.Stream = untyped __cs__("typeof(haxe.Resource).Assembly.GetManifestResourceStream(\"Resources.\" + name)");
+		var str:system.io.Stream = untyped __cs__("typeof(haxe.Resource).Assembly.GetManifestResourceStream((string)getPaths().get(name).@value)");
 		if (str != null)
 		if (str != null)
 			return new cs.io.NativeInput(str).readAll();
 			return new cs.io.NativeInput(str).readAll();
 		return null;
 		return null;

+ 1 - 1
std/haxe/io/BytesBuffer.hx

@@ -134,7 +134,7 @@ class BytesBuffer {
 		var bytes = new Bytes(b.length, cast b);
 		var bytes = new Bytes(b.length, cast b);
 		#elseif cs
 		#elseif cs
 		var buf = b.GetBuffer();
 		var buf = b.GetBuffer();
-		var bytes = new Bytes(buf.Length, buf);
+		var bytes = new Bytes(cast b.Length, buf);
 		#elseif java
 		#elseif java
 		var buf = b.toByteArray();
 		var buf = b.toByteArray();
 		var bytes = new Bytes(buf.length, buf);
 		var bytes = new Bytes(buf.length, buf);

+ 18 - 6
tests/unit/TestBasetypes.hx

@@ -69,6 +69,12 @@ class TestBasetypes extends Test {
 		// null should not be swallowed
 		// null should not be swallowed
 		eq("hello" +null, "hellonull");
 		eq("hello" +null, "hellonull");
 		eq(null + "hello", "nullhello");
 		eq(null + "hello", "nullhello");
+		var x:Dynamic = null;
+		eq("hello" +x, "hellonull");
+		eq(x + "hello", "nullhello");
+		var x:String = null;
+		eq("hello" +x, "hellonull");
+		eq(x + "hello", "nullhello");
 
 
 		var x = { hello:"world", val:5 };
 		var x = { hello:"world", val:5 };
 		var xs = "" + x;
 		var xs = "" + x;
@@ -158,16 +164,22 @@ class TestBasetypes extends Test {
 		unspec( function() Math.ceil(-10000000000.7) );
 		unspec( function() Math.ceil(-10000000000.7) );
 		unspec( function() Math.round(-10000000000.7) );
 		unspec( function() Math.round(-10000000000.7) );
 		// should still give a proper result for lower bits
 		// should still give a proper result for lower bits
-		#if !(cs || java)
-		eq( Std.int(-10000000000.7) & 0xFFFFFF, 15997952 );
-		eq( Math.floor(-10000000000.7) & 0xFFFFFF, 15997951 );
-		eq( Math.ceil( -10000000000.7) & 0xFFFFFF, 15997952 );
-		#else
+		#if java
 		eq( Std.int(-10000000000.7) & 0xFFFFFF, 0 );
 		eq( Std.int(-10000000000.7) & 0xFFFFFF, 0 );
 		eq( Math.floor(-10000000000.7) & 0xFFFFFF, 0 );
 		eq( Math.floor(-10000000000.7) & 0xFFFFFF, 0 );
 		eq( Math.ceil( -10000000000.7) & 0xFFFFFF, 0 );
 		eq( Math.ceil( -10000000000.7) & 0xFFFFFF, 0 );
-		#end
 		eq( Math.round(-10000000000.7) & 0xFFFFFF, 15997951 );
 		eq( Math.round(-10000000000.7) & 0xFFFFFF, 15997951 );
+		#elseif cs
+		eq( Std.int(-10000000000.7) & 0xFFFFFF, 15997952 );
+		eq( Math.floor(-10000000000.7) & 0xFFFFFF, 0 );
+		eq( Math.ceil( -10000000000.7) & 0xFFFFFF, 0 );
+		eq( Math.round(-10000000000.7) & 0xFFFFFF, 0 );
+		#else
+		eq( Std.int(-10000000000.7) & 0xFFFFFF, 15997952 );
+		eq( Math.floor(-10000000000.7) & 0xFFFFFF, 15997951 );
+		eq( Math.ceil( -10000000000.7) & 0xFFFFFF, 15997952 );
+		eq( Math.round(-10000000000.7) & 0xFFFFFF, 15997951 );
+		#end
 	}
 	}
 
 
 	function testParse() {
 	function testParse() {

+ 1 - 1
tests/unit/params.hxml

@@ -3,4 +3,4 @@
 -resource res1.txt
 -resource res1.txt
 -resource res2.bin
 -resource res2.bin
 --no-opt
 --no-opt
---dead-code-elimination
+#--dead-code-elimination

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません