typeloadFunction.ml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. (*
  2. The Haxe Compiler
  3. Copyright (C) 2005-2019 Haxe Foundation
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. *)
  16. (* Typing of functions and their arguments. *)
  17. open Globals
  18. open Ast
  19. open Type
  20. open Typecore
  21. open DisplayTypes.DisplayMode
  22. open DisplayException
  23. open Common
  24. open Error
  25. let type_function_arg ctx t e opt p =
  26. (* TODO https://github.com/HaxeFoundation/haxe/issues/8461 *)
  27. (* delay ctx PTypeField (fun() ->
  28. if ExtType.is_void (follow t) then
  29. error "Arguments of type Void are not allowed" p
  30. ); *)
  31. if opt then
  32. let e = (match e with None -> Some (EConst (Ident "null"),null_pos) | _ -> e) in
  33. ctx.t.tnull t, e
  34. else
  35. let t = match e with Some (EConst (Ident "null"),null_pos) -> ctx.t.tnull t | _ -> t in
  36. t, e
  37. let save_field_state ctx =
  38. let old_ret = ctx.ret in
  39. let old_fun = ctx.curfun in
  40. let old_opened = ctx.opened in
  41. let old_monos = ctx.monomorphs.perfunction in
  42. let old_in_function = ctx.in_function in
  43. let locals = ctx.locals in
  44. (fun () ->
  45. ctx.locals <- locals;
  46. ctx.ret <- old_ret;
  47. ctx.curfun <- old_fun;
  48. ctx.opened <- old_opened;
  49. ctx.monomorphs.perfunction <- old_monos;
  50. ctx.in_function <- old_in_function;
  51. )
  52. let type_var_field ctx t e stat do_display p =
  53. if stat then ctx.curfun <- FunStatic else ctx.curfun <- FunMember;
  54. let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in
  55. let e = type_expr ctx e (WithType.with_type t) in
  56. let e = AbstractCast.cast_or_unify ctx t e p in
  57. match t with
  58. | TType ({ t_path = ([],"UInt") },[]) | TAbstract ({ a_path = ([],"UInt") },[]) when stat -> { e with etype = t }
  59. | _ -> e
  60. let type_var_field ctx t e stat do_display p =
  61. let save = save_field_state ctx in
  62. Std.finally save (type_var_field ctx t e stat do_display) p
  63. let type_function_params ctx fd fname p =
  64. let params = ref [] in
  65. params := Typeload.type_type_params ctx ([],fname) (fun() -> !params) p fd.f_params;
  66. !params
  67. let type_function_arg_value ctx t c do_display =
  68. match c with
  69. | None -> None
  70. | Some e ->
  71. let p = pos e in
  72. let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in
  73. let e = ctx.g.do_optimize ctx (type_expr ctx e (WithType.with_type t)) in
  74. unify ctx e.etype t p;
  75. let rec loop e = match e.eexpr with
  76. | TConst _ -> Some e
  77. | TField({eexpr = TTypeExpr _},FEnum _) -> Some e
  78. | TField({eexpr = TTypeExpr _},FStatic({cl_kind = KAbstractImpl a},cf)) when a.a_enum && has_class_field_flag cf CfEnum -> Some e
  79. | TCast(e,None) -> loop e
  80. | _ ->
  81. if ctx.com.display.dms_kind = DMNone || ctx.com.display.dms_inline && ctx.com.display.dms_error_policy = EPCollect then
  82. display_error ctx "Parameter default value should be constant" p;
  83. None
  84. in
  85. loop e
  86. let process_function_arg ctx n t c do_display check_name p =
  87. if check_name && starts_with n '$' then error "Function argument names starting with a dollar are not allowed" p;
  88. type_function_arg_value ctx t c do_display
  89. let convert_fargs fd =
  90. List.map (fun ((_,pn),_,m,_,_) -> (pn,m)) fd.f_args
  91. let type_function ctx args fargs ret fmode e do_display p =
  92. let fargs = List.map2 (fun (n,c,t) (pn,m) ->
  93. let c = process_function_arg ctx n t c do_display true pn in
  94. let v = add_local_with_origin ctx TVOArgument n t pn in
  95. v.v_meta <- v.v_meta @ m;
  96. if do_display && DisplayPosition.display_position#enclosed_in pn then
  97. DisplayEmitter.display_variable ctx v pn;
  98. if n = "this" then v.v_meta <- (Meta.This,[],null_pos) :: v.v_meta;
  99. v,c
  100. ) args fargs in
  101. ctx.in_function <- true;
  102. ctx.curfun <- fmode;
  103. ctx.ret <- ret;
  104. ctx.opened <- [];
  105. ctx.monomorphs.perfunction <- [];
  106. let e = match e with
  107. | None ->
  108. if ctx.com.display.dms_error_policy = EPIgnore then
  109. (* when we don't care because we're in display mode, just act like
  110. the function has an empty block body. this is fine even if function
  111. defines a return type, because returns aren't checked in this mode
  112. *)
  113. EBlock [],p
  114. else
  115. error "Function body required" p
  116. | Some e -> e
  117. in
  118. let is_position_debug = Meta.has (Meta.Custom ":debug.position") ctx.curfield.cf_meta in
  119. let e = if not do_display then begin
  120. if is_position_debug then print_endline ("syntax:\n" ^ (Expr.dump_with_pos e));
  121. type_expr ctx e NoValue
  122. end else begin
  123. let is_display_debug = Meta.has (Meta.Custom ":debug.display") ctx.curfield.cf_meta in
  124. if is_display_debug then print_endline ("before processing:\n" ^ (Expr.dump_with_pos e));
  125. let e = if !Parser.had_resume then e else Display.ExprPreprocessing.process_expr ctx.com e in
  126. if is_display_debug then print_endline ("after processing:\n" ^ (Expr.dump_with_pos e));
  127. type_expr ctx e NoValue
  128. end in
  129. let e = match e.eexpr with
  130. | TMeta((Meta.MergeBlock,_,_), ({eexpr = TBlock el} as e1)) -> e1
  131. | _ -> e
  132. in
  133. let has_return e =
  134. let rec loop e =
  135. match e.eexpr with
  136. | TReturn (Some _) -> raise Exit
  137. | TFunction _ -> ()
  138. | _ -> Type.iter loop e
  139. in
  140. try loop e; false with Exit -> true
  141. in
  142. begin match follow ret with
  143. | TAbstract({a_path=[],"Void"},_) -> ()
  144. (* We have to check for the presence of return expressions here because
  145. in the case of Dynamic ctx.ret is still a monomorph. If we indeed
  146. don't have a return expression we can link the monomorph to Void. We
  147. can _not_ use type_iseq to avoid the Void check above because that
  148. would turn Dynamic returns to Void returns. *)
  149. | TMono t when not (has_return e) -> ignore(link t ret ctx.t.tvoid)
  150. | _ when ctx.com.display.dms_error_policy = EPIgnore -> ()
  151. | _ -> (try TypeloadCheck.return_flow ctx e with Exit -> ())
  152. end;
  153. let rec loop e =
  154. match e.eexpr with
  155. | TCall ({ eexpr = TConst TSuper },_) -> raise Exit
  156. | TFunction _ -> ()
  157. | _ -> Type.iter loop e
  158. in
  159. let has_super_constr() =
  160. match ctx.curclass.cl_super with
  161. | None ->
  162. None
  163. | Some (csup,tl) ->
  164. try
  165. let cf = get_constructor csup in
  166. Some (Meta.has Meta.CompilerGenerated cf.cf_meta,TInst(csup,tl))
  167. with Not_found ->
  168. None
  169. in
  170. let e = if fmode <> FunConstructor then
  171. e
  172. else begin
  173. delay ctx PForce (fun () -> TypeloadCheck.check_final_vars ctx e);
  174. match has_super_constr() with
  175. | Some (was_forced,t_super) ->
  176. (try
  177. loop e;
  178. if was_forced then
  179. let e_super = mk (TConst TSuper) t_super e.epos in
  180. let e_super_call = mk (TCall(e_super,[])) ctx.t.tvoid e.epos in
  181. concat e_super_call e
  182. else begin
  183. display_error ctx "Missing super constructor call" p;
  184. e
  185. end
  186. with
  187. Exit -> e);
  188. | None ->
  189. e
  190. end in
  191. let e = match ctx.curfun, ctx.vthis with
  192. | (FunMember|FunConstructor), Some v ->
  193. let ev = mk (TVar (v,Some (mk (TConst TThis) ctx.tthis p))) ctx.t.tvoid p in
  194. (match e.eexpr with
  195. | TBlock l ->
  196. if ctx.com.config.pf_this_before_super then
  197. { e with eexpr = TBlock (ev :: l) }
  198. else begin
  199. let rec has_v e = match e.eexpr with
  200. | TLocal v' when v == v -> true
  201. | _ -> check_expr has_v e
  202. in
  203. let rec loop el = match el with
  204. | e :: el ->
  205. if has_v e then
  206. ev :: e :: el
  207. else
  208. e :: loop el
  209. | [] ->
  210. (* should not happen... *)
  211. []
  212. in
  213. { e with eexpr = TBlock (loop l) }
  214. end
  215. | _ -> mk (TBlock [ev;e]) e.etype p)
  216. | _ -> e
  217. in
  218. List.iter (fun r -> r := Closed) ctx.opened;
  219. List.iter (fun (m,p) -> safe_mono_close ctx m p) ctx.monomorphs.perfunction;
  220. if is_position_debug then print_endline ("typing:\n" ^ (Texpr.dump_with_pos "" e));
  221. e , fargs
  222. let type_function ctx args fargs ret fmode e do_display p =
  223. let save = save_field_state ctx in
  224. Std.finally save (type_function ctx args fargs ret fmode e do_display) p
  225. let add_constructor ctx c force_constructor p =
  226. let super() =
  227. match c.cl_super with
  228. | None -> None
  229. | Some ({ cl_constructor = Some cfsup } as csup,cparams) ->
  230. Some(cfsup,csup,cparams)
  231. | Some (csup,cparams) ->
  232. try
  233. let cfsup = Type.get_constructor csup in
  234. Some(cfsup,csup,cparams)
  235. with Not_found ->
  236. None
  237. in
  238. match c.cl_constructor, super() with
  239. | None, Some(cfsup,csup,cparams) when not (has_class_flag c CExtern) ->
  240. let cf = {
  241. cfsup with
  242. cf_pos = p;
  243. cf_meta = List.filter (fun (m,_,_) -> m = Meta.CompilerGenerated) cfsup.cf_meta;
  244. cf_doc = None;
  245. cf_expr = None;
  246. } in
  247. let r = exc_protect ctx (fun r ->
  248. let t = mk_mono() in
  249. r := lazy_processing (fun() -> t);
  250. let ctx = { ctx with
  251. curfield = cf;
  252. pass = PTypeField;
  253. } in
  254. ignore (follow cfsup.cf_type); (* make sure it's typed *)
  255. List.iter (fun cf -> ignore (follow cf.cf_type)) cf.cf_overloads;
  256. let map_arg (v,def) =
  257. (*
  258. let's optimize a bit the output by not always copying the default value
  259. into the inherited constructor when it's not necessary for the platform
  260. *)
  261. let null () = Some (Texpr.Builder.make_null v.v_type v.v_pos) in
  262. match ctx.com.platform, def with
  263. | _, Some _ when not ctx.com.config.pf_static -> v, null()
  264. | Flash, Some ({eexpr = TConst (TString _)}) when not (has_class_flag csup CExtern) -> v, null()
  265. | Cpp, Some ({eexpr = TConst (TString _)}) -> v, def
  266. | Cpp, Some _ -> { v with v_type = ctx.t.tnull v.v_type }, null()
  267. | _ -> v, def
  268. in
  269. let args = (match cfsup.cf_expr with
  270. | Some { eexpr = TFunction f } ->
  271. List.map map_arg f.tf_args
  272. | _ ->
  273. let values = get_value_meta cfsup.cf_meta in
  274. match follow cfsup.cf_type with
  275. | TFun (args,_) ->
  276. List.map (fun (n,o,t) ->
  277. let def = try
  278. type_function_arg_value ctx t (Some (PMap.find n values)) false
  279. with Not_found ->
  280. if o then Some (Texpr.Builder.make_null t null_pos) else None
  281. in
  282. map_arg (alloc_var (VUser TVOArgument) n (if o then ctx.t.tnull t else t) p,def) (* TODO: var pos *)
  283. ) args
  284. | _ -> die "" __LOC__
  285. ) in
  286. let p = c.cl_pos in
  287. let vars = List.map (fun (v,def) -> alloc_var (VUser TVOArgument) v.v_name (apply_params csup.cl_params cparams v.v_type) v.v_pos, def) args in
  288. let super_call = mk (TCall (mk (TConst TSuper) (TInst (csup,cparams)) p,List.map (fun (v,_) -> mk (TLocal v) v.v_type p) vars)) ctx.t.tvoid p in
  289. let constr = mk (TFunction {
  290. tf_args = vars;
  291. tf_type = ctx.t.tvoid;
  292. tf_expr = super_call;
  293. }) (TFun (List.map (fun (v,c) -> v.v_name, c <> None, v.v_type) vars,ctx.t.tvoid)) p in
  294. cf.cf_expr <- Some constr;
  295. cf.cf_type <- t;
  296. unify ctx t constr.etype p;
  297. t
  298. ) "add_constructor" in
  299. cf.cf_type <- TLazy r;
  300. c.cl_constructor <- Some cf;
  301. | None,_ when force_constructor ->
  302. let constr = mk (TFunction {
  303. tf_args = [];
  304. tf_type = ctx.t.tvoid;
  305. tf_expr = mk (TBlock []) ctx.t.tvoid p;
  306. }) (tfun [] ctx.t.tvoid) p in
  307. let cf = mk_field "new" constr.etype p null_pos in
  308. add_class_field_flag cf CfConstructor;
  309. cf.cf_expr <- Some constr;
  310. cf.cf_type <- constr.etype;
  311. cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos];
  312. cf.cf_kind <- Method MethNormal;
  313. c.cl_constructor <- Some cf;
  314. | _ ->
  315. (* nothing to do *)
  316. ()
  317. ;;
  318. Typeload.type_function_params_rec := type_function_params