Bläddra i källkod

[java/cs] Fixed how type parameters are inferred - now TAnon works, and type parameter typedefs also. Fixed Issue #884

Caue Waneck 13 år sedan
förälder
incheckning
62efecc531
1 ändrade filer med 50 tillägg och 15 borttagningar
  1. 50 15
      gencommon.ml

+ 50 - 15
gencommon.ml

@@ -62,6 +62,18 @@ let debug_type = (s_type (print_context()))
 
 let debug_expr = s_expr debug_type
 
+let follow_once t =
+  match t with
+	| TMono r ->
+		(match !r with
+		| Some t -> t
+		| _ -> t_dynamic (* avoid infinite loop / should be the same in this context *))
+	| TLazy f ->
+		!f()
+	| TType (t,tl) ->
+		apply_params t.t_types tl t.t_type
+	| _ -> t
+
 let t_empty = TAnon({ a_fields = PMap.empty; a_status = ref (Closed) })
 
 (* the undefined is a special var that works like null, but can have special meaning *)
@@ -3403,39 +3415,62 @@ struct
   
   let priority = max_dep -. 20.
   
-  let iter2 = List.iter2
-  (*
-  let rec iter2 f a1 a2 =
-    match (a1, a2) with
-      | (h1 :: tl1), (h2 :: tl2) -> f h1 h2; iter2 f tl1 tl2
-      | _ -> ()*)
-  
   (* this function will receive the original function argument, the applied function argument and the original function parameters. *)
   (* from this info, it will infer the applied tparams for the function *)
   (* this function is used by CastDetection module *)
   let infer_params gen pos (original_args:((string * bool * t) list * t)) (applied_args:((string * bool * t) list * t)) (params:(string * t) list) : tparams =
     let args_list args = ( List.map (fun (_,_,t) -> t) (fst args) ) @ [snd args] in
     let params_tbl = Hashtbl.create (List.length params) in
-    (*List.iter (fun (s,t) -> match t with | TInst(cl,[]) -> Hashtbl.add params_tbl cl.cl_path cl | _ -> assert false) params;*)
     
-    let rec get_arg is_follow original applied = 
+    let pmap_iter2 fn orig_pmap applied_pmap =
+      PMap.iter (fun name cf -> 
+        try
+          let applied_cf = PMap.find name applied_pmap in
+          fn cf applied_cf
+        with | Not_found -> () (* 'swallow' not_found expressions as there might be unsafe casts or untyped behavior here *)
+      ) orig_pmap
+    in
+    
+    let rec get_arg original applied = 
       match (original, applied) with
         | TInst( ({ cl_kind = KTypeParameter } as cl ), []), _ ->
           Hashtbl.replace params_tbl cl.cl_path applied
         | TInst(cl, params), TInst(cl2, params2) ->
-          iter2 (get_arg is_follow) params params2
+          List.iter2 (get_arg) params params2
         | TEnum(e, params), TEnum(e2, params2) ->
-          iter2 (get_arg is_follow) params params2
+          List.iter2 (get_arg) params params2
         | TFun(params, ret), TFun(params2, ret2) ->
-          iter2 (get_arg false) ( args_list (params, ret) ) ( args_list (params2, ret2) )
-        | _ -> if not(is_follow) then get_arg true (follow original) (follow applied)
+          List.iter2 (get_arg) ( args_list (params, ret) ) ( args_list (params2, ret2) )
+        | TAnon (a_original), TAnon (a_applied) ->
+          pmap_iter2 (fun cf_o cf_a -> get_arg cf_o.cf_type cf_a.cf_type ) a_original.a_fields a_applied.a_fields
+        | TAnon (a_original), TInst(cl, params) ->
+          PMap.iter (fun name cf ->
+            match field_access gen applied name with
+              | FClassField (cl, params, cf, is_static, actual_t) ->
+                let t = apply_params cl.cl_types params actual_t in
+                get_arg cf.cf_type t
+              | FDynamicField t -> get_arg cf.cf_type (apply_params cl.cl_types params t)
+              | FNotFound -> (* the field may not be there *) ()
+              | _ -> assert false
+          ) a_original.a_fields
+        | TType(t_o, params_o), TType(t_a, params_a) when t_o == t_a ->
+          List.iter2 (get_arg) params_o params_a
+        | _, TType _
+        | _, TMono _
+        | _, TLazy _ ->
+          get_arg original (follow_once applied)
+        | TType _, _
+        | TMono _, _
+        | TLazy _, _ ->
+          get_arg (follow_once original) applied
+        | _ -> ()
     in
     
     let original = args_list original_args in
     let applied = args_list applied_args in
     
-    iter2 (fun original applied ->
-      get_arg false original applied
+    List.iter2 (fun original applied ->
+      get_arg original applied
     ) original applied;
     
     List.map (fun (_,t) ->