matcher.ml 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  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. type pvar = tvar * pos
  21. type con_def =
  22. | CEnum of tenum * tenum_field
  23. | CConst of tconstant
  24. | CAny
  25. | CType of module_type
  26. | CArray of int
  27. | CFields of int * (string * tclass_field) list
  28. | CExpr of texpr
  29. and con = {
  30. c_def : con_def;
  31. c_type : t;
  32. c_pos : pos;
  33. }
  34. and st_def =
  35. | SVar of tvar
  36. | SField of st * tclass_field
  37. | SEnum of st * tenum_field * int
  38. | SArray of st * int
  39. | STuple of st * int * int
  40. and st = {
  41. st_def : st_def;
  42. st_type : t;
  43. st_pos : pos;
  44. }
  45. and dt =
  46. | Switch of st * (con * dt) list
  47. | Bind of ((tvar * pos) * st) list * dt
  48. | Goto of int
  49. | Expr of int
  50. | Guard of int * dt * dt option
  51. (* Pattern *)
  52. type pat_def =
  53. | PAny
  54. | PVar of pvar
  55. | PCon of con * pat list
  56. | POr of pat * pat
  57. | PBind of pvar * pat
  58. | PTuple of pat array
  59. and pat = {
  60. p_def : pat_def;
  61. p_type : t;
  62. p_pos : pos;
  63. }
  64. type out = {
  65. mutable o_pos : pos;
  66. o_id : int;
  67. o_catch_all : bool;
  68. mutable o_num_paths : int;
  69. }
  70. type pat_vec = pat array * out
  71. type pat_matrix = pat_vec list
  72. (* Context *)
  73. type pattern_ctx = {
  74. mutable pc_locals : (string, pvar) PMap.t;
  75. mutable pc_sub_vars : (string, pvar) PMap.t option;
  76. mutable pc_reify : bool;
  77. mutable pc_is_complex : bool;
  78. }
  79. type matcher = {
  80. ctx : typer;
  81. need_val : bool;
  82. dt_lut : dt DynArray.t;
  83. dt_cache : (dt,int) Hashtbl.t;
  84. mutable dt_count : int;
  85. mutable outcomes : out list;
  86. mutable toplevel_or : bool;
  87. mutable has_extractor : bool;
  88. mutable expr_map : (int,texpr * texpr option) PMap.t;
  89. mutable is_exhaustive : bool;
  90. }
  91. type type_finiteness =
  92. | Infinite (* type has inifite constructors (e.g. Int, String) *)
  93. | CompileTimeFinite (* type is considered finite only at compile-time but has inifite possible run-time values (enum abstracts) *)
  94. | RunTimeFinite (* type is truly finite (Bool, enums) *)
  95. exception Not_exhaustive of pat * st
  96. exception Not_exhaustive_default
  97. exception Unrecognized_pattern of Ast.expr
  98. let arity con = match con.c_def with
  99. | CEnum (_,{ef_type = TFun(args,_)}) -> List.length args
  100. | CEnum _ -> 0
  101. | CConst _ -> 0
  102. | CType mt -> 0
  103. | CArray i -> i
  104. | CFields (i,_) -> i
  105. | CExpr _ -> 0
  106. | CAny -> 0
  107. let mk_st def t p = {
  108. st_def = def;
  109. st_type = t;
  110. st_pos = p;
  111. }
  112. let mk_out mctx id e eg is_catch_all p =
  113. let out = {
  114. o_pos = p;
  115. o_id = id;
  116. o_catch_all = is_catch_all;
  117. o_num_paths = 0;
  118. } in
  119. mctx.outcomes <- out :: mctx.outcomes;
  120. mctx.expr_map <- PMap.add id (e,eg) mctx.expr_map;
  121. out
  122. let clone_out mctx out p =
  123. let out = {out with o_pos = p; } in
  124. mctx.outcomes <- out :: mctx.outcomes;
  125. out
  126. let get_guard mctx id =
  127. snd (PMap.find id mctx.expr_map)
  128. let get_expr mctx id =
  129. fst (PMap.find id mctx.expr_map)
  130. let mk_pat pdef t p = {
  131. p_def = pdef;
  132. p_type = t;
  133. p_pos = p;
  134. }
  135. let mk_con cdef t p = {
  136. c_def = cdef;
  137. c_type = t;
  138. c_pos = p;
  139. }
  140. let mk_con_pat cdef pl t p = mk_pat (PCon(mk_con cdef t p,pl)) t p
  141. let mk_any t p = mk_pat PAny t p
  142. let any = mk_any t_dynamic Ast.null_pos
  143. let fake_tuple_type = TInst(mk_class null_module ([],"-Tuple") null_pos, [])
  144. let mk_type_pat ctx mt t p =
  145. let rec loop = function
  146. | TClassDecl _ -> "Class"
  147. | TEnumDecl _ -> "Enum"
  148. | TAbstractDecl a when Meta.has Meta.RuntimeValue a.a_meta -> "Class"
  149. | TTypeDecl t ->
  150. begin match follow (monomorphs t.t_params t.t_type) with
  151. | TInst(c,_) -> loop (TClassDecl c)
  152. | TEnum(en,_) -> loop (TEnumDecl en)
  153. | TAbstract(a,_) -> loop (TAbstractDecl a)
  154. | _ -> error "Cannot use this type as a value" p
  155. end
  156. | _ -> error "Cannot use this type as a value" p
  157. in
  158. let tcl = Typeload.load_instance ctx {tname=loop mt;tpackage=[];tsub=None;tparams=[]} p true in
  159. let t2 = match tcl with TAbstract(a,_) -> TAbstract(a,[mk_mono()]) | _ -> assert false in
  160. unify ctx t t2 p;
  161. mk_con_pat (CType mt) [] t2 p
  162. let mk_subs st con =
  163. let map = match follow st.st_type with
  164. | TInst(c,pl) -> apply_params c.cl_params pl
  165. | TEnum(en,pl) -> apply_params en.e_params pl
  166. | TAbstract(a,pl) -> apply_params a.a_params pl
  167. | _ -> fun t -> t
  168. in
  169. match con.c_def with
  170. | CFields (_,fl) -> List.map (fun (s,cf) -> mk_st (SField(st,cf)) (map cf.cf_type) st.st_pos) fl
  171. | CEnum (en,({ef_type = TFun _} as ef)) ->
  172. let rec loop t = match follow t with
  173. | TEnum(_,pl) -> pl
  174. | TAbstract({a_path = [],"EnumValue"},[]) -> []
  175. | TAbstract(a,pl) -> loop (Abstract.get_underlying_type a pl)
  176. | _ -> []
  177. in
  178. let pl = loop con.c_type in
  179. begin match apply_params en.e_params pl (monomorphs ef.ef_params ef.ef_type) with
  180. | TFun(args,r) ->
  181. ExtList.List.mapi (fun i (_,_,t) ->
  182. mk_st (SEnum(st,ef,i)) t st.st_pos
  183. ) args
  184. | _ ->
  185. assert false
  186. end
  187. | CArray 0 -> []
  188. | CArray i ->
  189. let t = match follow con.c_type with TInst({cl_path=[],"Array"},[t]) -> t | TDynamic _ as t -> t | _ -> assert false in
  190. ExtList.List.init i (fun i -> mk_st (SArray(st,i)) t st.st_pos)
  191. | CEnum _ | CConst _ | CType _ | CExpr _ | CAny ->
  192. []
  193. let get_tuple_params t = match t with
  194. | TFun(tl,tr) when tr == fake_tuple_type -> Some tl
  195. | _ -> None
  196. (* Printing *)
  197. let s_type = s_type (print_context())
  198. let rec s_con con = match con.c_def with
  199. | CEnum(_,ef) -> ef.ef_name
  200. | CAny -> "_"
  201. | CConst c -> s_const c
  202. | CType mt -> s_type_path (t_path mt)
  203. | CArray i -> "[" ^(string_of_int i) ^ "]"
  204. | CFields (_,fl) -> String.concat "," (List.map (fun (s,_) -> s) fl)
  205. | CExpr e -> s_expr s_type e
  206. let rec s_pat pat = match pat.p_def with
  207. | PVar (v,_) -> v.v_name
  208. | PCon (c,[]) -> s_con c
  209. | PCon (c,pl) -> s_con c ^ "(" ^ (String.concat "," (List.map s_pat pl)) ^ ")"
  210. | POr (pat1,pat2) -> s_pat pat1 ^ " | " ^ s_pat pat2
  211. | PAny -> "_"
  212. | PBind((v,_),pat) -> v.v_name ^ "=" ^ s_pat pat
  213. | PTuple pl -> "(" ^ (String.concat " " (Array.to_list (Array.map s_pat pl))) ^ ")"
  214. let rec s_pat_vec pl =
  215. String.concat " " (Array.to_list (Array.map s_pat pl))
  216. let rec s_pat_matrix pmat =
  217. String.concat "\n" (List.map (fun (pl,out) -> (s_pat_vec pl) ^ "->" ^ "") pmat)
  218. let st_args l r v =
  219. (if l > 0 then (String.concat "," (ExtList.List.make l "_")) ^ "," else "")
  220. ^ v ^
  221. (if r > 0 then "," ^ (String.concat "," (ExtList.List.make r "_")) else "")
  222. let rec s_st st =
  223. (match st.st_def with
  224. | SVar v -> v.v_name
  225. | SEnum (st,ef,i) -> s_st st ^ "." ^ ef.ef_name ^ "." ^ (string_of_int i)
  226. | SArray (st,i) -> s_st st ^ "[" ^ (string_of_int i) ^ "]"
  227. | STuple (st,i,a) -> "(" ^ (st_args i (a - i - 1) (s_st st)) ^ ")"
  228. | SField (st,cf) -> s_st st ^ "." ^ cf.cf_name)
  229. (* Pattern parsing *)
  230. let unify_enum_field en pl ef t =
  231. let t2 = match follow ef.ef_type with
  232. | TFun(_,r) -> r
  233. | t2 -> t2
  234. in
  235. let t2 = (apply_params en.e_params pl (monomorphs ef.ef_params t2)) in
  236. Type.unify t2 t
  237. let unify ctx a b p =
  238. try unify_raise ctx a b p with Error (Unify l,p) -> error (error_msg (Unify l)) p
  239. let rec is_value_type = function
  240. | TMono r ->
  241. (match !r with None -> false | Some t -> is_value_type t)
  242. | TType (t,tl) ->
  243. is_value_type (apply_params t.t_params tl t.t_type)
  244. | TInst({cl_path=[],"String"},[]) ->
  245. true
  246. | TAbstract _ ->
  247. true
  248. | _ ->
  249. false
  250. (* Determines if a type allows null-matching. This is similar to is_nullable, but it infers Null<T> on monomorphs *)
  251. let rec matches_null ctx t = match t with
  252. | TMono r ->
  253. (match !r with None -> r := Some (ctx.t.tnull (mk_mono())); true | Some t -> matches_null ctx t)
  254. | TType ({ t_path = ([],"Null") },[_]) ->
  255. true
  256. | TLazy f ->
  257. matches_null ctx (!f())
  258. | TType (t,tl) ->
  259. matches_null ctx (apply_params t.t_params tl t.t_type)
  260. | TFun _ ->
  261. false
  262. | TAbstract (a,_) -> not (Meta.has Meta.NotNull a.a_meta)
  263. | _ ->
  264. true
  265. let to_pattern ctx e t =
  266. let perror p = error "Unrecognized pattern" p in
  267. let verror n p = error ("Variable " ^ n ^ " must appear exactly once in each sub-pattern") p in
  268. let mk_var tctx s t p =
  269. let v = match tctx.pc_sub_vars with
  270. | Some vmap -> fst (try PMap.find s vmap with Not_found -> verror s p)
  271. | None -> alloc_var s t
  272. in
  273. unify ctx t v.v_type p;
  274. if PMap.mem s tctx.pc_locals then verror s p;
  275. tctx.pc_locals <- PMap.add s (v,p) tctx.pc_locals;
  276. v
  277. in
  278. let rec loop pctx e t =
  279. let p = pos e in
  280. match fst e with
  281. | ECheckType(e, CTPath({tpackage=["haxe";"macro"]; tname="Expr"})) ->
  282. let old = pctx.pc_reify in
  283. pctx.pc_reify <- true;
  284. let e = loop pctx e t in
  285. pctx.pc_reify <- old;
  286. e
  287. | EParenthesis e ->
  288. loop pctx e t
  289. | ECast(e1,None) ->
  290. loop pctx e1 t
  291. | EConst(Ident "null") ->
  292. if not (matches_null ctx t) then error ("Null-patterns are only allowed on nullable types (found " ^ (s_type t) ^ ")") p;
  293. mk_con_pat (CConst TNull) [] t p
  294. | EConst((Ident ("false" | "true") | Int _ | String _ | Float _) as c) ->
  295. let e = Codegen.type_constant ctx.com c p in
  296. unify ctx e.etype t p;
  297. let c = match e.eexpr with TConst c -> c | _ -> assert false in
  298. mk_con_pat (CConst c) [] t p
  299. | EMeta((Meta.Macro,[],_),(ECall (e1,args),_)) ->
  300. let path, field, args = Codegen.get_macro_path ctx e1 args p in
  301. begin match ctx.g.do_macro ctx MExpr path field args p with
  302. | Some e -> loop pctx e t
  303. | None -> error "Macro failure" p
  304. end
  305. | EField _ ->
  306. let e = type_expr ctx e (WithType t) in
  307. let e = match Optimizer.make_constant_expression ctx ~concat_strings:true e with Some e -> e | None -> e in
  308. (match e.eexpr with
  309. | TConst c | TCast({eexpr = TConst c},None) ->
  310. mk_con_pat (CConst c) [] t p
  311. | TTypeExpr mt ->
  312. mk_type_pat ctx mt t p
  313. | TField(_, FEnum(en,ef)) ->
  314. begin try
  315. unify_enum_field en (List.map (fun _ -> mk_mono()) en.e_params) ef t
  316. with Unify_error l ->
  317. error (error_msg (Unify l)) p
  318. end;
  319. mk_con_pat (CEnum(en,ef)) [] t p
  320. | _ -> error "Constant expression expected" p)
  321. | ECall(ec,el) ->
  322. let ec = type_expr ctx ec (WithType t) in
  323. (match follow ec.etype with
  324. | TEnum(en,pl)
  325. | TFun(_,TEnum(en,pl)) ->
  326. let ef = match ec.eexpr with
  327. | TField (_,FEnum (_,f)) -> f
  328. | _ -> error ("Expected constructor for enum " ^ (s_type_path en.e_path)) p
  329. in
  330. let monos = List.map (fun _ -> mk_mono()) ef.ef_params in
  331. let tl,r = match apply_params en.e_params pl (apply_params ef.ef_params monos ef.ef_type) with
  332. | TFun(args,r) ->
  333. unify ctx r t p;
  334. List.map (fun (n,_,t) -> t) args,r
  335. | _ -> error "No arguments expected" p
  336. in
  337. let rec loop2 i el tl = match el,tl with
  338. | (EConst(Ident "_"),pany) :: [], t :: tl ->
  339. let pat = mk_pat PAny t_dynamic pany in
  340. (ExtList.List.make ((List.length tl) + 1) pat)
  341. | e :: el, t :: tl ->
  342. let pat = loop pctx e t in
  343. pat :: loop2 (i + 1) el tl
  344. | e :: _, [] ->
  345. error "Too many arguments" (pos e);
  346. | [],_ :: _ ->
  347. error "Not enough arguments" p;
  348. | [],[] ->
  349. []
  350. in
  351. let el = loop2 0 el tl in
  352. (* We want to change the original monomorphs back to type parameters, but we don't want to do that
  353. if they are bound to other monomorphs (issue #4578). *)
  354. List.iter2 (fun m (_,t) -> match m,follow m with TMono m1, TMono m2 when m1 == m2 -> Type.unify m t | _ -> ()) monos ef.ef_params;
  355. pctx.pc_is_complex <- true;
  356. mk_con_pat (CEnum(en,ef)) el r p
  357. | _ -> perror p)
  358. | EConst(Ident "_") ->
  359. begin match get_tuple_params t with
  360. | Some tl ->
  361. let pl = List.map (fun (_,_,t) -> mk_any t p) tl in
  362. mk_pat (PTuple (Array.of_list pl)) t_dynamic p
  363. | None ->
  364. mk_any t p
  365. end
  366. | EConst(Ident s) ->
  367. begin try
  368. let ec = match follow t with
  369. | TEnum(en,pl) ->
  370. let ef = try
  371. PMap.find s en.e_constrs
  372. with Not_found when not (is_lower_ident s) ->
  373. error (string_error s en.e_names ("Expected constructor for enum " ^ (s_type_path en.e_path))) p
  374. in
  375. (match ef.ef_type with
  376. | TFun (args,_) ->
  377. let msg = Printf.sprintf "Enum constructor %s.%s requires parameters %s"
  378. (s_type_path en.e_path)
  379. ef.ef_name
  380. (String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (s_type t)) args))
  381. in
  382. error msg p
  383. | _ -> ());
  384. let et = mk (TTypeExpr (TEnumDecl en)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics en) }) p in
  385. mk (TField (et,FEnum (en,ef))) (apply_params en.e_params pl ef.ef_type) p
  386. | TAbstract({a_impl = Some c} as a,_) when Meta.has Meta.Enum a.a_meta ->
  387. let cf = PMap.find s c.cl_statics in
  388. Type.unify (follow cf.cf_type) t;
  389. let e = begin match cf.cf_expr with
  390. | Some ({eexpr = TConst c | TCast({eexpr = TConst c},None)} as e) -> e
  391. | _ -> raise Not_found
  392. end in
  393. e
  394. | _ ->
  395. let old = ctx.untyped in
  396. ctx.untyped <- true;
  397. let e = try type_expr ctx e (WithType t) with _ -> ctx.untyped <- old; raise Not_found in
  398. ctx.untyped <- old;
  399. e
  400. in
  401. let ec = match Optimizer.make_constant_expression ctx ~concat_strings:true ec with Some e -> e | None -> ec in
  402. (match ec.eexpr with
  403. | TField (_,FEnum (en,ef)) ->
  404. begin try unify_raise ctx ec.etype t ec.epos with Error (Unify _,_) -> raise Not_found end;
  405. begin try
  406. unify_enum_field en (List.map (fun _ -> mk_mono()) en.e_params) ef t;
  407. with Unify_error l ->
  408. error (error_msg (Unify l)) p
  409. end;
  410. mk_con_pat (CEnum(en,ef)) [] t p
  411. | TConst c | TCast({eexpr = TConst c},None) ->
  412. begin try unify_raise ctx ec.etype t ec.epos with Error (Unify _,_) -> raise Not_found end;
  413. unify ctx ec.etype t p;
  414. mk_con_pat (CConst c) [] t p
  415. | TTypeExpr mt ->
  416. mk_type_pat ctx mt t p
  417. | _ ->
  418. raise Not_found);
  419. with Not_found ->
  420. begin match get_tuple_params t with
  421. | Some tl ->
  422. let s = String.concat "," (List.map (fun (_,_,t) -> s_type t) tl) in
  423. error ("Pattern should be tuple [" ^ s ^ "]") p
  424. | None ->
  425. if not (is_lower_ident s) && s.[0] <> '`' then error "Capture variables must be lower-case" p;
  426. let v = mk_var pctx s t p in
  427. mk_pat (PVar (v,p)) v.v_type p
  428. end
  429. end
  430. | (EObjectDecl fl) ->
  431. let is_matchable cf = match cf.cf_kind with Method _ -> false | _ -> true in
  432. let is_valid_field_name fields co n p =
  433. try
  434. let cf = PMap.find n fields in
  435. begin match co with
  436. | Some c when not (Typer.can_access ctx c cf false) -> error ("Cannot match against private field " ^ n) p
  437. | _ -> ()
  438. end
  439. with Not_found ->
  440. error ((s_type t) ^ " has no field " ^ n ^ " that can be matched against") p;
  441. in
  442. pctx.pc_is_complex <- true;
  443. let loop_fields fields =
  444. let sl,pl,i = PMap.foldi (fun n cf (sl,pl,i) ->
  445. if not (is_matchable cf) then
  446. sl,pl,i
  447. else
  448. let pat = try
  449. if pctx.pc_reify && cf.cf_name = "pos" then raise Not_found;
  450. loop pctx (List.assoc cf.cf_name fl) cf.cf_type
  451. with Not_found ->
  452. (mk_any cf.cf_type p)
  453. in
  454. (n,cf) :: sl,pat :: pl,i + 1
  455. ) fields ([],[],0) in
  456. mk_con_pat (CFields(i,sl)) pl t p
  457. in
  458. let fields = match follow t with
  459. | TAnon {a_fields = fields} ->
  460. fields
  461. | TInst(c,tl) ->
  462. let fields = ref PMap.empty in
  463. let rec loop c tl =
  464. begin match c.cl_super with
  465. | Some (csup,tlsup) -> loop csup (List.map (apply_params c.cl_params tl) tlsup)
  466. | None -> ()
  467. end;
  468. PMap.iter (fun n cf -> fields := PMap.add n {cf with cf_type = apply_params c.cl_params tl (monomorphs cf.cf_params cf.cf_type)} !fields) c.cl_fields
  469. in
  470. loop c tl;
  471. !fields
  472. | TAbstract({a_impl = Some c} as a,tl) ->
  473. let fields = List.fold_left (fun acc cf ->
  474. if Meta.has Meta.Impl cf.cf_meta then
  475. PMap.add cf.cf_name cf acc
  476. else acc
  477. ) PMap.empty c.cl_ordered_statics in
  478. PMap.map (fun cf -> {cf with cf_type = apply_params a.a_params tl (monomorphs cf.cf_params cf.cf_type)}) fields
  479. | _ ->
  480. error ((s_type t) ^ " cannot be matched against a structure") p
  481. in
  482. List.iter (fun (n,(_,p)) -> is_valid_field_name fields None n p) fl;
  483. loop_fields fields
  484. | EArrayDecl [] ->
  485. mk_con_pat (CArray 0) [] t p
  486. | EArrayDecl el ->
  487. pctx.pc_is_complex <- true;
  488. begin match follow t with
  489. | TInst({cl_path=[],"Array"},[t2]) | (TDynamic _ as t2) ->
  490. let pl = ExtList.List.mapi (fun i e ->
  491. loop pctx e t2
  492. ) el in
  493. mk_con_pat (CArray (List.length el)) pl t p
  494. | TFun(tl,tr) when tr == fake_tuple_type ->
  495. let pl = try
  496. List.map2 (fun e (_,_,t) -> loop pctx e t) el tl
  497. with Invalid_argument _ ->
  498. error ("Invalid number of arguments: expected " ^ (string_of_int (List.length tl)) ^ ", found " ^ (string_of_int (List.length el))) p
  499. in
  500. mk_pat (PTuple (Array.of_list pl)) t p
  501. | _ ->
  502. error ((s_type t) ^ " should be Array") p
  503. end
  504. | EBinop(OpAssign,(EConst(Ident s),p2),e1) ->
  505. let v = mk_var pctx s t p in
  506. let pat1 = loop pctx e1 t in
  507. mk_pat (PBind((v,p),pat1)) t p2
  508. | EBinop(OpOr,(EBinop(OpOr,e1,e2),p2),e3) ->
  509. loop pctx (EBinop(OpOr,e1,(EBinop(OpOr,e2,e3),p2)),p) t
  510. | EBinop(OpOr,e1,e2) ->
  511. let old = pctx.pc_locals in
  512. let pat1 = loop pctx e1 t in
  513. begin match pat1.p_def with
  514. | PAny | PVar _ ->
  515. display_error ctx "This pattern is unused" (pos e2);
  516. pat1
  517. | _ ->
  518. let pctx2 = {
  519. pc_sub_vars = Some pctx.pc_locals;
  520. pc_locals = old;
  521. pc_reify = pctx.pc_reify;
  522. pc_is_complex = pctx.pc_is_complex;
  523. } in
  524. let pat2 = loop pctx2 e2 t in
  525. pctx.pc_is_complex <- pctx2.pc_is_complex;
  526. PMap.iter (fun s (_,p) -> if not (PMap.mem s pctx2.pc_locals) then verror s p) pctx.pc_locals;
  527. mk_pat (POr(pat1,pat2)) pat2.p_type (punion pat1.p_pos pat2.p_pos);
  528. end
  529. | _ ->
  530. raise (Unrecognized_pattern e)
  531. in
  532. let pctx = {
  533. pc_locals = PMap.empty;
  534. pc_sub_vars = None;
  535. pc_reify = false;
  536. pc_is_complex = false;
  537. } in
  538. let x = loop pctx e t in
  539. x, pctx.pc_locals, pctx.pc_is_complex
  540. let get_pattern_locals ctx e t =
  541. try
  542. let _,locals,_ = to_pattern ctx e t in
  543. PMap.foldi (fun n v acc -> PMap.add n v acc) locals PMap.empty
  544. with Unrecognized_pattern _ ->
  545. PMap.empty
  546. (* Match compilation *)
  547. let expr_eq e1 e2 = e1 == e2 || match e1.eexpr,e2.eexpr with
  548. | TConst ct1,TConst ct2 ->
  549. ct1 = ct2
  550. | TField(_,FStatic(c1,cf1)),TField(_,FStatic(c2,cf2)) ->
  551. c1 == c2 && cf1.cf_name = cf2.cf_name
  552. | _ ->
  553. false
  554. let unify_con con1 con2 = match con1.c_def,con2.c_def with
  555. | CExpr e1, CExpr e2 ->
  556. expr_eq e1 e2
  557. | CConst c1,CConst c2 ->
  558. c1 = c2
  559. | CEnum(e1,ef1),CEnum(e2,ef2) ->
  560. e1 == e2 && ef1.ef_name = ef2.ef_name
  561. | CFields (i1,fl1),CFields (i2,fl2) ->
  562. (try
  563. List.iter (fun (s,_) -> if not (List.mem_assoc s fl1) then raise Not_found) fl2;
  564. true
  565. with Not_found ->
  566. false)
  567. | CType mt1,CType mt2 ->
  568. t_path mt1 = t_path mt2
  569. | CArray a1, CArray a2 ->
  570. a1 == a2
  571. | CAny, CAny ->
  572. true
  573. | _ ->
  574. false
  575. let array_tl arr = Array.sub arr 1 (Array.length arr - 1)
  576. let spec mctx con pmat =
  577. let a = arity con in
  578. let r = DynArray.create () in
  579. let add pv out =
  580. DynArray.add r (pv,out)
  581. in
  582. let rec loop2 pv out = match pv.(0).p_def with
  583. | PCon(c2,pl) when unify_con c2 con ->
  584. add (Array.append (Array.of_list pl) (array_tl pv)) out
  585. | PCon(c2,pl) ->
  586. ()
  587. | PAny | PVar _->
  588. add (Array.append (Array.make a (mk_any (pv.(0).p_type) (pv.(0).p_pos))) (array_tl pv)) out
  589. | PBind(_,pat) ->
  590. loop2 (Array.append [|pat|] (array_tl pv)) out
  591. | PTuple tl ->
  592. loop2 tl out
  593. | POr _ ->
  594. assert false
  595. in
  596. let rec loop pmat = match pmat with
  597. | (pv,out) :: pl ->
  598. loop2 pv out;
  599. loop pl
  600. | [] ->
  601. ()
  602. in
  603. loop pmat;
  604. DynArray.to_list r
  605. let default mctx pmat =
  606. let r = DynArray.create () in
  607. let add pv out =
  608. DynArray.add r (pv,out)
  609. in
  610. let rec loop2 pv out = match pv.(0).p_def with
  611. | PCon _ ->
  612. ()
  613. | PAny | PVar _->
  614. add (array_tl pv) out
  615. | PBind(_,pat) ->
  616. loop2 (Array.append [|pat|] (array_tl pv)) out
  617. | PTuple tl ->
  618. loop2 tl out
  619. | POr _ ->
  620. assert false
  621. in
  622. let rec loop pmat = match pmat with
  623. | (pv,out) :: pl ->
  624. loop2 pv out;
  625. loop pl;
  626. | [] ->
  627. ()
  628. in
  629. loop pmat;
  630. DynArray.to_list r
  631. let pick_column pmat =
  632. let rec loop i pv = if Array.length pv = 0 then -1 else match pv.(0).p_def with
  633. | PVar _ | PAny ->
  634. loop (i + 1) (array_tl pv)
  635. | PTuple pl ->
  636. loop i pl
  637. | _ ->
  638. i
  639. in
  640. loop 0 (fst (List.hd pmat))
  641. let swap_pmat_columns i pmat =
  642. List.map (fun (pv,out) ->
  643. let pv = match pv with [|{p_def = PTuple pt}|] -> pt | _ -> pv in
  644. let tmp = pv.(i) in
  645. Array.set pv i pv.(0);
  646. Array.set pv 0 tmp;
  647. pv,out
  648. ) pmat
  649. let swap_columns i (row : 'a list) : 'a list =
  650. match row with
  651. | rh :: rt ->
  652. let rec loop count acc col = match col with
  653. | [] -> acc
  654. | ch :: cl when i = count ->
  655. ch :: (List.rev acc) @ [rh] @ cl
  656. | ch :: cl ->
  657. loop (count + 1) (ch :: acc) cl
  658. in
  659. loop 1 [] rt
  660. | _ ->
  661. []
  662. let expand_or mctx (pmat : pat_matrix) =
  663. let rec loop pat = match pat.p_def with
  664. | POr(pat1,pat2) ->
  665. let pat1 = loop pat1 in
  666. let pat2 = loop pat2 in
  667. pat1 @ pat2
  668. | PBind(v,pat1) ->
  669. let pat1 = loop pat1 in
  670. List.map (fun pat1 ->
  671. {pat with p_def = PBind(v,pat1)}
  672. ) pat1
  673. | PTuple(pl) ->
  674. let pat1 = loop pl.(0) in
  675. List.map (fun pat1 ->
  676. let a1 = Array.copy pl in
  677. a1.(0) <- pat1;
  678. {pat with p_def = PTuple a1}
  679. ) pat1
  680. | _ ->
  681. [pat]
  682. in
  683. let rec loop2 pmat = match pmat with
  684. | (pv,out) :: pmat ->
  685. let pat = loop pv.(0) in
  686. let pat' = ExtList.List.mapi (fun i pat ->
  687. (* TODO: This should really be active, but currently causes problems with or-patterns in
  688. tuples (issue #2610). We will disable this for the 3.1.0 release, which means issue
  689. #2508 is open again. *)
  690. (* let out = if i = 0 then out else clone_out mctx out pat.p_pos in *)
  691. let a1 = Array.copy pv in
  692. a1.(0) <- pat;
  693. a1,out
  694. ) pat in
  695. pat' @ (loop2 pmat)
  696. | [] ->
  697. []
  698. in
  699. loop2 pmat
  700. let column_sigma mctx st pmat =
  701. let acc = ref [] in
  702. let bindings = ref [] in
  703. let unguarded = Hashtbl.create 0 in
  704. let add c g =
  705. if not (List.exists (fun c2 -> unify_con c2 c) !acc) then acc := c :: !acc;
  706. if not g then Hashtbl.replace unguarded c.c_def true;
  707. in
  708. let bind_st out st v =
  709. if not (List.exists (fun ((v2,p),_) -> v2.v_id == (fst v).v_id) !bindings) then bindings := (v,st) :: !bindings
  710. in
  711. let rec loop pmat = match pmat with
  712. | (pv,out) :: pr ->
  713. let rec loop2 out = function
  714. | PCon (c,_) ->
  715. add c ((get_guard mctx out.o_id) <> None);
  716. | PVar v ->
  717. bind_st out st v;
  718. | PBind(v,pat) ->
  719. bind_st out st v;
  720. loop2 out pat.p_def
  721. | PAny ->
  722. ()
  723. | PTuple tl ->
  724. loop2 out tl.(0).p_def
  725. | POr _ ->
  726. assert false
  727. in
  728. loop2 out pv.(0).p_def;
  729. loop pr
  730. | [] ->
  731. ()
  732. in
  733. loop pmat;
  734. List.rev_map (fun con -> con,not (Hashtbl.mem unguarded con.c_def)) !acc,!bindings
  735. let rec all_ctors mctx t =
  736. let h = ref PMap.empty in
  737. if is_explicit_null t then h := PMap.add (CConst TNull) Ast.null_pos !h;
  738. match follow t with
  739. | TAbstract({a_path = [],"Bool"},_) ->
  740. h := PMap.add (CConst(TBool true)) Ast.null_pos !h;
  741. h := PMap.add (CConst(TBool false)) Ast.null_pos !h;
  742. h,RunTimeFinite
  743. | TAbstract({a_impl = Some c} as a,pl) when Meta.has Meta.Enum a.a_meta ->
  744. List.iter (fun cf ->
  745. ignore(follow cf.cf_type);
  746. if Meta.has Meta.Impl cf.cf_meta then match cf.cf_expr with
  747. | Some {eexpr = TConst c | TCast ({eexpr = TConst c},None)} -> h := PMap.add (CConst c) cf.cf_pos !h
  748. | _ -> ()
  749. ) c.cl_ordered_statics;
  750. h,CompileTimeFinite
  751. | TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> all_ctors mctx (Abstract.get_underlying_type a pl)
  752. | TInst({cl_path=[],"String"},_)
  753. | TInst({cl_path=[],"Array"},_) ->
  754. h,Infinite
  755. | TEnum(en,pl) ->
  756. PMap.iter (fun _ ef ->
  757. let tc = monomorphs mctx.ctx.type_params t in
  758. try unify_enum_field en pl ef tc;
  759. h := PMap.add (CEnum(en,ef)) ef.ef_pos !h
  760. with Unify_error _ ->
  761. ()
  762. ) en.e_constrs;
  763. h,RunTimeFinite
  764. | TAnon a ->
  765. h,CompileTimeFinite
  766. | TInst(_,_) ->
  767. h,CompileTimeFinite
  768. | _ ->
  769. h,Infinite
  770. let rec collapse_pattern pl = match pl with
  771. | pat :: [] ->
  772. pat
  773. | pat :: pl ->
  774. let pat2 = collapse_pattern pl in
  775. mk_pat (POr(pat,pat2)) pat.p_type (punion pat.p_pos pat2.p_pos)
  776. | [] ->
  777. assert false
  778. let bind_remaining out pv stl =
  779. let rec loop stl pv =
  780. if Array.length pv = 0 then
  781. []
  782. else
  783. match stl,pv.(0).p_def with
  784. | st :: stl,PAny ->
  785. loop stl (array_tl pv)
  786. | st :: stl,PVar v ->
  787. (v,st) :: loop stl (array_tl pv)
  788. | stl,PTuple pl ->
  789. loop stl pl
  790. | _ :: _,_->
  791. loop stl (array_tl pv)
  792. | [],_ ->
  793. []
  794. in
  795. loop stl pv
  796. let get_cache mctx dt =
  797. match dt with Goto _ -> dt | _ ->
  798. try
  799. Goto (Hashtbl.find mctx.dt_cache dt)
  800. with Not_found ->
  801. Hashtbl.replace mctx.dt_cache dt mctx.dt_count;
  802. mctx.dt_count <- mctx.dt_count + 1;
  803. DynArray.add mctx.dt_lut dt;
  804. dt
  805. let rec compile mctx stl pmat toplevel =
  806. let guard id dt1 dt2 = get_cache mctx (Guard(id,dt1,dt2)) in
  807. let expr id = get_cache mctx (Expr id) in
  808. let bind bl dt = get_cache mctx (Bind(bl,dt)) in
  809. let switch st cl = get_cache mctx (Switch(st,cl)) in
  810. let compile mctx stl pmat toplevel =
  811. try
  812. compile mctx stl pmat toplevel
  813. with Not_exhaustive_default when stl <> [] ->
  814. raise (Not_exhaustive(any,List.hd stl))
  815. in
  816. get_cache mctx (match pmat with
  817. | [] ->
  818. (match stl with
  819. | st :: stl ->
  820. let all,inf = all_ctors mctx st.st_type in
  821. let pl = PMap.foldi (fun cd p acc -> (mk_con_pat cd [] t_dynamic p) :: acc) !all [] in
  822. begin match pl,inf with
  823. | _,Infinite
  824. | [],_ ->
  825. raise (Not_exhaustive(any,st))
  826. | _ ->
  827. raise (Not_exhaustive(collapse_pattern pl,st))
  828. end
  829. | _ ->
  830. (* This can happen in cases a value is required and all default cases are guarded (issue #3150).
  831. Not a particularly elegant solution, may want to revisit this later. *)
  832. raise Not_exhaustive_default)
  833. | ([|{p_def = PTuple pt}|],out) :: pl ->
  834. compile mctx stl ((pt,out) :: pl) toplevel
  835. | (pv,out) :: pl ->
  836. let i = pick_column pmat in
  837. if i = -1 then begin
  838. out.o_num_paths <- out.o_num_paths + 1;
  839. let bl = bind_remaining out pv stl in
  840. let dt = match (get_guard mctx out.o_id) with
  841. | None ->
  842. expr out.o_id
  843. | Some _ ->
  844. let dt = match pl with
  845. | [] ->
  846. if mctx.need_val then raise Not_exhaustive_default
  847. else None
  848. | _ ->
  849. Some (compile mctx stl pl false)
  850. in
  851. guard out.o_id (expr out.o_id) dt
  852. in
  853. (if bl = [] then dt else bind bl dt)
  854. end else if i > 0 then begin
  855. let pmat = swap_pmat_columns i pmat in
  856. let stls = swap_columns i stl in
  857. compile mctx stls pmat toplevel
  858. end else begin
  859. let st_head,st_tail = match stl with st :: stl -> st,stl | _ -> assert false in
  860. let pmat = expand_or mctx pmat in
  861. let sigma,bl = column_sigma mctx st_head pmat in
  862. let all,inf = all_ctors mctx pv.(0).p_type in
  863. let cases = List.map (fun (c,g) ->
  864. if not g then all := PMap.remove c.c_def !all;
  865. let spec = spec mctx c pmat in
  866. let hsubs = mk_subs st_head c in
  867. let subs = hsubs @ st_tail in
  868. let dt = compile mctx subs spec false in
  869. c,dt
  870. ) sigma in
  871. let def = default mctx pmat in
  872. let dt = match def,cases with
  873. | _ when inf = RunTimeFinite && PMap.is_empty !all ->
  874. switch st_head cases
  875. | [],_ when inf = CompileTimeFinite && PMap.is_empty !all ->
  876. switch st_head cases
  877. | [],_ when inf = Infinite && not mctx.need_val && toplevel ->
  878. (* ignore exhaustiveness, but mark context so we do not generate @:exhaustive metadata *)
  879. mctx.is_exhaustive <- false;
  880. switch st_head cases
  881. | [],_ when inf = Infinite ->
  882. raise (Not_exhaustive(any,st_head))
  883. | [],_ ->
  884. let pl = PMap.foldi (fun cd p acc -> (mk_con_pat cd [] t_dynamic p) :: acc) !all [] in
  885. (* toplevel null can be omitted because the French dig runtime errors (issue #3054) *)
  886. if toplevel && (match pl with
  887. | [{p_def = PCon ({c_def = (CConst TNull)},_)}] -> true
  888. | _ -> false) then
  889. switch st_head cases
  890. else
  891. raise (Not_exhaustive(collapse_pattern pl,st_head))
  892. | def,[] ->
  893. compile mctx st_tail def false
  894. | def,_ ->
  895. let cdef = mk_con CAny t_dynamic st_head.st_pos in
  896. let def = compile mctx st_tail def false in
  897. let cases = cases @ [cdef,def] in
  898. switch st_head cases
  899. in
  900. if bl = [] then dt else bind bl dt
  901. end)
  902. let rec collapse_case el = match el with
  903. | e :: [] ->
  904. e
  905. | e :: el ->
  906. let e2 = collapse_case el in
  907. EBinop(OpOr,e,e2),punion (pos e) (pos e2)
  908. | [] ->
  909. assert false
  910. let mk_const ctx p = function
  911. | TString s -> mk (TConst (TString s)) ctx.com.basic.tstring p
  912. | TInt i -> mk (TConst (TInt i)) ctx.com.basic.tint p
  913. | TFloat f -> mk (TConst (TFloat f)) ctx.com.basic.tfloat p
  914. | TBool b -> mk (TConst (TBool b)) ctx.com.basic.tbool p
  915. | TNull -> mk (TConst TNull) (ctx.com.basic.tnull (mk_mono())) p
  916. | _ -> error "Unsupported constant" p
  917. let rec convert_st ctx st = match st.st_def with
  918. | SVar v -> mk (TLocal v) v.v_type st.st_pos
  919. | SField (sts,cf) ->
  920. let e = convert_st ctx sts in
  921. Typer.acc_get ctx (Typer.type_field ctx e cf.cf_name st.st_pos Typer.MGet) st.st_pos
  922. | SArray (sts,i) -> mk (TArray(convert_st ctx sts,mk_const ctx st.st_pos (TInt (Int32.of_int i)))) st.st_type st.st_pos
  923. | STuple (st,_,_) -> convert_st ctx st
  924. | SEnum (sts,ef,i) -> mk (TEnumParameter(convert_st ctx sts, ef, i)) st.st_type st.st_pos
  925. let convert_con ctx con = match con.c_def with
  926. | CConst c -> mk_const ctx con.c_pos c
  927. | CType mt -> mk (TTypeExpr mt) t_dynamic con.c_pos
  928. | CExpr e -> e
  929. | CEnum(e,ef) when Meta.has Meta.FakeEnum e.e_meta ->
  930. let e_mt = !type_module_type_ref ctx (TEnumDecl e) None con.c_pos in
  931. mk (TField(e_mt,FEnum(e,ef))) con.c_type con.c_pos
  932. | CEnum(e,ef) -> mk_const ctx con.c_pos (TInt (Int32.of_int ef.ef_index))
  933. | CArray i -> mk_const ctx con.c_pos (TInt (Int32.of_int i))
  934. | CAny | CFields _ -> assert false
  935. let convert_switch mctx st cases loop =
  936. let ctx = mctx.ctx in
  937. let e_st = convert_st ctx st in
  938. let p = e_st.epos in
  939. let mk_index_call () =
  940. let ttype = match follow (Typeload.load_instance ctx { tpackage = ["std"]; tname="Type"; tparams=[]; tsub = None} p true) with TInst(c,_) -> c | t -> assert false in
  941. let cf = PMap.find "enumIndex" ttype.cl_statics in
  942. let ec = (!type_module_type_ref) ctx (TClassDecl ttype) None p in
  943. let ef = mk (TField(ec, FStatic(ttype,cf))) (tfun [e_st.etype] ctx.t.tint) p in
  944. let e = make_call ctx ef [e_st] ctx.t.tint p in
  945. e
  946. in
  947. let wrap_exhaustive e =
  948. if mctx.is_exhaustive then
  949. mk (TMeta((Meta.Exhaustive,[],e.epos),e)) e.etype e.epos
  950. else
  951. e
  952. in
  953. let e = match follow st.st_type with
  954. | TEnum(en,_) when Meta.has Meta.FakeEnum en.e_meta ->
  955. wrap_exhaustive (e_st)
  956. | TEnum(_) ->
  957. wrap_exhaustive (mk_index_call())
  958. | TAbstract(a,pl) when (match Abstract.get_underlying_type a pl with TEnum(_) -> true | _ -> false) ->
  959. wrap_exhaustive (mk_index_call())
  960. | TInst({cl_path = [],"Array"},_) as t ->
  961. mk (TField (e_st,quick_field t "length")) ctx.t.tint p
  962. | TAbstract(a,_) when Meta.has Meta.Enum a.a_meta ->
  963. wrap_exhaustive (e_st)
  964. | TAbstract({a_path = [],"Bool"},_) ->
  965. wrap_exhaustive (e_st)
  966. | _ ->
  967. let rec loop cases = match cases with
  968. | [] -> e_st
  969. | (con,_) :: cases ->
  970. begin match con.c_def with
  971. | CEnum _ -> mk_index_call()
  972. | CArray _ -> mk (TField (e_st,FDynamic "length")) ctx.t.tint p
  973. | _ -> loop cases
  974. end
  975. in
  976. loop cases
  977. in
  978. let null = ref None in
  979. let def = ref None in
  980. let cases = List.filter (fun (con,dt) ->
  981. match con.c_def with
  982. | CConst TNull ->
  983. null := Some (loop dt);
  984. false
  985. | CAny ->
  986. def := Some (loop dt);
  987. false
  988. | _ ->
  989. true
  990. ) cases in
  991. let dt = match cases with
  992. | [{c_def = CFields _},dt] -> loop dt
  993. | _ -> DTSwitch(e, List.map (fun (c,dt) -> convert_con ctx c, loop dt) cases, !def)
  994. in
  995. match !null with
  996. | None when is_explicit_null st.st_type && (!def <> None || not mctx.need_val) ->
  997. let econd = mk (TBinop(OpNotEq,e_st,mk (TConst TNull) st.st_type p)) ctx.t.tbool p in
  998. DTGuard(econd,dt,!def)
  999. | None ->
  1000. dt
  1001. | Some dt_null ->
  1002. let t = match ctx.t.tnull ctx.t.tint with
  1003. | TType(t,_) ->TType(t,[st.st_type])
  1004. | t -> t
  1005. in
  1006. let e_null = mk (TConst TNull) t p in
  1007. let econd = mk (TBinop(OpEq,e_st, e_null)) ctx.t.tbool p in
  1008. DTGuard(econd,dt_null,Some dt)
  1009. (* Decision tree compilation *)
  1010. let transform_extractors eval cases p =
  1011. let efail = (EThrow(EConst(Ident "false"),p)),p in
  1012. let cfail = [(EConst (Ident "_"),p)],None,Some efail in
  1013. let has_extractor = ref false in
  1014. let rec loop cases = match cases with
  1015. | (epat,eg,e) :: cases ->
  1016. let ex = ref [] in
  1017. let exc = ref 0 in
  1018. let rec find_ex in_or e = match fst e with
  1019. | EBinop(OpArrow,_,_) when in_or ->
  1020. error "Extractors in or patterns are not allowed" (pos e)
  1021. | EBinop(OpArrow, e1, e2) ->
  1022. let ec = EConst (Ident ("__ex" ^ string_of_int (!exc))),snd e in
  1023. let rec map_left e = match fst e with
  1024. | EConst(Ident "_") -> ec
  1025. | _ -> Ast.map_expr map_left e
  1026. in
  1027. let ecall = map_left e1 in
  1028. ex := (ecall,e2) :: !ex;
  1029. incr exc;
  1030. has_extractor := true;
  1031. ec
  1032. | EBinop(OpOr,e1,e2) ->
  1033. let e1 = find_ex true e1 in
  1034. let e2 = find_ex true e2 in
  1035. (EBinop(OpOr,e1,e2)),(pos e)
  1036. | _ ->
  1037. Ast.map_expr (find_ex in_or) e
  1038. in
  1039. let p = match e with None -> p | Some e -> pos e in
  1040. let epat = match epat with
  1041. | [epat] -> [find_ex false epat]
  1042. | _ -> List.map (find_ex true) epat
  1043. in
  1044. let cases = loop cases in
  1045. if !exc = 0 then
  1046. (epat,eg,e) :: cases
  1047. else begin
  1048. let esubjects = EArrayDecl (List.map fst !ex),p in
  1049. let case1 = [EArrayDecl (List.map snd !ex),p],eg,e in
  1050. let cases2 = match cases with
  1051. | [] -> [case1]
  1052. | [[EConst (Ident "_"),_],_,e] -> case1 :: [[(EConst (Ident "_"),p)],None,e]
  1053. | _ ->
  1054. case1 :: [[(EConst (Ident "_"),p)],None,Some (ESwitch(eval,cases,None),p)]
  1055. in
  1056. let eswitch = (ESwitch(esubjects,cases2,None)),p in
  1057. let case = epat,None,Some eswitch in
  1058. begin match epat with
  1059. | [EConst(Ident _),_] ->
  1060. [case;cfail]
  1061. | _ ->
  1062. case :: cases
  1063. end
  1064. end
  1065. | [] ->
  1066. []
  1067. in
  1068. let cases = loop cases in
  1069. cases,!has_extractor
  1070. let extractor_depth = ref 0
  1071. let match_expr ctx e cases def with_type p =
  1072. let need_val,with_type,tmono = match with_type with
  1073. | NoValue -> false,NoValue,None
  1074. | WithType t | WithTypeResume t when (match follow t with TMono _ -> true | _ -> false) ->
  1075. (* we don't want to unify with each case individually, but instead at the end after unify_min *)
  1076. true,Value,Some with_type
  1077. | t -> true,t,None
  1078. in
  1079. (* turn default into case _ *)
  1080. let cases = match cases,def with
  1081. | [],None -> []
  1082. | cases,Some def ->
  1083. let p = match def with
  1084. | None -> p
  1085. | Some (_,p) -> p
  1086. in
  1087. cases @ [[(EConst(Ident "_")),p],None,def]
  1088. | _ -> cases
  1089. in
  1090. let cases,has_extractor = transform_extractors e cases p in
  1091. (* type subject(s) *)
  1092. let array_match = ref false in
  1093. let evals = match fst e with
  1094. | EArrayDecl el | EParenthesis(EArrayDecl el,_) when (match el with [(EFor _ | EWhile _),_] -> false | _ -> true) ->
  1095. array_match := true;
  1096. List.map (fun e -> type_expr ctx e Value) el
  1097. | _ ->
  1098. let e = type_expr ctx e Value in
  1099. begin match follow e.etype with
  1100. (* TODO: get rid of the XmlType check *)
  1101. | TEnum(en,_) when (match en.e_path with (["neko" | "php" | "flash" | "cpp"],"XmlType") -> true | _ -> false) ->
  1102. raise Exit
  1103. | TAbstract({a_path=[],("Int" | "Float" | "Bool")},_) | TInst({cl_path = [],"String"},_) when (Common.defined ctx.com Common.Define.NoPatternMatching) ->
  1104. raise Exit;
  1105. | _ ->
  1106. ()
  1107. end;
  1108. [e]
  1109. in
  1110. let var_inits = ref [] in
  1111. let save = save_locals ctx in
  1112. let a = List.length evals in
  1113. (* turn subjects to subterms and handle variable initialization where necessary *)
  1114. let stl = ExtList.List.mapi (fun i e ->
  1115. let rec loop e = match e.eexpr with
  1116. | TParenthesis e | TMeta(_,e) ->
  1117. loop e
  1118. | TLocal v ->
  1119. mk_st (SVar v) e.etype e.epos
  1120. | _ ->
  1121. let v = gen_local ctx e.etype in
  1122. var_inits := (v, Some e) :: !var_inits;
  1123. ctx.locals <- PMap.add v.v_name v ctx.locals;
  1124. mk_st (SVar v) e.etype e.epos
  1125. in
  1126. let st = loop e in
  1127. if a = 1 then st else mk_st (STuple(st,i,a)) st.st_type st.st_pos
  1128. ) evals in
  1129. let tl = List.map (fun st -> st.st_type) stl in
  1130. (* create matcher context *)
  1131. let mctx = {
  1132. ctx = ctx;
  1133. need_val = need_val;
  1134. outcomes = [];
  1135. toplevel_or = false;
  1136. dt_lut = DynArray.create ();
  1137. dt_cache = Hashtbl.create 0;
  1138. dt_count = 0;
  1139. has_extractor = has_extractor;
  1140. expr_map = PMap.empty;
  1141. is_exhaustive = true;
  1142. } in
  1143. (* flatten cases *)
  1144. let cases = List.map (fun (el,eg,e) ->
  1145. List.iter (fun e -> match fst e with EBinop(OpOr,_,_) -> mctx.toplevel_or <- true; | _ -> ()) el;
  1146. match el with
  1147. | [] ->
  1148. let p = match e with None -> p | Some e -> pos e in
  1149. error "case without a pattern is not allowed" p
  1150. | _ ->
  1151. collapse_case el,eg,e
  1152. ) cases in
  1153. let is_complex = ref false in
  1154. if mctx.has_extractor then incr extractor_depth;
  1155. let add_pattern_locals (pat,locals,complex) =
  1156. PMap.iter (fun n (v,p) -> ctx.locals <- PMap.add n v ctx.locals) locals;
  1157. if complex then is_complex := true;
  1158. pat
  1159. in
  1160. (* evaluate patterns *)
  1161. let pl = ExtList.List.mapi (fun i (ep,eg,e) ->
  1162. let save = save_locals ctx in
  1163. (* type case patterns *)
  1164. let pl,restore,with_type =
  1165. try
  1166. (* context type parameters are turned into monomorphs until the pattern has been typed *)
  1167. let monos = List.map (fun _ -> mk_mono()) ctx.type_params in
  1168. let t = match tl with [t] when not !array_match -> t | tl -> tfun tl fake_tuple_type in
  1169. let t = apply_params ctx.type_params monos t in
  1170. let pl = [add_pattern_locals (to_pattern ctx ep t)] in
  1171. let old_ret = ctx.ret in
  1172. ctx.ret <- apply_params ctx.type_params monos ctx.ret;
  1173. let restore = PMap.fold (fun v acc ->
  1174. (* apply context monomorphs to locals and replace them back after typing the case body *)
  1175. let t = v.v_type in
  1176. v.v_type <- apply_params ctx.type_params monos v.v_type;
  1177. (fun () -> v.v_type <- t) :: acc
  1178. ) ctx.locals [fun() -> ctx.ret <- old_ret] in
  1179. (* turn any still unknown types back to type parameters *)
  1180. List.iter2 (fun m (_,t) -> match follow m with TMono _ -> Type.unify m t | _ -> ()) monos ctx.type_params;
  1181. pl,restore,(match with_type with
  1182. | WithType t -> WithType (apply_params ctx.type_params monos t)
  1183. | WithTypeResume t -> WithTypeResume (apply_params ctx.type_params monos t)
  1184. | _ -> with_type);
  1185. with Unrecognized_pattern (e,p) ->
  1186. error "Case expression must be a constant value or a pattern, not an arbitrary expression" p
  1187. in
  1188. let is_catch_all = match pl with
  1189. | [{p_def = PAny | PVar _}] -> true
  1190. | _ -> false
  1191. in
  1192. (* type case body *)
  1193. let e = match e with
  1194. | None ->
  1195. mk (TBlock []) ctx.com.basic.tvoid (pos ep)
  1196. | Some e ->
  1197. type_expr ctx e with_type
  1198. in
  1199. let e = match with_type with
  1200. | WithType t ->
  1201. Codegen.AbstractCast.cast_or_unify ctx t e e.epos;
  1202. | WithTypeResume t ->
  1203. (try Codegen.AbstractCast.cast_or_unify_raise ctx t e e.epos with Error (Unify l,p) -> raise (Typer.WithTypeError (l,p)));
  1204. | _ -> e
  1205. in
  1206. (* type case guard *)
  1207. let eg = match eg with
  1208. | None -> None
  1209. | Some e ->
  1210. let eg = type_expr ctx e (WithType ctx.com.basic.tbool) in
  1211. unify ctx eg.etype ctx.com.basic.tbool eg.epos;
  1212. Some eg
  1213. in
  1214. List.iter (fun f -> f()) restore;
  1215. save();
  1216. let out = mk_out mctx i e eg is_catch_all (pos ep) in
  1217. Array.of_list pl,out
  1218. ) cases in
  1219. let check_unused () =
  1220. let unused p =
  1221. display_error ctx "This pattern is unused" p;
  1222. let old_error = ctx.on_error in
  1223. ctx.on_error <- (fun ctx s p -> ctx.on_error <- old_error; raise Exit);
  1224. let check_expr e p =
  1225. try begin match fst e with
  1226. | EConst(Ident ("null" | "true" | "false")) -> ()
  1227. | EConst(Ident _) ->
  1228. ignore (type_expr ctx e Value);
  1229. display_error ctx "Case expression must be a constant value or a pattern, not an arbitrary expression" (pos e)
  1230. | _ -> ()
  1231. end with Exit -> ()
  1232. in
  1233. let rec loop prev cl = match cl with
  1234. | (_,Some _,_) :: cl -> loop prev cl
  1235. | ((e,p2),_,_) :: cl ->
  1236. if p2.pmin >= p.pmin then check_expr prev p else loop (e,p2) cl
  1237. | [] ->
  1238. check_expr prev p
  1239. in
  1240. (match cases with (e,_,_) :: cl -> loop e cl | [] -> assert false);
  1241. ctx.on_error <- old_error;
  1242. in
  1243. let had_catch_all = ref false in
  1244. List.iter (fun out ->
  1245. if out.o_catch_all && not !had_catch_all then
  1246. had_catch_all := true
  1247. else if out.o_num_paths = 0 then begin
  1248. unused out.o_pos;
  1249. if mctx.toplevel_or then begin match evals with
  1250. | [{etype = t}] when (match follow t with TAbstract({a_path=[],"Int"},[]) -> true | _ -> false) ->
  1251. display_error ctx "Note: Int | Int is an or-pattern now" p;
  1252. | _ -> ()
  1253. end;
  1254. end
  1255. ) (List.rev mctx.outcomes);
  1256. in
  1257. let dt = try
  1258. (* compile decision tree *)
  1259. compile mctx stl pl true
  1260. with Not_exhaustive(pat,st) ->
  1261. let rec s_st_r top pre st v = match st.st_def with
  1262. | SVar v1 ->
  1263. if not pre then v else begin try
  1264. let e = match List.assoc v1 !var_inits with Some e -> e | None -> assert false in
  1265. (Type.s_expr_pretty "" (Type.s_type (print_context())) e) ^ v
  1266. with Not_found ->
  1267. v1.v_name ^ v
  1268. end
  1269. | STuple(st,i,a) ->
  1270. let r = a - i - 1 in
  1271. Printf.sprintf "[%s]" (st_args i r (s_st_r top false st v))
  1272. | SArray(st,i) ->
  1273. s_st_r false true st (Printf.sprintf "[%i]%s" i (if top then " = " ^ v else v))
  1274. | SField({st_def = SVar v1},cf) when v1.v_name.[0] = '`' ->
  1275. cf.cf_name ^ (if top then " = " ^ v else v)
  1276. | SField(st,cf) ->
  1277. s_st_r false true st (Printf.sprintf ".%s%s" cf.cf_name (if top then " = " ^ v else v))
  1278. | SEnum(st,ef,i) ->
  1279. let len = match follow ef.ef_type with TFun(args,_) -> List.length args | _ -> 0 in
  1280. s_st_r false false st (Printf.sprintf "%s(%s)" ef.ef_name (st_args i (len - 1 - i) v))
  1281. in
  1282. let pat = match follow st.st_type with
  1283. | TAbstract({a_impl = Some cl} as a,_) when Meta.has Meta.Enum a.a_meta ->
  1284. let rec s_pat pat = match pat.p_def with
  1285. | PCon ({c_def = CConst c},[]) when c <> TNull ->
  1286. let cf = List.find (fun cf ->
  1287. match cf.cf_expr with
  1288. | Some ({eexpr = TConst c2 | TCast({eexpr = TConst c2},None)}) -> c = c2
  1289. | _ -> false
  1290. ) cl.cl_ordered_statics in
  1291. cf.cf_name
  1292. | PVar (v,_) -> v.v_name
  1293. | PCon (c,[]) -> s_con c
  1294. | PCon (c,pl) -> s_con c ^ "(" ^ (String.concat "," (List.map s_pat pl)) ^ ")"
  1295. | POr (pat1,pat2) -> s_pat pat1 ^ " | " ^ s_pat pat2
  1296. | PAny -> "_"
  1297. | PBind((v,_),pat) -> v.v_name ^ "=" ^ s_pat pat
  1298. | PTuple pl -> "(" ^ (String.concat " " (Array.to_list (Array.map s_pat pl))) ^ ")"
  1299. in
  1300. s_pat pat
  1301. | _ ->
  1302. s_pat pat
  1303. in
  1304. let msg = "Unmatched patterns: " ^ (s_st_r true false st pat) in
  1305. if !extractor_depth > 0 then begin
  1306. display_error ctx msg st.st_pos;
  1307. error "Note: Patterns with extractors may require a default pattern" st.st_pos;
  1308. end else
  1309. error msg st.st_pos
  1310. | Not_exhaustive_default ->
  1311. error "Unmatched patterns: _" p;
  1312. in
  1313. save();
  1314. (* check for unused patterns *)
  1315. if !extractor_depth = 0 then check_unused();
  1316. if mctx.has_extractor then decr extractor_depth;
  1317. (* determine type of switch statement *)
  1318. let t = if not need_val then
  1319. mk_mono()
  1320. else match with_type with
  1321. | WithType t | WithTypeResume t -> t
  1322. | _ -> try Typer.unify_min_raise ctx (List.rev_map (fun (_,out) -> get_expr mctx out.o_id) (List.rev pl)) with Error (Unify l,p) -> error (error_msg (Unify l)) p
  1323. in
  1324. (* unify with expected type if necessary *)
  1325. begin match tmono with
  1326. | None -> ()
  1327. | Some (WithType t2) -> unify ctx t2 t p
  1328. | Some (WithTypeResume t2) -> (try unify_raise ctx t2 t p with Error (Unify l,p) -> raise (Typer.WithTypeError (l,p)))
  1329. | _ -> assert false
  1330. end;
  1331. (* count usage *)
  1332. let usage = Array.make (DynArray.length mctx.dt_lut) 0 in
  1333. (* we always want to keep the first part *)
  1334. let first = (match dt with Goto i -> i | _ -> Hashtbl.find mctx.dt_cache dt) in
  1335. Array.set usage first 2;
  1336. let rec loop dt = match dt with
  1337. | Goto i -> Array.set usage i ((Array.get usage i) + 1)
  1338. | Switch(st,cl) -> List.iter (fun (_,dt) -> loop dt) cl
  1339. | Bind(bl,dt) -> loop dt
  1340. | Expr e -> ()
  1341. | Guard(e,dt1,dt2) ->
  1342. loop dt1;
  1343. match dt2 with None -> () | Some dt -> (loop dt)
  1344. in
  1345. DynArray.iter loop mctx.dt_lut;
  1346. (* filter parts that will be inlined and keep a map to them*)
  1347. let map = Array.make (DynArray.length mctx.dt_lut) 0 in
  1348. let lut = DynArray.create() in
  1349. let rec loop i c =
  1350. if c < DynArray.length mctx.dt_lut then begin
  1351. let i' = if usage.(c) > 1 then begin
  1352. DynArray.add lut (DynArray.get mctx.dt_lut c);
  1353. i + 1
  1354. end else i in
  1355. Array.set map c i;
  1356. loop i' (c + 1)
  1357. end
  1358. in
  1359. loop 0 0;
  1360. (* reindex *)
  1361. let rec loop dt = match dt with
  1362. | Goto i -> if usage.(i) > 1 then DTGoto (map.(i)) else loop (DynArray.get mctx.dt_lut i)
  1363. | Switch(st,cl) -> convert_switch mctx st cl loop
  1364. | Bind(bl,dt) -> DTBind(List.map (fun (v,st) -> v,convert_st ctx st) bl,loop dt)
  1365. | Expr id -> DTExpr (get_expr mctx id)
  1366. | Guard(id,dt1,dt2) -> DTGuard((match get_guard mctx id with Some e -> e | None -> assert false),loop dt1, match dt2 with None -> None | Some dt -> Some (loop dt))
  1367. in
  1368. let lut = DynArray.map loop lut in
  1369. {
  1370. dt_first = map.(first);
  1371. dt_dt_lookup = DynArray.to_array lut;
  1372. dt_type = t;
  1373. dt_var_init = List.rev !var_inits;
  1374. dt_is_complex = !is_complex;
  1375. }
  1376. ;;
  1377. match_expr_ref := match_expr;
  1378. get_pattern_locals_ref := get_pattern_locals