diff options
Diffstat (limited to 'typing/parmatch.ml')
| -rw-r--r-- | typing/parmatch.ml | 380 |
1 files changed, 211 insertions, 169 deletions
diff --git a/typing/parmatch.ml b/typing/parmatch.ml index 99bb5afe93..939d244bad 100644 --- a/typing/parmatch.ml +++ b/typing/parmatch.ml @@ -30,7 +30,9 @@ let make_pat desc ty tenv = let omega = make_pat Tpat_any Ctype.none Env.empty let extra_pat = - make_pat (Tpat_var (Ident.create "+")) Ctype.none Env.empty + make_pat + (Tpat_var (Ident.create "+", mknoloc "+")) + Ctype.none Env.empty let rec omegas i = if i <= 0 then [] else omega :: omegas (i-1) @@ -55,9 +57,9 @@ let records_args l1 l2 = (* Invariant: fields are already sorted by Typecore.type_label_a_list *) let rec combine r1 r2 l1 l2 = match l1,l2 with | [],[] -> List.rev r1, List.rev r2 - | [],(_,p2)::rem2 -> combine (omega::r1) (p2::r2) [] rem2 - | (_,p1)::rem1,[] -> combine (p1::r1) (omega::r2) rem1 [] - | (lbl1,p1)::rem1, (lbl2,p2)::rem2 -> + | [],(_,_,_,p2)::rem2 -> combine (omega::r1) (p2::r2) [] rem2 + | (_,_,_,p1)::rem1,[] -> combine (p1::r1) (omega::r2) rem1 [] + | (_,_,lbl1,p1)::rem1, (_, _,lbl2,p2)::rem2 -> if lbl1.lbl_pos < lbl2.lbl_pos then combine (p1::r1) (omega::r2) rem1 l2 else if lbl1.lbl_pos > lbl2.lbl_pos then @@ -78,7 +80,7 @@ let rec compat p q = | Tpat_constant c1, Tpat_constant c2 -> c1=c2 | Tpat_tuple ps, Tpat_tuple qs -> compats ps qs | Tpat_lazy p, Tpat_lazy q -> compat p q - | Tpat_construct (c1,ps1), Tpat_construct (c2,ps2) -> + | Tpat_construct (_, _, c1,ps1), Tpat_construct (_, _, c2,ps2) -> c1.cstr_tag = c2.cstr_tag && compats ps1 ps2 | Tpat_variant(l1,Some p1, r1), Tpat_variant(l2,Some p2,_) -> l1=l2 && compat p1 p2 @@ -86,7 +88,7 @@ let rec compat p q = l1 = l2 | Tpat_variant (_, None, _), Tpat_variant (_,Some _, _) -> false | Tpat_variant (_, Some _, _), Tpat_variant (_, None, _) -> false - | Tpat_record l1,Tpat_record l2 -> + | Tpat_record (l1,_),Tpat_record (l2,_) -> let ps,qs = records_args l1 l2 in compats ps qs | Tpat_array ps, Tpat_array qs -> @@ -135,7 +137,7 @@ let find_label lbl lbls = try let name,_,_ = List.nth lbls lbl.lbl_pos in name - with Failure "nth" -> "*Unkown label*" + with Failure "nth" -> Ident.create "*Unknown label*" let rec get_record_labels ty tenv = match get_type_descr ty tenv with @@ -156,7 +158,7 @@ let get_constr_name tag ty tenv = match tag with | Cstr_exception (path, _) -> Path.name path | _ -> try - let name,_,_ = get_constr tag ty tenv in name + let name,_,_ = get_constr tag ty tenv in Ident.name name with | Datarepr.Constr_not_found -> "*Unknown constructor*" @@ -167,7 +169,7 @@ let is_cons tag v = match get_constr_name tag v.pat_type v.pat_env with let rec pretty_val ppf v = match v.pat_desc with | Tpat_any -> fprintf ppf "_" - | Tpat_var x -> Ident.print ppf x + | Tpat_var (x,_) -> Ident.print ppf x | Tpat_constant (Const_int i) -> fprintf ppf "%d" i | Tpat_constant (Const_char c) -> fprintf ppf "%C" c | Tpat_constant (Const_string s) -> fprintf ppf "%S" s @@ -177,13 +179,13 @@ let rec pretty_val ppf v = match v.pat_desc with | Tpat_constant (Const_nativeint i) -> fprintf ppf "%ndn" i | Tpat_tuple vs -> fprintf ppf "@[(%a)@]" (pretty_vals ",") vs - | Tpat_construct ({cstr_tag=tag},[]) -> + | Tpat_construct (_, _, {cstr_tag=tag},[]) -> let name = get_constr_name tag v.pat_type v.pat_env in fprintf ppf "%s" name - | Tpat_construct ({cstr_tag=tag},[w]) -> + | Tpat_construct (_, _, {cstr_tag=tag},[w]) -> let name = get_constr_name tag v.pat_type v.pat_env in fprintf ppf "@[<2>%s@ %a@]" name pretty_arg w - | Tpat_construct ({cstr_tag=tag},vs) -> + | Tpat_construct (_, _, {cstr_tag=tag},vs) -> let name = get_constr_name tag v.pat_type v.pat_env in begin match (name, vs) with ("::", [v1;v2]) -> @@ -195,36 +197,42 @@ let rec pretty_val ppf v = match v.pat_desc with fprintf ppf "`%s" l | Tpat_variant (l, Some w, _) -> fprintf ppf "@[<2>`%s@ %a@]" l pretty_arg w - | Tpat_record lvs -> + | Tpat_record (lvs,_) -> fprintf ppf "@[{%a}@]" (pretty_lvals (get_record_labels v.pat_type v.pat_env)) (List.filter (function - | (_,{pat_desc=Tpat_any}) -> false (* do not show lbl=_ *) + | (_,_,_,{pat_desc=Tpat_any}) -> false (* do not show lbl=_ *) | _ -> true) lvs) | Tpat_array vs -> fprintf ppf "@[[| %a |]@]" (pretty_vals " ;") vs | Tpat_lazy v -> fprintf ppf "@[<2>lazy@ %a@]" pretty_arg v - | Tpat_alias (v,x) -> + | Tpat_alias (v, TPat_alias (x,_)) -> fprintf ppf "@[(%a@ as %a)@]" pretty_val v Ident.print x + | Tpat_alias (v, TPat_unpack) -> + fprintf ppf "@[(module %a@)@]" pretty_val v | Tpat_or (v,w,_) -> fprintf ppf "@[(%a|@,%a)@]" pretty_or v pretty_or w + | Tpat_alias (v, TPat_constraint ctyp) -> (* TODO *) + pretty_val ppf v + | Tpat_alias (v, TPat_type _) -> (* TODO *) + pretty_val ppf v and pretty_car ppf v = match v.pat_desc with -| Tpat_construct ({cstr_tag=tag}, [_ ; _]) +| Tpat_construct (_,_,{cstr_tag=tag}, [_ ; _]) when is_cons tag v -> fprintf ppf "(%a)" pretty_val v | _ -> pretty_val ppf v and pretty_cdr ppf v = match v.pat_desc with -| Tpat_construct ({cstr_tag=tag}, [v1 ; v2]) +| Tpat_construct (_,_,{cstr_tag=tag}, [v1 ; v2]) when is_cons tag v -> fprintf ppf "%a::@,%a" pretty_car v1 pretty_cdr v2 | _ -> pretty_val ppf v and pretty_arg ppf v = match v.pat_desc with -| Tpat_construct (_,_::_) -> fprintf ppf "(%a)" pretty_val v +| Tpat_construct (_,_,_,_::_) -> fprintf ppf "(%a)" pretty_val v | _ -> pretty_val ppf v and pretty_or ppf v = match v.pat_desc with @@ -240,12 +248,12 @@ and pretty_vals sep ppf = function and pretty_lvals lbls ppf = function | [] -> () - | [lbl,v] -> + | [_, _,lbl,v] -> let name = find_label lbl lbls in - fprintf ppf "%s=%a" name pretty_val v - | (lbl,v)::rest -> + fprintf ppf "%a=%a" Ident.print name pretty_val v + | (_, _, lbl,v)::rest -> let name = find_label lbl lbls in - fprintf ppf "%s=%a;@ %a" name pretty_val v (pretty_lvals lbls) rest + fprintf ppf "%a=%a;@ %a" Ident.print name pretty_val v (pretty_lvals lbls) rest let top_pretty ppf v = fprintf ppf "@[%a@]@?" pretty_val v @@ -263,7 +271,7 @@ let prerr_pat v = (* Check top matching *) let simple_match p1 p2 = match p1.pat_desc, p2.pat_desc with - | Tpat_construct(c1, _), Tpat_construct(c2, _) -> + | Tpat_construct(_, _, c1, _), Tpat_construct(_,_, c2, _) -> c1.cstr_tag = c2.cstr_tag | Tpat_variant(l1, _, _), Tpat_variant(l2, _, _) -> l1 = l2 @@ -283,30 +291,30 @@ let simple_match p1 p2 = (* extract record fields as a whole *) let record_arg p = match p.pat_desc with | Tpat_any -> [] -| Tpat_record args -> args +| Tpat_record (args,_) -> args | _ -> fatal_error "Parmatch.as_record" (* Raise Not_found when pos is not present in arg *) let get_field pos arg = - let _,p = List.find (fun (lbl,_) -> pos = lbl.lbl_pos) arg in + let _,_,_, p = List.find (fun (_,_,lbl,_) -> pos = lbl.lbl_pos) arg in p let extract_fields omegas arg = List.map - (fun (lbl,_) -> + (fun (_,_,lbl,_) -> try get_field lbl.lbl_pos arg with Not_found -> omega) omegas let all_record_args lbls = match lbls with -| ({lbl_all=lbl_all},_)::_ -> +| (_,_,{lbl_all=lbl_all},_)::_ -> let t = Array.map - (fun lbl -> lbl,omega) lbl_all in + (fun lbl -> Path.Pident (Ident.create "?temp?"), mknoloc (Longident.Lident "?temp?"), lbl,omega) lbl_all in List.iter - (fun ((lbl,_) as x) -> t.(lbl.lbl_pos) <- x) + (fun ((_,_, lbl,_) as x) -> t.(lbl.lbl_pos) <- x) lbls ; Array.to_list t | _ -> fatal_error "Parmatch.all_record_args" @@ -315,18 +323,18 @@ let all_record_args lbls = match lbls with (* Build argument list when p2 >= p1, where p1 is a simple pattern *) let rec simple_match_args p1 p2 = match p2.pat_desc with | Tpat_alias (p2,_) -> simple_match_args p1 p2 -| Tpat_construct(cstr, args) -> args +| Tpat_construct(_,_, cstr, args) -> args | Tpat_variant(lab, Some arg, _) -> [arg] | Tpat_tuple(args) -> args -| Tpat_record(args) -> extract_fields (record_arg p1) args +| Tpat_record(args,_) -> extract_fields (record_arg p1) args | Tpat_array(args) -> args | Tpat_lazy arg -> [arg] | (Tpat_any | Tpat_var(_)) -> begin match p1.pat_desc with - Tpat_construct(_, args) -> omega_list args + Tpat_construct(_,_, _,args) -> omega_list args | Tpat_variant(_, Some _, _) -> [omega] | Tpat_tuple(args) -> omega_list args - | Tpat_record(args) -> omega_list args + | Tpat_record(args,_) -> omega_list args | Tpat_array(args) -> omega_list args | Tpat_lazy _ -> [omega] | _ -> [] @@ -344,21 +352,20 @@ let rec normalize_pat q = match q.pat_desc with | Tpat_alias (p,_) -> normalize_pat p | Tpat_tuple (args) -> make_pat (Tpat_tuple (omega_list args)) q.pat_type q.pat_env - | Tpat_construct (c,args) -> - make_pat (Tpat_construct (c,omega_list args)) q.pat_type q.pat_env + | Tpat_construct (lid, lid_loc, c,args) -> + make_pat (Tpat_construct (lid, lid_loc, c,omega_list args)) q.pat_type q.pat_env | Tpat_variant (l, arg, row) -> make_pat (Tpat_variant (l, may_map (fun _ -> omega) arg, row)) q.pat_type q.pat_env | Tpat_array (args) -> make_pat (Tpat_array (omega_list args)) q.pat_type q.pat_env - | Tpat_record (largs) -> - make_pat (Tpat_record (List.map (fun (lbl,_) -> lbl,omega) largs)) + | Tpat_record (largs, closed) -> + make_pat (Tpat_record (List.map (fun (lid,lid_loc,lbl,_) -> lid, lid_loc, lbl,omega) largs, closed)) q.pat_type q.pat_env | Tpat_lazy _ -> make_pat (Tpat_lazy omega) q.pat_type q.pat_env | Tpat_or _ -> fatal_error "Parmatch.normalize_pat" - (* Build normalized (cf. supra) discriminating pattern, in the non-data type case @@ -375,19 +382,19 @@ let discr_pat q pss = acc_pat acc pss | (({pat_desc = Tpat_tuple _} as p)::_)::_ -> normalize_pat p | (({pat_desc = Tpat_lazy _} as p)::_)::_ -> normalize_pat p - | (({pat_desc = Tpat_record largs} as p)::_)::pss -> + | (({pat_desc = Tpat_record (largs,closed)} as p)::_)::pss -> let new_omegas = List.fold_right - (fun (lbl,_) r -> + (fun (lid, lid_loc, lbl,_) r -> try let _ = get_field lbl.lbl_pos r in r with Not_found -> - (lbl,omega)::r) + (lid, lid_loc, lbl,omega)::r) largs (record_arg acc) in acc_pat - (make_pat (Tpat_record new_omegas) p.pat_type p.pat_env) + (make_pat (Tpat_record (new_omegas, closed)) p.pat_type p.pat_env) pss | _ -> acc in @@ -412,26 +419,26 @@ let do_set_args erase_mutable q r = match q with | {pat_desc = Tpat_tuple omegas} -> let args,rest = read_args omegas r in make_pat (Tpat_tuple args) q.pat_type q.pat_env::rest -| {pat_desc = Tpat_record omegas} -> +| {pat_desc = Tpat_record (omegas,closed)} -> let args,rest = read_args omegas r in make_pat (Tpat_record - (List.map2 (fun (lbl,_) arg -> + (List.map2 (fun (lid, lid_loc, lbl,_) arg -> if erase_mutable && (match lbl.lbl_mut with | Mutable -> true | Immutable -> false) then - lbl, omega + lid, lid_loc, lbl, omega else - lbl,arg) - omegas args)) + lid, lid_loc, lbl, arg) + omegas args, closed)) q.pat_type q.pat_env:: rest -| {pat_desc = Tpat_construct (c,omegas)} -> +| {pat_desc = Tpat_construct (lid, lid_loc, c,omegas)} -> let args,rest = read_args omegas r in make_pat - (Tpat_construct (c,args)) q.pat_type q.pat_env:: + (Tpat_construct (lid, lid_loc, c,args)) q.pat_type q.pat_env:: rest | {pat_desc = Tpat_variant (l, omega, row)} -> let arg, rest = @@ -596,14 +603,14 @@ let row_of_pat pat = not. *) -let generalized_constructor x = - match x with - ({pat_desc = Tpat_construct(c,_);pat_env=env},_) -> +let generalized_constructor x = + match x with + ({pat_desc = Tpat_construct(_,_,c,_);pat_env=env},_) -> c.cstr_generalized | _ -> assert false -let clean_env env = - let rec loop = +let clean_env env = + let rec loop = function | [] -> [] | x :: xs -> @@ -612,12 +619,12 @@ let clean_env env = loop env let full_match ignore_generalized closing env = match env with -| ({pat_desc = Tpat_construct ({cstr_tag=Cstr_exception _},_)},_)::_ -> +| ({pat_desc = Tpat_construct (_,_,{cstr_tag=Cstr_exception _},_)},_)::_ -> false -| ({pat_desc = Tpat_construct(c,_);pat_type=typ},_) :: _ -> +| ({pat_desc = Tpat_construct(_,_,c,_);pat_type=typ},_) :: _ -> if ignore_generalized then (* remove generalized constructors; those cases will be handled separately *) - let env = clean_env env in + let env = clean_env env in List.length env = c.cstr_normal else List.length env = c.cstr_consts + c.cstr_nonconsts @@ -656,12 +663,12 @@ let full_match ignore_generalized closing env = match env with | _ -> fatal_error "Parmatch.full_match" let full_match_gadt env = match env with - | ({pat_desc = Tpat_construct(c,_);pat_type=typ},_) :: _ -> + | ({pat_desc = Tpat_construct(_,_,c,_);pat_type=typ},_) :: _ -> List.length env = c.cstr_consts + c.cstr_nonconsts | _ -> true let extendable_match env = match env with -| ({pat_desc = Tpat_construct({cstr_tag=(Cstr_constant _|Cstr_block _)},_)} as p,_) :: _ -> +| ({pat_desc = Tpat_construct(_,_,{cstr_tag=(Cstr_constant _|Cstr_block _)},_)} as p,_) :: _ -> let path = get_type_path p.pat_type p.pat_env in not (Path.same path Predef.path_bool || @@ -674,7 +681,7 @@ let should_extend ext env = match ext with | None -> false | Some ext -> match env with | ({pat_desc = - Tpat_construct({cstr_tag=(Cstr_constant _|Cstr_block _)},_)} as p,_) + Tpat_construct(_, _,{cstr_tag=(Cstr_constant _|Cstr_block _)},_)} as p,_) :: _ -> let path = get_type_path p.pat_type p.pat_env in Path.same path ext @@ -703,7 +710,9 @@ let complete_tags nconsts nconstrs tags = (* build a pattern from a constructor list *) let pat_of_constr ex_pat cstr = - {ex_pat with pat_desc = Tpat_construct (cstr,omegas cstr.cstr_arity)} + {ex_pat with pat_desc = Tpat_construct ( + Path.Pident (Ident.create "?pat_of_constr?"), mknoloc (Longident.Lident "?pat_of_constr?"), + cstr,omegas cstr.cstr_arity)} let rec pat_of_constrs ex_pat = function | [] -> raise Empty @@ -729,7 +738,7 @@ let rec adt_path env ty = | _ -> raise Not_an_adt ;; -let rec map_filter f = +let rec map_filter f = function [] -> [] | x :: xs -> @@ -738,9 +747,9 @@ let rec map_filter f = | Some y -> y :: map_filter f xs (* Sends back a pattern that complements constructor tags all_tag *) -let complete_constrs p all_tags = +let complete_constrs p all_tags = match p.pat_desc with - | Tpat_construct (c,_) -> + | Tpat_construct (_,_,c,_) -> begin try let not_tags = complete_tags c.cstr_consts c.cstr_nonconsts all_tags in let constrs = Env.find_constructors (adt_path p.pat_env p.pat_type) p.pat_env in @@ -771,22 +780,22 @@ let build_other_constant proj make first next p env = *) let build_other ext env = match env with -| ({pat_desc = Tpat_construct ({cstr_tag=Cstr_exception _} as c,_)},_) +| ({pat_desc = Tpat_construct (lid, lid_loc, ({cstr_tag=Cstr_exception _} as c),_)},_) ::_ -> make_pat (Tpat_construct - ({c with + (lid, lid_loc, {c with cstr_tag=(Cstr_exception (Path.Pident (Ident.create "*exception*"), Location.none))}, [])) Ctype.none Env.empty -| ({pat_desc = Tpat_construct (_,_)} as p,_) :: _ -> +| ({pat_desc = Tpat_construct (_,_, _,_)} as p,_) :: _ -> begin match ext with | Some ext when Path.same ext (get_type_path p.pat_type p.pat_env) -> extra_pat | _ -> let get_tag = function - | {pat_desc = Tpat_construct (c,_)} -> c.cstr_tag + | {pat_desc = Tpat_construct (_,_,c,_)} -> c.cstr_tag | _ -> fatal_error "Parmatch.get_tag" in let all_tags = List.map (fun (p,_) -> get_tag p) env in pat_of_constrs p (complete_constrs p all_tags) @@ -899,11 +908,11 @@ let build_other ext env = match env with | [] -> omega | _ -> omega -let build_other_gadt ext env = +let build_other_gadt ext env = match env with - | ({pat_desc = Tpat_construct (_,_)} as p,_) :: _ -> + | ({pat_desc = Tpat_construct _} as p,_) :: _ -> let get_tag = function - | {pat_desc = Tpat_construct (c,_)} -> c.cstr_tag + | {pat_desc = Tpat_construct (_,_,c,_)} -> c.cstr_tag | _ -> fatal_error "Parmatch.get_tag" in let all_tags = List.map (fun (p,_) -> get_tag p) env in let cnstrs = complete_constrs p all_tags in @@ -912,7 +921,7 @@ let build_other_gadt ext env = Format.eprintf "@.@."; *) pats | _ -> assert false - + (* Core function : Is the last row of pattern matrix pss + qs satisfiable ? @@ -922,14 +931,19 @@ let build_other_gadt ext env = 2- qs <= es (es matches qs) *) +let snd3 (_,x,_) = x +let thd4 (_,_,x,_) = x + let rec has_instance p = match p.pat_desc with | Tpat_variant (l,_,r) when is_absent l r -> false | Tpat_any | Tpat_var _ | Tpat_constant _ | Tpat_variant (_,None,_) -> true | Tpat_alias (p,_) | Tpat_variant (_,Some p,_) -> has_instance p | Tpat_or (p1,p2,_) -> has_instance p1 || has_instance p2 - | Tpat_construct (_,ps) | Tpat_tuple ps | Tpat_array ps -> has_instances ps - | Tpat_record lps -> has_instances (List.map snd lps) - | Tpat_lazy p -> has_instance p + | Tpat_construct (_, _,_,ps) | Tpat_tuple ps | Tpat_array ps -> has_instances ps + | Tpat_record (lps,_) -> has_instances (List.map (fun (_,_,_,x) -> x) lps) + | Tpat_lazy p + -> has_instance p + and has_instances = function | [] -> true @@ -976,14 +990,14 @@ type 'a result = | Rsome of 'a (* This matching value *) let rec orify_many = - let rec orify x y = - make_pat (Tpat_or (x, y, None)) x.pat_type x.pat_env + let rec orify x y = + make_pat (Tpat_or (x, y, None)) x.pat_type x.pat_env in function | [] -> assert false | [x] -> x | x :: xs -> orify x (orify_many xs) - + let rec try_many f = function | [] -> Rnone | (p,pss)::rest -> @@ -997,13 +1011,13 @@ let rec try_many_gadt f = function | (p,pss)::rest -> match f (p,pss) with | Rnone -> try_many f rest - | Rsome sofar -> - let others = try_many f rest in + | Rsome sofar -> + let others = try_many f rest in match others with Rnone -> Rsome sofar | Rsome sofar' -> Rsome (sofar @ sofar') - + let rec exhaust ext pss n = match pss with @@ -1053,8 +1067,8 @@ let rec exhaust ext pss n = match pss with | Empty -> fatal_error "Parmatch.exhaust" end -let combinations f lst lst' = - let rec iter2 x = +let combinations f lst lst' = + let rec iter2 x = function [] -> [] | y :: ys -> @@ -1066,10 +1080,33 @@ let combinations f lst lst' = | x :: xs -> iter2 x lst' @ iter xs in iter lst - + +(* +let print_pat pat = + let rec string_of_pat pat = + match pat.pat_desc with + Tpat_var _ -> "v" + | Tpat_any -> "_" + | Tpat_alias (p, x) -> Printf.sprintf "(%s) as ?" (string_of_pat p) + | Tpat_constant n -> "0" + | Tpat_construct (_, lid, _, _) -> + Printf.sprintf "%s" (String.concat "." (Longident.flatten lid.txt)) + | Tpat_lazy p -> + Printf.sprintf "(lazy %s)" (string_of_pat p) + | Tpat_or (p1,p2,_) -> + Printf.sprintf "(%s | %s)" (string_of_pat p1) (string_of_pat p2) + | Tpat_tuple list -> + Printf.sprintf "(%s)" (String.concat "," (List.map string_of_pat list)) + | Tpat_variant (_, _, _) -> "variant" + | Tpat_record (_, _) -> "record" + | Tpat_array _ -> "array" + in + Printf.fprintf stderr "PAT[%s]\n%!" (string_of_pat pat) +*) + (* strictly more powerful than exhaust; however, exhaust was kept for backwards compatibility *) -let rec exhaust_gadt ext pss n = match pss with +let rec exhaust_gadt (ext:Path.t option) (pss:Typedtree.pattern list list) (n:int) = match pss with | [] -> Rsome [omegas n] | []::_ -> Rnone | pss -> @@ -1112,34 +1149,33 @@ let rec exhaust_gadt ext pss n = match pss with | Rsome r -> try let missing_trailing = build_other_gadt ext constrs in - let before = - match before with - Rnone -> [] - | Rsome lst -> lst + let before = + match before with + Rnone -> [] + | Rsome lst -> lst in - let dug = + let dug = combinations - (fun head tail -> - head :: tail) + (fun head tail -> head :: tail) missing_trailing r in - Rsome (dug @ before) + Rsome (dug @ before) with (* cannot occur, since constructors don't make a full signature *) | Empty -> fatal_error "Parmatch.exhaust" end -let exhaust_gadt ext pss n = - let ret = exhaust_gadt ext pss n in +let exhaust_gadt ext pss n = + let ret = exhaust_gadt ext pss n in match ret with Rnone -> Rnone | Rsome lst -> (* The following line is needed to compile stdlib/printf.ml *) if lst = [] then Rsome (omegas n) else - let singletons = - List.map - (function + let singletons = + List.map + (function [x] -> x | _ -> assert false) lst @@ -1470,7 +1506,7 @@ let rec le_pat p q = | Tpat_alias(p,_), _ -> le_pat p q | _, Tpat_alias(q,_) -> le_pat p q | Tpat_constant(c1), Tpat_constant(c2) -> c1 = c2 - | Tpat_construct(c1,ps), Tpat_construct(c2,qs) -> + | Tpat_construct(_,_,c1,ps), Tpat_construct(_,_,c2,qs) -> c1.cstr_tag = c2.cstr_tag && le_pats ps qs | Tpat_variant(l1,Some p1,_), Tpat_variant(l2,Some p2,_) -> (l1 = l2 && le_pat p1 p2) @@ -1479,7 +1515,7 @@ let rec le_pat p q = | Tpat_variant(_,_,_), Tpat_variant(_,_,_) -> false | Tpat_tuple(ps), Tpat_tuple(qs) -> le_pats ps qs | Tpat_lazy p, Tpat_lazy q -> le_pat p q - | Tpat_record l1, Tpat_record l2 -> + | Tpat_record (l1,_), Tpat_record (l2,_) -> let ps,qs = records_args l1 l2 in le_pats ps qs | Tpat_array(ps), Tpat_array(qs) -> @@ -1520,19 +1556,19 @@ let rec lub p q = match p.pat_desc,q.pat_desc with | Tpat_lazy p, Tpat_lazy q -> let r = lub p q in make_pat (Tpat_lazy r) p.pat_type p.pat_env -| Tpat_construct (c1,ps1), Tpat_construct (c2,ps2) +| Tpat_construct (lid, lid_loc, c1,ps1), Tpat_construct (_, _,c2,ps2) when c1.cstr_tag = c2.cstr_tag -> let rs = lubs ps1 ps2 in - make_pat (Tpat_construct (c1,rs)) p.pat_type p.pat_env + make_pat (Tpat_construct (lid, lid_loc, c1,rs)) p.pat_type p.pat_env | Tpat_variant(l1,Some p1,row), Tpat_variant(l2,Some p2,_) when l1=l2 -> let r=lub p1 p2 in make_pat (Tpat_variant (l1,Some r,row)) p.pat_type p.pat_env | Tpat_variant (l1,None,row), Tpat_variant(l2,None,_) when l1 = l2 -> p -| Tpat_record l1,Tpat_record l2 -> +| Tpat_record (l1,closed),Tpat_record (l2,_) -> let rs = record_lubs l1 l2 in - make_pat (Tpat_record rs) p.pat_type p.pat_env + make_pat (Tpat_record (rs, closed)) p.pat_type p.pat_env | Tpat_array ps, Tpat_array qs when List.length ps = List.length qs -> let rs = lubs ps qs in @@ -1554,13 +1590,13 @@ and record_lubs l1 l2 = let rec lub_rec l1 l2 = match l1,l2 with | [],_ -> l2 | _,[] -> l1 - | (lbl1,p1)::rem1, (lbl2,p2)::rem2 -> + | (lid1, lid1_loc, lbl1,p1)::rem1, (lid2, lid2_loc, lbl2,p2)::rem2 -> if lbl1.lbl_pos < lbl2.lbl_pos then - (lbl1,p1)::lub_rec rem1 l2 + (lid1, lid1_loc, lbl1,p1)::lub_rec rem1 l2 else if lbl2.lbl_pos < lbl1.lbl_pos then - (lbl2,p2)::lub_rec l1 rem2 + (lid2, lid2_loc, lbl2,p2)::lub_rec l1 rem2 else - (lbl1,lub p1 p2)::lub_rec rem1 rem2 in + (lid1, lid1_loc, lbl1,lub p1 p2)::lub_rec rem1 rem2 in lub_rec l1 l2 and lubs ps qs = match ps,qs with @@ -1673,11 +1709,11 @@ let check_partial_all v casel = (************************) - let rec get_first f = + let rec get_first f = function | [] -> None - | x :: xs -> - match f x with + | x :: xs -> + match f x with | None -> get_first f xs | x -> x @@ -1685,11 +1721,11 @@ let check_partial_all v casel = (* conversion from Typedtree.pattern to Parsetree.pattern list *) module Conv = struct open Parsetree - let mkpat desc = + let mkpat desc = {ppat_desc = desc; ppat_loc = Location.none} - let rec select : 'a list list -> 'a list list = + let rec select : 'a list list -> 'a list list = function | xs :: [] -> List.map (fun y -> [y]) xs | (x::xs)::ys -> @@ -1700,20 +1736,20 @@ module Conv = struct select (xs::ys) | _ -> [] - let name_counter = ref 0 - let fresh () = - let current = !name_counter in + let name_counter = ref 0 + let fresh () = + let current = !name_counter in name_counter := !name_counter + 1; "#$%^@*@" ^ string_of_int current - let conv (typed: Typedtree.pattern) : - Parsetree.pattern list * - (string,Types.constructor_description) Hashtbl.t * - (string,Types.label_description) Hashtbl.t - = - let constrs = Hashtbl.create 0 in - let labels = Hashtbl.create 0 in - let rec loop pat = + let conv (typed: Typedtree.pattern) : + Parsetree.pattern list * + (string,Path.t * Types.constructor_description) Hashtbl.t * + (string,Path.t * Types.label_description) Hashtbl.t + = + let constrs = Hashtbl.create 0 in + let labels = Hashtbl.create 0 in + let rec loop pat = match pat.pat_desc with Tpat_or (a,b,_) -> loop a @ loop b @@ -1721,27 +1757,28 @@ module Conv = struct [mkpat Ppat_any] | Tpat_alias (p,_) -> loop p | Tpat_tuple lst -> - let results = select (List.map loop lst) in + let results = select (List.map loop lst) in List.map (fun lst -> mkpat (Ppat_tuple lst)) results - | Tpat_construct (cstr,lst) -> - let id = fresh () in - Hashtbl.add constrs id cstr; + | Tpat_construct (cstr_path, cstr_lid, cstr,lst) -> + let id = fresh () in + let lid = { cstr_lid with txt = Longident.Lident id } in + Hashtbl.add constrs id (cstr_path,cstr); let results = select (List.map loop lst) in begin match lst with [] -> - [mkpat (Ppat_construct(Longident.Lident id, None, false))] + [mkpat (Ppat_construct(lid, None, false))] | _ -> - List.map + List.map (fun lst -> - let arg = + let arg = match lst with [] -> assert false | [x] -> Some x | _ -> Some (mkpat (Ppat_tuple lst)) in - mkpat (Ppat_construct(Longident.Lident id, arg, false))) + mkpat (Ppat_construct(lid, arg, false))) results end | Tpat_variant(label,p_opt,row_desc) -> @@ -1749,38 +1786,40 @@ module Conv = struct | None -> [mkpat (Ppat_variant(label, None))] | Some p -> - let results = loop p in + let results = loop p in List.map (fun p -> mkpat (Ppat_variant(label, Some p))) results end - | Tpat_record subpatterns -> - let pats = + | Tpat_record (subpatterns, _closed_flag) -> + let pats = select - (List.map (fun (_,x) -> (loop x)) subpatterns) + (List.map (fun (_,_,_,x) -> (loop x)) subpatterns) in - let label_idents = - List.map - (fun (lbl,_) -> - let id = fresh () in - Hashtbl.add labels id lbl; - Longident.Lident id) + let label_idents = + List.map + (fun (lbl_path,_,lbl,_) -> + let id = fresh () in + Hashtbl.add labels id (lbl_path, lbl); + Longident.Lident id) subpatterns - in + in List.map (fun lst -> - let lst = List.combine label_idents lst in - mkpat (Ppat_record (lst, Open))) + let lst = List.map2 (fun lid pat -> + (mknoloc lid, pat) + ) label_idents lst in + mkpat (Ppat_record (lst, Open))) pats | Tpat_array lst -> - let results = select (List.map loop lst) in + let results = select (List.map loop lst) in List.map (fun lst -> mkpat (Ppat_array lst)) results | Tpat_lazy p -> - let results = loop p in + let results = loop p in List.map (fun p -> mkpat (Ppat_lazy p)) results in - let ps = loop typed in + let ps = loop typed in (ps, constrs, labels) end @@ -1804,10 +1843,13 @@ let do_check_partial ?pred exhaust loc casel pss = match pss with begin match exhaust None pss (List.length ps) with | Rnone -> Total | Rsome [u] -> - let v = - match pred with + let v = + match pred with | Some pred -> - let (patterns,constrs,labels) = Conv.conv u in + let (patterns,constrs,labels) = Conv.conv u in +(* Hashtbl.iter (fun s (path, _) -> + Printf.fprintf stderr "CONV: %s -> %s \n%!" s (Path.name path)) constrs + ; *) get_first (pred constrs labels) patterns | None -> Some u in @@ -1838,10 +1880,10 @@ let do_check_partial ?pred exhaust loc casel pss = match pss with fatal_error "Parmatch.check_partial" end -let do_check_partial_normal loc casel pss = +let do_check_partial_normal loc casel pss = do_check_partial exhaust loc casel pss -let do_check_partial_gadt pred loc casel pss = +let do_check_partial_gadt pred loc casel pss = do_check_partial ~pred exhaust_gadt loc casel pss @@ -1866,7 +1908,7 @@ let extendable_path path = Path.same path Predef.path_option) let rec collect_paths_from_pat r p = match p.pat_desc with -| Tpat_construct({cstr_tag=(Cstr_constant _|Cstr_block _)},ps) -> +| Tpat_construct(_, _, {cstr_tag=(Cstr_constant _|Cstr_block _)},ps) -> let path = get_type_path p.pat_type p.pat_env in List.fold_left collect_paths_from_pat @@ -1874,16 +1916,17 @@ let rec collect_paths_from_pat r p = match p.pat_desc with ps | Tpat_any|Tpat_var _|Tpat_constant _| Tpat_variant (_,None,_) -> r | Tpat_tuple ps | Tpat_array ps -| Tpat_construct ({cstr_tag=Cstr_exception _}, ps)-> +| Tpat_construct (_, _, {cstr_tag=Cstr_exception _}, ps)-> List.fold_left collect_paths_from_pat r ps -| Tpat_record lps -> +| Tpat_record (lps,_) -> List.fold_left - (fun r (_,p) -> collect_paths_from_pat r p) + (fun r (_, _, _, p) -> collect_paths_from_pat r p) r lps | Tpat_variant (_, Some p, _) | Tpat_alias (p,_) -> collect_paths_from_pat r p | Tpat_or (p1,p2,_) -> collect_paths_from_pat (collect_paths_from_pat r p1) p2 -| Tpat_lazy p -> +| Tpat_lazy p + -> collect_paths_from_pat r p @@ -1967,16 +2010,15 @@ let rec inactive pat = match pat with false | Tpat_any | Tpat_var _ | Tpat_constant _ | Tpat_variant (_, None, _) -> true -| Tpat_tuple ps | Tpat_construct (_, ps) | Tpat_array ps -> +| Tpat_tuple ps | Tpat_construct (_, _, _, ps) | Tpat_array ps -> List.for_all (fun p -> inactive p.pat_desc) ps | Tpat_alias (p,_) | Tpat_variant (_, Some p, _) -> inactive p.pat_desc -| Tpat_record ldps -> - List.exists (fun (_, p) -> inactive p.pat_desc) ldps +| Tpat_record (ldps,_) -> + List.exists (fun (_, _, _, p) -> inactive p.pat_desc) ldps | Tpat_or (p,q,_) -> inactive p.pat_desc && inactive q.pat_desc - (* A `fluid' pattern is both irrefutable and inactive *) let fluid pat = irrefutable pat && inactive pat.pat_desc @@ -1986,7 +2028,7 @@ let fluid pat = irrefutable pat && inactive pat.pat_desc - + (********************************) (* Exported exhustiveness check *) (********************************) @@ -1996,7 +2038,7 @@ let fluid pat = irrefutable pat && inactive pat.pat_desc on exhaustive matches only. *) -let check_partial_param do_check_partial do_check_fragile loc casel = +let check_partial_param do_check_partial do_check_fragile loc casel = if Warnings.is_active (Warnings.Partial_match "") then begin let pss = initial_matrix casel in let pss = get_mins le_pats pss in @@ -2008,11 +2050,11 @@ let check_partial_param do_check_partial do_check_fragile loc casel = end ; total end else - Partial + Partial -let check_partial = - check_partial_param - do_check_partial_normal +let check_partial = + check_partial_param + do_check_partial_normal do_check_fragile_normal let check_partial_gadt pred loc casel = @@ -2020,7 +2062,7 @@ let check_partial_gadt pred loc casel = let first_check = check_partial loc casel in match first_check with | Partial -> Partial - | Total -> + | Total -> (* checks for missing GADT constructors *) check_partial_param (do_check_partial_gadt pred) do_check_fragile_gadt loc casel |
