瀏覽代碼

[java/cs] Type.enumEq recursive behaviour and fixed generic type equality for C#

Caue Waneck 13 年之前
父節點
當前提交
17f84b3064

+ 25 - 3
gencs.ml

@@ -244,6 +244,7 @@ struct
         | _ -> false
     in
     
+    let is_cl t = match gen.greal_type t with | TInst ( { cl_path = (["System"], "Type") }, [] ) -> true | _ -> false in
     
     let rec run e =
       match e.eexpr with 
@@ -320,6 +321,15 @@ struct
             }, [ run e2 ])
           }
         
+        | TBinop ( (Ast.OpEq as op), e1, e2 )
+        | TBinop ( (Ast.OpNotEq as op), e1, e2 ) when is_cl e1.etype ->
+          let static = mk_static_field_access_infer (runtime_cl) "typeEq" e.epos [] in
+          let ret = { e with eexpr = TCall(static, [run e1; run e2]); } in
+          if op = Ast.OpNotEq then
+            { ret with eexpr = TUnop(Ast.Not, Ast.Prefix, ret) }
+          else
+            ret
+        
         | _ -> Type.map_expr run e
     in
     run
@@ -524,11 +534,15 @@ let configure gen =
   
   let ti64 = match ( get_type gen ([], "Int64") ) with | TTypeDecl t -> TType(t,[]) | _ -> assert false in
   
+  let ttype = get_cl ( get_type gen (["System"], "Type") ) in
+  
   let rec real_type t =
     let t = gen.gfollow#run_f t in
     let ret = match t with
       | TInst( { cl_path = (["haxe"], "Int32") }, [] ) -> gen.gcon.basic.tint
       | TInst( { cl_path = (["haxe"], "Int64") }, [] ) -> ti64
+      | TInst( { cl_path = ([], "Class") }, _ )
+      | TInst( { cl_path = ([], "Enum") }, _ ) -> TInst(ttype,[])
       | TEnum(_, [])
       | TInst(_, []) -> t
       | TInst(cl, params) when 
@@ -630,7 +644,6 @@ let configure gen =
       | TInst ({ cl_kind = KTypeParameter; cl_path=p }, []) -> snd p
       | TMono r -> (match !r with | None -> "object" | Some t -> t_s (run_follow gen t))
       | TInst ({ cl_path = [], "String" }, []) -> "string"
-      | TInst ({ cl_path = [], "Class" }, _) | TInst ({ cl_path = [], "Enum" }, _) -> "System.Type"
       | TEnum ({ e_path = p }, params) -> (path_s p)
       | TInst (({ cl_path = p } as cl), params) -> (path_param_s (TClassDecl cl) p params)
       | TType (({ t_path = p } as t), params) -> (path_param_s (TTypeDecl t) p params)
@@ -1552,7 +1565,6 @@ let configure gen =
     match real_type t with
       | TDynamic _ | TAnon _ | TMono _
       | TInst( { cl_kind = KTypeParameter }, _ )
-      | TInst( { cl_path = ([], "String") }, [] )
       | TInst( { cl_path = (["haxe";"lang"], "Null") }, _ ) -> true
       | _ -> false
   in
@@ -1620,10 +1632,20 @@ let configure gen =
   let hx_exception = get_cl (get_type gen (["haxe";"lang"], "HaxeException")) in
   let hx_exception_t = TInst(hx_exception, []) in
   
+  let rec is_exception t =
+    match follow t with
+      | TInst(cl,_) -> 
+        if cl == base_exception then
+          true
+        else
+          (match cl.cl_super with | None -> false | Some (cl,arg) -> is_exception (TInst(cl,arg)))
+      | _ -> false
+  in
+  
   TryCatchWrapper.configure gen 
   (
     TryCatchWrapper.traverse gen 
-      (fun t -> try unify t base_exception_t; false with | Unify_error _ -> true)
+      (fun t -> not (is_exception (real_type t)))
       (fun throwexpr expr ->
         let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], base_exception_t)) expr.epos in
         { throwexpr with eexpr = TThrow { expr with eexpr = TCall(wrap_static, [expr]) }; etype = gen.gcon.basic.tvoid }

