Browse Source

[typer] start on `@:op(a())`

see #10119
Simon Krajewski 4 years ago
parent
commit
439a73fa00

+ 1 - 0
src/core/tFunctions.ml

@@ -212,6 +212,7 @@ let null_abstract = {
 	a_array = [];
 	a_read = None;
 	a_write = None;
+	a_call = None;
 	a_enum = false;
 }
 

+ 1 - 0
src/core/tType.ml

@@ -311,6 +311,7 @@ and tabstract = {
 	mutable a_array : tclass_field list;
 	mutable a_read : tclass_field option;
 	mutable a_write : tclass_field option;
+	mutable a_call : tclass_field option;
 	a_enum : bool;
 }
 

+ 27 - 11
src/typing/callUnification.ml

@@ -505,28 +505,44 @@ object(self)
 	   used with actual expression calls and not with something like field calls. *)
 	method expr_call (e : texpr) (el : expr list) =
 		check_assign();
+		let default t =
+			let el = List.map (fun e -> type_expr ctx e WithType.value) el in
+			let t = if t == t_dynamic then
+				t_dynamic
+			else if ctx.untyped then
+				mk_mono()
+			else
+				error (s_type (print_context()) e.etype ^ " cannot be called") e.epos
+			in
+			mk (TCall (e,el)) t p
+		in
 		let rec loop t = match follow t with
 		| TFun (args,r) ->
 			let el, tfunc = unify_call_args ctx el args r p false false false in
 			let r = match tfunc with TFun(_,r) -> r | _ -> die "" __LOC__ in
 			mk (TCall (e,el)) r p
-		| TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta ->
-			loop (Abstract.get_underlying_type a tl)
+		| TAbstract(a,tl) as t ->
+			let check_callable () =
+				if Meta.has Meta.Callable a.a_meta then
+					loop (Abstract.get_underlying_type a tl)
+				else
+					default t
+				in
+			begin match a.a_call,a.a_impl with
+			| Some cf,Some c ->
+				let e_static = Builder.make_static_this c e.epos in
+				let fa = FieldAccess.create e_static cf (FHAbstract(a,tl,c)) false e.epos in
+				self#field_call fa [e] el
+			| _ ->
+				check_callable();
+			end
 		| TMono _ ->
 			let t = mk_mono() in
 			let el = List.map (fun e -> type_expr ctx e WithType.value) el in
 			unify ctx (tfun (List.map (fun e -> e.etype) el) t) e.etype e.epos;
 			mk (TCall (e,el)) t p
 		| t ->
-			let el = List.map (fun e -> type_expr ctx e WithType.value) el in
-			let t = if t == t_dynamic then
-				t_dynamic
-			else if ctx.untyped then
-				mk_mono()
-			else
-				error (s_type (print_context()) e.etype ^ " cannot be called") e.epos
-			in
-			mk (TCall (e,el)) t p
+			default t
 		in
 		loop e.etype
 

+ 8 - 0
src/typing/typeloadFields.ml

@@ -1100,6 +1100,14 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 					(try type_eq EqStrict t (tfun [targ] (mk_mono())) with Unify_error l -> raise (Error ((Unify l),cf.cf_pos)));
 					a.a_unops <- (op,flag,cf) :: a.a_unops;
 					allow_no_expr();
+				| (Meta.Op,[ECall _,_],_) :: _ ->
+					begin match a.a_call with
+					| None ->
+						a.a_call <- Some cf
+					| Some cf' ->
+						cf'.cf_overloads <- cf :: cf'.cf_overloads
+					end;
+					allow_no_expr();
 				| ((Meta.Resolve,_,_) | (Meta.Op,[EField _,_],_)) :: _ ->
 					let targ = if fctx.is_abstract_member then tthis else ta in
 					let check_fun t1 t2 =

+ 1 - 0
src/typing/typeloadModule.ml

@@ -330,6 +330,7 @@ let module_pass_1 ctx m tdecls loadp =
 				a_this = mk_mono();
 				a_read = None;
 				a_write = None;
+				a_call = None;
 				a_enum = List.mem AbEnum d.d_flags || Meta.has Meta.Enum d.d_meta;
 			} in
 			if a.a_enum && not (Meta.has Meta.Enum a.a_meta) then a.a_meta <- (Meta.Enum,[],null_pos) :: a.a_meta;