Prechádzať zdrojové kódy

[cs] safe way to cast to type parameters

Caue Waneck 13 rokov pred
rodič
commit
6ea3027b8b
2 zmenil súbory, kde vykonal 28 pridanie a 0 odobranie
  1. 9 0
      gencs.ml
  2. 19 0
      std/cs/internal/Runtime.hx

+ 9 - 0
gencs.ml

@@ -237,6 +237,11 @@ struct
       | TInst(cl,_) -> cl
       | TInst(cl,_) -> cl
       | _ -> assert false
       | _ -> assert false
   
   
+  let is_tparam t =
+    match follow t with
+      | TInst( { cl_kind = KTypeParameter }, _ ) -> true
+      | _ -> false
+  
   let traverse gen runtime_cl =
   let traverse gen runtime_cl =
     let basic = gen.gcon.basic in
     let basic = gen.gcon.basic in
     let tchar = match ( get_type gen (["cs"], "Char16") ) with | TTypeDecl t -> t | _ -> assert false in
     let tchar = match ( get_type gen (["cs"], "Char16") ) with | TTypeDecl t -> t | _ -> assert false in
@@ -320,6 +325,10 @@ struct
             }, [ run e1; run e2 ])
             }, [ run e1; run e2 ])
           }
           }
         
         
+        | TCast(expr, _) when is_tparam e.etype ->
+          let static = mk_static_field_access_infer (runtime_cl) "genericCast" e.epos [e.etype] in
+          { e with eexpr = TCall(static, [mk_local (alloc_var "$type_param" e.etype) expr.epos; run expr]); }
+        
         | TBinop( (Ast.OpNotEq as op), e1, e2)
         | TBinop( (Ast.OpNotEq as op), e1, e2)
         | TBinop( (Ast.OpEq as op), e1, e2) when is_struct e1.etype || is_struct e2.etype ->
         | TBinop( (Ast.OpEq as op), e1, e2) when is_struct e1.etype || is_struct e2.etype ->
           let mk_ret e = match op with | Ast.OpNotEq -> { e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) } | _ -> e in
           let mk_ret e = match op with | Ast.OpNotEq -> { e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) } | _ -> e in

+ 19 - 0
std/cs/internal/Runtime.hx

@@ -604,6 +604,25 @@ import system.Type;
 		return false;
 		return false;
 	}
 	}
 	
 	
+	
+	@:functionBody('
+		if (obj is To)
+			return (To) obj;
+		else if (obj == null)
+			return default(To);
+		if (typeof(To) == typeof(double))
+			return (To)(object) toDouble(obj);
+		else if (typeof(To) == typeof(int))
+			return (To)(object) toInt(obj);
+		else
+			return (To) obj;
+	')
+	public static function genericCast<To>(obj:Dynamic):To
+	{
+		return null;
+	}
+	
+	//TODO: change from genericCast to getConverter, so we don't need to handle extra boxing associated with it
 	/*@:functionBody('
 	/*@:functionBody('
 		if (typeof(To).TypeHandle == typeof(double).TypeHandle)
 		if (typeof(To).TypeHandle == typeof(double).TypeHandle)
 			return (System.Converter<object,To>) new System.Converter<object,double>(toDouble);
 			return (System.Converter<object,To>) new System.Converter<object,double>(toDouble);