+ 11 - 4
genjava.ml

@@ -1668,13 +1668,20 @@ let configure gen =
   let hx_exception = get_cl (get_type gen (["haxe";"lang"], "HaxeException")) in
   let hx_exception_t = TInst(hx_exception, []) in
   
+  let rec is_exception t =
+    match follow t with
+      | TInst(cl,_) -> 
+        if cl == base_exception then
+          true
+        else
+          (match cl.cl_super with | None -> false | Some (cl,arg) -> is_exception (TInst(cl,arg)))
+      | _ -> false
+  in
+  
   TryCatchWrapper.configure gen 
   (
     TryCatchWrapper.traverse gen 
-      (fun t -> 
-        match real_type t with
-          | TDynamic _ | TAnon _ | TMono _ | TLazy _ | TEnum _ -> true
-          | _ -> try unify t base_exception_t; false with | Unify_error _ -> true)
+      (fun t -> not (is_exception (real_type t)))
       (fun throwexpr expr ->
         let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], base_exception_t)) expr.epos in
         { throwexpr with eexpr = TThrow { expr with eexpr = TCall(wrap_static, [expr]) }; etype = gen.gcon.basic.tvoid }

+ 7 - 1
std/cs/_std/Type.hx

@@ -267,7 +267,13 @@ enum ValueType {
 	{
 		return null;
 	}
-
+	
+	@:functionBody('
+			if (a is haxe.lang.Enum)
+				return a.Equals(b);
+			else
+				return haxe.lang.Runtime.eq(a, b);
+	')
 	public static function enumEq<T>( a : T, b : T ) : Bool 
 	{
 		return untyped a.Equals(b);

+ 1 - 1
std/cs/_std/haxe/lang/HxObject.hx

@@ -1 +1 @@
-package haxe.lang;
private typedef StdType = Type;
import system.Type;

@:native('haxe.lang.HxObject')
private class HxObject implements IHxObject
{
	
}

@:native('haxe.lang.IHxObject')
private interface IHxObject
{
	
}

@:native('haxe.lang.DynamicObject')
private class DynamicObject extends HxObject, implements Dynamic
{
	
}

interface IGenericObject
{
	
}

@:native('haxe.lang.Enum')
@:skip_ctor
private class Enum
{
	@:readonly private var index:Int;
	@:readonly private var params:Array<{}>;
	
	public function new(index:Int, params:Array<{}>)
	{
		this.index = index;
		this.params = params;
	}
	
	@:final public function getTag():String
	{
		var cl:Dynamic = StdType.getClass(this);
		return cl.constructs[index];
	}
	
	public function toString():String
	{
		if (params == null) return getTag();
		var ret = new StringBuf();
		ret.add(getTag()); ret.add("(");
		
		var first = true;
		
		for (p in params)
		{
			if (first)
				first = false;
			else
				ret.add(",");
			ret.add(p);
		}
		
		ret.add(")");
		return ret.toString();
	}
	
	public function equals(obj:Dynamic)
	{
		if (obj == this) //we cannot use == as .Equals !
			return true;
		
		var obj:Enum = cast obj;
		var ret = obj != null && Std.is(obj, StdType.getClass(this)) && obj.index == this.index;
		if (!ret) 
			return false;
		if (obj.params == this.params)
			return true;
		var len = 0;
		if (obj.params == null || this.params == null || (len = this.params.length) != obj.params.length)
			return false;
		
		for (i in 0...len)
		{
			if (obj.params[i] != this.params[i])
				return false;
		}
		return true;
	}
	
	
}
+package haxe.lang;
private typedef StdType = Type;
import system.Type;

@:native('haxe.lang.HxObject')
private class HxObject implements IHxObject
{
	
}

@:native('haxe.lang.IHxObject')
private interface IHxObject
{
	
}

@:native('haxe.lang.DynamicObject')
private class DynamicObject extends HxObject, implements Dynamic
{
	public function toString():String
	{
		var ret = new StringBuf();
		ret.add("{");
		var first = true;
		for (f in Reflect.fields(this))
		{
			if( first )
				first = false;
			else
				ret.add(",");
			ret.add(" "); ret.add(f);
			ret.add(" : ");
			ret.add(Reflect.field(this, f));
		}
		if (!first) ret.add(" ");
		ret.add("}");
		
		return ret.toString();
	}
}

interface IGenericObject
{
	
}

@:native('haxe.lang.Enum')
@:skip_ctor
private class Enum
{
	@:readonly private var index:Int;
	@:readonly private var params:Array<{}>;
	
	public function new(index:Int, params:Array<{}>)
	{
		this.index = index;
		this.params = params;
	}
	
	@:final public function getTag():String
	{
		var cl:Dynamic = StdType.getClass(this);
		return cl.constructs[index];
	}
	
	public function toString():String
	{
		if (params == null) return getTag();
		var ret = new StringBuf();
		ret.add(getTag()); ret.add("(");
		
		var first = true;
		
		for (p in params)
		{
			if (first)
				first = false;
			else
				ret.add(",");
			ret.add(p);
		}
		
		ret.add(")");
		return ret.toString();
	}
	
	public function Equals(obj:Dynamic)
	{
		if (obj == this) //we cannot use == as .Equals !
			return true;
		
		var obj:Enum = cast obj;
		var ret = obj != null && Std.is(obj, StdType.getClass(this)) && obj.index == this.index;
		if (!ret) 
			return false;
		if (obj.params == this.params)
			return true;
		var len = 0;
		if (obj.params == null || this.params == null || (len = this.params.length) != obj.params.length)
			return false;
		
		for (i in 0...len)
		{
			if (!StdType.enumEq(obj.params[i], this.params[i]))
				return false;
		}
		return true;
	}
	
	
}

+ 10 - 2
std/cs/_std/haxe/lang/Runtime.hx

@@ -92,8 +92,6 @@ import system.Type;
 				return v1.Equals(v2);
 			}
 			
-			//add here haxe.lang.Equatable test
-			
 			return false;
 	')
 	public static function eq(v1:Dynamic, v2:Dynamic):Bool
@@ -536,6 +534,16 @@ import system.Type;
 			return null;
 		return obj + "";
 	}
+	
+	@:functionBody('
+			if (t1 == null || t2 == null)
+				return t1 == t2;
+			return t1.Name.Equals(t2.Name);
+	')
+	public static function typeEq(t1:system.Type, t2:system.Type):Bool
+	{
+		return false;
+	}
 }
 
 @:native("haxe.lang.EmptyObject") private enum EmptyObject

+ 1 - 0
std/cs/_std/system/Type.hx

@@ -5,6 +5,7 @@ import system.reflection.ConstructorInfo;
 @:native("System.Type")
 extern class Type 
 {
+	public var Name(default, null):String;
 	public var BaseType(default, null):Type;
 	public var IsInterface(default, null):Bool;
 	public var ContainsGenericParameters(default, null):Bool;

+ 7 - 1
std/java/_std/Type.hx

@@ -41,7 +41,7 @@ enum ValueType {
 		if (o instanceof haxe.lang.DynamicObject || o instanceof java.lang.Class)
 			return null;
 			
-		return = (java.lang.Class<T>) o.getClass();
+		return (java.lang.Class<T>) o.getClass();
 	')
 	public static function getClass<T>( o : T ) : Class<T> untyped 
 	{
@@ -345,6 +345,12 @@ enum ValueType {
 		return null;
 	}
 
+	@:functionBody('
+			if (a instanceof haxe.lang.Enum)
+				return a.equals(b);
+			else
+				return haxe.lang.Runtime.eq(a, b);
+	')
 	public static function enumEq<T>( a : T, b : T ) : Bool untyped 
 	{
 		return a.equals(b);

File diff suppressed because it is too large
+ 0 - 0
std/java/_std/haxe/lang/HxObject.hx


Some files were not shown because too many files changed in this diff