Browse Source

[typer] rewrite get_overloads to something humans can read

also cache it
Simon Krajewski 5 years ago
parent
commit
fc9d361f38

+ 1 - 1
src/codegen/gencommon/castDetect.ml

@@ -775,7 +775,7 @@ let handle_type_parameter gen e e1 ef ~clean_ef ~overloads_cast_to_base f elist
 						(* FIXME: this is a workaround for issue #1743 . Uncomment this code after it was solved *)
 						(* let t, cf = List.find (fun (t,cf2) -> cf == cf2) (Overloads.get_overloads cl (field_name f)) in *)
 						(* cf, t, false *)
-						select_overload gen e1.etype (Overloads.get_overloads cl (field_name f)) cl.cl_params params, false
+						select_overload gen e1.etype (Overloads.get_overloads gen.gcon cl (field_name f)) cl.cl_params params, false
 					| FStatic(c,f) ->
 						(* workaround for issue #1743 *)
 						(* f,f.cf_type, false *)

+ 1 - 1
src/codegen/gencommon/fixOverrides.ml

@@ -71,7 +71,7 @@ let run ~explicit_fn_name ~get_vmtype gen =
 					let ftype = apply_params iface.cl_params itl f.cf_type in
 					let real_ftype = get_real_fun gen (apply_params iface.cl_params real_itl f.cf_type) in
 					replace_mono real_ftype;
-					let overloads = Overloads.get_overloads c f.cf_name in
+					let overloads = Overloads.get_overloads gen.gcon c f.cf_name in
 					try
 						let t2, f2 =
 							match overloads with

+ 36 - 20
src/codegen/overloads.ml

@@ -71,29 +71,45 @@ let compare_overload_args ?(get_vmtype) ?(ctx) t1 t2 f1 f2 =
 let same_overload_args ?(get_vmtype) t1 t2 f1 f2 =
 	compare_overload_args ?get_vmtype t1 t2 f1 f2 <> Different
 
-(** retrieves all overloads from class c and field i, as (Type.t * tclass_field) list *)
-let rec get_overloads c i =
-	let ret = try
-			let f = PMap.find i c.cl_fields in
-			match f.cf_kind with
+let collect_overloads c i =
+	let acc = ref [] in
+	let rec loop map c =
+		let maybe_add cf =
+			let t = map cf.cf_type in
+			if not (List.exists (fun (t2,cf2) -> same_overload_args t t2 cf cf2) !acc) then acc := (t,cf) :: !acc
+		in
+		begin try
+			let cf = PMap.find i c.cl_fields in
+			begin match cf.cf_kind with
 				| Var _ ->
-					(* @:libType may generate classes that have a variable field in a superclass of an overloaded method *)
-					[]
+					()
 				| Method _ ->
-					(f.cf_type, f) :: (List.map (fun f -> f.cf_type, f) f.cf_overloads)
-		with | Not_found -> []
+					maybe_add cf;
+					List.iter maybe_add cf.cf_overloads
+			end;
+		with Not_found ->
+			()
+		end;
+		match c.cl_super with
+			| None when c.cl_interface ->
+				List.iter (fun (c,tl) ->
+					loop (fun t -> apply_params c.cl_params tl (map t)) c
+				) c.cl_implements
+			| None ->
+				()
+			| Some (c,tl) ->
+				loop (fun t -> apply_params c.cl_params tl (map t)) c
 	in
-	let rsup = match c.cl_super with
-	| None when c.cl_interface ->
-			let ifaces = List.concat (List.map (fun (c,tl) ->
-				List.map (fun (t,f) -> apply_params c.cl_params tl t, f) (get_overloads c i)
-			) c.cl_implements) in
-			ret @ ifaces
-	| None -> ret
-	| Some (c,tl) ->
-			ret @ ( List.map (fun (t,f) -> apply_params c.cl_params tl t, f) (get_overloads c i) )
-	in
-	ret @ (List.filter (fun (t,f) -> not (List.exists (fun (t2,f2) -> same_overload_args t t2 f f2) ret)) rsup)
+	loop (fun t -> t) c;
+	List.rev !acc
+
+let get_overloads (com : Common.context) c i =
+	try
+		Hashtbl.find com.overload_cache (c.cl_path,i)
+	with Not_found ->
+		let l = collect_overloads c i in
+		Hashtbl.add com.overload_cache (c.cl_path,i) l;
+		l
 
 (** Overload resolution **)
 module Resolution =

+ 3 - 0
src/context/common.ml

@@ -304,6 +304,7 @@ type context = {
 	cached_macros : (path * string,(((string * bool * t) list * t * tclass * Type.tclass_field) * module_def)) Hashtbl.t;
 	mutable stored_typed_exprs : (int, texpr) PMap.t;
 	pass_debug_messages : string DynArray.t;
+	overload_cache : ((path * string),(Type.t * tclass_field) list) Hashtbl.t;
 	(* output *)
 	mutable file : string;
 	mutable flash_version : float;
@@ -669,6 +670,7 @@ let create version s_version args =
 		get_messages = (fun() -> []);
 		filter_messages = (fun _ -> ());
 		pass_debug_messages = DynArray.create();
+		overload_cache = Hashtbl.create 0;
 		basic = {
 			tvoid = m;
 			tint = m;
@@ -713,6 +715,7 @@ let clone com =
 			defines_signature = com.defines.defines_signature;
 		};
 		native_libs = create_native_libs();
+		overload_cache = Hashtbl.create 0;
 	}
 
 let file_time file = Extc.filetime file

+ 1 - 1
src/typing/calls.ml

@@ -264,7 +264,7 @@ let unify_field_call ctx fa el args ret p inline =
 				List.map (fun (t,cf) ->
 					let monos = Monomorph.spawn_constrained_monos map cf.cf_params in
 					map (apply_params cf.cf_params monos t),cf
-				) (Overloads.get_overloads c cf.cf_name)
+				) (Overloads.get_overloads ctx.com c cf.cf_name)
 			in
 			cfl,Some c,cf,(fun cf -> FInstance(c,tl,cf))
 		| FClosure(co,cf) ->

+ 2 - 2
src/typing/typeloadCheck.ml

@@ -219,7 +219,7 @@ let check_overriding ctx c f =
 					display_error ctx msg p
 		in
 		if ctx.com.config.pf_overload && Meta.has Meta.Overload f.cf_meta then begin
-			let overloads = Overloads.get_overloads csup i in
+			let overloads = Overloads.get_overloads ctx.com csup i in
 			List.iter (fun (t,f2) ->
 				(* check if any super class fields are vars *)
 				match f2.cf_kind with
@@ -348,7 +348,7 @@ module Inheritance = struct
 				let t2, f2 = class_field_no_interf c i in
 				let t2, f2 =
 					if ctx.com.config.pf_overload && (f2.cf_overloads <> [] || Meta.has Meta.Overload f2.cf_meta) then
-						let overloads = Overloads.get_overloads c i in
+						let overloads = Overloads.get_overloads ctx.com c i in
 						is_overload := true;
 						let t = (apply_params intf.cl_params params f.cf_type) in
 						List.find (fun (t1,f1) -> Overloads.same_overload_args t t1 f f1) overloads

+ 1 - 1
src/typing/typeloadFields.ml

@@ -1251,7 +1251,7 @@ let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p =
 				let f = PMap.find m c.cl_statics in
 				(f.cf_type, f) :: (List.map (fun f -> f.cf_type, f) f.cf_overloads)
 			else
-				Overloads.get_overloads c m
+				Overloads.get_overloads ctx.com c m
 		else
 			[ if fctx.is_static then
 				let f = PMap.find m c.cl_statics in