filters.ml 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. (*
  2. The Haxe Compiler
  3. Copyright (C) 2005-2015 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. open Ast
  17. open Common
  18. open Type
  19. open Typecore
  20. (* PASS 1 begin *)
  21. let rec verify_ast ctx e =
  22. let not_null e e1 = match e1.eexpr with
  23. | TConst TNull ->
  24. (* TODO: https://github.com/HaxeFoundation/haxe/issues/4072 *)
  25. (* display_error ctx ("Invalid null expression: " ^ (s_expr_pretty "" (s_type (print_context())) e)) e.epos *)
  26. ()
  27. | _ -> ()
  28. in
  29. let rec loop e = match e.eexpr with
  30. | TField(e1,_) ->
  31. not_null e e1;
  32. ()
  33. | TArray(e1,e2) ->
  34. not_null e e1;
  35. loop e1;
  36. loop e2
  37. | TCall(e1,el) ->
  38. not_null e e1;
  39. loop e1;
  40. List.iter loop el
  41. | TUnop(_,_,e1) ->
  42. not_null e e1;
  43. loop e1
  44. (* probably too messy *)
  45. (* | TBinop((OpEq | OpNotEq),e1,e2) ->
  46. loop e1;
  47. loop e2
  48. | TBinop((OpAssign | OpAssignOp _),e1,e2) ->
  49. not_null e e1;
  50. loop e1;
  51. loop e2
  52. | TBinop(op,e1,e2) ->
  53. not_null e e1;
  54. not_null e e2;
  55. loop e1;
  56. loop e2 *)
  57. | TTypeExpr(TClassDecl {cl_kind = KAbstractImpl a}) when not (Meta.has Meta.RuntimeValue a.a_meta) ->
  58. error "Cannot use abstract as value" e.epos
  59. | _ ->
  60. Type.iter loop e
  61. in
  62. loop e
  63. (*
  64. Wraps implicit blocks in TIf, TFor, TWhile, TFunction and TTry with real ones
  65. *)
  66. let rec blockify_ast e =
  67. match e.eexpr with
  68. | TIf(e1,e2,eo) ->
  69. {e with eexpr = TIf(blockify_ast e1,mk_block (blockify_ast e2),match eo with None -> None | Some e -> Some (mk_block (blockify_ast e)))}
  70. | TFor(v,e1,e2) ->
  71. {e with eexpr = TFor(v,blockify_ast e1,mk_block (blockify_ast e2))}
  72. | TWhile(e1,e2,flag) ->
  73. {e with eexpr = TWhile(blockify_ast e1,mk_block (blockify_ast e2),flag)}
  74. | TFunction tf ->
  75. {e with eexpr = TFunction {tf with tf_expr = mk_block (blockify_ast tf.tf_expr)}}
  76. | TTry(e1,cl) ->
  77. {e with eexpr = TTry(mk_block (blockify_ast e1),List.map (fun (v,e) -> v,mk_block (blockify_ast e)) cl)}
  78. | TSwitch(e1,cases,def) ->
  79. let e1 = blockify_ast e1 in
  80. let cases = List.map (fun (el,e) ->
  81. el,mk_block (blockify_ast e)
  82. ) cases in
  83. let def = match def with None -> None | Some e -> Some (mk_block (blockify_ast e)) in
  84. {e with eexpr = TSwitch(e1,cases,def)}
  85. | _ ->
  86. Type.map_expr blockify_ast e
  87. (*
  88. Pushes complex right-hand side expression inwards.
  89. return { exprs; value; } -> { exprs; return value; }
  90. x = { exprs; value; } -> { exprs; x = value; }
  91. var x = { exprs; value; } -> { var x; exprs; x = value; }
  92. *)
  93. let promote_complex_rhs com e =
  94. let rec is_complex e = match e.eexpr with
  95. | TBlock _ | TSwitch _ | TIf _ | TTry _ | TCast(_,Some _) -> true
  96. | TBinop(_,e1,e2) -> is_complex e1 || is_complex e2
  97. | TParenthesis e | TMeta(_,e) | TCast(e, None) | TField(e,_) -> is_complex e
  98. | _ -> false
  99. in
  100. let rec loop f e = match e.eexpr with
  101. | TBlock(el) ->
  102. begin match List.rev el with
  103. | elast :: el -> {e with eexpr = TBlock(block (List.rev ((loop f elast) :: el)))}
  104. | [] -> e
  105. end
  106. | TSwitch(es,cases,edef) ->
  107. {e with eexpr = TSwitch(es,List.map (fun (el,e) -> List.map find el,loop f e) cases,match edef with None -> None | Some e -> Some (loop f e)); }
  108. | TIf(eif,ethen,eelse) ->
  109. {e with eexpr = TIf(find eif, loop f ethen, match eelse with None -> None | Some e -> Some (loop f e)); }
  110. | TTry(e1,el) ->
  111. {e with eexpr = TTry(loop f e1, List.map (fun (el,e) -> el,loop f e) el); }
  112. | TParenthesis e1 when not (Common.defined com Define.As3) ->
  113. {e with eexpr = TParenthesis(loop f e1)}
  114. | TMeta(m,e1) ->
  115. { e with eexpr = TMeta(m,loop f e1)}
  116. | TReturn _ | TThrow _ ->
  117. find e
  118. | TContinue | TBreak ->
  119. e
  120. | _ ->
  121. f (find e)
  122. and block el =
  123. let r = ref [] in
  124. List.iter (fun e ->
  125. match e.eexpr with
  126. | TVar(v,eo) ->
  127. begin match eo with
  128. | Some e when is_complex e ->
  129. let e = find e in
  130. r := (loop (fun e -> mk (TBinop(OpAssign,mk (TLocal v) v.v_type e.epos,e)) v.v_type e.epos) e)
  131. :: ((mk (TVar (v,None)) com.basic.tvoid e.epos))
  132. :: !r
  133. | Some e ->
  134. r := (mk (TVar (v,Some (find e))) com.basic.tvoid e.epos) :: !r
  135. | None -> r := (mk (TVar (v,None)) com.basic.tvoid e.epos) :: !r
  136. end
  137. | TReturn (Some e1) when (match follow e1.etype with TAbstract({a_path=[],"Void"},_) -> true | _ -> false) ->
  138. r := ({e with eexpr = TReturn None}) :: e1 :: !r
  139. | _ -> r := (find e) :: !r
  140. ) el;
  141. List.rev !r
  142. and find e = match e.eexpr with
  143. | TReturn (Some e1) -> loop (fun er -> {e with eexpr = TReturn (Some er)}) e1
  144. | TBinop(OpAssign | OpAssignOp _ as op, ({eexpr = TLocal _ | TField _ | TArray _} as e1), e2) -> loop (fun er -> {e with eexpr = TBinop(op, e1, er)}) e2
  145. | TBlock(el) -> {e with eexpr = TBlock (block el)}
  146. | _ -> Type.map_expr find e
  147. in
  148. find e
  149. (* Adds final returns to functions as required by some platforms *)
  150. let rec add_final_return e =
  151. let rec loop e t =
  152. let def_return p =
  153. let c = (match follow t with
  154. | TAbstract ({ a_path = [],"Int" },_) -> TInt 0l
  155. | TAbstract ({ a_path = [],"Float" },_) -> TFloat "0."
  156. | TAbstract ({ a_path = [],"Bool" },_) -> TBool false
  157. | _ -> TNull
  158. ) in
  159. { eexpr = TReturn (Some { eexpr = TConst c; epos = p; etype = t }); etype = t_dynamic; epos = p }
  160. in
  161. match e.eexpr with
  162. | TBlock el ->
  163. (match List.rev el with
  164. | [] -> e
  165. | elast :: el ->
  166. match loop elast t with
  167. | { eexpr = TBlock el2 } -> { e with eexpr = TBlock ((List.rev el) @ el2) }
  168. | elast -> { e with eexpr = TBlock (List.rev (elast :: el)) })
  169. | TReturn _ ->
  170. e
  171. | _ ->
  172. { e with eexpr = TBlock [e;def_return e.epos] }
  173. in
  174. let e = Type.map_expr add_final_return e in
  175. match e.eexpr with
  176. | TFunction f ->
  177. let f = (match follow f.tf_type with
  178. | TAbstract ({ a_path = [],"Void" },[]) -> f
  179. | _ -> { f with tf_expr = loop f.tf_expr f.tf_type }
  180. ) in
  181. { e with eexpr = TFunction f }
  182. | _ -> e
  183. let rec wrap_js_exceptions com e =
  184. let rec is_error t =
  185. match follow t with
  186. | TInst ({cl_path = (["js"],"Error")},_) -> true
  187. | TInst ({cl_super = Some (csup,tl)}, _) -> is_error (TInst (csup,tl))
  188. | _ -> false
  189. in
  190. let rec loop e =
  191. match e.eexpr with
  192. | TThrow eerr when not (is_error eerr.etype) ->
  193. let terr = List.find (fun mt -> match mt with TClassDecl {cl_path = ["js";"_Boot"],"HaxeError"} -> true | _ -> false) com.types in
  194. let cerr = match terr with TClassDecl c -> c | _ -> assert false in
  195. let ewrap = { eerr with eexpr = TNew (cerr,[],[eerr]) } in
  196. { e with eexpr = TThrow ewrap }
  197. | _ ->
  198. Type.map_expr loop e
  199. in
  200. loop e
  201. (* -------------------------------------------------------------------------- *)
  202. (* CHECK LOCAL VARS INIT *)
  203. let check_local_vars_init e =
  204. let intersect vl1 vl2 =
  205. PMap.mapi (fun v t -> t && PMap.find v vl2) vl1
  206. in
  207. let join vars cvars =
  208. List.iter (fun v -> vars := intersect !vars v) cvars
  209. in
  210. let restore vars old_vars declared =
  211. (* restore variables declared in this block to their previous state *)
  212. vars := List.fold_left (fun acc v ->
  213. try PMap.add v (PMap.find v old_vars) acc with Not_found -> PMap.remove v acc
  214. ) !vars declared;
  215. in
  216. let declared = ref [] in
  217. let rec loop vars e =
  218. match e.eexpr with
  219. | TLocal v ->
  220. let init = (try PMap.find v.v_id !vars with Not_found -> true) in
  221. if not init then begin
  222. if v.v_name = "this" then error "Missing this = value" e.epos
  223. else error ("Local variable " ^ v.v_name ^ " used without being initialized") e.epos
  224. end
  225. | TVar (v,eo) ->
  226. begin
  227. match eo with
  228. | None ->
  229. declared := v.v_id :: !declared;
  230. vars := PMap.add v.v_id false !vars
  231. | Some e ->
  232. loop vars e
  233. end
  234. | TBlock el ->
  235. let old = !declared in
  236. let old_vars = !vars in
  237. declared := [];
  238. List.iter (loop vars) el;
  239. restore vars old_vars (List.rev !declared);
  240. declared := old;
  241. | TBinop (OpAssign,{ eexpr = TLocal v },e) when PMap.mem v.v_id !vars ->
  242. loop vars e;
  243. vars := PMap.add v.v_id true !vars
  244. | TIf (e1,e2,eo) ->
  245. loop vars e1;
  246. let vbase = !vars in
  247. loop vars e2;
  248. (match eo with
  249. | None -> vars := vbase
  250. (* ignore else false cases (they are added by the side-effect handler) *)
  251. | Some {eexpr = TConst (TBool(false))} -> ()
  252. | Some e ->
  253. let v1 = !vars in
  254. vars := vbase;
  255. loop vars e;
  256. vars := intersect !vars v1)
  257. | TWhile (cond,e,flag) ->
  258. (match flag with
  259. | NormalWhile when (match cond.eexpr with TParenthesis {eexpr = TConst (TBool true)} -> false | _ -> true) ->
  260. loop vars cond;
  261. let old = !vars in
  262. loop vars e;
  263. vars := old;
  264. | _ ->
  265. loop vars e;
  266. loop vars cond)
  267. | TTry (e,catches) ->
  268. let cvars = List.map (fun (v,e) ->
  269. let old = !vars in
  270. loop vars e;
  271. let v = !vars in
  272. vars := old;
  273. v
  274. ) catches in
  275. loop vars e;
  276. join vars cvars;
  277. | TSwitch (e,cases,def) ->
  278. loop vars e;
  279. let cvars = List.map (fun (ec,e) ->
  280. let old = !vars in
  281. List.iter (loop vars) ec;
  282. vars := old;
  283. loop vars e;
  284. let v = !vars in
  285. vars := old;
  286. v
  287. ) cases in
  288. (match def with
  289. | None when (match e.eexpr with TMeta((Meta.Exhaustive,_,_),_) | TParenthesis({eexpr = TMeta((Meta.Exhaustive,_,_),_)}) -> true | _ -> false) ->
  290. (match cvars with
  291. | cv :: cvars ->
  292. PMap.iter (fun i b -> if b then vars := PMap.add i b !vars) cv;
  293. join vars cvars
  294. | [] -> ())
  295. | None -> ()
  296. | Some e ->
  297. loop vars e;
  298. join vars cvars)
  299. (* mark all reachable vars as initialized, since we don't exit the block *)
  300. | TBreak | TContinue | TReturn None ->
  301. vars := PMap.map (fun _ -> true) !vars
  302. | TThrow e | TReturn (Some e) ->
  303. loop vars e;
  304. vars := PMap.map (fun _ -> true) !vars
  305. | TFunction _ ->
  306. (* do not recurse into functions, their code is only relevant when executed *)
  307. ()
  308. | _ ->
  309. Type.iter (loop vars) e
  310. in
  311. loop (ref PMap.empty) e;
  312. e
  313. (* -------------------------------------------------------------------------- *)
  314. (* BLOCK VARIABLES CAPTURE *)
  315. (*
  316. For some platforms, it will simply mark the variables which are used in closures
  317. using the v_capture flag so it can be processed in a more optimized
  318. For Flash/JS platforms, it will ensure that variables used in loop sub-functions
  319. have an unique scope. It transforms the following expression :
  320. for( x in array )
  321. funs.push(function() return x++);
  322. Into the following :
  323. for( _x in array ) {
  324. var x = [_x];
  325. funs.push(function(x) { function() return x[0]++; }(x));
  326. }
  327. *)
  328. type usage =
  329. | Block of ((usage -> unit) -> unit)
  330. | Loop of ((usage -> unit) -> unit)
  331. | Function of ((usage -> unit) -> unit)
  332. | Declare of tvar
  333. | Use of tvar
  334. | Assign of tvar
  335. let rec local_usage f e =
  336. match e.eexpr with
  337. | TBinop ((OpAssign | OpAssignOp _), { eexpr = TLocal v }, e2) ->
  338. local_usage f e2;
  339. f (Assign v)
  340. | TUnop ((Increment | Decrement), _, { eexpr = TLocal v }) ->
  341. f (Assign v)
  342. | TLocal v ->
  343. f (Use v)
  344. | TVar (v,eo) ->
  345. (match eo with None -> () | Some e -> local_usage f e);
  346. f (Declare v);
  347. | TFunction tf ->
  348. let cc f =
  349. List.iter (fun (v,_) -> f (Declare v)) tf.tf_args;
  350. local_usage f tf.tf_expr;
  351. in
  352. f (Function cc)
  353. | TBlock l ->
  354. f (Block (fun f -> List.iter (local_usage f) l))
  355. | TFor (v,it,e) ->
  356. local_usage f it;
  357. f (Loop (fun f ->
  358. f (Declare v);
  359. local_usage f e;
  360. ))
  361. | TWhile _ ->
  362. f (Loop (fun f ->
  363. iter (local_usage f) e
  364. ))
  365. | TTry (e,catchs) ->
  366. local_usage f e;
  367. List.iter (fun (v,e) ->
  368. f (Block (fun f ->
  369. f (Declare v);
  370. local_usage f e;
  371. ))
  372. ) catchs;
  373. | _ ->
  374. iter (local_usage f) e
  375. let captured_vars com e =
  376. let t = com.basic in
  377. let impl = match com.platform with
  378. (* optimized version for C#/Java - use native arrays *)
  379. | Cs | Java ->
  380. let cnativearray =
  381. match (List.find (fun md -> match md with
  382. | TClassDecl ({ cl_path = ["cs"|"java"],"NativeArray" }) -> true
  383. | _ -> false
  384. ) com.types)
  385. with TClassDecl cl -> cl | _ -> assert false
  386. in
  387. object
  388. method captured_type t = TInst (cnativearray,[t])
  389. method mk_ref v ve p =
  390. match ve with
  391. | None ->
  392. let eone = mk (TConst (TInt (Int32.of_int 1))) t.tint p in
  393. let t = match v.v_type with TInst (_, [t]) -> t | _ -> assert false in
  394. mk (TNew (cnativearray,[t],[eone])) v.v_type p
  395. | Some e ->
  396. { (Optimizer.mk_untyped_call "__array__" p [e]) with etype = v.v_type }
  397. method mk_ref_access e v =
  398. mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
  399. method mk_init av v pos =
  400. let elocal = mk (TLocal v) v.v_type pos in
  401. let earray = { (Optimizer.mk_untyped_call "__array__" pos [elocal]) with etype = av.v_type } in
  402. mk (TVar (av,Some earray)) t.tvoid pos
  403. end
  404. (* default implementation - use haxe array *)
  405. | _ ->
  406. object
  407. method captured_type = t.tarray
  408. method mk_ref v ve p =
  409. mk (TArrayDecl (match ve with None -> [] | Some e -> [e])) v.v_type p
  410. method mk_ref_access e v =
  411. mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
  412. method mk_init av v pos =
  413. mk (TVar (av,Some (mk (TArrayDecl [mk (TLocal v) v.v_type pos]) av.v_type pos))) t.tvoid pos
  414. end
  415. in
  416. let mk_var v used =
  417. let v2 = alloc_var v.v_name (PMap.find v.v_id used) in
  418. v2.v_meta <- v.v_meta;
  419. v2
  420. in
  421. let rec wrap used e =
  422. match e.eexpr with
  423. | TVar (v,ve) ->
  424. let v,ve =
  425. if PMap.mem v.v_id used then
  426. v, Some (impl#mk_ref v (Option.map (wrap used) ve) e.epos)
  427. else
  428. v, (match ve with None -> None | Some e -> Some (wrap used e))
  429. in
  430. { e with eexpr = TVar (v,ve) }
  431. | TLocal v when PMap.mem v.v_id used ->
  432. impl#mk_ref_access e v
  433. | TFor (v,it,expr) when PMap.mem v.v_id used ->
  434. let vtmp = mk_var v used in
  435. let it = wrap used it in
  436. let expr = wrap used expr in
  437. mk (TFor (vtmp,it,Type.concat (impl#mk_init v vtmp e.epos) expr)) e.etype e.epos
  438. | TTry (expr,catchs) ->
  439. let catchs = List.map (fun (v,e) ->
  440. let e = wrap used e in
  441. try
  442. let vtmp = mk_var v used in
  443. vtmp, Type.concat (impl#mk_init v vtmp e.epos) e
  444. with Not_found ->
  445. v, e
  446. ) catchs in
  447. mk (TTry (wrap used expr,catchs)) e.etype e.epos
  448. | TFunction f ->
  449. (*
  450. list variables that are marked as used, but also used in that
  451. function and which are not declared inside it !
  452. *)
  453. let fused = ref PMap.empty in
  454. let tmp_used = ref used in
  455. let rec browse = function
  456. | Block f | Loop f | Function f -> f browse
  457. | Use v | Assign v ->
  458. if PMap.mem v.v_id !tmp_used then fused := PMap.add v.v_id v !fused;
  459. | Declare v ->
  460. tmp_used := PMap.remove v.v_id !tmp_used
  461. in
  462. local_usage browse e;
  463. let vars = PMap.fold (fun v acc -> v :: acc) !fused [] in
  464. (* in case the variable has been marked as used in a parallel scope... *)
  465. let fexpr = ref (wrap used f.tf_expr) in
  466. let fargs = List.map (fun (v,o) ->
  467. if PMap.mem v.v_id used then
  468. let vtmp = mk_var v used in
  469. fexpr := Type.concat (impl#mk_init v vtmp e.epos) !fexpr;
  470. vtmp, o
  471. else
  472. v, o
  473. ) f.tf_args in
  474. let e = { e with eexpr = TFunction { f with tf_args = fargs; tf_expr = !fexpr } } in
  475. (*
  476. Create a new function scope to make sure that the captured loop variable
  477. will not be overwritten in next loop iteration
  478. *)
  479. if com.config.pf_capture_policy = CPLoopVars then
  480. mk (TCall (
  481. Codegen.mk_parent (mk (TFunction {
  482. tf_args = List.map (fun v -> v, None) vars;
  483. tf_type = e.etype;
  484. tf_expr = mk_block (mk (TReturn (Some e)) e.etype e.epos);
  485. }) (TFun (List.map (fun v -> v.v_name,false,v.v_type) vars,e.etype)) e.epos),
  486. List.map (fun v -> mk (TLocal v) v.v_type e.epos) vars)
  487. ) e.etype e.epos
  488. else
  489. e
  490. | _ ->
  491. map_expr (wrap used) e
  492. and do_wrap used e =
  493. if PMap.is_empty used then
  494. e
  495. else
  496. let used = PMap.map (fun v ->
  497. let vt = v.v_type in
  498. v.v_type <- impl#captured_type vt;
  499. v.v_capture <- true;
  500. vt
  501. ) used in
  502. wrap used e
  503. and out_loop e =
  504. match e.eexpr with
  505. | TFor _ | TWhile _ ->
  506. (*
  507. collect variables that are declared in loop but used in subfunctions
  508. *)
  509. let vars = ref PMap.empty in
  510. let used = ref PMap.empty in
  511. let depth = ref 0 in
  512. let rec collect_vars in_loop = function
  513. | Block f ->
  514. let old = !vars in
  515. f (collect_vars in_loop);
  516. vars := old;
  517. | Loop f ->
  518. let old = !vars in
  519. f (collect_vars true);
  520. vars := old;
  521. | Function f ->
  522. incr depth;
  523. f (collect_vars false);
  524. decr depth;
  525. | Declare v ->
  526. if in_loop then vars := PMap.add v.v_id !depth !vars;
  527. | Use v | Assign v ->
  528. try
  529. let d = PMap.find v.v_id !vars in
  530. if d <> !depth then used := PMap.add v.v_id v !used;
  531. with Not_found ->
  532. ()
  533. in
  534. local_usage (collect_vars false) e;
  535. do_wrap !used e
  536. | _ ->
  537. map_expr out_loop e
  538. and all_vars e =
  539. let vars = ref PMap.empty in
  540. let used = ref PMap.empty in
  541. let assigned = ref PMap.empty in
  542. let depth = ref 0 in
  543. let rec collect_vars = function
  544. | Block f ->
  545. let old = !vars in
  546. f collect_vars;
  547. vars := old;
  548. | Loop f ->
  549. let old = !vars in
  550. f collect_vars;
  551. vars := old;
  552. | Function f ->
  553. incr depth;
  554. f collect_vars;
  555. decr depth;
  556. | Declare v ->
  557. vars := PMap.add v.v_id !depth !vars;
  558. | Use v ->
  559. (try
  560. let d = PMap.find v.v_id !vars in
  561. if d <> !depth then used := PMap.add v.v_id v !used;
  562. with Not_found -> ())
  563. | Assign v ->
  564. (try
  565. let d = PMap.find v.v_id !vars in
  566. (* different depth - needs wrap *)
  567. if d <> !depth then begin
  568. used := PMap.add v.v_id v !used;
  569. assigned := PMap.add v.v_id v !assigned;
  570. end
  571. (* same depth but assigned after being used on a different depth - needs wrap *)
  572. else if PMap.mem v.v_id !used then
  573. assigned := PMap.add v.v_id v !assigned;
  574. with Not_found -> ())
  575. in
  576. local_usage collect_vars e;
  577. (* mark all capture variables - also used in rename_local_vars at later stage *)
  578. PMap.iter (fun _ v -> v.v_capture <- true) !used;
  579. !assigned
  580. in
  581. let captured = all_vars e in
  582. match com.config.pf_capture_policy with
  583. | CPNone -> e
  584. | CPWrapRef -> do_wrap captured e
  585. | CPLoopVars -> out_loop e
  586. (* -------------------------------------------------------------------------- *)
  587. (* RENAME LOCAL VARS *)
  588. let rename_local_vars ctx e =
  589. let cfg = ctx.com.config in
  590. let all_scope = (not cfg.pf_captured_scope) || (not cfg.pf_locals_scope) in
  591. let vars = ref PMap.empty in
  592. let all_vars = ref PMap.empty in
  593. let vtemp = alloc_var "~" t_dynamic in
  594. let rebuild_vars = ref false in
  595. let rebuild m =
  596. PMap.fold (fun v acc -> PMap.add v.v_name v acc) m PMap.empty
  597. in
  598. let save() =
  599. let old = !vars in
  600. if cfg.pf_unique_locals || not cfg.pf_locals_scope then (fun() -> ()) else (fun() -> vars := if !rebuild_vars then rebuild old else old)
  601. in
  602. let rename vars v =
  603. let count = ref 1 in
  604. while PMap.mem (v.v_name ^ string_of_int !count) vars do
  605. incr count;
  606. done;
  607. v.v_name <- v.v_name ^ string_of_int !count;
  608. in
  609. let declare v p =
  610. (match follow v.v_type with
  611. | TAbstract ({a_path = [],"Void"},_) -> error "Arguments and variables of type Void are not allowed" p
  612. | _ -> ());
  613. (* chop escape char for all local variables generated *)
  614. if is_gen_local v then v.v_name <- "_g" ^ String.sub v.v_name 1 (String.length v.v_name - 1);
  615. let look_vars = (if not cfg.pf_captured_scope && v.v_capture then !all_vars else !vars) in
  616. (try
  617. let v2 = PMap.find v.v_name look_vars in
  618. (*
  619. block_vars will create some wrapper-functions that are declaring
  620. the same variable twice. In that case do not perform a rename since
  621. we are sure it's actually the same variable
  622. *)
  623. if v == v2 then raise Not_found;
  624. rename look_vars v;
  625. with Not_found ->
  626. ());
  627. vars := PMap.add v.v_name v !vars;
  628. if all_scope then all_vars := PMap.add v.v_name v !all_vars;
  629. in
  630. (*
  631. This is quite a rare case, when a local variable would otherwise prevent
  632. accessing a type because it masks the type value or the package name.
  633. *)
  634. let check t =
  635. match (t_infos t).mt_path with
  636. | [], name | name :: _, _ ->
  637. let vars = if cfg.pf_locals_scope then vars else all_vars in
  638. (try
  639. let v = PMap.find name !vars in
  640. if v == vtemp then raise Not_found; (* ignore *)
  641. rename (!vars) v;
  642. rebuild_vars := true;
  643. vars := PMap.add v.v_name v !vars
  644. with Not_found ->
  645. ());
  646. vars := PMap.add name vtemp !vars
  647. in
  648. let check_type t =
  649. match follow t with
  650. | TInst (c,_) -> check (TClassDecl c)
  651. | TEnum (e,_) -> check (TEnumDecl e)
  652. | TType (t,_) -> check (TTypeDecl t)
  653. | TAbstract (a,_) -> check (TAbstractDecl a)
  654. | TMono _ | TLazy _ | TAnon _ | TDynamic _ | TFun _ -> ()
  655. in
  656. let rec loop e =
  657. match e.eexpr with
  658. | TVar (v,eo) ->
  659. if not cfg.pf_locals_scope then declare v e.epos;
  660. (match eo with None -> () | Some e -> loop e);
  661. if cfg.pf_locals_scope then declare v e.epos;
  662. | TFunction tf ->
  663. let old = save() in
  664. List.iter (fun (v,_) -> declare v e.epos) tf.tf_args;
  665. loop tf.tf_expr;
  666. old()
  667. | TBlock el ->
  668. let old = save() in
  669. (* we have to look ahead for vars on these targets (issue #3344) *)
  670. begin match ctx.com.platform with
  671. | Js ->
  672. let rec check_var e = match e.eexpr with
  673. | TVar (v,eo) ->
  674. (match eo with None -> () | Some e -> loop e);
  675. declare v e.epos
  676. | TBlock _ ->
  677. ()
  678. | _ ->
  679. Type.iter check_var e
  680. in
  681. List.iter check_var el
  682. | _ ->
  683. ()
  684. end;
  685. List.iter loop el;
  686. old()
  687. | TFor (v,it,e1) ->
  688. loop it;
  689. let old = save() in
  690. declare v e.epos;
  691. loop e1;
  692. old()
  693. | TTry (e,catchs) ->
  694. loop e;
  695. List.iter (fun (v,e) ->
  696. let old = save() in
  697. declare v e.epos;
  698. check_type v.v_type;
  699. loop e;
  700. old()
  701. ) catchs;
  702. | TTypeExpr t ->
  703. check t
  704. | TNew (c,_,_) ->
  705. Type.iter loop e;
  706. check (TClassDecl c);
  707. | TCast (e,Some t) ->
  708. loop e;
  709. check t;
  710. | TConst TSuper ->
  711. check_type e.etype
  712. | _ ->
  713. Type.iter loop e
  714. in
  715. declare (alloc_var "this" t_dynamic) Ast.null_pos; (* force renaming of 'this' vars in abstract *)
  716. begin match ctx.curclass.cl_path with
  717. | s :: _,_ | [],s -> declare (alloc_var s t_dynamic) Ast.null_pos
  718. end;
  719. loop e;
  720. e
  721. let check_unification ctx e t =
  722. begin match e.eexpr,t with
  723. | TLocal v,TType({t_path = ["cs"],("Ref" | "Out")},_) ->
  724. (* TODO: this smells of hack, but we have to deal with it somehow *)
  725. v.v_capture <- true
  726. | _ ->
  727. ()
  728. end;
  729. e
  730. (* PASS 1 end *)
  731. (* Saves a class state so it can be restored later, e.g. after DCE or native path rewrite *)
  732. let save_class_state ctx t = match t with
  733. | TClassDecl c ->
  734. let mk_field_restore f =
  735. let rec mk_overload_restore f =
  736. f.cf_name,f.cf_kind,f.cf_expr,f.cf_type,f.cf_meta,f.cf_params
  737. in
  738. ( f,mk_overload_restore f, List.map (fun f -> f,mk_overload_restore f) f.cf_overloads )
  739. in
  740. let restore_field (f,res,overloads) =
  741. let restore_field (f,(name,kind,expr,t,meta,params)) =
  742. f.cf_name <- name; f.cf_kind <- kind; f.cf_expr <- expr; f.cf_type <- t; f.cf_meta <- meta; f.cf_params <- params;
  743. f
  744. in
  745. let f = restore_field (f,res) in
  746. f.cf_overloads <- List.map restore_field overloads;
  747. f
  748. in
  749. let mk_pmap lst =
  750. List.fold_left (fun pmap f -> PMap.add f.cf_name f pmap) PMap.empty lst
  751. in
  752. let meta = c.cl_meta and path = c.cl_path and ext = c.cl_extern and over = c.cl_overrides in
  753. let sup = c.cl_super and impl = c.cl_implements in
  754. let csr = Option.map (mk_field_restore) c.cl_constructor in
  755. let ofr = List.map (mk_field_restore) c.cl_ordered_fields in
  756. let osr = List.map (mk_field_restore) c.cl_ordered_statics in
  757. let init = c.cl_init in
  758. c.cl_restore <- (fun() ->
  759. c.cl_super <- sup;
  760. c.cl_implements <- impl;
  761. c.cl_meta <- meta;
  762. c.cl_extern <- ext;
  763. c.cl_path <- path;
  764. c.cl_init <- init;
  765. c.cl_ordered_fields <- List.map restore_field ofr;
  766. c.cl_ordered_statics <- List.map restore_field osr;
  767. c.cl_fields <- mk_pmap c.cl_ordered_fields;
  768. c.cl_statics <- mk_pmap c.cl_ordered_statics;
  769. c.cl_constructor <- Option.map restore_field csr;
  770. c.cl_overrides <- over;
  771. )
  772. | _ ->
  773. ()
  774. (* PASS 2 begin *)
  775. let rec is_removable_class c =
  776. match c.cl_kind with
  777. | KGeneric ->
  778. (Meta.has Meta.Remove c.cl_meta ||
  779. (match c.cl_super with
  780. | Some (c,_) -> is_removable_class c
  781. | _ -> false) ||
  782. List.exists (fun (_,t) -> match follow t with
  783. | TInst(c,_) ->
  784. Codegen.has_ctor_constraint c || Meta.has Meta.Const c.cl_meta
  785. | _ ->
  786. false
  787. ) c.cl_params)
  788. | KTypeParameter _ ->
  789. (* this shouldn't happen, have to investigate (see #4092) *)
  790. true
  791. | _ ->
  792. false
  793. let remove_generic_base ctx t = match t with
  794. | TClassDecl c when is_removable_class c ->
  795. c.cl_extern <- true
  796. | _ ->
  797. ()
  798. (* Removes extern and macro fields, also checks for Void fields *)
  799. let remove_extern_fields ctx t = match t with
  800. | TClassDecl c ->
  801. if not (Common.defined ctx.com Define.DocGen) then begin
  802. c.cl_ordered_fields <- List.filter (fun f ->
  803. let b = Codegen.is_removable_field ctx f in
  804. if b then c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
  805. not b
  806. ) c.cl_ordered_fields;
  807. c.cl_ordered_statics <- List.filter (fun f ->
  808. let b = Codegen.is_removable_field ctx f in
  809. if b then c.cl_statics <- PMap.remove f.cf_name c.cl_statics;
  810. not b
  811. ) c.cl_ordered_statics;
  812. end
  813. | _ ->
  814. ()
  815. (* PASS 2 end *)
  816. (* PASS 3 begin *)
  817. (* Checks if a private class' path clashes with another path *)
  818. let check_private_path ctx t = match t with
  819. | TClassDecl c when c.cl_private ->
  820. let rpath = (fst c.cl_module.m_path,"_" ^ snd c.cl_module.m_path) in
  821. if Hashtbl.mem ctx.g.types_module rpath then error ("This private class name will clash with " ^ s_type_path rpath) c.cl_pos;
  822. | _ ->
  823. ()
  824. (* Rewrites class or enum paths if @:native metadata is set *)
  825. let apply_native_paths ctx t =
  826. let get_native_name meta =
  827. let rec get_native meta = match meta with
  828. | [] -> raise Not_found
  829. | (Meta.Native,[v],p as meta) :: _ ->
  830. meta
  831. | _ :: meta ->
  832. get_native meta
  833. in
  834. let (_,e,mp) = get_native meta in
  835. match e with
  836. | [Ast.EConst (Ast.String name),p] ->
  837. name,p
  838. | [] ->
  839. raise Not_found
  840. | _ ->
  841. error "String expected" mp
  842. in
  843. let get_real_name meta name =
  844. let name',p = get_native_name meta in
  845. (Meta.RealPath,[Ast.EConst (Ast.String (name)), p], p), name'
  846. in
  847. let get_real_path meta path =
  848. let name,p = get_native_name meta in
  849. (Meta.RealPath,[Ast.EConst (Ast.String (s_type_path path)), p], p), parse_path name
  850. in
  851. try
  852. (match t with
  853. | TClassDecl c ->
  854. let did_change = ref false in
  855. let field cf = try
  856. let meta,name = get_real_name cf.cf_meta cf.cf_name in
  857. cf.cf_name <- name;
  858. cf.cf_meta <- meta :: cf.cf_meta;
  859. List.iter (fun cf -> cf.cf_name <- name) cf.cf_overloads;
  860. did_change := true
  861. with Not_found ->
  862. ()
  863. in
  864. let fields cfs old_map =
  865. did_change := false;
  866. List.iter field cfs;
  867. if !did_change then
  868. List.fold_left (fun map f -> PMap.add f.cf_name f map) PMap.empty cfs
  869. else
  870. old_map
  871. in
  872. c.cl_fields <- fields c.cl_ordered_fields c.cl_fields;
  873. c.cl_statics <- fields c.cl_ordered_statics c.cl_statics;
  874. let meta,path = get_real_path c.cl_meta c.cl_path in
  875. c.cl_meta <- meta :: c.cl_meta;
  876. c.cl_path <- path;
  877. | TEnumDecl e ->
  878. let meta,path = get_real_path e.e_meta e.e_path in
  879. e.e_meta <- meta :: e.e_meta;
  880. e.e_path <- path;
  881. | TAbstractDecl a when Meta.has Meta.CoreType a.a_meta ->
  882. let meta,path = get_real_path a.a_meta a.a_path in
  883. a.a_meta <- meta :: a.a_meta;
  884. a.a_path <- path;
  885. | _ ->
  886. ())
  887. with Not_found ->
  888. ()
  889. (* Adds the __rtti field if required *)
  890. let add_rtti ctx t =
  891. let rec has_rtti c =
  892. Meta.has Meta.Rtti c.cl_meta || match c.cl_super with None -> false | Some (csup,_) -> has_rtti csup
  893. in
  894. match t with
  895. | TClassDecl c when has_rtti c && not (PMap.mem "__rtti" c.cl_statics) ->
  896. let f = mk_field "__rtti" ctx.t.tstring c.cl_pos in
  897. let str = Genxml.gen_type_string ctx.com t in
  898. f.cf_expr <- Some (mk (TConst (TString str)) f.cf_type c.cl_pos);
  899. c.cl_ordered_statics <- f :: c.cl_ordered_statics;
  900. c.cl_statics <- PMap.add f.cf_name f c.cl_statics;
  901. | _ ->
  902. ()
  903. (* Adds member field initializations as assignments to the constructor *)
  904. let add_field_inits ctx t =
  905. let is_as3 = Common.defined ctx.com Define.As3 && not ctx.in_macro in
  906. let apply c =
  907. let ethis = mk (TConst TThis) (TInst (c,List.map snd c.cl_params)) c.cl_pos in
  908. (* TODO: we have to find a variable name which is not used in any of the functions *)
  909. let v = alloc_var "_g" ethis.etype in
  910. let need_this = ref false in
  911. let inits,fields = List.fold_left (fun (inits,fields) cf ->
  912. match cf.cf_kind,cf.cf_expr with
  913. | Var _, Some _ ->
  914. if is_as3 then (inits, cf :: fields) else (cf :: inits, cf :: fields)
  915. | Method MethDynamic, Some e when is_as3 ->
  916. (* TODO : this would have a better place in genSWF9 I think - NC *)
  917. (* we move the initialization of dynamic functions to the constructor and also solve the
  918. 'this' problem along the way *)
  919. let rec use_this v e = match e.eexpr with
  920. | TConst TThis ->
  921. need_this := true;
  922. mk (TLocal v) v.v_type e.epos
  923. | _ -> Type.map_expr (use_this v) e
  924. in
  925. let e = Type.map_expr (use_this v) e in
  926. let cf2 = {cf with cf_expr = Some e} in
  927. (* if the method is an override, we have to remove the class field to not get invalid overrides *)
  928. let fields = if List.memq cf c.cl_overrides then begin
  929. c.cl_fields <- PMap.remove cf.cf_name c.cl_fields;
  930. fields
  931. end else
  932. cf2 :: fields
  933. in
  934. (cf2 :: inits, fields)
  935. | _ -> (inits, cf :: fields)
  936. ) ([],[]) c.cl_ordered_fields in
  937. c.cl_ordered_fields <- (List.rev fields);
  938. match inits with
  939. | [] -> ()
  940. | _ ->
  941. let el = List.map (fun cf ->
  942. match cf.cf_expr with
  943. | None -> assert false
  944. | Some e ->
  945. let lhs = mk (TField(ethis,FInstance (c,List.map snd c.cl_params,cf))) cf.cf_type e.epos in
  946. cf.cf_expr <- None;
  947. let eassign = mk (TBinop(OpAssign,lhs,e)) e.etype e.epos in
  948. if is_as3 then begin
  949. let echeck = mk (TBinop(OpEq,lhs,(mk (TConst TNull) lhs.etype e.epos))) ctx.com.basic.tbool e.epos in
  950. mk (TIf(echeck,eassign,None)) eassign.etype e.epos
  951. end else
  952. eassign;
  953. ) inits in
  954. let el = if !need_this then (mk (TVar((v, Some ethis))) ethis.etype ethis.epos) :: el else el in
  955. match c.cl_constructor with
  956. | None ->
  957. let ct = TFun([],ctx.com.basic.tvoid) in
  958. let ce = mk (TFunction {
  959. tf_args = [];
  960. tf_type = ctx.com.basic.tvoid;
  961. tf_expr = mk (TBlock el) ctx.com.basic.tvoid c.cl_pos;
  962. }) ct c.cl_pos in
  963. let ctor = mk_field "new" ct c.cl_pos in
  964. ctor.cf_kind <- Method MethNormal;
  965. c.cl_constructor <- Some { ctor with cf_expr = Some ce };
  966. | Some cf ->
  967. match cf.cf_expr with
  968. | Some { eexpr = TFunction f } ->
  969. let bl = match f.tf_expr with {eexpr = TBlock b } -> b | x -> [x] in
  970. let ce = mk (TFunction {f with tf_expr = mk (TBlock (el @ bl)) ctx.com.basic.tvoid c.cl_pos }) cf.cf_type cf.cf_pos in
  971. c.cl_constructor <- Some {cf with cf_expr = Some ce }
  972. | _ ->
  973. assert false
  974. in
  975. match t with
  976. | TClassDecl c ->
  977. apply c
  978. | _ ->
  979. ()
  980. (* Adds the __meta__ field if required *)
  981. let add_meta_field ctx t = match t with
  982. | TClassDecl c ->
  983. (match Codegen.build_metadata ctx.com t with
  984. | None -> ()
  985. | Some e ->
  986. let f = mk_field "__meta__" t_dynamic c.cl_pos in
  987. f.cf_expr <- Some e;
  988. let can_deal_with_interface_metadata () = match ctx.com.platform with
  989. | Flash when Common.defined ctx.com Define.As3 -> false
  990. | Php -> false
  991. | _ -> true
  992. in
  993. if c.cl_interface && not (can_deal_with_interface_metadata()) then begin
  994. (* borrowed from gencommon, but I did wash my hands afterwards *)
  995. let path = fst c.cl_path,snd c.cl_path ^ "_HxMeta" in
  996. let ncls = mk_class c.cl_module path c.cl_pos in
  997. let cf = mk_field "__meta__" e.etype e.epos in
  998. cf.cf_expr <- Some e;
  999. ncls.cl_statics <- PMap.add "__meta__" cf ncls.cl_statics;
  1000. ncls.cl_ordered_statics <- cf :: ncls.cl_ordered_statics;
  1001. ctx.com.types <- (TClassDecl ncls) :: ctx.com.types;
  1002. c.cl_meta <- (Meta.Custom ":hasMetadata",[],e.epos) :: c.cl_meta
  1003. end else begin
  1004. c.cl_ordered_statics <- f :: c.cl_ordered_statics;
  1005. c.cl_statics <- PMap.add f.cf_name f c.cl_statics
  1006. end)
  1007. | _ ->
  1008. ()
  1009. (* Removes interfaces tagged with @:remove metadata *)
  1010. let check_remove_metadata ctx t = match t with
  1011. | TClassDecl c ->
  1012. c.cl_implements <- List.filter (fun (c,_) -> not (Meta.has Meta.Remove c.cl_meta)) c.cl_implements;
  1013. | _ ->
  1014. ()
  1015. (* Checks for Void class fields *)
  1016. let check_void_field ctx t = match t with
  1017. | TClassDecl c ->
  1018. let check f =
  1019. match follow f.cf_type with TAbstract({a_path=[],"Void"},_) -> error "Fields of type Void are not allowed" f.cf_pos | _ -> ();
  1020. in
  1021. List.iter check c.cl_ordered_fields;
  1022. List.iter check c.cl_ordered_statics;
  1023. | _ ->
  1024. ()
  1025. (* Interfaces have no 'super', but can extend many other interfaces.
  1026. This makes the first extended (implemented) interface the super for efficiency reasons (you can get one for 'free')
  1027. and leaves the remaining ones as 'implemented' *)
  1028. let promote_first_interface_to_super ctx t = match t with
  1029. | TClassDecl c when c.cl_interface ->
  1030. begin match c.cl_implements with
  1031. | ({ cl_path = ["cpp";"rtti"],_ },_ ) :: _ -> ()
  1032. | first_interface :: remaining ->
  1033. c.cl_super <- Some first_interface;
  1034. c.cl_implements <- remaining
  1035. | _ -> ()
  1036. end
  1037. | _ ->
  1038. ()
  1039. let commit_features ctx t =
  1040. let m = (t_infos t).mt_module in
  1041. Hashtbl.iter (fun k v ->
  1042. Common.add_feature ctx.com k;
  1043. ) m.m_extra.m_features
  1044. let check_reserved_type_paths ctx t =
  1045. let check path pos =
  1046. if List.mem path ctx.com.config.pf_reserved_type_paths then
  1047. ctx.com.warning ("Type path " ^ (s_type_path path) ^ " is reserved on this target") pos
  1048. in
  1049. match t with
  1050. | TClassDecl c when not c.cl_extern -> check c.cl_path c.cl_pos
  1051. | TEnumDecl e when not e.e_extern -> check e.e_path e.e_pos
  1052. | _ -> ()
  1053. (* PASS 3 end *)
  1054. let run_expression_filters ctx filters t =
  1055. let run e =
  1056. List.fold_left (fun e f -> f e) e filters
  1057. in
  1058. match t with
  1059. | TClassDecl c when is_removable_class c -> ()
  1060. | TClassDecl c ->
  1061. ctx.curclass <- c;
  1062. let rec process_field f =
  1063. (match f.cf_expr with
  1064. | Some e when not (Codegen.is_removable_field ctx f) ->
  1065. Codegen.AbstractCast.cast_stack := f :: !Codegen.AbstractCast.cast_stack;
  1066. f.cf_expr <- Some (run e);
  1067. Codegen.AbstractCast.cast_stack := List.tl !Codegen.AbstractCast.cast_stack;
  1068. | _ -> ());
  1069. List.iter process_field f.cf_overloads
  1070. in
  1071. List.iter process_field c.cl_ordered_fields;
  1072. List.iter process_field c.cl_ordered_statics;
  1073. (match c.cl_constructor with
  1074. | None -> ()
  1075. | Some f -> process_field f);
  1076. (match c.cl_init with
  1077. | None -> ()
  1078. | Some e ->
  1079. c.cl_init <- Some (run e));
  1080. | TEnumDecl _ -> ()
  1081. | TTypeDecl _ -> ()
  1082. | TAbstractDecl _ -> ()
  1083. let pp_counter = ref 1
  1084. let is_cached t =
  1085. let m = (t_infos t).mt_module.m_extra in
  1086. if m.m_processed = 0 then m.m_processed <- !pp_counter;
  1087. m.m_processed <> !pp_counter
  1088. let apply_filters_once ctx filters t =
  1089. if not (is_cached t) then run_expression_filters ctx filters t
  1090. let next_compilation() =
  1091. incr pp_counter
  1092. let iter_expressions fl mt =
  1093. match mt with
  1094. | TClassDecl c ->
  1095. let field cf = match cf.cf_expr with
  1096. | None -> ()
  1097. | Some e -> List.iter (fun f -> f e) fl
  1098. in
  1099. List.iter field c.cl_ordered_statics;
  1100. List.iter field c.cl_ordered_fields;
  1101. (match c.cl_constructor with None -> () | Some cf -> field cf)
  1102. | _ ->
  1103. ()
  1104. let run com tctx main =
  1105. begin match com.display with
  1106. | DMUsage | DMPosition ->
  1107. Codegen.detect_usage com;
  1108. | _ ->
  1109. ()
  1110. end;
  1111. if not (Common.defined com Define.NoDeprecationWarnings) then
  1112. Codegen.DeprecationCheck.run com;
  1113. let use_static_analyzer = Common.defined com Define.Analyzer in
  1114. (* this part will be a bit messy until we make the analyzer the default *)
  1115. let new_types = List.filter (fun t -> not (is_cached t)) com.types in
  1116. if use_static_analyzer then begin
  1117. (* PASS 1: general expression filters *)
  1118. let filters = [
  1119. Codegen.AbstractCast.handle_abstract_casts tctx;
  1120. check_local_vars_init;
  1121. Optimizer.inline_constructors tctx;
  1122. Optimizer.reduce_expression tctx;
  1123. blockify_ast;
  1124. captured_vars com;
  1125. ] in
  1126. List.iter (run_expression_filters tctx filters) new_types;
  1127. Analyzer.Run.run_on_types tctx new_types;
  1128. List.iter (iter_expressions [verify_ast tctx]) new_types;
  1129. let filters = [
  1130. Optimizer.sanitize com;
  1131. if com.config.pf_add_final_return then add_final_return else (fun e -> e);
  1132. if com.platform = Js then wrap_js_exceptions com else (fun e -> e);
  1133. rename_local_vars tctx;
  1134. ] in
  1135. List.iter (run_expression_filters tctx filters) new_types;
  1136. end else begin
  1137. (* PASS 1: general expression filters *)
  1138. let filters = [
  1139. Codegen.AbstractCast.handle_abstract_casts tctx;
  1140. blockify_ast;
  1141. check_local_vars_init;
  1142. Optimizer.inline_constructors tctx;
  1143. ( if (Common.defined com Define.NoSimplify) || (Common.defined com Define.Cppia) ||
  1144. ( match com.platform with Cpp -> false | _ -> true ) then
  1145. fun e -> e
  1146. else
  1147. fun e ->
  1148. let save = save_locals tctx in
  1149. let timer = timer "analyzer-simplify-apply" in
  1150. let e = try snd (Analyzer.Simplifier.apply com e) with Exit -> e in
  1151. timer();
  1152. save();
  1153. e );
  1154. if com.foptimize then (fun e -> Optimizer.reduce_expression tctx e) else Optimizer.sanitize com;
  1155. captured_vars com;
  1156. promote_complex_rhs com;
  1157. if com.config.pf_add_final_return then add_final_return else (fun e -> e);
  1158. if com.platform = Js then wrap_js_exceptions com else (fun e -> e);
  1159. rename_local_vars tctx;
  1160. ] in
  1161. List.iter (run_expression_filters tctx filters) new_types;
  1162. List.iter (iter_expressions [verify_ast tctx]) new_types;
  1163. end;
  1164. next_compilation();
  1165. List.iter (fun f -> f()) (List.rev com.filters); (* macros onGenerate etc. *)
  1166. List.iter (save_class_state tctx) new_types;
  1167. List.iter (fun t ->
  1168. remove_generic_base tctx t;
  1169. remove_extern_fields tctx t;
  1170. ) com.types;
  1171. (* update cache dependencies before DCE is run *)
  1172. Codegen.update_cache_dependencies com;
  1173. (* check @:remove metadata before DCE so it is ignored there (issue #2923) *)
  1174. List.iter (check_remove_metadata tctx) com.types;
  1175. (* DCE *)
  1176. let dce_mode = if Common.defined com Define.As3 then
  1177. "no"
  1178. else
  1179. (try Common.defined_value com Define.Dce with _ -> "no")
  1180. in
  1181. begin match dce_mode with
  1182. | "full" -> Dce.run com main (not (Common.defined com Define.Interp))
  1183. | "std" -> Dce.run com main false
  1184. | "no" -> Dce.fix_accessors com
  1185. | _ -> failwith ("Unknown DCE mode " ^ dce_mode)
  1186. end;
  1187. (* always filter empty abstract implementation classes (issue #1885) *)
  1188. List.iter (fun mt -> match mt with
  1189. | TClassDecl({cl_kind = KAbstractImpl _} as c) when c.cl_ordered_statics = [] && c.cl_ordered_fields = [] && not (Meta.has Meta.Used c.cl_meta) ->
  1190. c.cl_extern <- true
  1191. | TClassDecl({cl_kind = KAbstractImpl a} as c) when Meta.has Meta.Enum a.a_meta ->
  1192. let is_runtime_field cf =
  1193. not (Meta.has Meta.Enum cf.cf_meta)
  1194. in
  1195. (* also filter abstract implementation classes that have only @:enum fields (issue #2858) *)
  1196. if not (List.exists is_runtime_field c.cl_ordered_statics) then
  1197. c.cl_extern <- true
  1198. | _ -> ()
  1199. ) com.types;
  1200. (* PASS 3: type filters *)
  1201. let type_filters = [
  1202. check_private_path;
  1203. apply_native_paths;
  1204. add_rtti;
  1205. (match com.platform with | Java | Cs -> (fun _ _ -> ()) | _ -> add_field_inits);
  1206. add_meta_field;
  1207. check_void_field;
  1208. (match com.platform with | Cpp -> promote_first_interface_to_super | _ -> (fun _ _ -> ()) );
  1209. commit_features;
  1210. (if com.config.pf_reserved_type_paths <> [] then check_reserved_type_paths else (fun _ _ -> ()));
  1211. ] in
  1212. List.iter (fun t -> List.iter (fun f -> f tctx t) type_filters) com.types